我想做一個Prolog謂詞,讓我測試一個給定的值是一個大於0的整數,也給我一個有效的整數給定一個變量。現在看起來是這樣的:謂詞,生成整數和測試如果整數
intgr(1).
intgr(X) :- intgr(Y), X is Y+1.
這將產生所有整數,但作爲intgr使用時(8),它會發現,它是有效的,然後一直循環下去。任何想法如何解決這個問題?
我想做一個Prolog謂詞,讓我測試一個給定的值是一個大於0的整數,也給我一個有效的整數給定一個變量。現在看起來是這樣的:謂詞,生成整數和測試如果整數
intgr(1).
intgr(X) :- intgr(Y), X is Y+1.
這將產生所有整數,但作爲intgr使用時(8),它會發現,它是有效的,然後一直循環下去。任何想法如何解決這個問題?
爲了生成自然數,你可以很容易地編寫一個尾遞歸(因此更節省空間)的謂詞。例如:
next_integer(I) :-
next_integer(1, I).
next_integer(I, I).
next_integer(I, J) :-
I2 is I + 1,
next_integer(I2, J).
但要注意已經提供了幾個Prolog的編譯器,無論是作爲一個內置的謂詞或作爲庫斷言,事實上的標準between/3
謂詞,它允許你枚舉整數在給定的時間間隔。例如:
?- between(1, 3, I).
I = 1 ;
I = 2 ;
I = 3.
根據執行情況,您可能還可以使用此謂詞來測試一個整數屬於給定的時間間隔不留虛假的選擇點。例如:
?- between(1, 3, 2).
true.
回到你的問題,在回溯你的謂詞環路,說測試是沒有什麼在它的時候,你傳遞參數不會再通過繼續添加一個在每遍找到。一種解決方案是使用標準內置謂詞var/1
來測試參數,並在參數綁定時切斷第一個解決方案。例如:
next_integer(I) :-
( var(I) ->
next_integer(1, I).
; integer(I) ->
next_integer(1, I),
!
; fail % or error
)
next_integer(I, I).
next_integer(I, J) :-
I2 is I + 1,
next_integer(I2, J).
希望這會有所幫助。
這裏首先說明你的程序沒有終止的原因。看到這一點,我會添加目標false
到你的程序:
intgr(1) :- false. intgr(X) :- intgr(Y), false,X is Y+1.
什麼是現在有趣的是下面的屬性。鑑於您的程序的任何查詢,
如果此片段(failure-slice)不終止,那麼您的原始程序也不會終止。
在這個片段中可能更容易看出:這個程序如何終止是沒有辦法的。變量X
僅在頭部出現一次。在程序的可見部分沒有進一步的參考,因此沒有人關心X
的具體實例。即:無論您將什麼作爲參數intgr/1
,您的定義都將循環。什麼! intgr(-1)
環,intgr(stop)
環,intgr(X)
環,intgr(1)
環。
有關故障切片以及如何使用它們的更多信息,請參閱標籤failure-slice。
要刪除問題,必須在程序的可見部分更改。不要看透視部分 - 他們將無法改善終止。
我會使用length(_, N)
其中包括0。下面是使用library(clpfd)
另一種方式:
?- X #> 0.
如果你堅持枚舉的解決方案:
nat(0).
nat(X0) :-
X0 #> 0,
X1 #= X0-1,
nat(X1).
偉大的和CLP(FD)的教科書用例。 +1。在現代Prolog系統中,'X#> 0'是描述所有大於0的整數的好方法。 – mat
'next_integer'暗示的'integer' – false
謝謝!使用var/1正是我所需要的,使其能夠按照我的意願工作! INTEGR(1)。 intgr(X): - (var(X),intgr(Y),X是Y + 1); (不是(var(X)),整數(X))。 – Jambaman