2014-10-09 50 views
1
r1(X,Z) :- backwards(X,Z). 

r1_10(X,Z) :- 
    r1(X,Z), 

我有这段代码。这个想法是,如果r1满足10次,r1_10会被满足。我对Prolog很陌生,我不确定如何真正地正确地循环。我在考虑只是强制同一行10次,但我需要能够做到像r1_30这样的事情,所以这将是很多代码没有理由。试图制定一个目标,如果另一个目标在Prolog中运行10次,则满足

谢谢!

编辑: 这个答案有很多帮助,但只是为了澄清我的问题。基本上,我有目标r1,它调用了我的反向/ 2谓词,这简直让我反思了这个列表。我有两种向后/ 2谓词,其中一种包括累加器,另一种不是。 r1_10只是一个目标,最终会告诉我,使用累加器的那个速度更快,更好。目标r1_10仅仅是一个运行目标r1 10次的方法。我很确定我不需要不同的结果,我只需要知道r1完成10次后它会成功。希望这可以帮助!

回答

2

目前尚不清楚“满意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/2between/3是事实上的标准谓词。对于第一个参数的每个解决方案,第二个参数为true(因此实现生成和测试循环)时,forall/2谓词为true。

我们可以使用一些更多细节,包括你想要完成什么,包括你想要重复的目标的性质。

相关问题