[英]SWI-prolog : how to make a circular list by using some facts
loop1(a).
loop1(b).
loop1(c).
loop1(d).
circular(d, a).
circular(b, c).
circular(b, d).
circular(a, b).
所以當我打電話:
in_cycle(a, Cycle).
它會返回:
[a,b,d,a]
如果我打電話給:
in_cycle(b, Cycle).
它會返回:
[b,d,a,b].
但是,如果您致電:
in_cycle(c, Cycle).
它會返回:
false. (because no loop is included).
這是我的嘗試:
in_cycle(C,Cycle) :- circular(C,Cycle1),in_cycle(Cycle1,Cycle).
我知道此謂詞有一個非常嚴重的問題:它不會停止...我真的想知道我應該添加哪種基本情況,以便該謂詞停止? 我應該添加一個條件,以便當序言找到相同的字母時,序言將停止嗎?
如果有人可以幫助我,將不勝感激!
- - - -更新 - - - -
check([Y,_|Z]) :- check([Y|Z]).
in_cycle(C, [C]).
in_cycle(C, [C, C1|Cycle]) :- circular(C, C1),check([C,C1|Cycle]),
in_cycle(C1, [C1|Cycle]).
circular(a, a).
被循環[a]
? 知道最短的周期是什么,可以幫助您找到謂詞的完成條件(其中之一)。 in_cycle/2
永遠不會提及任何列表。 您需要使用[Head | Tail]
[Head | Tail]
構造在其中某處,以便能夠將元素添加到列表中。 in_cycle(Current_symbol, Cycle, Start_symbol)
。 然后,您可以從in_cycle/2
調用它。 讓我們看看您的嘗試:
in_cycle(C, Cycle) :-
circular(C, Cycle1),
in_cycle(Cycle1, Cycle).
您可以在提示符處使用trace
命令查看正在發生的情況: trace, in_cycle(a, X).
按空格鍵單步執行程序。 按h尋求幫助,按a退出。 使用notrace.
再次退出跟蹤模式。
在逐步執行此過程時,您會發現謂詞很好地循環了整個循環,但是X
永遠不會成為列表。 那很糟。
讓我們嘗試建立一個清單。 正如我在第(3)點中提到的那樣,您已經對列表有所了解。 列表的第一個元素與in_cycle
的第一個參數in_cycle
。 更重要的是,列表的第二個元素與您在circular/2
可以找到的元素相同。 因此,我們知道一個循環至少包含兩個元素。 這個怎么樣?
in_cycle(First, [First, Next|Cycle]) :-
circular(First, Next),
in_cycle(Next, [Next|Cycle]).
如果您現在跟蹤它,您會發現X
發生了一些事情,但實際上仍然沒有任何有用的東西。 Cycle
仍然是一個謎,我們只是在不斷地了解事實。 您在這里需要一些結束條件。 讓我們嘗試一個簡單的方法:
in_cycle(First, [First]).
in_cycle(First, [First, Next|Cycle]) :-
circular(First, Next),
in_cycle(Next, [Next|Cycle]).
哇! in_cycle(a, X)
突然給出結果! 似乎所有使用以a
開頭的circular
連接的列表。 那不是我們想要的,但是也許我們正在接近?
一個問題是in_cycle(Next, [Next|Cycle])
實際上不正確!
如果執行in_cycle(a, X)
,您已經知道X
應該成為[a, b, d, a]
,因此將這些值填充到in_cycle(First, [First, Next|Cycle])
,您將獲得:
First = a
Next = b
Cycle = [d, a]
當您進入in_cycle(Next, [Next|Cycle])
,這意味着它是in_cycle(b, [b, d, a])
。 但是[b, d, a]
不是一個循環! 您需要能夠以某種方式區分這兩種情況。 一種方法是調用一個單獨的謂詞,如我在(4)中提到的那樣,以跟蹤您的起始元素是什么。
如果您可以找到返回該節點的路徑,則該節點處於循環中。 使用path/4
:
in_cycle(C, [C|Cs]) :-
circular(C, A),
path(circular, Cs, A,C).
現在,該謂詞是否終止? 我們如何系統地測試呢? 我們如何確保我們不會忘記任何特殊情況? 對於像這樣的純單調程序,終止測試是微不足道的1 :只需接受最通用的查詢 ! 那是:
?- in_cycle(C, Cs).
C = d,
Cs = "dabd" % [d,a,b,d]
; C = b,
Cs = "bdab"
; C = a, Cs = "abda"
; false. % it terminates!
(請參閱此答案,如何獲得"bdab"
代替[b,d,a,b]
)。
Prolog的優點是上述查詢構成了終止證明 。 您可以構成的每個查詢都包含在上述查詢中。 並且由於更一般的查詢已經終止,因此任何更具體的查詢也將終止! 任何!
所有這一切,甚至對於circular/2
任何可變自由事實都成立。 但是,這種證明不能像針對特定事實的證明那樣容易地進行。
1請注意, 瑣碎的意思是屬於瑣事 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.