我正在尝试创建一个显示问题解决方案的程序,我需要一种方法来显示它创建的解决方案。我有两个操作可用于解决问题,并且它们的调用顺序很重要。
test(a) :- write('use a ').
test(b) :- write('use b '), fail.
test(c) :- test(a), test(b), test(a).
test(c) :- test(a), test(a).
请注意这是一个例子,不应按字面意思理解。将测试(a)和测试(b)视为操作和测试(c),作为检查哪个订单有效的功能。
现在test(c).
将打印失败的那些。导致输出"使用b使用a"。
答案 0 :(得分:3)
请考虑使用描述目标列表的DCG,而不是使用副作用。您的示例可以轻松转换为具有少量机械重写步骤的DCG,例如:
test(a) --> ['use a'].
test(b) --> ['use b'], { false }.
test(c) --> test(a), test(b), test(a).
test(c) --> test(a), test(a).
然后你可以查询:
?- phrase(test(c), Ls).
Ls = ['use a', 'use a'].
当您有这样的列表Ls
时,您可以轻松地以任何您想要的方式编写它。请注意,虽然顶层已经以有用的方式打印每个解决方案,但您可能没有理由这样做。
答案 1 :(得分:1)
您的问题似乎是对assertz / retract的合理调用。
这些内置程序允许跟踪时间顺序,并存储任意Prolog术语,然后你可以写
:- dynamic results/2.
test(a) :- a_code(Result), assertz(results(a, Result)).
test(b) :- b_code(Result), assertz(results(b, Result)).
test(c) :- test(a), test(b), test(a).
test(c) :- test(a), test(a).
check_results :- forall(retract(Name, Result), writeln(Name = Result)).
如果要跟踪失败的执行,可以扩展该架构:
test(a) :- a_code(Result) -> assertz(results(ok(a), Result)) ; assertz(results(ko(a), _)).
test(b) :- b_code(Result) -> assertz(results(ok(b), Result)) ; assertz(results(ko(b), _)).