[英]SWI-Prolog: How to stop the predicate when the list is empty? (predicate included)
course(cmput325).
course(cmput175).
course(cmput201).
course(cmput204).
prerequisite(cmput204, cmput325).
prerequisite(cmput175, cmput201).
prerequisite(cmput175, cmput204).
我需要寫一個新的謂詞
can_take(+L,?C).
定義:
L是學生已經參加的課程列表。 如果還提供了C,則謂詞應檢查學生是否具有C的所有必修課程。如果C是變量,則通過回溯,謂詞應一次生成一門課程,以便學生現在就可以學習。 課程可以按任何順序進行,但是每個課程只能生成一次,並且您不應該返回學生已經參加的任何課程。
例:
?- findall(C, can_take([cmput175], C), L).
should return
L = [cmput201, cmput204].
這是我的謂詞:
can_take(L,C) :- prerequisite(L,C).
can_take([L|List],C) :- prerequisite(L,C),can_take(List,C).
該謂詞沒有返回正確的結果,而只是返回了false。 我認為這是因為我沒有確定L為空時的條件,但是,如果我嘗試在其中一個中添加L \\ == []的話。 它仍然給我錯誤...我應該怎么做才能使該謂詞停止並給我結果?
------- -------更新
pre(X,C) :- prerequisite(X,C).
pre(X,C) :- prerequisite(X,Y), pre(Y,C).
pre2(C,L) :- findall(L1,pre(L1,C),L).
required(C,L) :- pre2(C,L1),sort(L1,L).
can_take([],_).
can_take(L,C) :- required(C,L).
can_take([L|List],C) :- prerequisite(L,C),can_take(List,C).
這是我的代碼測試:
?- required(cmput325,L).
L = [cmput175, cmput204].
?- required(cmput204,L).
L = [cmput175].
?- can_take([cmput175],X).
X = cmput201 ;
X = cmput204 ;
?- findall(C, can_take([cmput175], C), L).
L = [cmput201, cmput204].
?- can_take([cmput204],cmput325).
false. (this one is OK)
?- can_take([cmput175,cmput204],cmput325).
true ;
false. (this one is OK)
?- can_take([cmput175],cmput204).
true ;
true ;
false.
最后一個還不行,因為我不希望它返回兩個真實的語句...所以我想要的就是讓它在第二行或最后一行返回true時停止它。 對於我的作業,不允許使用cut operator!,還有其他方法嗎?
(我假設即使您已經上過這門課,您也可以再次參加。這至少是我所知道的規則。)
您可以參加一門課程,前提是您已經參加了所有必修課程。
Prolog中沒有直接的“全部”。 但是你可以這樣寫
您可以參加一門課程,前提是沒有尚未參加的必修課程。
can_take(Takens, Next) :-
course(Next),
iwhen( ground(Takens),
\+ ( prerequisite(Required, Next), \+ member(Required, Takens) ) ).
這使用iwhen/2
來防止Takens
未完全實例化的情況。
請注意,您的示例略有不同:
?- findall(C, can_take([cmput175], C), L).
L = [cmput175, cmput201, cmput204].
% ^^^^^^^^
放棄
您的問題本質上是非單調的:通過增加需求的事實,您正在減少可能修讀的課程。 作為初學者,寧願堅持本質上單調的問題。 在這方面,Prolog真正出類拔萃。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.