如何在prolog中追踪clpfd的回溯?

时间:2017-01-30 11:43:24

标签: prolog sudoku clpfd

我使用sudokuprolog进行clpfd library解算。我必须跟踪回溯和每个标有行和列的方块以及它以下列形式得到的数字:

(1 ,1 ,1)              
(9 ,2 ,1)              
BT
(5 ,2 ,1)              

我的问题是如何从算法中获取上述信息?

另一个问题:算法本身是否遵守arc-consistency规则?

1 个答案:

答案 0 :(得分:2)

我认为这不是一个特别好的主意,但是这里有一些东西使用SWI-Prolog的属性变量,只要其中一个变量被绑定就打印出一组变量的绑定:

:- use_module(library(clpfd)).

% Vars is a list of Name-Variable pairs where Variable is a free variable
% and Name is an atom or some other identifier for the variable.
trace_vars(Vars) :-
    maplist(trace_var(Vars), Vars).

trace_var(Vars, Id-V) :-
    when(ground(V), print_new_binding(Vars, Id-V)).

print_new_binding(Vars, Id-V) :-
    format('new binding ~w, all bindings now: ~w~n', [Id-V, Vars]).

在某种意义上,您可以使用它来“追踪”事物:

?- Vars = [a-A,b-B,c-C], trace_vars(Vars), [A,B,C] ins 0..1, A #< B, B #< C.
new binding a-0, all bindings now: [a-0,b-_G211,c-_G217]
new binding b-1, all bindings now: [a-0,b-1,c-_G217]
false.

这仅打印新绑定,包括之前绑定的变量,但打印变量在回溯时未绑定的时刻。这些信息是隐含的(并且需要丑陋的黑客才能变得明确):

?- Vars = [a-A,b-B,c-C], trace_vars(Vars), [A,B,C] ins 0..1, labeling([], [A,B,C]).
new binding a-0, all bindings now: [a-0,b-_G208,c-_G214]
new binding b-0, all bindings now: [a-0,b-0,c-_G214]
new binding c-0, all bindings now: [a-0,b-0,c-0]
Vars = [a-0, b-0, c-0],
A = B, B = C, C = 0 ;
new binding c-1, all bindings now: [a-0,b-0,c-1]
Vars = [a-0, b-0, c-1],
A = B, B = 0,
C = 1 ;
new binding b-1, all bindings now: [a-0,b-1,c-_G214]
new binding c-0, all bindings now: [a-0,b-1,c-0]
Vars = [a-0, b-1, c-0],
A = C, C = 0,
B = 1 ;
new binding c-1, all bindings now: [a-0,b-1,c-1]
Vars = [a-0, b-1, c-1],
A = 0,
B = C, C = 1 ;
new binding a-1, all bindings now: [a-1,b-_G208,c-_G214]
...

对于您的使用案例,请使用坐标作为Vars列表中的标识符,例如[(1,1)-Var11, (1,2)-Var12, ...]

我认为以这种方式观看clpfd并不会启发你。

编辑:正如mat在评论中指出的那样,向print_new_binding/2添加失败的第二个子句允许您在撤消绑定之前重新访问变量:

print_new_binding(_Vars, Id-_V) :-
    format('undo binding for ~w~n', [Id]),
    false.