目前尚不清楚「滿意10倍」是什麼意思。你的意思是r1/2
謂詞將有10個解決方案嗎?一個例子是目標member(X, [1,2,3,4,5,6,7,8,9,0])
,其在回溯時將連續實例化變量X
到每個列表元素。如果是這樣,一種解決方案可能是使用標準的findall/3
謂詞來計算目標的所有解決方案的列表,然後計算列表的長度。例如:
r1_10(X,Z) :-
findall(_, r1(X,Z), Solutions),
length(Solutions, 10).
該斷言可以通過使用附加的參數來傳遞的解決方案,以檢查的數量很容易地推廣。它也可以通過使用另一個參數來通過目標本身來推廣。另一方面,如果你想簡單地調用一個目標N次,你可以定義一個需要一個目標和一個計數器的謂詞。例如:
call_n_times(N, Goal) :-
between(1, N, _), % generate, on backtracking, all numbers in the interval [1,N]
once(Goal),
fail.
call_n_times(_, _).
但是,此定義假定目標永遠不會失敗(或引發錯誤)。從你的問題來看,如果目標不能滿足N次,應該會發生什麼。在這種情況下,呼叫者是否應該失敗?如果是這樣,你將需要一個不同的定義。例如(再次假設目標從未失敗或引發錯誤):
call_n_times(0, _) :- !. % green cut just to avoid a spurious choice-point
call_n_times(N, Goal) :-
N > 0,
once(Goal),
M is N - 1,
call_n_times(M, Goal).
但是這個定義仍然可能會有問題。例如,如果你傳遞一個非地面目標,即有變量的目標,並且調用該目標,則會以阻止其在下一步中成功的方式實例化其所有變量的一部分。爲了避免這種潛在的問題的一種方法是使用下面的緊湊型定義:
call_n_times(N, Goal) :-
forall(between(1,N,_), Goal).
forall/2
和between/3
是事實上的標準謂詞。對於第一個參數的每個解決方案,第二個參數爲true(因此實現生成和測試循環)時,forall/2
謂詞爲true。
我們可以使用一些更多細節,包括你想要完成什麼,包括你想要重複的目標的性質。