2011-05-14 38 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. 

所以謂語將被證明屬實後,前三個條款將失敗。