Solving Classic Sudoku Problems with Z3 Theorem Prover

Solving Classic Sudoku Problems with Z3 Theorem Prover


Sudoku is simple yet attractive game. It is played on a 9x9 grid (variants available), divided into nine 3x3 subgrids. The goal is to fill in the empty cells with digits from 1 to 9, in such a way that each digit appears once in every row, every column, and every subgrid.

Z3 is an open-source high-performance theorem prover (satisfiability modulo theories - SAT solver) developed by Microsoft Research. It provides a powerful and efficient tool for solving complex logical formulas and equations.

Procedure is simple:

  1. Create a Z3 Solver:

    solver = Solver()
  2. Generate variables for each cell:

    X = [[Int("cell_%s_%s" % (i+1, j+1)) for j in range(9)] for i in range(9)]
  3. Generate digit constraints:

    for i in range(9):
        for j in range(9):
            solver.add(And(1 <= X[i][j], X[i][j] <= 9))
  4. Generate row constraints:

    for i in range(9):
        solver.add(Distinct(X[i]))
  5. Generate column constrains:

    for i in range(9):
        solver.add(Distinct([X[j][i] for j in range(9)]))
  6. Generate subsquare constraints:

    for i in range(3):
        for j in range(3):
            solver.add(Distinct([X[i*3+k][j*3+l] for k in range(3) for l in range(3)]))

    I create a couple helper functions for reading a 81-length string as a sudoku problem and display them pretty in console. You can see them in full code.

  7. Now we can solve some classic sudoku problems with Z3:

    Problem:
    . . . | . . 6 | . . .
    . 5 9 | . . . | . . 8
    2 . . | . . 8 | . . .
    - - - + - - - + - - -
    . 4 5 | . . . | . . .
    . . 3 | . . . | . . .
    . . 6 | . . 3 | . 5 4
    - - - + - - - + - - -
    . . . | 3 2 5 | . . 6
    . . . | . . . | . . .
    . . . | . . . | . . .
    
    Solution:
    4 3 8 | 2 5 6 | 9 7 1
    6 5 9 | 7 1 4 | 2 3 8
    2 1 7 | 9 3 8 | 4 6 5
    - - - + - - - + - - -
    1 4 5 | 6 9 2 | 7 8 3
    8 7 3 | 5 4 1 | 6 2 9
    9 2 6 | 8 7 3 | 1 5 4
    - - - + - - - + - - -
    7 9 4 | 3 2 5 | 8 1 6
    3 8 2 | 1 6 9 | 5 4 7
    5 6 1 | 4 8 7 | 3 9 2

Full code is available at: https://github.com/mrtkp9993/notebooks-blog-posts/blob/main/00_z3_sudoku.ipynb