我需要在再次触发之前检查规则是否已经“触发”。我的意思是在断言一个新事实之前,我需要知道在之前的循环迭代中是否已经断言了相同的事实。
我尝试使用列表,但我认为它们对我的问题并不那么“友好”。我还能用什么来做到这一点?
我需要在再次触发之前检查规则是否已经“触发”。我的意思是在断言一个新事实之前,我需要知道在之前的循环迭代中是否已经断言了相同的事实。
我尝试使用列表,但我认为它们对我的问题并不那么“友好”。我还能用什么来做到这一点?
我将上面的评论改写为一个答案,以详细说明它。
您可能会考虑在生成解决方案后会失败的故障驱动循环,并迫使 Prolog 回溯并探索其他可能性:
failure_driven_loop(Info):- generate(Info,Term), fail.
failure_driven_loop(Info).
(示例来自Paul Brna 的书)。在此示例Term
中,记录一个解决方案并generate/2
为给定的Info
. 当所有解决方案都用尽时,需要第二个子句才能使循环成功。
一旦生成了一个解决方案,第一个子句失败并且执行回溯,即,Prolog 将尝试为 找到不同的证明generate(Info,Term)
,这通常会涉及不同的子句,无论是generate/2
它自己还是直接或间接调用的谓词之一generate/2
。如果您想确保一旦generate/2
使用了它的一个子句,它就不应该尝试重复使用相同的子句,您应该添加削减,即,而不是
generate(Info,Term) :- solve_somehow(Info,Term).
generate(Info,Term) :- solve_in_some_other_way(Info,Term).
你应该写
generate(Info,Term) :- solve_somehow(Info,Term), !.
generate(Info,Term) :- solve_in_some_other_way(Info,Term), !.
找到的解决方案generate/2
可以用 记录下来assert
。正如@CapelliC 所指出的,如果您的程序回溯,则断言不会撤消,因此故障驱动循环会保留您的解决方案:
:- dynamic solution/1.
failure_driven_loop(Info):- generate(Info,Term), assert(solution(Term)), fail.
failure_driven_loop(Info).