线性规划速度 > 0-1 整数线性规划 > 整数线性规划 > 混合整数线性规划 > 非线性规划
在现实问题中,应用最广泛的数学规划问题类型是混合整数线性规划(MILP)。
MODEL = gurobipy.Model()#创建模型
x = MODEL.addVars(创建变量, vtype=gurobipy.GRB.CONTINUOUS, name="X")#创建变量
MODEL.update()#更新变量环境
MODEL.setObjective(创建目标函数, sense=gurobipy.GRB.MINIMIZE)#创建目标函数
MODEL.addConstrs(创建约束条件) #创建约束条件
MODEL.optimize() #执行最优化

MODEL = gurobipy.Model(name="")
name 为模块名默认为空
import gurobipy as GRB
MODEL = GRB.Model("Model_name") #创建模型
x = MODEL.addVar(lb=0.0, ub=gurobipy.GRB.INFINITY, vtype=gurobipy.GRB.CONTINUOUS, name="")
lb = 0.0 #变量的下界,默认为 0
ub = GRB.INFINITY: 变量的上界,默认为无穷大
vtype = GRB.CONTINUOUS #变量的类型,默认为连续型,可改为 GRB.BINARY 0-1变量,GRB.INTEGER 整型
name = "" #变量名,默认为空
x1 = MODEL.addVar(lb=0, ub=1, name="x1")
x = MODEL.addVars(*indexes, lb=0, ub=gurobipy.GRB.INFINITY, vtype=gurobipy.GRB.CONTINUOUS, name="")
# *indexes 不能含有中文字符 索引的集合
x = MODEL.addVars(3, 4, 5, vtype=gurobipy.GRB.BINARY, name="C")
# 创建 3*4*5 个变量,使用 x[1,2,3] 进行访问
MODEL.update()
MODEL.setObjective(expression, sense=None)
expression #表达式,可以是一次或二次函数类型
sense #求解类型,可以是 GRB.MINIMIZE(最小值) 或 GRB.MAXIMIZE(最大值)
MODEL.setObjective(8 * x1 + 10 * x2 + 7 * x3 + 6 * x4 + 11 * x5 + 9 * x6, GRB.GRB.MINIMIZE)
MODEL.setObjectiveN(expression, index, priority=0, weight=1.0, abstol=0, reltol=0, name="")
expression # 表达式,可以是一次或二次函数类型
index # 目标函数对应的序号 (默认 0,1,2,…), 以 index=0 作为目标函数的值, 其余值需要另外设置参数
priority # 分层序列法多目标决策优先级(整数值), 值越大优先级越高
weight #线性加权多目标决策权重(在优先级相同时发挥作用)
abstol # 分层序列法多目标决策时允许的目标函数值最大的降低量
reltol #分层序列法多目标决策时允许的目标函数值最大的降低比率 reltol*|目标函数值|
注意: 所有的目标函数都为线性的,并且目标函数的优化方向一致(全部最大化或全部最小化)。可以通过乘以 -1 实现不同的优化方向。
# Obj1 = x + y weight = 1
# Obj2 = x - 5 * y weight = -2
# MODEL.setObjectiveN(x + y, index=0, weight=1, name='obj1')
# MODEL.setObjectiveN(x -5 * y, index=1, weight=-2, name='obj2')
# 即转化为: (x + y) - 2 * (x - 5 * y) = - x + 11 * y
# Obj1 = x + y priority = 5
# Obj2 = x - 5 * y priority = 1
# MODEL.setObjectiveN(x + y, index=0, priority=5, name='obj1')
# MODEL.setObjectiveN(x -5 * y, index=1, priority=1, name='obj2')
# 即转化为: 先优化 Obj1,再优化 Obj2(按照 priority 的大小关系)
注意: Gurobi 按照优先级大小优化(先优化Obj1),若没有设定abstol或reltol,在优化低优先级目标时,不会改变高优先级的目标值。假设Obj1=10,在优化 Obj2 时只能在使得 Obj1=10 的所有解中挑选最优解
MODEL.setObjectiveN(x + y, index=0, weight=1, priority=5, name='obj1')
MODEL.setObjectiveN(x -5 * y, index=1, weight=-2, priority=1, name='obj2')
# 则 先优化 Obj1 再优化 Obj2 最后相加作为目标值, 由于优先级不同, weight不会起作用
通过参数 ObjNumber 选择特定的目标,进而获得对应的目标函数值。
MODEL.setParam(gurobipy.GRB.Param.ObjNumber, i) # 第 i 个目标
print(MODEL.ObjNVal) # 打印第 i 个值
for i in range(model.NumObj):
model.setParam(GRB.Param.ObjNumber, i)
print('Obj%d = ' %(i+1), model.ObjNVal)
setPWLObj(var,x,y)
• var #指定变量的目标函数是分段线性
• x #定义分段线性目标函数的点的横坐标值(非减序列)
• y #定义分段线性目标函数的点的纵坐标值
例1:


m.setPWLObj(x, [0, 2, 5], [0, 2, 3])
m.setAttr(GRB.Attr.ModelSense, -1)
注意: 对一些非线性模型,可以使用这一功能去线性逼近。
例2:


m.setPWLObj(x, [0,1/4, 1,7/4, 2], [3,41/9, 2,41/9,3])
MODEL.addConstr(expression, name="")
expression # 布尔表达式,可以是一次或二次函数类型
name # 约束式的名称
# 单个约束
MODEL.addConstr(12 * x1 + 9 * x2 + 25 * x3 + 20 * x4 + 17 * x5 + 13 * x6 >= 60, "c0")
# 多个约束
x = MODEL.addVars(20, 8, vtype=gurobipy.GRB.BINARY)
# 写法 1
for i in range(20):
MODEL.addConstr(x.sum(i, "*") <= 1)
# 写法 2
MODEL.addConstrs(x.sum(i, "*") <= 1 for i in range(20))
# 写法 2 的等价写法:
MODEL.addConstrs(sum(x[i, j] for j in range(8) <= 1 for i in range(20))
addGenConstrMax(resvar, vars, constant, name )
• resvar 变量(x = max(x1,x2,10))
• vars 一组变量(可以包含常数)
• constant 常数
• name 广义约束名称
例如: z = max(x, y, 3)
m.addGenConstrMax(z, [x, y], 3, "maxconstr")
m.addGenConstrMax(z, [x, y, 3], name="maxconstr")
换成一般的约束表达方式:
m.addConstr(z == max_([x, y, 3]), "maxconstr")
m.addConstr(z == max_(x, y, 3), "maxconstr")
addGenConstrMin( resvar, vars, constant, name )
• resvar 变量(x = min(x1,x2,10))
• vars 一组变量(可以包含常数)
• constant 常数
• name 广义约束名称
例如: z = min(x, y, 3)
m.addGenConstrMin(z, [x, y], 3, "minconstr")
m.addGenConstrMin(z, [x, y, 3], name="minconstr")
换成一般的约束表达方式:
m.addConstr(z == min_([x, y, 3]), "minconstr")
m.addConstr(z == min_(x, y, 3), "minconstr")
addGenConstrAbs( resvar, argvars, name )
• resvar 变量
• argvar 变量
• name 广义约束名称
例如: x = |y|
m.addGenConstrAbs(x, y, "absconstr")
换成一般的约束表达方式:
m.addConstr(x == abs_(y), "absconstr")
一组变量的值全等于1,则取1,否则取0。
addGenConstrAnd( resvar, vars, name )
• resvar 变量
• vars 一组变量
• name 广义约束名称
例如: x = 1且y = 1,那么z = 1,否则 z = 0
m.addGenConstrAnd(z, [x,y], "andconstr")
换成一般的约束表达方式:
m.addConstr(z == and_(x, y), "andconstr")
一组变量的值有一个等于1,则取1,否则取0。
addGenConstrOr( resvar, vars, name )
• resvar 变量
• vars 一组变量
• name 广义约束名称
例如: x = 0且y = 0,那么z = 0,否则 z = 1
m.addGenConstrOr(z, [x,y], "orconstr")
换成一般的约束表达方式:
m.addConstr(z == or_(x, y), "orconstr")
MODEL.addRange(expression, min_value, max_value, name="")
# 表达式 min_value<=expression<=max_value 的简写, 但这里的 min_value, max_value 必须是具体的实数值, 不能含有变量
例如: 5 <= x + y + z <= 10
m.addRange(x+y+z, 5, 10, "c")
换成一般的约束表达方式:
m.addConstr(x+y+z==[5,12])
MODEL.addGenConstrIndicator(binvar, binval, expression, name="")
# 指示变量 binvar 的值取 binval 时, 进行约束 expression
# 指示变量的值为1,约束成立,否则约束可以被违反。

# 案例: 如果生产某一类型汽车 (x[i] > 0), 则至少要生产 80 辆
# %% 方法一
for i in range(3):
MODEL.addGenConstrIndicator(y[i + 1], 0, x[i + 1] >= 80)
MODEL.addGenConstrIndicator(y[i + 1], 1, x[i + 1] == 0)
# 以上代码等价于
for i in range(3):
MODEL.addConstr(x[i + 1] >= 80 * y[i + 1])
MODEL.addConstr(x[i + 1] <= 1000 * y[i + 1])
例2: 如果 z = 1,则 x+y <= 4
m.addGenConstrIndicator(z, True, x + y, GRB.LESS_EQUAL, 4, 'indicator')
换成一般的约束表达方式:
m.addConstr((z == 1) >>(x + y<= 4))
MODEL.Params.LogToConsole=True # 显示求解过程
MODEL.Params.MIPGap=0.0001 # 百分比界差
MODEL.Params.TimeLimit=100 # 限制求解时间为 100s
MODEL.Params.Presolve = -1 # 预处理程度, 0关闭,1保守,2激进
MODEL.Params.MIPFocus = 0 # 求解侧重点. 1快速找到可行解, 2证明最有, 3侧重边界提升, 0均衡搜索
MODEL.Params.SolutionLimit = inf # 求解数量, 默认求所有解, 比较出最优的结果, 只需要可行解时可以设置该参数为1
MODEL.Params.NonConvex = 1 # 默认求解器,改为 2 时可以解决非凸二次优化问题
MODEL.optimize()
整数规划/混合整数规划问题评价准则: 百分比界差

OPT 为当前的最优解,LP 为去掉整数约東后的松弛最优解百分比界差是数学规划领域常用的评价参数,具体可视为在去除问题参数整数取值的限制后,问题松弛解与最优解之间的绝对差距
#单目标获得目标值和单个变量值
print("Obj = ",m.ObjVal)
for i in range(N):
print(y[i].VarName,' = ',y[i].x)
# 查看多个变量取值
for var in MODEL.getVars():
print(f"{var.varName}: {round(var.X, 3)}")
# 查看多目标规划模型的目标函数值
for i in range(MODEL.NumObj):
MODEL.setParam(gurobipy.GRB.Param.ObjNumber, i)
print(f"Obj {i+1} = {MODEL.ObjNVal}")






















在建模过程中,经常要对带下标数据做挑选,不同下标的数据进行组合,这样面临着二个处理方法。

列表、元组和字典建模优点
列表、元组和字典建模缺点
对于约束系数稀疏的模型,会占用不必要的内存来存储那些系数为0的部分,模型较大时,有可能导致内存溢出;
虽然可以得到对偶问题的具体形式,但是对偶问题的公式形式却不能得出(这个严格来讲不算是这种建模方式的缺点)。
不方便对每个决策变量赋予独一无二的变量名。
例题

import gurobipy as grb
import numpy as np
if __name__ == "__main__":
m = grb.Model("LP")
m.setParam('OutputFlag', 1)
x = m.addMVar(2, lb=0, ub=grb.GRB.INFINITY)
c = np.array([[3, 5]])
A = np.array([[1, 0],
[0, 2],
[3, 2]])
b = np.array([4, 12, 18])
m.addConstr(A @ x <= b)
m.Params.timelimit = 9999999999999999999999
m.setObjective(c @ x, grb.GRB.MAXIMIZE)
m.update()
m.optimize()
print('x_1={}'.format(x[0].x))
print('x_2={}'.format(x[1].x))
求解器支持用户向模型输入一个或多个已知的全部或部分可行解(一个可行解包括了模型所有变量的取值)。例如,当前问题的可行方案,以及用户通过其他算法获得的可行解等,都可以直接输入给求解器以期加速或帮助求解器进行求解。

# 将变量x_1_12的初值设置为0
x[0,12].start = 1.0
# 循环为x_ij赋值完整的一组初始解,data为存放初始解的矩阵
for i in range(len(data)):
for j in range(len(data[i])):
x[i,j].start = data[i][j]

# 为模型m2设置要输入的初始解个数为2个
m2.NumStart = 2
# 将该可行解设置为第一个输入的可行解
m2.Params.StartNumber = 0
# 将该可行解设置为第二个输入的可行解
m2.Params.StartNumber = 1
详细参考:https://mp.weixin.qq.com/s/R76jmojKGqm6ZC1dy7hSQQ
在默认状态下,Gurobi的目标是为具有单一目标函数的MIP模型寻找一个最优解。然而在Gurobi的branch and cut算法迭代的过程中,可能会通过启发式算法(也就是求解日志行首标注为H的行)得到整数可行解,也有可能通过分支切割得到整数可行解(也就是求解日志行首标注*的行)。所以在求解MIP的过程中,求解器往往会得到多个次优的可行解(Sub-Optimal Solutions)。
Solution Pool(以下简称Pool)顾名思义就是将迭代过程中产生的整数可行解存储下来的集合。(solution pool存储的只是一部分整数可行解,并不是MIP的所有可行解)。许多情况下这些可行解能够为我们提供有价值的信息,因此为方便用户了解这些解的具体情况,Gurobi提供了Solution Pool一系列相关的操作方法。
Solution Pool相关Parameters:

具体可参考该文章:https://zhuanlan.zhihu.com/p/545591977
例1. 最简单的线性规划模型

from gurobipy import * # 在Python中调用gurobi求解包
M_LP=Model("LP_Exam") # 创建模型
# 变量声明
OF =M_LP.addVar(lb=-GRB.INFINITY,ub=GRB.INFINITY, name="OF")
x1 =M_LP.addVar(lb=-GRB.INFINITY,ub=GRB.INFINITY, name="x1")
x2 =M_LP.addVar(lb=-GRB.INFINITY,ub=GRB.INFINITY, name="x2")
x3 =M_LP.addVar(lb=-GRB.INFINITY,ub=GRB.INFINITY, name="x3")
# 设置目标函数
M_LP.setObjective(x1+3*x2+3*x3,GRB.MINIMIZE)
# 添加约束
M_LP.addConstr(x1+2*x2>=3,"Con1")
M_LP.addConstr(x2+x3>=5,"Con2")
M_LP.addConstr(x1+x3==4,"Con3")
# Optimize model
M_LP.optimize()
# 输出名为‘LP_Expression’的 .lp文件
M_LP.write("LP_Expression.lp")
# 输出结果
print('**************')
print(' The optimal solution ')
print('**************')
print('OF is :',M_LP.ObjVal) # 输出目标值
print('x1 is :',x1.x) # 输出 X1 的值
print('x2 is :',x2.x)
print('x3 is :',x3.x)
例2. 具有边界的变量

# 方法1:在变量声明时进行设定
x1=M_LP.addVar(lb=0,ub=5, name="x1")
# 方法2:将变量边界以约束的形式加入模型中
M_LP.addConstr(x1>=0,"Bound_Con11")
M_LP.addConstr(x1<=5,"Bound_Con12")
from gurobipy import * # 在Python中调用gurobi求解包
Max_Obj=1 # 用于判定目标函数求最大值还是求最小值
M_LP=Model("LP_Exam2")
# 变量声明
OF =M_LP.addVar(lb=-GRB.INFINITY,ub=GRB.INFINITY, name="OF")
x1 =M_LP.addVar(lb=0,ub=5, name="x1")
x2 =M_LP.addVar(lb=0,ub=3, name="x2")
x3 =M_LP.addVar(lb=0,ub=2, name="x3")
# 设置目标函数
if Max_Obj==0:
M_LP.setObjective(x1+2*x2-3*x3,GRB.MINIMIZE)
else:
M_LP.setObjective(x1+2*x2-3*x3,GRB.MAXIMIZE)
# 添加约束
M_LP.addConstr(x1+2*x2<=3,"Con1")
M_LP.addConstr(x2+x3<=2,"Con2")
M_LP.addConstr(x1+x2+x3==4,"Con3")
# 对变量边界进行限定的第二种写法:以x1为例
# M_LP.addConstr(x1>=0,"Bound_Con11")
# M_LP.addConstr(x1<=5,"Bound_Con12")
# Optimize model
M_LP.optimize()
M_LP.write("LP_Expression2.lp")
print('**************')
print(' The optimal solution ')
print('**************')
print('OF is :',M_LP.ObjVal) # 输出目标值
print('x1 is :',x1.x) # .x 用于输出 X1 的值
print('x2 is :',x2.x)
print('x3 is :',x3.x)
例1. 
M_LP=Model("LP_Exam2")
N_i=4
N_j=4
# 设置变量
x =M_MIP.addVars(N_i,N_j,vtype=GRB.BINARY, name="x")
# 设置约束
M_MIP.addConstrs((sum(x[i,j] for j in range(N_j))<=1 for i in range(N_i)),"Con1")
M_MIP.addConstrs((sum(x[i,j] for i in range(N_i))<=1 for j in range(N_j)),"Con2")
# 汇总解
x_c=np.zeros((N_i,N_j))
for i in range(N_i):
for j in range(N_j):
x_c[i,j]=x[i,j].x
在新的Gurobi求解器(9.0以上版本)中,包含了非线性/非凸问题的求解。注意:

from gurobipy import *
# 创建模型
M_NLP=Model("NLP")
# 变量声明
x1 =M_NLP.addVar(lb=1,ub=3, name="x1")
x2 =M_NLP.addVar(lb=1,ub=3, name="x2")
x3 =M_NLP.addVar(lb=1,ub=3, name="x3")
x4 =M_NLP.addVar(lb=1,ub=3, name="x4")
y14 =M_NLP.addVar(lb=0,ub=300, name="y14")
y23 =M_NLP.addVar(lb=0,ub=300, name="y23")
# 设置目标函数
M_NLP.setObjective(y14*(x1+x2+x3)+x2,GRB.MAXIMIZE)
# 添加约束
M_NLP.addConstr(y14*y23>=20,"Con1")
M_NLP.addConstr(x1*x1+x2*x2+x3*x3+x4*x4==30,"Con2")
# 表示乘积项
M_NLP.addConstr(y14==x1*x4,"Con_y14")
M_NLP.addConstr(y23==x2*x3,"Con_y23")
M_NLP.Params.NonConvex=2 ###求解重点
# Optimize model
M_NLP.optimize()
M_NLP.write("NLP.lp")
print('**************')
print(' The optimal solution ')
print('**************')
print('Obj is :',M_NLP.ObjVal) # 输出目标值
print('x1 is :',x1.x) # 输出 x1 的值
print('x2 is :',x2.x) # 输出 x2 的值
print('x3 is :',x3.x) # 输出 x3 的值
print('x4 is :',x4.x) # 输出 x4 的值
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po