python调用SCIP求解数独游戏(Sudoku)

文章目录

  • 数独问题定义
  • python调用SCIP求解
  • 参考文献

数独问题定义

根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫格( 3 ∗ 3 3*3 33)内的数字均含1~9,且不重复 。

Sudoku is a puzzle played on a partially filled 9x9 grid. The task is to complete the assignment using numbers from 1 to 9 such that the entries in each row, each column and each major 3x3 block are pairwise different.

python调用SCIP求解

  • 完整实现代码如下
import pyscipopt as opt
import numpy as np

# ==========测试数据==========
# 其中0表示未填充的数字
init = [[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]]

N = 9  # 棋盘网格grip大小
n = 3  # 宫块square大小
Number = [1, 2, 3, 4, 5, 6, 7, 8, 9]  # 填充数字的集合1~9 (为直观显示)

model = opt.Model()
# ==========定义变量==========
# 决策0-1变量: 第i行第j列是否为k
x = {}
for i in range(9):
    for j in range(9):
        for k in Number:
            x[i,j,k] = model.addVar(vtype='B', name=str(i)+'_'+str(j)+'_'+str(k))

# ==========定义约束==========
# fill in initial values
for i in range(9):
    for j in range(9):
        if init[i][j] != 0:
            model.addCons(x[i, j, init[i][j]] == 1)

# 约束1: 每个网格内有且只有一个数字
for i in range(N):
    for j in range(N):
        model.addCons(opt.quicksum(x[i, j, k] for k in Number) == 1)

# 约束2: 行列约束
for idx in range(N):
    for k in Number:
        # 每一行有且只有一个数字
        model.addCons(opt.quicksum(x[idx, j, k] for j in range(N)) == 1)
        # 每一列有且只有一个数字  
        model.addCons(opt.quicksum(x[i, idx, k] for i in range(N)) == 1) 

# 约束3: 宫格约束                  
for row in range(n):
    for col in range(n):
        for k in Number:
            model.addCons(opt.quicksum(x[i+n*row, j+n*col, k] for i in range(n) for j in range(n)) == 1)

# ==========定义目标==========
# 不需要设置目标函数,获取可行解即可
model.optimize()

# ==========输出结果==========
if model.getStatus() == 'optimal':
    print('Sudoku solution:')
    sol = np.zeros((N, N),dtype=int)
    for (i, j, k) in x.keys():
        if model.getVal(x[i,j,k]) == 1:
            sol[i,j] = k
    # 可视化显示
    row, col = sol.shape
    for i in range(row):
        print_row = ''
        for j in range(col):
            sep = ' ' if j%3 != 0 else'|'
            print_row += '{}{}'.format(sep, sol[i,j])
        print_row += '|'
        print(print_row)
        if (i+1)%3 == 0 and i != row-1:
            print('-'*len(print_row))
  • 结果
    python调用SCIP求解数独游戏(Sudoku)_第1张图片

参考文献

[1] Simonis H . Sudoku as a constraint problem[J]. proc of fourth international workshop on modelling & reformulating constraint satisfaction problems cp, 2005.

你可能感兴趣的:(运筹优化,python)