COPT求解器
COPT
简介
杉数求解器COPT(Cardinal Optimizer)是杉数自主研发的针对大规模优化问题的高效数学规划求解器套件,也是支撑杉数端到端供应链平台的核心组件,是目前同时具备大规模混合整数规划、线性规划(单纯形法和内点法)、半定规划、(混合整数)二阶锥规划以及(混合整数)凸二次规划和(混合整数)凸二次约束规划问题求解能力的综合性能数学规划求解器。
其实现在感觉这个 COPT 在国内挺冷门的,自己就来看看官方文档以及一些课程,同步写在这篇文档下吧。
注意事项
在写代码找到了一些很难被发现的东西,就写在这里吧。
- 对于COPT的变量,在
addVar()
中默认lb=0,rb=COPT.INFINITY
,也就是 $[0,+\infty)$
模型的求解状态
可以通过访问Model.status
查看模型求解状态,COPT.UNSTARTED
表示当前模型未开始求解。下面列出4个常见的求解状态。
模型求解状态 | 对应取值 |
---|---|
COPT.UNSTARTED |
0 |
COPT.OPTIMAL |
1 |
COPT.INFEASIBLE |
2 |
COPT.UNBOUNDED |
3 |
求解器的优化参数
通过 Model.setParam()
设置求解器的优化参数
setParam(paramname, newval)
paramname
为指定的优化参数,newval
为指定的优化参数新值。
下面有一些可能会用到的优化参数,可以随时查看全部:
TimeLimit
- 浮点数参数,优化求解的时间限制(秒)。
- 默认值 $10^{20}$
- 最小值 $0$
- 最大值 $10^{20}$
LpMethod
- 整数参数,求解线性规划问题的算法。
- 默认值 -1
- 可选值
- -1:自动选择:对于线性规划问题,选择对偶单纯形法,对于混合整数线性规划问题,选择对偶单纯形法或内点法之一。
- 1:对偶单纯形法。
- 2:内点法
- 3:直接Crossover。
- 4:并发求解(同时启动单纯形法与内点法求解)。
- 5:基于稀疏和数值范围等特征自动选择单纯形法或者内点法。
- 6:使用一阶算法(PDLP)求解。
结果获取及分析
求解完成后,若模型有最优解,则可以获取模型求解状态、决策变量最优解、目标函数最优值等信息,通过访问Model
, Val
类的成员属性获取。
Model.getVars()
获取模型中所有的决策变量,Model.getConstrs()
获取模型中所有的约束条件。
获取模型结果的主要成员属性和方法如下表所示:
信息项 | 成员属性/方法 |
---|---|
模型求解状态 | Model.status |
目标函数值 | Model.objval |
所有决策变量 | Model.getVars() |
变量名称 | Var.name , Var.getName() |
变量取值 | Var.x |
变量状态 | Var.basis |
Model.status == COPT.OPTIMAL
表示模型成功求得最优解,更多模型可能状态如下表所示:
模型求解的状态 | 含义 |
---|---|
COPT.UNSTARTED |
未开始求解 |
COPT.OPTIMAL |
成功求解 |
COPT.INFEASIBLE |
模型无解 |
COPT.UNBOUNDED |
最优值无界 |
COPT.INF_OR_UNB |
模型无解或最优值无界 |
COPT.NUMERICAL |
求解遇到数值问题 |
COPT.NODELIMIT |
节点限制前未成功求解 |
COPT.TIMEOUT |
时间限制前未成功求解 |
COPT.UNFINISHED |
求解终止。但由于数值问题,求解器无法给出结果 |
multidict()
摘要
multidict(data)
描述
将输入的字典对象拆分为键与多个字典对象并返回。
可以将输入的字典对象data
拆分为键和多个字典对象。参数data
是待拆分的字典对象,每个key
映射 n 个值,拆分后会形成 n 个新的字典对象。
例子
1 |
|
Model.addGenConstrAnd()
摘要
addGenConstrAnd(resvar, vars, name="")
描述
添加一条逻辑 and
约束,$y=x_1 \ \text{and} \ x_2 \dots\text{and} \ x_n$ 至模型中。
参量
resvar
:等式左端项 y
,二进制型
vars
:用 and
连接的变量,一般为列表类型
name
:约束名称,可选参数
例子
1 |
|
同理,添加一条逻辑 or
约束,为Model.addGenConstrOr()
,这里不再赘述。
Model.addGenConstrAbs()
摘要
addGenConstrAbs(resvar, argvar, name="")
描述
添加⼀条形如 $cy+d=|ax+b|$ 的约束到模型中。
参量
resvar
:$cy+d$ ,可取值为 Var
类、 MVar
类、 LinExpr
类 或 MLinExpr
对象。
argvar
:$ax+b$ ,可取值为 Var
类、 MVar
类、 LinExpr
类 或 MLinExpr
对象。
name
:约束名称,可选参数
Model.addGenConstrMin()
摘要
addGenConstrMin(resvar, vars, constant=None, name="")
描述
添加⼀条形如 $y=\min{x_1,x_2,\dots,x_n,c}$ 的约束到模型中。
参量
resvar
:等式左端项 y
vars
:等式右端 $\min{}$ 函数的变量
constant
:等式右端 $\min{}$ 函数中的常数项,可选参数
name
:约束名称,可选参数
添加最大值同理:Model.addGenConstrMax()
Model.addGenConstrPWL()
摘要
addGenConstrPWL(xvar, yvar, xpts, ypts, name="")
描述
添加形如 $y=f(x)$ 的约束。
参量
xvar
:x
,可取值为 Var
类对象或 MVar
类对象。
yvar
:等式左端项 y
xpts
: $\hat{x}$,分段点的横坐标,需按照取值从小到大的顺序排列,可取值为 List
类。
ypts
:$\hat{y}$,分段点的纵坐标,可取值为 List
类。
name
:约束名称,可选参数
例子
1 |
|
quicksum()
摘要
quicksum(data)
描述
快速构建表达式,求和
参量
data
:生成表达式待加项
例子
1 |
|
这里提一下这里的写法有点奇怪:列表推导式的基本语法如下:[表达式 for 元素 in 可迭代对象 if 条件]
,这种可以比较优美的写出一个列表,感觉还挺符合阅读习惯的。
Model.addGenConstrIndicator()
摘要
addGenConstrIndicator(binvar, binval, lhs, sense=None, rhs=None, type=COPT.INDICATOR_IF, name="")
描述
添加一个指定类型的指示约束(Indicator)到模型中
参量
binvar
:Indicator变量。
binval
:Indicator变量的取值,可取值为 True
或 False
。
lhs
:Indicator约束中线性约束的左端项或线性约束构建器。
sense
:Indicator约束中线性约束的类型。可选参量(其实可以省略,直接放到 lhs
上一起写))
rhs
:Indicator约束中线性约束的左端项或线性约束构建器。(其实可以省略,直接放到 lhs
上一起写)
type
:Indicator约束的类型。可选参量。有以下参数可以选:
COPT.INDICATOR_IF
(If-Then约束)COPT.INDICATOR_ONLYIF
(Only-If约束)COPT.INDICATOR_ONLYIF
(If-and-Only-If约束)
model.addVars()
摘要
addVars(*indices, lb=0.0, ub=COPT.INFINITY, obj=0.0, vtype=COPT.CONTINUOUS, nameprefix="C")
描述
添加一组变量到模型中,并返回一个 tupledict 类对象, 其键为变量的下标,值为相应的 Var 类对象。
这里的 lb,ub,vtype
与 addVar()
中一致,但是其中 *indices
和nameprefix
两个参数的设置有所区别,如下表所示:
参数 | 含义 | 描述 |
---|---|---|
*indices |
变量下标 | 2种指定方式 |
nameprefix |
变量名称前缀 | 默认C,实际名称:前缀+下标 |
参数 *indices
指定决策变量的下标,方式有如下两种:
指定决策变量的维度规模(dense的形式)
model.addVars(2)
创建2个决策变量,存储在一维数组中,形如$x[0],x[1],x[2]$model.addVars(2,3)
创建6个决策变量,存储在二维数组中,形如$x[0,0],x[0,1],…,x[1,2]$model.addVars(2,3,4)
创建24个决策变量,存储在三维数组中,形如$x[0,0,0],x[0,0,1],…,x[1,1,2]$通过提供具体的下标列表(tuplelist)(sparse的形式),tuplelist是list的子类,其中的每个元素是tuple类型:
可以看这个例子,
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!