Добавление вектора в прологе - PullRequest
2 голосов
/ 03 февраля 2010

Я пишу предикат, чтобы добавить два вектора. Вот что я придумал:

add( [], [], 0 ).
add( [A], 0, A ).
add( [A], [B], C ) :- C is A + B.
add( A, B, C ) :- add( B, A, C ).
add( [H1|T1], [H2|T2], WYNIK ) :- X is H1 + H2, add( T1, T2, Y ), append( [X], Y, WYNIK ).

Первые четыре строки работают отлично, но я не могу заставить работать последнюю - что я делаю не так?

Ответы [ 2 ]

3 голосов
/ 04 февраля 2010

В этом порядке последняя строка никогда не будет запущена. Линия:

add( A, B, C ) :- add( B, A, C ).

объединится с чем-либо, что еще не было обработано правилом над ним.

1 голос
/ 03 марта 2010

Как заметил Джефф, проблема в правиле:

add( A, B, C ) :- add( B, A, C ).

В общем, это правило, которое выражает то, что вы хотите быть правдой, но это не помогает вам решить цель. Запрос add(1,2,X) по этому правилу приводит к подзапросу add(2,1,X), что приводит к подзапросу add(1,2,X): разрешение SLD может тратить вечно на эту ветку (если у него нет других правил более высокого приоритета, и он не определяет что правило не прогрессирует), никуда не деться. Вы должны использовать такое правило только с условиями (например, strictlylessthan (B,A)), которые гарантируют, что правило применимо только тогда, когда оно может выполнять полезную работу. Проблема таких правил является причиной, по которой Пролог на самом деле не является декларативным языком.

Чтобы восстановить коммутативность, вам нужно добавить правило:

add (0, [A], A).

Ваш предикат добавления является нечетным: add([1],0,1) - это истина, как и add([1],[0],1), но add([0],1,1) - это не так, как и add([1],[0],[1]). add совершенно значим с вычислительной точки зрения, но действительно ли это то, что вы хотите?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...