如何从Prolog中保留函数的第一个结果?

时间:2014-06-04 14:58:34

标签: caching prolog logic memoization

我需要编写一个自定义函数,该函数将被其他固定函数多次调用。在此函数中,在第一个调用时,它将返回文件的总行数。此函数的第二个调用时间forward,将返回此文件的小部分中的行数。我的问题是如何保留第一个返回的结果(文件的总行数)并将其用于我的函数的下一个调用时间。我只需要在这个函数中编写或声明任何东西(不在调用者中)。像这样:

myFunction(Input, MyResult, FirstResult) :-
   calculateInputFunction(Input, Result),
   !,
   MyResult is Result,
   ... .

问题是,每次调用myFunction时,它都会收到不同的Input并返回不同的MyResult。但我想保留第一个MyResult用于myFunction的下一个调用时间。我怎样才能做到这一点?非常感谢你的回答。

myFunction([V1,V2], Result) :-
  reset,
  cached_all(a(V1,V2)),
  use V1, V2 to calculate Result, 
  ...
  reset,
  finishedCode. 

以上是我的功能,还有其他函数通过将V1,V2的值传递给该函数并返回Result来调用myFunction。

1 个答案:

答案 0 :(得分:2)

您需要的是某种形式的缓存机制。这必须以某种方式使用一些全球资源。动态数据库通常用于此目的 目的。这是一个非常简单的形式。在该领域中更为复杂的技术在表格的概念下是已知的。

:- dynamic(cachedgoal_sol/2).

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


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

cached_call(Goal) :-
   \+ ( cachedgoal_sol(Skel,_), eq(Skel, Goal) ),  % No fitting Goal was cached
   copy_term(Goal, Skel),
      catch(
        (  Goal,
           assertz(cachedgoal_sol(Skel,Goal)),
           fail
        ),
        Pat,
        (reset, throw(Pat))).
cached_call(Goal) :-
   cachedgoal_sol(Skel,XGoal),
    eq(Skel, Goal),
    XGoal = Goal.

用法:从reset.开始,然后将Goal换行为cached_call(Goal)。当事情发生变化时,不要忘记重置!

以下是一些解释:

reset/0只删除所有缓存的结果。

eq/2等于重命名变量,只要两个参数的变量集是不相交的。

cachedgoal_sol/2是一个动态谓词。它用于存储特定目标的解决方案(实际上:答案)。为此,它在第一个参数中保留实际目标的副本,在第二个参数中保留实际答案/解决方案。请注意,对于一个谓词,可能存在多个不同的查询。说:member(X,[a,b,c])member(X,[X1,X2,X3])。这些查询将彼此独立地处理和缓存。

如果必须重新缓存目标,则会创建该术语的副本以具有"密钥"用于缓存。然后,执行目标并存储每个答案 - 这是彻底完成的。对于有多个答案的查询,这尤其有用。

此外,目标受catch/3捕获所有错误Pat的保护。以这种方式,在执行目标时发生的所有错误都将导致reset缓存。这对于非终止查询尤为重要:cached_call(length(L,N))否则会在缓存中留下有限数量的解决方案 - 这会使缓存处于不一致状态......

在任何情况下,第一个句子总是失败。所以这只是为了更新缓存的副作用。

第二个子句现在使用缓存。请注意,XGoal = Goal"在左侧"后面是不可能的,因为eq/2必须确保我们仅使用同一查询的结果。

正如我已经说过的:这是一种非常天真的方式,但至少它很简单且相对健壮。


关于你原来的节目。你现在可以写:

..., cached_call(calculateInputFunction(Input, Result)), ...

每当你需要这个价值时。