2017-01-30 5 views
3

sudokuprologを使用してclpfd libraryを使用してソルバーを作成しています。私はバックトラックと、行と列と、それは次の形式で取得する数で標識したすべての正方形をトレースする必要があります。プロローグでclpfdのバックトラックを追跡する方法は?

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

私の質問は、私はアルゴリズムから上記の情報を得ることができる方法ですか?

別の質問:アルゴリズムはarc-consistencyのルールを単独で観察していますか?

+1

あなたがトレースを必要な理由最初の場所?そして、弧整合性はclpfdによって観察されます。 – false

+0

私が必要とするのは、どの変数がアルゴリズムのすべてのステップでどの値を取るかを知ることです。トレースは私の頭に来た最初のアイデアだった。 –

+0

部分的にインスタンス化された引数を持つクエリを発行するだけで、[タグ:プロローグ - トップレベル]で多くのことを追跡できます。 – 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

'when(ground(Var) 'Freeze(Var、Goal)'の使用を検討してください。変数が* unbound *になったときを表示するには、 "Goal"に2番目の節が必要です。これは "Variable is unbound"を出力してから*失敗します。バックトラック時に、バインディングが取り消されるたびに、これが表示されます。 – mat

+0

素晴らしいチップ、ありがとう!私は編集を加えました。 'freeze/2'と' when/2'との関係では、私は後者を読みやすくすることが分かりました。 'Freeze(Var、Goal)'と 'いつ(nonvar(var)、Goal) 'に関連する違いがありますか? –

+1

私がそれを見ているように、 'when/2'の問題は、' when(Cond、...) 'のような一般的な条件が容認されやすいことをユーザーに容易に導くことができるということです。限られた十分に進歩したPrologシステムでは、このような間違いは容易に検出され、ドメインエラー*につながりますが、以前はこのような間違いがトレースを通って数時間と数日かかることがありました。ちなみにこれは友人に起こった;-) 'freeze/2'はそれほど一般的ではありませんが、このユースケースでは十分であり、よりシンプルな構成を好むでしょう。 – mat

関連する問題