2017-01-30 52 views
3

我正在使用clpfd libraryprolog解決sudoku。我有跟蹤標記的行和列,並得到下面的表格數量回溯每平方:如何在序言中追蹤clpfd的回溯?

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

我的問題是我怎麼能得到從算法上面的信息?

另一個問題:算法本身是否遵守規則arc-consistency

+1

爲什麼你需要痕跡,第一名?而且,clpfd可以觀察到弧一致性。 – false

+0

我只需要知道哪個變量在算法的每個步驟中都取哪個值。追蹤是我想到的第一個想法。 –

+0

您可以通過簡單地使用部分實例化的參數發出查詢來觀察很多內容,而無需跟蹤[tag:prolog-toplevel]。 – false

回答

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在工作會啓發你。

編輯:作爲墊指出的意見,增加了失敗秒子句print_new_binding/2讓您的結合破滅前重溫一個變量:

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

而不是「當(地面(瓦爾),目標)',考慮使用'freeze(Var,Goal)'。要顯示變量何時再次變爲* unbound *,您只需要第二個「目標」子句,該子句打印「變量未綁定」,然後失敗*。在回溯時,每當綁定被撤消時,您都會看到這發出! – mat

+0

真棒小費,謝謝!我添加了一個編輯。關於'freeze/2'與'when/2'的關係,我發現後者更清晰。 'freeze(Var,Goal)'和'when(nonvar(Var),Goal)'之間是否有任何相關的區別? –

+1

正如我所看到的,'when/2'的問題在於,它容易讓用戶相信像'when(Cond,...)'這樣的一般條件是可以接受的,但實際上,可接受的條件是非常有限。在足夠先進的Prolog系統中,這樣的錯誤很容易被檢測到並導致*域錯誤*,但之前,這樣的錯誤可能導致通過跟蹤涉水幾天甚至幾天,不知道爲什麼當「明顯」持有時條件失敗。順便說一下,這發生在一位朋友身上;-)'freeze/2'不太一般,但在這個用例中就足夠了,我寧願更簡單的構造。 – mat