4

我々はそのようにしようとすると、青と白の四角でグリッドを埋める次パズルにおいて:3イン行ロジックパズル:リスト/配列における配列の制約のために最適化

  • A 3同じ色の行(または列)は許されません。
  • それぞれの行と列には、同じ数の青と白の四角形があります。

    0 _ _ _ 1 _ 
    _ 0 _ _ _ _ 
    _ _ _ _ _ 0 
    1 _ _ 0 _ _ 
    _ _ 1 1 _ _ 
    _ 0 _ _ 1 _ 
    

    そして、私たちはかなり迅速に

    0 1 0 0 1 1 
    0 0 1 1 0 1 
    1 1 0 1 0 0 
    1 1 0 0 1 0 
    0 0 1 1 0 1 
    1 0 1 0 1 0 
    

    があることを確認することができます:我々は今、1と0と白と青を表す場合

example_puzzle

は、我々が得ますこの例の解決策です。私は次のように書いた制約として

constraints(Board,N) :- 
    N2 is N // 2, 
    (for(I,1,N), param(Board,N2,N) 
    do 
     Row is Board[I,1..N], 
     Col is Board[1..N,I], 
     ic_global:sequence_total(N2,N2,1,2,3,Row), 
     ic_global:sequence_total(N2,N2,1,2,3,Col) 
    ). 

sequence_total/6は/値1が指定された行の行/ COLおよびそのすべての配列に正確N2回(Nの1.5倍)を発生することを確実にします3要素のcolは1の値の1〜2倍を含むべきです(値1の3つの正方形は互いに隣り合うことはありません)。

私は、18×18のパズルのインスタンス(*)について、以下の結果を得る:

Solved in 147 backtracks 
Yes (10.39s cpu, solution 1) 

「のみ」147のバックトラックが必要とされているので、任意の検索が行われる前に、制約が非常によく自分の仕事をしているように見えます。しかし、実際には、バックトラックの量と比較して、実行時間は私にとって本当に長いようです。私はこれが起こっているすべてのシーケンスチェックのためであると推測していますか? search/6の選択/選択方法のいずれかを変更しても、実行時間にほとんど影響がないという事実は、そのことを確認しているようです。

もしそうなら、N個の同一要素が互いに隣り合わず、実行時間が改善されるように、リスト/アレイ内の制約シーケンスに他のより効率的な方法がありますか?

EDIT

以下@jschimpfが提供する分解バージョンを使用した後、次のような結果が得られた:

Solved in 310 backtracks 
Yes (0.22s cpu, solution 1) 

新しい制約がシーケンス/ 6ほど強力ではありませんが、我々は必要なのです私たちの稼働時間は10.39秒から0.22秒に減少したので、全体的な結果は非常に望ましいものです。

サンプルデータ:この質問に使用

パズルは(バックトラックなしで解決)

問題(P(6,1)、[(1,1,0)、(1、 5,1)、(2,2,0)、(3,6,0)、(4,1,1)、(4,4,0)、(5,3,1)、(5,4、 1)、(6,2,0)、(6,5,1)])。私は私の結果を掲示しているため

パズル(*):

問題(P(18,1)、[(1,3,0)、(1,9,0)、( 1,10,0)、(1,12,0)、(1,14,0)、(1,18,1)、(2,4,0)、(2,7,1)、(2、 8,1)、(3,2,1)、(3,6,0)、(3,16,0)、(3,17,0)、(4,2,1)、(4,4、 1)、(4,10,1)、(4,13,1)、(4,18,1)、(5,8,1)、(5,10,1)、(5,15,0) 、(5,16,1)、(6,12,1)、(7,3,0)、(7,4,0)、(7,6,1)、(7,9,0)、 (7,1,0)、(7,17,0)、(8,1,1)、(8,4,0)、(8,8,1)、(8,15,1) 16,1)、(9,7,0)、(9,10,0)、(9,14,0)、(10,2,1)、(10,4,1)、(10,6,7) 1)、(10,13,1)、(11,7,0)、(11,10,1)、(12,1,1)、(12,4,1)、(12,7,1) 、(12,15,1)、(12,16,1)、(13,1,1)、(13,6,0)、(13,8,1)、(13,10,0)、 13,16,1)、(14,5,1)、(14,10,0)、(14,13,1)、(15,1,1)、(15,3,1) 12,0)、(15,13,​​1)、(15,15,0)、(16,2,1)、(16,4,0)、(16,12,0)、(16,18,0) 0)、 (17,9,0)、(17,15,0)、(17,18,0)、(18,2,1)、(18,8,1)、(18,11,1)、(18 、15,1)、(18,16,1)])。

+1

良い質問、+1!いくつかのサンプルインスタンスを用意してください。 – mat

+2

ありがとうございます。私は答えを編集しました。 – SND

+2

ありがとうございます。可能であれば、三項用語を使用して、その象徴を表現してください。現在、例えば ''、'(1、 '、' 1,0))'を使用しています。つまり、 "andsリスト"とも呼ばれるネストされた "ands"です。クリーナー表現は、例えば 'x_y_v(1、1、0)'です。 – mat

答えて

2

それは、この場合には、シーケンス制約の手作り、分解バージョンがはるかに効率的である、ということが判明しました。実施例1又は2のいずれかの3要素のサブシーケンスの和を拘束

sequence_1_2([X1,X2,X3|Xs]) :- !, 
    S #:: 1..2, 
    X1+X2+X3 #= S, 
    sequence_1_2([X2,X3|Xs]). 
sequence_1_2(_). 

ために使用し、

..., 
    sum(Row) #= N2, 
    sequence_1_2(Row), 

とsequence_total/6制約を置き換えるこれは0.2まで解決時間をもたらし秒。

関連する問題