2015-12-15 52 views
1

我正在爲我的序言課程的任務,但我卡在如何處理一些線索的邏輯難題,非常感謝一些提示/技巧/援助:Prolog的名單拼圖

比利,費爾南多,史蒂文和扎卡里都有醫生的約會。不幸的是,醫生的計算機系統崩潰了,他不記得誰的背痛,胃灼熱,臀部疼痛或帶狀皰疹,以及約會是在上午9點,上午10點,上午11點還是在12點。幸運的是,以下線索在哪裏找到:

  • 患有燒心和比利的人,其中一人有約1100人,另一人約會0900人。
  • 燒心患者在髖關節疼痛患者後2小時有約會。
  • 帶狀皰疹病人是比利還是費爾南多
  • 扎克里有一個約會後的背痛患者。

到目前爲止,我有這個,但看到在一個無限循環的扎卡里謂詞結果如何我相當肯定我有一種錯誤的做法吧。

sublist([], _). 
sublist([X|XS], [X|XSS]) :- sublist(XS, XSS). 
sublist([X|XS], [_|XSS]) :- sublist([X|XS], XSS). 

ziekte(X,Y,Z):- 
    Appointments = [0900,1000,1100,1200], 
    member(ziekte(Billy,_),Appointments), 
    member(ziekte(Fernando,_),Appointments), 
    member(ziekte(Steven,_),Appointments), 
    member(ziekte(Zachary,_),Appointments), 
    sublist([ziekte(Billy,_),ziekte(_,heartburn)],[0900,1100]), 
    sublist([ziekte(Billy,shingles),ziekte(Fernando,shingles)],Appointments). 

ziekte(_,back-pain,Y) :- 
    ziekte(Zachary,_,X), 
    X > Y. 

ziekte(_,hip-pain,0900) :- 
    ziekte(_,heartburn,1100). 

ziekte(_,hip-pain,1000) :- 
    ziekte(_,heartburn,1200). 

我發現自己很難得到我的頭,所以感謝您的任何麻煩。

回答

1

這裏有幾個問題。首先,Prolog原子總是小寫或引號; BillyFernando等是變量,這可能不是你想要的,所以你需要解決這個問題。

其次,有一些混亂的代碼在這裏:「我有一個數字,[900,1000,1100,1200]的列表,ziekte(V1,_)是它」

Appointments = [0900,1000,1100,1200], 
member(ziekte(Billy,_),Appointments), 

你是說這裏有什麼,這顯然是錯誤的 - 這個列表中沒有ziekte/2結構。

我懷疑你可能患有開始Prolog程序員最常見的疾病:相信Prolog關係「返回」的價值。你認爲ziekte(Billy,_)會以某種方式導致ziekte/3在下面被調用,並且不知何故關係的第三個參數會出現在這個位置?它不會 - 結構ziekte(_,_)和下面定義的謂詞ziekte/3之間沒有關係,並且Prolog不會評估像這樣的嵌套表達式。

member(X, List)是做什麼用的?它嘗試統一X與每個值List。假設你有一個看起來像L = [appointment(zachary,back-pain,1100), appointment(steven,X,Y), appointment(Z,heartburn,900), ...]的列表。 member(appointment(billy,Ailment,900), L)做什麼?它試圖統一:

appointment(billy,Ailment,900) = appointment(zachary,back-pain,1100) 
    fails 
appointment(billy,Ailment,900) = appointment(steven,X,Y) 
    fails 
appointment(billy,Ailment,900) = appointment(Z,heartburn,900) 
    succeeds with 
    Ailment = heartburn 
    Z = billy 

如果你覺得這個令人驚訝,你需要更加努力地思考統一!

你有無限遞歸的原因是因爲你的謂詞ziekte/3自己調用。看看跟蹤:

trace, ziekte(X,Y,Z). 
    Call: (8) ziekte(_G4078, _G4079, _G4080) ? 
    Call: (9) _G4239=[900, 1000, 1100, 1200] ? 
    Exit: (9) [900, 1000, 1100, 1200]=[900, 1000, 1100, 1200] ? 
    Call: (9) lists:member(ziekte(_G4232, _G4233), [900, 1000, 1100, 1200]) ? 
    Fail: (9) lists:member(ziekte(_G4232, _G4233), [900, 1000, 1100, 1200]) ? 
    Redo: (8) ziekte(_G4078, _G4079, _G4080) ? 
    Call: (9) ziekte(_G4230, _G4231, _G4232) ? 
    Call: (10) _G4242=[900, 1000, 1100, 1200] ? 
    Exit: (10) [900, 1000, 1100, 1200]=[900, 1000, 1100, 1200] ? 
    Call: (10) lists:member(ziekte(_G4235, _G4236), [900, 1000, 1100, 1200]) ? 
    Fail: (10) lists:member(ziekte(_G4235, _G4236), [900, 1000, 1100, 1200]) ? 
    Redo: (9) ziekte(_G4230, _G4231, _G4232) ? 
    Call: (10) ziekte(_G4233, _G4234, _G4235) ? 
    Call: (11) _G4245=[900, 1000, 1100, 1200] ? 
    Exit: (11) [900, 1000, 1100, 1200]=[900, 1000, 1100, 1200] ? 
    Call: (11) lists:member(ziekte(_G4238, _G4239), [900, 1000, 1100, 1200]) ? 
    Fail: (11) lists:member(ziekte(_G4238, _G4239), [900, 1000, 1100, 1200]) ? 
    Redo: (10) ziekte(_G4233, _G4234, _G4235) ? 

這裏發生的事情是這樣的:你想進入ziekte(X,Y,Z)。 Prolog發現第一個子句,即頭部爲ziekte(X,Y,Z)的子句。它立即形成預約時間列表。然後檢查它是否存在ziekte/2結構。這失敗了。 Prolog回溯並嘗試下一個子句:頭部爲ziekte(_,back-pain,Y)的那個。本節正文中的第一個表達式是ziekte(Zachary,_,X)。我們再次發現:Prolog找到了ziekte的第一個子句,我們馬上回到了開始的地方。

現在你還有其他問題。注意你會得到很多單體變量警告。開始將這些視爲致命錯誤。

你對我的規則條款看起來很奇怪。我不知道他們怎麼可能工作,坦率地說。

我覺得你很迷茫!我強烈建議您查看Prolog的基礎知識。除非你使用Prolog,否則你不能僞造它,它確實與其他所有東西完全不同!

如果我是你,我會先用patient/1,time/1ailment/1這些事實來映射出域名。我在我的解決方案中大量使用了select/3,所以我會對其進行審查。還有plus/3。確保你對結構之間的差異(和相似之處)有一個具體的理解 - 當評估發生時和不發生時。然後回來再試一次!

編輯:對pastebin代碼的評論。

你的粘貼代碼的主要問題是你試圖用sublist/2產生排列,但它做的是給你有序的子集。你第一次通過你已經產生了一個解決方案集,失敗了,然後你花了你的餘下的時間在sublist/2

檢查了這一點:

?- ziekte(Y), sublist([Y1,Y2,Y3,Y4], Y). 
Y = [backpain, heartburn, hippain, shingles], 
Y1 = backpain, 
Y2 = heartburn, 
Y3 = hippain, 
Y4 = shingles ; 
false. 

這隻有一個解決辦法,所以你只有真正嘗試一次置換。當你用member([billy,_,Tijd1], Opl)打線時,你已經設置了Opl = [[billy, backpain, 900], [fernando, heartburn, 1000], [steven, hippain, 1100], [zachary, shingles, 1200]]。如果您使用某種方法來排列列表以生成不同的分配,但這樣做會很好,但前面的sublist/2調用沒有更多的解決方案,因此不會有任何其他分配給X1..X4,Y1..Y4,Z1 .. Z4,所以你失敗了,因爲你生成的唯一解決方案不成功。

+0

非常感謝,我從一個解決方案的一般結構到一個不同的問題(類似的結構問題,但關於與寵物的房子)..我會採取你的建議的心臟,並從我這一次從頭開始,謝謝再次。 – Neverendingsearch

+0

嘿丹尼爾里昂,在另一個試圖把握prolog我試圖重做作業(http://pasted.co/4d6de449)..而雖然(我認爲)我越來越接近解決方案(很大程度上感謝你,再次感謝)我現在有一個問題,太多Billies來了(我認爲這與第一個和第三個技巧是關於比利有關)。如果你能找到時間再次照亮你的光芒,我將永遠如此肆意。 – Neverendingsearch

+0

我已經編輯了我的答案,並對您的新代碼進行了一些討論。 –