关于约束的序言推理



我正在尝试使用 Prolog 来推理约束,然后查询知识库将这些约束传递给求解器(不能使用 clpfd(。

%a first example would be constrainsquare(Row,Col,Val)
constrainsquare(1,1,3).
constrainsquare(1,2,2).

然后我可以使用类似bagof/3的东西查询所有约束。这不是统计工厂,因为我也希望能够写

constrainsquare(3,4,8):-constrainsquare(3,3,7).

能够说如果解在位置3,3有一个7;它必然在位置3,4有一个8。 现在,您无法再使用类似bagof/3的内容收集所有约束。

你会如何在序言中从意识形态上做到这一点?

请注意,我不能简单地做

constrainsquare(L) :-
member(cs(1,1,3),L),
member(cs(1,2,2),L),
member(cs(3,4,8),L),
member(cs(3,3,7),L).

因为我会定期收到有关解决方案的新事实,并且无法更改现有事实。

目前,我正在考虑使用约束列表并执行类似操作

info(cell(1,1,3)).
info(cell(1,2,2)).
constrainsquare(I,[I]).
partialinfo(cell(3,4,8),cell(3,3,7)).
....

然后通过运行 bagoff 来查询它以获取[cell(1,1,3)],[cell(1,2,2)]...然后折叠/附加到[cell(1,1,3),cell(1,2,2)]但这感觉有点"meh"。我想知道"正确"的方式。

假设你有查询,我们称之为Q,你希望运行一组假设的事实。我们将这组事实称为Facts.您可以编写一个谓词,该谓词将动态地对这些事实运行查询,如下所示:

what_if_query(Q, Facts) :-
maplist(assertz, Facts),
call(Q),
maplist(retract, Facts).

如果Q接受一个参数作为结果,R,那么我们可以这样写:

what_if_query(Q, Facts, R) :-
maplist(assertz, Facts),
call(Q, R),
maplist(retract, Facts).

然后,如果你有一个事实场景列表,你可以写:

what_if_scenarios(Scenarios, Q, Results) :-
maplist(what_if_query(Q), Scenarios, Results).

"事实"可以是任何可断言的Prolog术语,因此也可以是规则:(Head :- P1, P2, ..., Pn)。例如,您的"事实"列表可以是:

[cs(1,1,3), cs(1,2,2), (cs(3,4,8) :- cs(3,3,7))]

最新更新