Упражнение на сложение пролога

У меня есть этот очень простой код как представление цифр. Проблема в том, что я использую функцию add2.

Пример: add2(s(0)+s(s(0)), s(s(0)), Z). возвращает s(s(s(s(s(0))))) правильно. Однако add2(0, s(0)+s(s(0)), Z). всегда returns s(0)+s(s(0)). Кто-нибудь может понять, почему это происходит?

numeral(0).
numeral(s(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).

add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).

%%  exercise 1
add2(X,Y,R) :- add(X,Y,R).
add2(X+Y,Z,R) :- add(X,Y,A),add2(A,Z,R).
add2(X,Y+Z,R) :- add(Y,Z,A),add2(X,A,R).

person user1015492    schedule 26.10.2011    source источник


Ответы (3)


Это происходит из-за комбинации первого предложения add2 и первого предложения add. Ваш add2(0, ..., ...) вызовет add(0, ..., ...), который всегда объединяет второй и третий аргумент.

person Giulio Piancastelli    schedule 27.10.2011

В Прологе функциональные символы, такие как инфикс +, не оцениваются. Кажется, вы пытаетесь оценить все вхождения +. Однако некоторые из них все еще не оцениваются, и это может быть довольно сложно, если вы попытаетесь сделать это ad hoc, как в add2/3. Рассмотрим add2(0+0+0,0,R), который не соответствует вашему определению.

То, что вы называете numeral/1, лучше было бы назвать expression/1.

Рассмотрите возможность определения вспомогательного предиката eval/2 для упрощения выражений до s(X)-чисел. Однако обратите внимание, что даже такое определение по-прежнему не работает для таких целей, как add2(0,0,0+0). Это неотъемлемая проблема, которую можно решить только с помощью ограничений или аналогичных методов...

person false    schedule 26.10.2011

Когда вы вызываете add2(0, s(0)+s(s(0)), Z), оно будет унифицировано с первым предложением add2/3, так как это первое предложение имеет только три переменные в заголовке, поэтому его можно унифицировать с любым вызовом add2/3. Это, в свою очередь, в вашем примере приведет к вызову первого предложения add/3, поэтому Z будет привязан к s(0)+s(s(0)).

Проблема с вашим кодом заключается в том, что более конкретные предложения add2/3 помещаются после общего предложения. Итак, чтобы ваш код работал, поместите первое предложение add2/3 последним и добавьте сокращения к двум другим, например.

add2(X+Y,Z,R) :- !,add(X,Y,A),add2(A,Z,R).

поскольку, когда заголовок этого предложения соответствует запросу, вы уверены, что выполняете правильное предложение, и у вас не возникнет проблем с откатом.

person twinterer    schedule 27.10.2011
comment
Что ж, это простое домашнее задание, так что я думаю, можно потребовать, чтобы входные данные были правильно заключены в скобки (если это слово...). - person twinterer; 27.10.2011
comment
Но: если вас действительно беспокоят такие случаи, как add2(0+0+0,0,R), замените вызовы add/3 в двух предложениях add2/3, которые обрабатывают оператор +, вызовами add2/3, например. add2(X+Y,Z,R) :- !,add2(X,Y,A),add2(A,Z,R).. - person twinterer; 27.10.2011
comment
Рассмотрите возможность добавления mul2/3 или функтора (*)/2, чтобы понять, почему имеет смысл отдельное определение — также в качестве домашнего задания. - person false; 27.10.2011
comment
Конечно, но это, вероятно, довольно быстро выходит за рамки его текущего домашнего задания. Также это отвлекает от более основной проблемы, заключающейся в том, что в его коде общее предложение add2/3 было помещено перед конкретными предложениями. Если кто-то борется с основами Пролога, то ожидать, что он не только решит проблему сложения, но и напишет синтаксический анализатор/оценщик общих выражений, довольно амбициозно. - person twinterer; 27.10.2011