3 回答

TA貢獻(xiàn)1775條經(jīng)驗(yàn) 獲得超8個(gè)贊
length/2適當(dāng)?shù)牧斜黹L度約束可能比不確定性稍強(qiáng)的有用。你可以找到一個(gè)日食實(shí)現(xiàn)它在這里,所謂的len/2。這樣,您將獲得以下行為:
?- N :: 1..3, len(Xs, N).
N = N{1 .. 3}
Xs = [_431|_482] % note it must contain at least one element!
There is 1 delayed goal.
Yes (0.00s cpu)
然后,您可以通過枚舉來枚舉有效列表N:
?- N :: 1..3, len(Xs, N), indomain(N).
N = 1
Xs = [_478]
Yes (0.00s cpu, solution 1, maybe more)
N = 2
Xs = [_478, _557]
Yes (0.02s cpu, solution 2, maybe more)
N = 3
Xs = [_478, _557, _561]
Yes (0.02s cpu, solution 3)
或通過生成具有良好舊標(biāo)準(zhǔn)的列表length/2:
?- N :: 1..3, len(Xs, N), length(Xs, _).
N = 1
Xs = [_488]
Yes (0.00s cpu, solution 1, maybe more)
N = 2
Xs = [_488, _555]
Yes (0.02s cpu, solution 2, maybe more)
N = 3
Xs = [_488, _555, _636]
Yes (0.02s cpu, solution 3)

TA貢獻(xiàn)1809條經(jīng)驗(yàn) 獲得超8個(gè)贊
以下基于clpfd和meta-predicate的巴洛克式變通辦法如何? tcount/3
:-use_module([ library(clpfd),library(lambda) ])。
list_FDlen(Xs,N):-
tcount(\ _ ^ =(true),Xs,N)。
讓我們查詢!
1..3中的?-N,list_FDlen(Xs,N)。
N = 1,Xs = [_A]
; N = 2,Xs = [_A,_B]
; N = 3,Xs = [_A,_B,_C]
; 假。%普遍終止
?.2中的?-N,list_FDlen(Xs,N)。
N = 0,Xs = []
; N = 1,Xs = [_A]
; N = 2,Xs = [_A,_B]
; 假。%也普遍終止
那這個(gè)特定的查詢呢?
?-2..sup中的N,list_FDlen(Xs,N)。
N = 2,Xs = [_A,_B]
; N = 3,Xs = [_A,_B,_C]
; N = 4,Xs = [_A,_B,_C,_D]
...%未終止(按預(yù)期)

TA貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超4個(gè)贊
讓我們從最明顯的一個(gè)開始。如果您切換目標(biāo),那么您將:
?- length(L, N), N in 1..3.
具有與以下相同的終止屬性:
? -長度(L,N),假,N的1..3。
因此很明顯,這一定不能以Prolog的執(zhí)行機(jī)制終止。
但是,如果放在N in 1..3前面,則可能會影響終止。為此,必須使用有限的手段來證明N從4開始不存在這種情況。您如何在沒有約束的系統(tǒng)中(即僅存在語法統(tǒng)一性)證明這一點(diǎn)?好吧,你不能。而length/2被普遍定義只是沒有約束的存在。隨著library(clpfd)事情是微不足道的,對于N #>= 4, N in 1..3簡單的故障1。還請注意,library(clpfd)與其合作不多l(xiāng)ibrary(clpq),可能也很有趣。
結(jié)果,您將需要定義自己的長度-對于您感興趣的每個(gè)約束包。這有點(diǎn)可惜,但是目前尚無通用的方法可以看到。(((也就是說,如果您有興趣并對此進(jìn)行了思考,您可能會想出一個(gè)不錯(cuò)的API,每個(gè)約束系統(tǒng)都應(yīng)遵循該API。A,我懷疑這將花費(fèi)數(shù)十年的時(shí)間。目前,還有很多差異很大))
所以這是第一種天真的方法fd_length/2:
fd_length([], N) :-
N #= 0.
fd_length([_|L], N0) :-
N0 #>= 1,
N1 #= N0-1,
fd_length(L, N1).
好的,可以對此進(jìn)行優(yōu)化以避免不必要的選擇點(diǎn)。但是還有一個(gè)更根本的問題:如果要確定length列表的長度N,這將創(chuàng)建N約束變量!但是我們只需要一個(gè)。
fd_length(L, N) :-
N #>= 0,
fd_length(L, N, 0).
fd_length([], N, N0) :-
N #= N0.
fd_length([_|L], N, N0) :-
N1 is N0+1,
N #>= N1,
fd_length(L, N, N1).
同樣,由于許多原因,這也不是完美的:它可以像當(dāng)前系統(tǒng)一樣使用Brent算法;并結(jié)合所有fd屬性。同樣,算術(shù)表達(dá)式可能也不是一個(gè)好主意。但我必須(#)/1在SWI中等待...
1:嚴(yán)格來說,這僅對SICStus,SWI和YAP而言“根本失敗”。對于在那些系統(tǒng)中,不會由于當(dāng)前表示的耗盡而導(dǎo)致意外故障。也就是說,他們的失敗總是可以被視為誠實(shí)。
- 3 回答
- 0 關(guān)注
- 650 瀏覽
添加回答
舉報(bào)