You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Gekko中实现'!='约束?数独求解器开发问题

在Gekko中实现数独的互不相同约束

问题背景

使用Gekko开发数独求解器(仅作兴趣研究),需要为每行、每列及3×3宫内的变量添加“互不相同”的约束。当前代码仅遵循预填充格子规则,其余格子均被填充为1.0。尝试直接用m.Equation(board[row,j] != board[row,i])表达不等约束时,出现“int类型对象无长度”错误;改用if3函数的方式也未达到预期效果。

正确实现方案

Gekko不支持直接用!=作为约束条件,对于整数变量,两个不同值的差的绝对值至少为1,因此可以借助m.abs()函数构建有效约束:

m.Equation(m.abs(board[row,i] - board[row,j]) >= 1)

修改后的完整代码

import itertools
from gekko import GEKKO

SQUARES = [
    ((0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2,1),(2,2)),
    ((0,3),(0,4),(0,5),(1,3),(1,4),(1,5),(2,3),(2,4),(2,5)),
    ((0,6),(0,7),(0,8),(1,6),(1,7),(1,8),(2,6),(2,7),(2,8)),
    ((3,0),(3,1),(3,2),(4,0),(4,1),(4,2),(5,0),(5,1),(5,2)),
    ((3,3),(3,4),(3,5),(4,3),(4,4),(4,5),(5,3),(5,4),(5,5)),
    ((3,6),(3,7),(3,8),(4,6),(4,7),(4,8),(5,6),(5,7),(5,8)),
    ((6,0),(6,1),(6,2),(7,0),(7,1),(7,2),(8,0),(8,1),(8,2)),
    ((6,3),(6,4),(6,5),(7,3),(7,4),(7,5),(8,3),(8,4),(8,5)),
    ((6,6),(6,7),(6,8),(7,6),(7,7),(7,8),(8,6),(8,7),(8,8))
]
BOARD_DIMS = (9,9)
PRE_FILLED_SQUARES = [
    (0,1,2),(0,3,5),(0,5,1),(0,7,9),(1,0,8),(1,3,2),
    (1,5,3),(1,8,6),(2,1,3),(2,4,6),(2,7,7),(3,2,1),
    (3,6,6),(4,0,5),(4,1,4),(4,7,1),(4,8,9),(5,2,2),
    (5,6,7),(6,1,9),(6,4,3),(6,7,8),(7,0,2),(7,3,8),
    (7,5,4),(7,8,7),(8,1,1),(8,3,9),(8,5,7),(8,7,6)
]

m = GEKKO()
m.options.SOLVER = 1  # 使用APOPT求解器,适配整数规划场景
board = m.Array(m.Var, BOARD_DIMS, lb=1, ub=9, integer=True, value=1)

# 预填充格子约束
for i,j,val in PRE_FILLED_SQUARES:
    board[i,j].value = val
    m.Equation(board[i,j] == val)

# 行约束:每行元素互不相同
for row in range(BOARD_DIMS[0]):
    for i,j in itertools.combinations(range(BOARD_DIMS[1]), r=2):
        m.Equation(m.abs(board[row,i] - board[row,j]) >= 1)

# 列约束:每列元素互不相同
for col in range(BOARD_DIMS[1]):
    for i,j in itertools.combinations(range(BOARD_DIMS[0]), r=2):
        m.Equation(m.abs(board[i,col] - board[j,col]) >= 1)

# 3×3宫约束:每宫元素互不相同
for square in SQUARES:
    for (y,x),(y_prime,x_prime) in itertools.combinations(square, r=2):
        m.Equation(m.abs(board[y,x] - board[y_prime,x_prime]) >= 1)

m.solve(disp=True)

# 格式化打印结果
for row in board:
    print([int(v.value[0]) for v in row])

关键说明

  • Gekko的APOPT求解器(SOLVER=1)专门针对整数规划问题优化,适合数独这类带整数约束的场景。
  • 直接使用!=无法被Gekko的求解器解析,利用整数变量的特性,通过绝对值约束确保两个变量差值至少为1,等价于“互不相同”的逻辑。
  • 移除了原代码中无效的if3逻辑,避免因逻辑判断引入的约束失效问题。

内容的提问来源于stack exchange,提问作者phdavis1027

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 05:55:01