Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Caching 如何从Prolog保存函数的第一个结果?_Caching_Prolog_Logic_Memoization - Fatal编程技术网

Caching 如何从Prolog保存函数的第一个结果?

Caching 如何从Prolog保存函数的第一个结果?,caching,prolog,logic,memoization,Caching,Prolog,Logic,Memoization,我需要编写一个自定义函数,它将被其他固定函数多次调用。在这个函数中,在第一次调用时,它将返回文件的总行数。此函数的第二次调用时间forward将返回此文件小部分中的行数。我的问题是如何保留第一个返回的结果(文件的总行数),并将其用于函数的下一次调用。我只需要在这个函数中编写或声明任何东西(不是在调用方中)。大概是这样的: myFunction(Input, MyResult, FirstResult) :- calculateInputFunction(Input, Result),

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

myFunction(Input, MyResult, FirstResult) :-
   calculateInputFunction(Input, Result),
   !,
   MyResult is Result,
   ... .
问题是,每次调用myFunction时,它都会接收不同的输入并返回不同的MyResult。但是我想保留第一个MyResult,以便在myFunction的下一次调用时使用。我该怎么做?非常感谢您提前回复

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

上面是我的函数,还有其他函数将调用我的函数,方法是将V1、V2的值传递到此函数并返回结果

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

:- 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\u调用(Goal)
。当情况发生变化时,不要忘记重置

以下是一些解释:

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

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

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

如果必须重新缓存一个目标,则会创建一个术语副本,为缓存创建一个“键”。然后,目标被执行,每个答案被存储——这是彻底地完成的。对于有多个答案的查询来说,这尤其有趣

此外,通过捕获所有错误
Pat
来保护目标。以这种方式,执行目标时发生的所有错误将导致缓存的重置。这对于非终止查询尤其重要:
cached\u调用(长度(L,N))
否则会在缓存中留下有限数量的解决方案-这会使缓存处于不一致的状态

在任何情况下,第一个子句总是失败。因此,这里只针对更新缓存的副作用

第二个子句现在使用缓存。请注意,
XGoal=Goal
“再往左”是不可能的,因为
eq/2
必须确保我们只使用相同查询的结果

正如我已经说过的:这是一种非常幼稚的方法,但至少它是简单且相对健壮的


至于你原来的计划。你现在可以写:

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

每次你需要这个值时。

实际上,我只想将第一个结果存储到这个参数中,并在下一次使用它。实际上,如果我可以声明一个全局变量,将第一个结果存储到这个变量中,并在下一次使用它,这可能是一个解决方案,但我认为使用全局变量不是一个好主意。嗨,false,非常感谢您的回答。谓词“cached_call”存储谓词“cachedgoal_sol”(本例中为myFunction)的目标(本例中的第一个结果),不是吗?首先,“cached_call”检查目标是否已经在数据库中(如果已经存在,则失败)。Skel是存储目标的临时变量。帕特是什么?在这种情况下,我知道这是个例外,但这意味着什么?。你能帮我澄清更多关于谓词的事情吗,比如eq(A,B),第二个“cached_调用”?抱歉,我是Prolog新手,所以理解您的代码有点困难。我更新了我的问题以显示我的常规代码。非常感谢你的帮助。