gurobi与python应用之模型编写,注意点,及调试技巧

gurobi与python应用2

  • 指南见refman,或者google进gurobi官网借助翻译软件为中文
  • 1.定义变量
  • 2.约束部分
  • 3.理解模型及其获取解的信息
    • 3.1 理解模型
  • 4.调试技巧
  • 注意事项

指南见refman,或者google进gurobi官网借助翻译软件为中文

1.定义变量

常见的定义变量是:
m.addvars()

// An highlighted block
addVars ( *indices, lb=0.0, ub=GRB.INFINITY, obj=0.0, vtype=GRB.CONTINUOUS,
name="" );
在Gurobi中主要用到的变量类型 vtype=
GRB.CONTINUOUS——连续变量(Gurobi默认变量类型,可以省略)
GRB.BINARY——二进制变量(0-1GRB.INTEGER——整数变量(1,2,3,4,5等整数)

默认下界为0。
当下界比0小,或是需要减少变量规模时,可以自行设置。
上界默认为无穷大。即GRB.INFINITY
变量边界尽可能明确,不要设置lb=-GRB.INFINITY,ub=GRB.INFINITY.

2.约束部分

(1)线性化处理
基本是用0&1变量做中间变量,进行转化。
(2)指数或对数形式有专门的语句

// 如指数型a^x:一般底数;以e为底
addGenConstrExp ( xvar, yvar, name="", options="" );
:
# y = 3^x
gc = model.addGenConstrExpA(x, y, 3.0, "expa")
# y = exp(x)>>>y=e^x
gc = model.addGenConstrExp(x, y)
//幂指型x^a:一般幂指,以e为底,两者写法一致
addGenConstrPow ( xvar, yvar, a, name="", options="" )
如:
# y = x^3.5
gc = model.addGenConstrPow(x, y, 3.5, "gf", "FuncPieces=1000")

通常作为中间变量,需要使用循环,然后其他变量线性表达式。

3.理解模型及其获取解的信息

3.1 理解模型

我们添加变量,目标函数和约束条件后,此时模型还没有并修改。模型此时是等待更新的状态。更新有三种方式:
(1)model.update(),即更新模型,比如下述代码部分。
(2)model.optimize(),这种是我们用的最多的。即直接求解,就包含了更新这一过程,所以更新与否我们平时是忽略的。
(3)model.write(),将模型导出成本地模型文件。

 {(10, 0): <gurobi.Var *Awaiting Model Update*>,
 (10, 1): <gurobi.Var *Awaiting Model Update*>,}
>>>model.getVars()
Out[2]: []
>>>model.update()
>>>model.getVars()
Out[4]: 
[<gurobi.Var x_10_0>,
 <gurobi.Var x_10_1>]

3.2 获取解的取值
当调用model.optimize()求解完模型后,此时再调用model.getVars(),可以在上述getVars()基础上获得变量的取值。注意此时获取的是所有的变量。
假如我们只想获取某一类变量,可以用:var.VarName.startswith(‘x’),这样的意思是获取x打头的变量。
var.x是获取变量的值,通常是用遍历的方式打印最终的结果,或是根据varName获取变量的值。

# print optimal solution
for var in model.getVars():
    if (var.x > 0):
        print(var.varName, '\t', var.x)   # '\t' 空格,展示方便

# 如varName = 'x_0_1_0'
model.getVarByName('x_0_1_0').x  # 即model.getVarByName(varName)根据变量名提取变量
备注:假如获取索引可以用
'x_0_1_0'.split('_')  # 按照'_'进行分割
 ['x', '0', '1', '0']

4.调试技巧

观察模型预处理时间、解的状态。
(1)预处理时间过久的话,可以自己在变量上下界那块设置;
(2)解是什么状态?
如果是不可行,infeasible solution的话。要么是模型写错了,要么是模型对了编程写错了(好好检查)。

//模型写错,也就是约束有矛盾的话可以调用:
m.computellS()
m.write(model.ilp)
//或者下面这种,直接输出矛盾的约束名称:
if m.status == GRB.Status.INFEASIBLE:
        print('Optimization was stopped with status %d' % m.status)
        # do IIS, find infeasible constraints
        m.computeIIS()
        for c in m.getConstrs():
            if c.IISConstr:
                print('%s' % c.constrName)

gurobi提供了一个函数computeIIS()可以帮我们迅速锁定出是有问题的约束条件。此时输出的ilp文件会打印出互相矛盾的约束,链接: 检查修改即可。
其实,正常情况下也建议m.write(model.lp)文件,核对一下约束
注意,代码中的是ilp文件,只打印出互相矛盾的约束,而lp文件打出所有的约束。不一样的。
(3)检查模型是否正确
a)输出lp文件,一一核对;
b)检查解是否对,如果不对,那么修改模型。

注意事项

(1)gurobi在求解的时候,整数变量(0-1变量)也以浮点数据在进行处理,因此在最终结果中可能会带小数。误差在1e-5内,都算作正常误差。
如果想得到不带小数的结果,需要设置 IntegralityFocus (仅限 9.1 或以后版本)参数,即:可以设置为:

m.Params.IntegralityFocus=1

对Python+Gurobi建模中,所有参数设置都可以写为: ‘Model.Params. xxxx = 1e-XX’ 的形式 ,如Model.Params. xxxx = 1e-9,表示精度在1e-9;再比如Model.Params. xxxx = 1e+inf,表示设置为1。
(2)range() 函数可创建一个整数列表,也就是给出 Ni=4,range(Ni)会创造 0,1,2,3四个整数数字, 而不是 1, 2, 3, 4,这是Python规定的。
for i in range(N_i) 表示令i 分别等于0,1,2,3,然后用于后续循环。

x_c=np.zeros((N_i,N_j))
利用 'np.zeros()' 定义一个名为'x_c',具有N_i行N_j列的全0行列式。

(3)gurobi中只能两个变量相乘,多了的话就要设置中间变量了。
(4)不要设置变量上下界为无穷大,否则会出错。
按照Gurobi 官方说法:
变量、约束条件、目标的系数取值合适的范围,使得变量的优化值范围在【-1e+4,1e+4】 之间,约束取值在【-1e+4, 1e+4】之间,目标取值【-1e+4, 1e+4】之间;
最大系数/最小系数 的比值在 1e+9 之内。
我们重新对变量 、 进行定义。

你可能感兴趣的:(运筹优化理论,学习思考总结,备忘边角料,python)