数独のアルゴリズムを考える ― 各種法の改善と高速化

26
数独のアルゴリズムを考える 各手法の改善と高速化 2015.3 Fumiya Funatsu

Transcript of 数独のアルゴリズムを考える ― 各種法の改善と高速化

Page 1: 数独のアルゴリズムを考える ― 各種法の改善と高速化

数独のアルゴリズムを考える

各手法の改善と高速化

2015.3 Fumiya Funatsu

Page 2: 数独のアルゴリズムを考える ― 各種法の改善と高速化

0. 意外と難しい数独のアルゴリズム

- 数独を解くプログラムは多数存在する- しかし全ての問題を解けるものは少ない

数独のアルゴリズムとはどんなものなのかを少しずつ考えてみたい

Page 3: 数独のアルゴリズムを考える ― 各種法の改善と高速化

0-1. 目的

- 数独のアルゴリズムを知る

- アルゴリズムの導出過程を知る

- 最終的に、妥当な計算量の完全なアルゴリズムを導く

Page 4: 数独のアルゴリズムを考える ― 各種法の改善と高速化

0-2. サンプル問題初級 上級

この両方をつかって、アルゴリズムを検討します

Page 5: 数独のアルゴリズムを考える ― 各種法の改善と高速化

0-2. 目次

- 1章では、各種アルゴリズムを検討、改善する

- 2章では、「消去法」の問題点の改善法について検討

Page 6: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1. アルゴリズムの検討

Page 7: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-1. 総当り法

- セルに当てはまる数字を全て検査する方法。

- メリット: 実装が簡単- デメリット: 計算量が膨大

9x9の場合: 9^81 = 1.98e+77 = これは 1無量大数 (1e+68) よりも大きな数字。

Page 8: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-1-1. 総当り法のイメージ

左図の様に

- 1セルに 9 通り- 1列に 9^9 通り- 9列に 9^9^9 通り

の解答パターンを全て走査することで、総当り的に答えを見つけ出す。

Page 9: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-1-2. 実装例

(1) 例えば、9x9 のセルを x+width*y 式で配列に変換する

例: [0,1,4,6, …, 0,7,5,2,0] ………………………………… (sources)

(2) 別の配列を作成し、81個の要素を1で初期化する …(ans)(3) ansにsourcesの値をセットする関数 merge()を作成

(4) ansを81桁の9進数とみなし、incl() 関数 (map++) を作る

(5) ”merge → check → incl → merge → ...” をループすると、最終的

に答えがansにセットされる。

Page 10: 数独のアルゴリズムを考える ― 各種法の改善と高速化

- 総当り法は計算量があまりに膨大だが、確実に答えが出る

- 現実的な計算でなく、結果が出るのに相当な時間がかかる

⇒ 別のアルゴリズムが必要

1-1-3. 考察

Page 11: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-2. 空欄総当り法

- 総当り法は 既知のセル まで計算して無駄なので、分からないセルのみ 総当りする方法。

- “初級”問題の場合: 9^32 = 3.44e+30- “上級”問題の場合: 9^59 = 2.00e+56

改善されたものの、依然として膨大な計算量。

しかし最適化の1ステップ

Page 12: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-2-1. 空欄総当り法のイメージ

- 総当り法では、左図のように全パターンを網羅する

- この改善では、各列の9^9通りから既に分かっている数字分のパターンを減らす

- 具体的には 9^(9-Ncol)と少なくなる(Ncolは各行の既知数の数)

Page 13: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-2-2. 実装例

(1) 方針は基本的に”総当り法”と同じ。

(2) ans配列の要素数を、81ではなく、sourcesの0の個数に設定する。

(3) merge関数を変更する必要があり、実装に工夫が必要. 単純にマージすると個数が合わない.(4) 案としては、sourcesとansの橋渡しをする連想配列(maps) を作成するとマージが楽。

(5) incl関数についてはそのままでも動作すると思われる

Page 14: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-2-3. 考察

- 総当り法のメリットを活かしつつ、計算量を減らすことが可能

- しかし、未だ計算量が膨大で、問題が難しくなるほど計算量が増えるデメリットがある。

⇒ 改善度が小さいので、別の方法を検討

Page 15: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-3. 順列法 - 「ある列は、必ず1〜Nを一つずつ含む」という性質を使い、1〜N

から既知の数字を除いた数列の全パターンを検査する方法。

- 例えば9x9で、各列に4つ既知の数字があるとすると、一列のパターン数は 9P5 = 9! / 4! = 15,120 …... (Pcol)

- 9列全ての組合せは Pcol ^ 9 = 4.13e+37- 計算量は「空欄総当り法」と同程度。

(計算量が膨大なので、他の方法を検討)

Page 16: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-4. 消去法

- 「あるセルに数字があると、その上下・同ブロックにはその数字が入らない」ことを利用した手法 (*1)

- *1の消去法を各数(N)に適用し、”あるブロックに1つだけ残った空欄”があれば、そこをNと確定する(*2)

- 最もよく利用される手法で、計算量が少ない。- *2で最終的に確定できないセルがある場合は、問題が解け

ないという難点がある。- そのためいくつか改善法がある (後述)

Page 17: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-4-1. 手順のイメージ

黄色のマスのみに”1”が入る。右ブロックは既に確定。続けて中央も確定。

Page 18: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-4-2. 消去法の問題点1

- 実際の数独の解き方と全く同じ

- もし手動で解けないと、この手法でも解けない

- 後述する手法を追加しないと、難易度の高い問題を解くことは不可能

Page 19: 数独のアルゴリズムを考える ― 各種法の改善と高速化

1-4-3. 消去法の問題点2- 消去法は、数独の一般的解法で直感的- 計算量が少なく、今までで最も妥当な手法

- しかし、最終的に ”セルに入る候補” が全て1つに絞れないと問題が解けない のが最大の難点。

⇒ この問題を解決する方法を、次章で検討する

Page 20: 数独のアルゴリズムを考える ― 各種法の改善と高速化

2. 消去法の問題を補う

Page 21: 数独のアルゴリズムを考える ― 各種法の改善と高速化

2-1. 消去法+総当り法

- 消去法で解けなかったセルに関して、総当り法を適用する。

- メリット: かならず答えが出る- デメリット: わからないセルが多いと、計算量が膨大にな

る。

- 中級程度の問題には利用価値あり、上級問題だと計算時間が相当長くなる可能性大。

Page 22: 数独のアルゴリズムを考える ― 各種法の改善と高速化

2-2. 消去法+背理法

- あるセルの数字候補を、仮に N だと仮定し、他のセルの「候補が1つのもの」だけを解いていく。

- もし途中で矛盾があれば、N が間違いだとわかる(次頁を参照)。

- これを消去法で解けなかったセルに適用する。

- 数独を手で解く際にも有効な方法。- ただ、仮定した部分に戻るための機能を実装する手間があ

り、答えが出ない可能性もまれにある。

Page 23: 数独のアルゴリズムを考える ― 各種法の改善と高速化

2-2-1. 補足: 背理法とは

《定義》ある命題pについて、仮にpを偽として (*1) 矛盾を導くことで、pが真である (*2) と証明する方法

- 数独では1つのセルの答えは複数あるので、*1は「仮にpをNとして」となり*2 は「pはNでない」に置き換えることができる。

- つまり、矛盾さえ導くことができれば、その候補を消すことができるということ。

Page 24: 数独のアルゴリズムを考える ― 各種法の改善と高速化

2-3. 消去法+背理法+総当り法

- 背理法において、もし答えが出なければ、残りは総当りにすれば必ず解ける。

- 現状でおそらく、完全に解答できるアルゴリズムで最も計算量が少ない解法。

- 99%以上の問題は消去法+背理法で済むため、計算量の心配はまずない。

おそらく最適な解法と考えられる

Page 25: 数独のアルゴリズムを考える ― 各種法の改善と高速化

2-4. 今回の結論

“ 消去法+背理法+総当り法 ”

Page 26: 数独のアルゴリズムを考える ― 各種法の改善と高速化

まとめ

最後の方は早足でしたが、要するに、

数独を解く際の手法をプログラムに落としこみ、

最後は総当り的に解く

ということです。「手で解ける」= 「現実的な計算量である」ということから考えると自明だったことですね。

さいごに: 是非自身でも最適な方法を考えてみて下さい。