2

在StackExchange 上的这个问题中,我问过(并且已经解决)我一直在尝试创建的 Prolog 程序。但是,虽然它原则上有效,但它并不能满足我现实世界的需要。

在我开始学习另一种语言(Datalog)之前,我想尝试一下我已经完成的工作,并知道如何在 Prolog 中实现一种方法来记忆早期查询的结果,这样同一个查询只执行一次。因此,我正在寻找一种将成功查询的结果添加到 List 的方法,如果再次询问相同的查询,它不会重做计算,而是使用记住的结果。

我的主要问题是我找不到将成功查询的结果保存在“向上传递”的列表中的方法。

% get this out of the way, quickly
isARelation( Source, Relation, Target, _) :-
    isADirectRelation( Source, Relation, Target).

% Structural Chains
isARelation( Source, Relation, Target, Visited) :-
    \+ member( [Source,Relation,Target], Visited),
    structuralOrDependencyRelation( RelationOne),
    structuralOrDependencyRelation( RelationTwo),
    weakest( Relation, RelationOne, RelationTwo),
    isADirectRelation( Source, RelationOne, Intermediate),
    isARelation( Intermediate, RelationTwo, Target, [[Source,RelationOne,Intermediate]|Visited]).
isARelation( Source, Relation, Target, Visited) :-
    \+ member( [Source,Relation,Target], Visited),
    structuralOrDependencyRelation( RelationOne),
    structuralOrDependencyRelation( RelationTwo),
    weakest( Relation, RelationOne, RelationTwo),
    isADirectRelation( Source, RelationTwo, Intermediate),
    isARelation( Intermediate, RelationOne, Target, [[Source,RelationTwo,Intermediate]|Visited]).

我如何实现第一次通话

isARelation(A, B, C, []).

计算结果,并进行第二次调用

isARelation(A, B, C, []).

使用较早发现的结果,该结果保持“全局”?

4

2 回答 2

4

这不是您问题的真正答案:(

另一个答案有正确的想法,但实现有问题。假设我们想要制作一个数字平方的记忆版本:

:- dynamic mem_square/2.

square(N, S) :-
    (   mem_square(N, S)
    ;   S is N*N,
        assertz(mem_square(N, S))
    ).

顺便说一句,另一个答案中的括号是完全没有必要的。这些也是不必要的,但这是您通常包装析取的方式,以防它是合取的一部分。换句话说, this:a ; (b, c)与 相同a ; b, c,但(a ; b), c又不相同。

现在,如果我从顶层加载这个程序并查询:

?- square(3, S).
S = 9. % first time it's fine

?- square(3, S).
S = 9 ;
S = 9. % now there's two

?- square(3, S).
S = 9 ;
S = 9 ;
S = 9. % now three

如果你继续查询一个记忆的事实,并回溯到它,你将继续一次又一次地计算并添加越来越多的相同副本。相反,你可以试试这个:

:- dynamic mem_square/2.

square(N, S) :-
    (   mem_square(N, S)
    ->  true
    ;   S is N*N,
        assertz(mem_square(N, S))
    ).

现在,没有选择的余地。

如果您打算选择多种解决方案,这仍然不是一个干净的实现。第一个之后的任何解决方案都将被->.

于 2017-01-20T18:46:55.373 回答
0

这是关于如何一般地执行制表功能的建议。我自己已经很久没有遵循这个建议了,所以这里可能存在不准确之处。如果我不在基地,希望其他人会出现并纠正我。

  1. 你有一个foo/4低效的谓词。
  2. 将此添加到您的文件中:

    :- dynamic(cached_foo/4).
    
  3. 重命名为什么foo/4compute_foo/4
  4. 创建一个如下所示的新谓词foo/4

    foo(X, Y, Z, Q) :-
      cached_foo(X, Y, Z, Q) ; 
      (
        compute_foo(X, Y, Z, Q), 
        assertz(cached_foo(X, Y, Z, Q))
      ).
    
于 2017-01-19T20:10:18.217 回答