Gurobi study notes - Matrix variables and eight queens problem cases
This section describes the matrix of variables Gurobi MVar
, and with eight cases in Queens Gurobi case to interpret directory
Matrix variables MVar
and tupledict
different.
The variable matrix Mvar
is in the form of variable NumPy ndarray, only the subscript index, obtained by multiplying a linear / matrix through a polynomial matrix expression of MVar Numpy MLinExpr
or MQuadExpr
.
Create a matrix of variables
Model.addMVar () Common
addMVar ( shape, lb=0.0, ub=GRB.INFINITY, obj=0.0, vtype=GRB.CONTINUOUS, name="" ) shape:矩阵向量的维度 lb, ub:分别为变量的上下限(可选) obj:变量在目标函数表达式中的系数(可选) vtype:变量类型(可选) x = model.addMVar(10) # 包含10个变量的一维矩阵变量 y = model.addMVar((3,4), vtype GRB.BINARY) # 3x4的0-1变量矩阵
Matrix Variable operation
Gurobi matrix variables can be used as Numpy in the matrix, its operations to create expressions should be noted that the dimension must be compatible. Equation is expressed as follows, for example:
x + 2 y + 3 z <= 4
x + y >= 1
x, y, z binary
Can be written as
# 一维矩阵变量
x = m.addMVar(shape=3, vtype=GRB.BINARY, name="x")
# 左端项系数矩阵
A = np.array([[1,2,3],[1,1,0]])
# 右端项
rhs = np.array([4.0, -1.0])
m.addConstr(A @ x <= rhs, name ="c")
Support matrix variables slicing operation, []
, :
to select a particular element of the matrix, and that tupledict
the object (i.e., addVars()
) is select()
different from the latter using wildcard operator * represents
Support matrix variable sum operation, but with tupledict
different variables. Using matrix variables slice select element directly call the sum()
function
y = model.addMVar((3,4), vtype GRB.BINARY) # 3x4的0-1变量矩阵
y[:,1]#选取第一列元素
Object contrast tuplelist
tupledict
A variable model.addVars()
or multidict()
create functions, indices used to access through the creation, but also has select()
, sum()
, prod()
a functional screening element and quickly build expressions.
model.addVars(*indices)
Objects created by the way, is essentially the result of the Cartesian product of a variety of collections
x = m.addVars(2,3, vtype=GRB.BINARY)
# 生成的元素是
x(0,0) x(0,1) x(0,2)
x(1,0) x(1,1) x(1,2)
# 三个组的笛卡尔积
y = m.addVars((1,2),(1,3),(2,3))
x(1,1,2) x(1,1,3) x(1,3,2) x(1,3,3)
x(2,1,2) x(2,1,3) x(2,3,2) x(2,3,3)
tupledict
Objects created to support the use of type string, and the index can use wildcards
commodities = ['Pencils', 'Pens']
nodes = ['Detroit', 'Denver']
flow = m.addVars(commodities, nodes, obj=cost, name="flow")
flow.select('*','*')
# flow('pencil','Detroit') flow('pencil','Denver')
# flow('pen','Detroit') flow('pen','Denver')
Eight Queens Case
The case exists in the case Gurobi directory folder根目录\examples\python\matrix2.py
Eight queens problem is an old and well-known problem is backtracking algorithms typical cases. The problem is an international chess player Max Bethel presented in 1848: the 8 × 8 grid of chess placed on the eight queens , it can not attack each other, that is, any two queens can not be in the same line, on the same row or the same slash and asked how many pendulum method. (Excerpt from Baidu Encyclopedia )
Suppose decision variables x(i,j)
as binary variables, variables represents the i-th row is placed queen j-th column, following conditions are required:
(1) placed in each row only one queen
(2) is placed in each column only one queen
(3) each only put a positive diagonal Queen
(4) Each diagonal ramp only put a queen
3,4 constraints generated by the generator, the code may be read all at once, to I n = 4 for example, a push of a calculated positive diagonal, the diagonal oblique empathy
#!/usr/bin/env python3.7
# Copyright 2019, Gurobi Optimization, LLC
# This example uses the Python matrix API to formulate the n-queens
# problem; it maximizes the number queens placed on an n x n
# chessboard without threatening each other.
#
# This example demonstrates NumPy slicing.
import numpy as np
import scipy.sparse as sp
import gurobipy as gp
from gurobipy import GRB
# Size of the n x n chess board
n = 8
try:
# Create a new model
m = gp.Model("matrix2")
# Create a 2-D array of binary variables
# x[i,j]=1 means that a queen is placed at square (i,j)
x = m.addMVar((n, n), vtype=GRB.BINARY, name="x")
# Set objective - maximize number of queens
m.setObjective(x.sum(), GRB.MAXIMIZE)
# Add row and column constraints
# 为每一行、列添加约束
for i in range(n):
# At most one queen per row
# 每一行最多放置一个皇后
m.addConstr(x[i, :].sum() <= 1, name="row"+str(i))
# At most one queen per column
# 每一列最多放置一个皇后
m.addConstr(x[:, i].sum() <= 1, name="col"+str(i))
# Add diagonal constraints
# 添加对角线约束
for i in range(1, 2*n):
# At most one queen per diagonal
# 每个正对角线最多防止一个皇后
# 生成器生成对矩阵的切片索引
diagn = (range(max(0, i-n), min(n, i)), range(min(n, i)-1, max(0, i-n)-1, -1))
m.addConstr(x[diagn].sum() <= 1, name="diag"+str(i))
# At most one queen per anti-diagonal
# 每个斜对角线最多防止一个皇后
# 生成器生成对矩阵的切片索引
adiagn = (range(max(0, i-n), min(n, i)), range(max(0, n-i), min(n, 2*n-i)))
m.addConstr(x[adiagn].sum() <= 1, name="adiag"+str(i))
# Optimize model
# 开始优化模型
m.optimize()
print(x.X)
print('Queens placed: %g' % m.objVal)
except gp.GurobiError as e:
print('Error code ' + str(e.errno) + ": " + str(e))
except AttributeError:
print('Encountered an attribute error')