2011-05-14 36 views
0

问题是我必须打印所有最小起始码,然后是最小主码,然后是最小甜点。 我写这如何在序言中打印多个答案

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

Prolog的测试谓词在他们的条款出现的顺序。它确实会使条件成真。当它试图证明findMeal时,它证明findall/3,它总是被证明是真实的,但是做了必要的统一,即。 SList在此之后受到约束。

然后它证明了findmin/2,它将Spm与10相结合,并留下选择点。它到达printStarter2,它试图证明它,所以它打印绿色并失败(失败/ 0,在子句末尾)。它回到选择点并且将Spm与'next'10(来自tomatoSalad)统一起来。推理引擎再次返回到printStarter,打印并再次失败。由于没有更多的选择点,并且最后的选择点失败,所以谓词不可证明,因此推理机停止并打印“失败”。

如果要解决这个问题,使打印所有的最低餐,打破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. 

所以谓语将被证明属实后,前三个条款将失败。