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

数独问题定义

根据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))
  • 结果
    请添加图片描述

参考文献

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值