"만족 한 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
가 사실상의 표준 조건은 다음과 같습니다이 잠재적 인 문제를 방지하는 한 가지 방법은 다음과 컴팩트 한 정의를 사용하는 것입니다. forall/2
술어는 첫 번째 인수의 각 솔루션에 대해 두 번째 인수가 참일 때 (따라서 생성 및 테스트 루프를 구현할 때) 참입니다.
반복하고자하는 목표의 성격을 포함하여 원하는 목표에 대해 더 자세히 설명 할 수 있습니다.