我们假设,我在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]
来动态创建新的子句,作为全局内存。
答案 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)
。这将消除回溯的需要,并将解释搜索空间树,然后可以在传递远程访问状态作为附加参数的情况下预先遍历遍历。