zoukankan      html  css  js  c++  java
  • Gurobi学习笔记—矩阵变量及八皇后问题案例

    Gurobi学习笔记—矩阵变量及八皇后问题案例

    本节将介绍Gurobi中的矩阵变量MVar,并且以Gurobi案例目录下的八皇后案例进行解读

    矩阵变量MVartupledict有所区别。

    矩阵变量Mvar是NumPy ndarray形式的变量,只能使用下标索引,通过Numpy的矩阵与MVar相乘得到线性/多项式矩阵表达式MLinExprMQuadExpr

    矩阵变量的创建

    1. Model.addMVar() 常用

      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变量矩阵
      

    矩阵变量的运算

    Gurobi中的矩阵变量可以当做Numpy中的矩阵,对其进行运算以创建表达式,需要注意的是维数一定要兼容。例如表示如下式子:

    x + 2 y + 3 z <= 4
    x +   y       >= 1
    x, y, z binary
    

    可写作

    # 一维矩阵变量
    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")
    

    矩阵变量支持切片操作,使用[],:选取矩阵中特定的元素,这一点与tupledict对象(即addVars())的select()不同,后者采用*表示通配符运算

    矩阵变量支持求和操作,但与tupledict变量不同。矩阵变量采用切片选取元素,后直接调用sum()函数

    y = model.addMVar((3,4), vtype GRB.BINARY) # 3x4的0-1变量矩阵
    y[:,1]#选取第一列元素
    

    与tuplelist对象的对比

    tupledict变量由model.addVars()或者multidict()函数创建,通过创建时使用的indices进行访问,同时具有select(), sum(), prod() 的功能筛选元素并快速构建表达式。

    model.addVars(*indices)方式创建的对象,本质上是多种集合的笛卡尔乘积的结果

    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对象支持采用字符串类型创建索引(字符串作为key),并且索引可使用通配符(select方法)
    注意:方括号索引时不能使用*

    MVar仅能通过数字按行列索引

    commodities = ['Pencils', 'Pens']
    nodes = ['Detroit', 'Denver']
    flow = m.addVars(commodities, nodes, obj=cost, name="flow")
    flow.select('*','*')
    flow[*,*] # 错误的引用方式
    flow['pencil','Detroit']
    flow['Pencils','Denver']
    

    八皇后案例

    该案例存在于Gurobi目录下案例文件夹中根目录examplespythonmatrix2.py

    八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。(摘自百度百科

    假设决策变量x(i,j)为0-1变量,变量为1代表在第i行第j列放置皇后,需满足下列条件:

    (1) 每行只放置一个皇后

    (2)每列只放置一个皇后

    (3)每条正对角线只放一个皇后

    (4)每个斜对角线只放一个皇后

    约束3,4由生成器生成,在代码中可能一下子看不懂,本人以n=4为例,推了一下正对角线的计算,斜对角线同理

    #!/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')
    
    
  • 相关阅读:
    各个控件说明
    html常用
    abp.message
    ABP框架——单表实体流程
    AngularJS $http和$.ajax
    AngularJS ng-if使用
    AngularJS 多级下拉框
    AngularJS 计时器
    AngularJS table循环数据
    Python之待学习记录
  • 原文地址:https://www.cnblogs.com/TianYuanSX/p/12364892.html
Copyright © 2011-2022 走看看