我正试图解决棋盘优化问题,其中一个制约因素是检查附近的单元格是否被占用:
subject to attack_each_cell {i in 1..n,j in 1..n}:
P[i,j]+P[i-1,j+2]+P[i-1,j-2]+P[i+1,j+2]+P[i+1,j-2]+P[i-2,j+1]+P[i-2,j-1]+P[i+2,j+1]+P[i+2,j-1]>=1上面约束的问题是,对于边框单元格,我得到了一个超出界限的错误,所以我的第二种方法是关于(i,j)索引的if-else语句:
P[i,j]
+ if i>1 and j<n-2 then P[i-1,j+2]
+ if i>1 and j>2 then P[i-1,j-2]
+ if i<n-1 and j<n-2 then P[i+1,j+2]
+ if i<n-1 and j>2 then P[i+1,j-2]
+ if i>2 and j<n-1 then P[i-2,j+1]
+ if i>2 and j>1 then P[i-2,j-1]
+ if i<n-2 and j<n-1 then P[i+2,j+1]
+ if i<n-2 and j>1 then P[i+2,j-1]
>=1这不起作用,因为语句似乎是嵌套的,而不是按顺序执行的。对如何修复代码有什么建议吗?
发布于 2017-11-04 22:34:15
备选案文1:增加括号以确定评估顺序。
选项2:重新制定约束。与其检查相对于参考单元格的骑士移动位置,然后必须处理超出界限的情况,不如检查董事会上的所有位置并接受那些从参考单元格中移动的骑士的位置:
subject to attack_each_cell {i in 1..n,j in 1..n}:
P[i,j]
+ sum{i1 in 1..n, j1 in 1..n: abs(i-i1) = 2 and abs(j-j1) = 1} P[i1,j1]
+ sum{i1 in 1..n, j1 in 1..n: abs(i-i1) = 1 and abs(j-j1) = 2} P[i1,j1]
>= 1;选项3:如上所述,但首先创建一个定义合法移动的集合,然后通过引用该集合来定义约束:
set KnightMoves := {(i,j) in
({-1,1} cross {-2,2})
union
({-2,2} cross {-1,1})
}; # this defines the set of moves {(-1,-2),(-1,2), ... (2,1)}
subject to attack_each_cell {i in 1..n,j in 1..n}:
P[i,j] + sum{i1 in 1..n, j1 in 1..n: (i-i1,j-j1) in KnightMoves} P[i1,j1]
>= 1;我最喜欢#3,因为它打破了“骑士如何移动”的逻辑,“任何不包含骑士的细胞都必须受到骑士的威胁”。这使得定制变得更容易一些,例如,如果您需要为不同类型的件解决问题,那么它可以很好地扩展到多个类型的问题:
subject to attack_each_cell {i in 1..n,j in 1..n}:
P[i,j]
+ sum{i1 in 1..n, j1 in 1..n: (i-i1,j-j1) in KnightMoves} Knights[i1,j1]
+ sum{i1 in 1..n, j1 in 1..n: (i-i1,j-j1) in BishopMoves} Bishops[i1,j1]
+ sum{i1 in 1..n, j1 in 1..n: (i-i1,j-j1) in Pawn} Pawns[i1,j1]
+ ...
>= 1;(编辑:嗯,如果你忽略了不跳跃的部分被其他人阻塞的问题,它就会这样做。)
https://stackoverflow.com/questions/47093414
复制相似问题