# 数独 このページでは、**Hi-QUBO** を使って数独パズルをイジングマシン(アニーリング)によって解く方法を紹介します。 --- ## 数独とは 数独(Sudoku)は、**9×9 グリッドに 1 〜 9 の数字を埋めるパズル**です。 次のルールを満たすように空欄に数字を入れていきます。 - 各行には 1 〜 9 の数字が一度ずつ現れること - 各列には 1 〜 9 の数字が一度ずつ現れること - 3×3 のブロック内にも 1 〜 9 の数字が一度ずつ現れること ヒントとして初期値がすでに何個か埋まっており、その状態から全てのマスを埋めると完成です。 --- ## イジングマシンによる解法の考え方 プログラムでは、数独のルールを **制約条件に変換**し、イジングマシンに解かせます。 各セルに入る数字は「バイナリ変数(0/1)」として表現し、制約を満たす組み合わせを最適化によって見つけます。 --- ## 制約条件の定式化 ### 変数定義 - $y_{i,j,k} \in \{0,1\}$ を 3 次元配列で定義 - $i,j=0,...,8$ が行・列、$k=0,...,8$ が数字(1〜9)を表す - $y_{i,j,k}=1$ のとき、セル $(i,j)$ は $k+1$ が入ることを意味する これにより変数が **$9 \times 9 \times 9 = 729$ 個** 作られます。 --- ### ルールからの制約 数独のルールは次のような one-hot 制約として定義できます: - **制約 (a)**: 1 マスには 1 個の数字しか入らない $$ \sum_{k=0}^8 y_{i,j,k} = 1 $$ - **制約 (b)**: 同じ行に同じ数字は 1 個 $$ \sum_{j=0}^8 y_{i,j,k} = 1 $$ - **制約 (c)**: 同じ列に同じ数字は 1 個 $$ \sum_{i=0}^8 y_{i,j,k} = 1 $$ - **制約 (d)**: 同じ $3 \times 3$ ブロックに同じ数字は 1 個 $$ \sum_{(i,j)\in \text{block}} y_{i,j,k} = 1 $$ --- ## コード例 以下はサンプルコードです。 :::{container} prog-cpp ```cpp #include #include int main() { const size_t num_size = 3; const size_t use_num = num_size*num_size; const size_t N = use_num; // 初期配置を配列で表記 std::vector> initial = { {5, 3, 0, 0, 7, 0, 0, 0, 0}, {6, 0, 0, 1, 9, 5, 0, 0, 0}, {0, 9, 8, 0, 0, 0, 0, 6, 0}, {8, 0, 0, 0, 6, 0, 0, 0, 3}, {4, 0, 0, 8, 0, 3, 0, 0, 1}, {7, 0, 0, 0, 2, 0, 0, 0, 6}, {0, 6, 0, 0, 0, 0, 2, 8, 0}, {0, 0, 0, 4, 1, 9, 0, 0, 5}, {0, 0, 0, 0, 8, 0, 0, 7, 9} }; // 変数の定義 auto y = qbpp::var("y", N, N, use_num); // 初期配置を変数に反映するための配列 qbpp::MapList ml; for (size_t i=0; i