как напечатать более одного ответа в прологе - PullRequest
0 голосов
/ 14 мая 2011

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

starter( greenSalad,10).
starter( seserSalad,20).
starter( tomatoSalad,10).
main( chicken,40).
main( pizza,30).
main( pasta,30).
dessert( raspberryCake,30).
dessert( fruitCake,20).
dessert( applepie,20).

min(Head,Tail,Head):- Head<Tail.
min(Head,Tail,Tail):- Tail<Head.
findmin([Only], Only).
findmin([Head|Tail], Minimum) :- findmin(Tail, TailMin), Minimum is
min(Head, TailMin).


**findMeal**2:-findall(Sp,starter(_,Sp),SList),findmin(SList,Spm),printStarter2(Spm),
    findall(Mp,main(_,Mp),MList),findmin(MList,Mpm),printMain2(Mpm),
    findall(Dp,dessert(_,Dp),DList),findmin(DList,Dpm),printDessert2(Dpm).


printStarter2(Spm):-starter(S,Spm),write(S),nl,fail.
printMain2(Mpm):-main(M,Mpm),write(M),nl,fail.
printDessert2(Dpm):-dessert(D,Dpm),write(D),nl,fail.

ПРОБЛЕМА: это дает все минимальные стартеры, затем останавливается без предоставления минимального основного и десерта

1 Ответ

1 голос
/ 14 мая 2011

Пролог-тесты предикатов в порядке их появления в предложении. Это делает несущественные объединения, которые сделали бы условие истинным. Когда он пытается доказать findMeal, он доказывает findall / 3, который всегда подтверждается, но выполняет необходимые объединения, т.е. SList связывается после этого.

Тогда это доказывает findmin / 2, который объединяет Spm с 10 и оставляет точку выбора. Он достигает printStarter2 и пытается это доказать, поэтому печатает зелёный цвет и терпит неудачу (fail / 0, в конце предложения). Он возвращается к точкам выбора и объединяет Spm с 'next' 10 (из tomatoSalad). Механизм логического вывода снова отправляется на printStarter, печатает и снова выходит из строя. Так как точек выбора больше нет, а последняя точка выбора не пройдена, предикат недоказуем, поэтому механизм вывода останавливается и выдает сообщение «fail».

Если вы хотите это исправить, распечатайте все минимальные приемы пищи, разбейте предикат findMeal на три части:

findMeal :- findall(Sp,starter(_,Sp),SList),findmin(SList,Spm),printStarter2(Spm).
findMeal :- findall(Mp,main(_,Mp),MList),findmin(MList,Mpm),printMain2(Mpm).
findMeal :- findall(Dp,dessert(_,Dp),DList),findmin(DList,Dpm),printDessert2(Dpm).

Это заставит механизм вывода создавать точки выбора в самом начале предиката проверки. Первый предикат потерпит неудачу после того же сценария, что и выше, но у механизма вывода будет больше точек выбора - следующее предложение findMeal и т. Д.

Кроме того, вы можете добавить еще одно предложение findMeal, пустое:

findMeal.

Таким образом, предикат подтвердится после трех предыдущих предложений.

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