问题
I am making a sudoku
solver with prolog
using clpfd library
. I have to trace the backtracks and every squares labeled with row and column and the number it gets in the following form:
(1 ,1 ,1)
(9 ,2 ,1)
BT
(5 ,2 ,1)
My question is how can I get the above information from the algorithm?
Another question: Does the algorithm observe arc-consistency
rules by itself?
回答1:
I don't think this is a particularly good idea, but here is something using SWI-Prolog's attributed variables that prints the bindings of a set of variables whenever one of them becomes bound:
:- 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]).
You can use this to "trace" things, in a sense:
?- 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.
This only prints new bindings, including for variables that were bound before, but it does not print the moment when variables become unbound on backtracking. That information is implicit (and would need ugly hacks to become explicit):
?- 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]
...
For your use case, use coordinates as identifiers in the Vars
list, e.g., [(1,1)-Var11, (1,2)-Var12, ...]
.
I don't think watching clpfd at work in this way will enlighten you, though.
Edit: As mat points out in the comments, adding a failing second clause to print_new_binding/2
allows you to revisit a variable before its binding is undone:
print_new_binding(_Vars, Id-_V) :-
format('undo binding for ~w~n', [Id]),
false.
来源:https://stackoverflow.com/questions/41935073/how-to-trace-backtracks-of-clpfd-in-prolog