规划求解器SCIP在jupyter上的使用教程
- 打开Anaconda Prompt, 安装SCIP求解器
pip install pyscipopt
- 再从Anaconda Prompt终端打开jupyter(此终端窗口勿关闭)
准备求解以下示例:
*pyscipopt的接口要求目标函数中不能包含非线性项
Maximize
obj: x1 + 2 x2 + 3 x3 + x4
Subject To
c1: - x1 + x2 + x3 + 10 x4 <= 20
c2: x1 - 3 x2 + x3 <= 30
c3: x2 - 3.5 x4 = 0
Bounds
0 <= x1 <= 40
2 <= x4 <= 3
General
x4
End
代码如下:
from pyscipopt import Model
model = Model("Example") # model name is optional
#添加变量
x1 = model.addVar("x1")
x2 = model.addVar("x2")
x3 = model.addVar("x3")
x4 = model.addVar("x4", vtype="INTEGER") #变量类型为整数
#添加目标函数
model.setObjective(x1 + 2*x2 + 3*x3 + x4, 'maximize') #默认minimize
#添加约束
model.addCons(- x1 + x2 + x3 + 10*x4 <= 20)
model.addCons(x1 - 3*x2 + x3 <= 30)
model.addCons(x2 - 3.5*x4 == 0)
model.addCons(0 <= (x1 <= 40)) #变量范围的写法→右边加括号
model.addCons(2 <=( x4 <= 3))
#求最优解
model.optimize()
sol = model.getBestSol() #获取最优解
objVal=model.getObjVal(model) #获取最优目标函数值
print("x1: {}".format(sol[x1]))
print("x2: {}".format(sol[x2]))
print("x3: {}".format(sol[x3]))
print("x4: {}".format(sol[x4]))
print("objVal: {}".format(objVal))
打印结果如下:
3. 最后,可从打开jupyter notebook的Anaconda Prompt终端中查看求解过程,包括剪枝等。
4. Tips:
a. SCIP支持直接!写进多个目标函数!相当于多目标求解,这点可以说相当精彩啊,很多求解器都做不到。
b. 当求解过程需要同时用到X[i, j]与X[i]时,用字典对X={}进行初始化是不行的,因为只能操作X[i, j]而无法操作X[i],但用数组array对其赋初始值0又不靠谱,这种情况下官方文档没有相关示例,经过探索,发现可以用dataframe承载一个矩阵式的变量,然后对此dataframe操作就比较方便了,如下:
X = pd.DataFrame(index=range(len(bu_list)), columns=range(T))
for height in range(len(bu_list)):
for length in range(T):
X.loc[height, length] = model.addVar(vtype='B', name='x_{}_{}'.format(height, length))
- 踩坑:
a. SCIP不支持非凸优化(比如约束中的多个变量连乘)
b. 同理不支持绝对值操作,如下图:
要改成两个线性约束:
否则就会造成求解器随意破坏约束的情况,太坑了…
以上。
转载请附出处,谢谢。