根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫格( 3 ∗ 3 3*3 3∗3)内的数字均含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.
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))
[1] Simonis H . Sudoku as a constraint problem[J]. proc of fourth international workshop on modelling & reformulating constraint satisfaction problems cp, 2005.