如何显示解决方案?

时间:2013-10-10 13:04:27

标签: prolog dcg

我正在尝试创建一个显示问题解决方案的程序,我需要一种方法来显示它创建的解决方案。我有两个操作可用于解决问题,并且它们的调用顺序很重要。

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"。

2 个答案:

答案 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), _)).