我正在使用clpfd library
與prolog
解決sudoku
。我有跟蹤標記的行和列,並得到下面的表格數量回溯每平方:如何在序言中追蹤clpfd的回溯?
(1 ,1 ,1)
(9 ,2 ,1)
BT
(5 ,2 ,1)
我的問題是我怎麼能得到從算法上面的信息?
另一個問題:算法本身是否遵守規則arc-consistency
?
我正在使用clpfd library
與prolog
解決sudoku
。我有跟蹤標記的行和列,並得到下面的表格數量回溯每平方:如何在序言中追蹤clpfd的回溯?
(1 ,1 ,1)
(9 ,2 ,1)
BT
(5 ,2 ,1)
我的問題是我怎麼能得到從算法上面的信息?
另一個問題:算法本身是否遵守規則arc-consistency
?
我不認爲這是一個特別好的主意,但這裏是使用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在工作會啓發你。
編輯:作爲墊指出的意見,增加了失敗秒子句print_new_binding/2
讓您的結合破滅前重溫一個變量:
print_new_binding(_Vars, Id-_V) :-
format('undo binding for ~w~n', [Id]),
false.
而不是「當(地面(瓦爾),目標)',考慮使用'freeze(Var,Goal)'。要顯示變量何時再次變爲* unbound *,您只需要第二個「目標」子句,該子句打印「變量未綁定」,然後失敗*。在回溯時,每當綁定被撤消時,您都會看到這發出! – mat
真棒小費,謝謝!我添加了一個編輯。關於'freeze/2'與'when/2'的關係,我發現後者更清晰。 'freeze(Var,Goal)'和'when(nonvar(Var),Goal)'之間是否有任何相關的區別? –
正如我所看到的,'when/2'的問題在於,它容易讓用戶相信像'when(Cond,...)'這樣的一般條件是可以接受的,但實際上,可接受的條件是非常有限。在足夠先進的Prolog系統中,這樣的錯誤很容易被檢測到並導致*域錯誤*,但之前,這樣的錯誤可能導致通過跟蹤涉水幾天甚至幾天,不知道爲什麼當「明顯」持有時條件失敗。順便說一下,這發生在一位朋友身上;-)'freeze/2'不太一般,但在這個用例中就足夠了,我寧願更簡單的構造。 – mat
爲什麼你需要痕跡,第一名?而且,clpfd可以觀察到弧一致性。 – false
我只需要知道哪個變量在算法的每個步驟中都取哪個值。追蹤是我想到的第一個想法。 –
您可以通過簡單地使用部分實例化的參數發出查詢來觀察很多內容,而無需跟蹤[tag:prolog-toplevel]。 – false