如何在prolog中存储函数的第一个返回值?

时间:2014-06-07 08:13:11

标签: prolog logic

我有这样的功能:

myFunction(V1, V2, Result) :-
  Result is V1/V1cover + V2/V2cover,
  write(Result).

myFunction(0,0,0).

keepValue(V1,V2,V1cover,V2cover) :-
  V1cover is V1,
  V2cover is V2.

还有其他函数多次调用myFunction并返回结果。但是,我想得到第一个结果,即第一次调用myFunction并保持它以后用于调用(在这种情况下,它是V1cover和V2cover)。例如,第一次调用myFunction(4,4,A)。然后它返回A = 2.之后我想保持V1cover(4)和V2cover(4)的值用于下一个被叫时间。我怎么能这样做?我尝试应用缓存的技术,并将其应用到myFunction:

 :- dynamic(cachedGoal_sol/2).

 reset :-
   retractall(cachedGoal_sol(_, _)).

 eq(A, B) :-
   subsumes_term(A, B),
   subsumes_term(B, A).

 cached_call(Goal) :-
   \+ (cachedGoal_sol(First,_), eq(First, Goal)),
   copy_term(Goal, First),
   catch(
   ( Goal,
     assertz(cachedGoal_sol(First, Goal)),
     fail
   ),
   Pat,
   (reset, throw(Pat))).

 cached_call(Goal) :-
   cachedGoal_sol(First, Results),
   eq(First, Goal),
   Results = Goal.

 myFunction(V1, V2, Result) :-
  **cached_call(keepValue(V1,V2,V1cover,V2cover),**
  Result is V1/V1cover + V2/V2cover,
  write(Result).

但它不起作用,当我尝试第二次运行myFunction(2,3,A)并跟踪程序时,它实际上存储了第一个调用的解决方案,但我无法获得V1cover,V2cover的第一个值,因为第二个cached_call()中的eq()失败。有没有办法只获得V1cover,V2cover的值而不接触V1,V2,因为它们是输入的?非常感谢您的回答。

2 个答案:

答案 0 :(得分:2)

您的代码有一些错误,而且有点太复杂了。我会尝试给你一个可能对其他人有用的答案。

假设我们需要一个谓词来存储有关首次满足目标的上下文的信息。

我将使用一个简单的例子。让我们说我们有一条规则可以找到1到4之间的数字对,加上6。

sum_to_six(X, Y) :- between(1, 4, X), between(1, 4, Y), X + Y =:= 6.

试图找到满足上述规则的所有对,得到以下答案:

?- findall(pair(X,Y), sum_to_six(X, Y), All).
All = [pair(2, 4), pair(3, 3), pair(4, 2)].

现在,让我们回到你的问题。让我们假设我们需要满足目标的第一对。我们应该修改谓词sum_to_six/2的规则。

sum_to_six(X, Y):-
        between(1, 4, X), between(1, 4, Y), X + Y =:= 6,
        store_first(pair(X,Y)).

子目标store_first(pair(X,Y))每次都成功,但是第一次断言pair(X,Y)(如果动态内存中没有其他pair(_,_))。所以,你需要的答案可能与此类似:

store_first(Goal):-
        Goal =.. [Name | Args],  %% Name is the name of the predicate
        length(Args, N),         %% N represents its arity
        length(NVars, N),
        Test =.. [Name | NVars], %% Test is a goal like p(_, _, _, ...)
        (
         Test, !
        ;
         assertz(Goal)
        ).

现在,要获取存储的信息:

?- retractall(pair(_,_)), findall(_, sum_to_six(_,_), _), pair(FirstX, FirstY).
FirstX = 2,
FirstY = 4.

答案 1 :(得分:1)

如果您只想要第一个答案,只需写下

即可
..., cached_call(once(Goal)), ....

使用this definition