Prolog中回溯过程中的状态传播

时间:2012-05-20 22:32:25

标签: prolog logic-programming sicstus-prolog

我们假设,我在Prolog中有一个简单的程序,它正在搜索某个状态空间:

search(State, State) :-
    is_solution(State).

search(State, Solution) :-
    generate(State, NewState),
    search(NewState, Solution).

我知道:

  • generate(State, NewState)为任何给定的NewState生成至少一个State
  • 整个州的空间是有限的

我想修改search谓词,以确保它始终能够在有限的时间内进行检查。所以我写了类似的东西:

search(State, Solution) :-
    empty_memory(EmptyMem),
    add(State, EmptyMem, Memory),
    search(State, Memory, Solution).

search(State, _, State) :-
    is_solution(State).

search(State, Memory, Solution) :-
    generate(State, NewState),
    \+ exist(NewState, Memory),
    add(NewState, Memory, NewMemory),
    search(NewState, NewMemory, Solution).

这是有效的,但它在回溯期间失去了计算状态,所以现在我有一个最大空间大小的搜索树。

在回溯期间传播状态是否有任何方法而不会丢失任何计算信息?我希望有一个包含O(space_size)节点的整个搜索树。有可能吗?

修改 我似乎应该使用assert/[1,2]来动态创建新的子句,作为全局内存。

3 个答案:

答案 0 :(得分:1)

在SICStus Prolog中,您可以使用黑板在回溯中存储信息:请参阅手册中的Blackboard Primitives。使用bb_put(Key, Value)在黑板上存储内容,然后使用bb_get(Key, Value)来检索它。请注意,bloackboard是按模块定义的。

答案 1 :(得分:1)

最干净的解决方案可能是使用支持B-Prolog,Ciao,XSB或YAP等表格的Prolog编译器。在这种情况下,您只需将generate / 2谓词声明为tabled。

答案 2 :(得分:1)

为什么不使用assert生成所有可能的状态,而不是使用findall(N, generate(S,N),ALL)。这将消除回溯的需要,并将解释搜索空间树,然后可以在传递远程访问状态作为附加参数的情况下预先遍历遍历。