How to trace backtracks of clpfd in prolog?

自闭症网瘾萝莉.ら 提交于 2020-01-04 02:22:08

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!