HiGHS开源求解器Pyhton调用方法

HiGHS开源求解器Pyhton调用方法目前发现 HiGHS 这一新的完全开源的求解器 在实际使用过程中比 SCIP 性能要好 但调用起来较为不方便 一是因为官方的教学文档没有写完 二是便捷的方法很少 例如 quicksum expr 表达式等

1.引言

目前发现HiGHS这一新的完全开源的求解器,在实际使用过程中比SCIP性能要好,但调用起来较为不方便,一是因为官方的教学文档没有写完,二是便捷的方法很少,例如quicksum、expr表达式等。

那么在研究实际问题中,我们更关注求解时间,也就可以手动排除一些障碍,并且经常尝试一些新的东西。网络上除官方文档外对这个求解器的调用方法的相关描述几乎没有,所以我就有幸成为第一批吃螃蟹的人了。

2.HiGHS官网

HiGHS的官方网站就放在这里了,具体的简介可以到官网里面去查:HiGHS - High-performance parallel linear optimization software (ed.ac.uk)

3.进入正题

3.1HiGHS安装

基于Python语言的好处是可以使用pip命令安装HiGHS。因此之间在Python环境中:

pip install highspy

那么highspy就安装到您的环境中了,并且由于HiGHS是完全开源的,因此不用担心自己下错版本。

3.2HiGHS调用

我们首先给出官方文档中的例子:

首先导入包。

import highspy import numpy as np

然后是初始化highspy的方法

h = highspy.Highs()

第一个例子给出的是读取mps模型文件,读取其他类型文件(.lp)也一样,改后缀即可:

import highspy h = highspy.Highs() filename = 'model.mps' h.readModel(filename) h.run() print('Model ', filename, ' has status ', h.getModelStatus())

官方的第二个例子是建立模型方法:

minimize f = x0 + x1

subject to

                x1 <= 7

                5 <= x0 + 2x1 <= 15

                6 <= 3x0 + 2x1

                0 <= x0 <= 4; 1 <= x1

给出的代码如下:

#此处获取HighsInf定义的极大值。 inf = highspy.kHighsInf #定义两个变量x1、x2,先使用的标识符和使用的常量。 # Define two variables, first using identifiers for the bound values, # and then using constants lower = 0#下界>=0 upper = 4#上界<=4 h.addVar(lower, upper)#添加变量,第一个参数为变量的最小值,第二个参数为变量的最大值 h.addVar(1, inf)#同理 # Define the objective coefficients (costs) of the two variables, # identifying the variable by index, and changing its cost from the # default value of zero #定义目标函数 cost = 1#目标函数前面的系数 h.changeColCost(0, cost)#函数的第一个参数为第几个变量的系数,第二个参数为系数值。 h.changeColCost(1, 1) #定义约束 # Define constraints for the model # The first constraint (x1<=7) has only one nonzero coefficient, # identified by variable index 1 and value 1 num_nz = 1 index = 1 value = 1 h.addRow(-inf, 7, num_nz, index, value)#第一个参数为下界,第二个参数为上界,第三个参数为约束中的变量个数,第四个参数为约束中变量的索引,即第几个添加进入的变量,是一个list。value为系数值list。 # The second constraint (5 <= x0 + 2x1 <= 15) has two nonzero # coefficients, so arrays of indices and values are required num_nz = 2 index = np.array([0, 1]) value = np.array([1, 2]) h.addRow(5, 15, num_nz, index, value) # The final constraint (6 <= 3x0 + 2x1) has the same indices but # different values num_nz = 2 value = np.array([3, 2]) h.addRow(6, inf, num_nz, index, value) # Access LP lp = h.getLp() num_nz = h.getNumNz() print('LP has ', lp.num_col_, ' columns', lp.num_row_, ' rows and ', num_nz, ' nonzeros') #调用h.run()求解模型 h.run()

相信看到这大家已经明白了,HiGHS确实有种新的感觉,因为面向用户太差了,但速度快且开源这一优点太棒了。上述代码中模型的约束和变量是一个一个添加的,可能大家觉得这样很麻烦,官方给出了一次添加多行多列的方法:

inf = highspy.kHighsInf#定义极大值 # The constraint matrix is defined with the rows below, but parameters # for an empty (column-wise) matrix must be passed cost = np.array([1, 1], dtype=np.double)#定义目标函数系数 lower = np.array([0, 1], dtype=np.double)#定义约束的下界 upper = np.array([4, inf], dtype=np.double)#定义约束的上界 num_nz = 0 start = 0 index = 0 value = 0 h.addCols(2, cost, lower, upper, num_nz, start, index, value)#第一个参数表示添加两列,第二个参数表示添加的cost系数,第三、四个参数表示变量的上下界,第五、六、七、八约束必须得跳过,因为就很无奈,定义这个列的时候还没有行。 #所以这个地方吐槽一下,明明有h.addVars()可以用,你用这个addCols()的好处就只有把目标函数定义了。 #然后添加约束行 # Add the rows, with the constraint matrix row-wise lower = np.array([-inf, 5, 6], dtype=np.double)#三个约束的上下界 upper = np.array([7, 15, inf], dtype=np.double) num_nz = 5 start = np.array([0, 1, 3]) index = np.array([1, 0, 1, 0, 1]) value = np.array([1, 1, 2, 3, 2], dtype=np.double) #这个地方太抽象了,为啥要这么搞数据接口呢,直接就在这放了个稀疏化表达方式,太难用了。 #第一个参数表示约束数量,第二、三个参数表示约束的上下界,第四个参数表示三个约束中用到的变量个数,第四个参数表示每行的起始位置,要根据这个值在index和value中找。index和value就不多解释了。 h.addRows(3, lower, upper, num_nz, start, index, value)

看到这已经让人很破防了,可能HiGHS自己也看不下去了,于是搞了个《Pass a model》,其意思大概就是给用户提供了个模板,然后直接修改这个模板的参数就完成了建模,有点没头没脑的大家一般也用不到。

#调用求解器求解 h.run() #输出各种结果。 solution = h.getSolution() basis = h.getBasis() info = h.getInfo() model_status = h.getModelStatus() print('Model status = ', h.modelStatusToString(model_status)) print() print('Optimal objective = ', info.objective_function_value) print('Iteration count = ', info.simplex_iteration_count) print('Primal solution status = ', h.solutionStatusToString(info.primal_solution_status)) print('Dual solution status = ', h.solutionStatusToString(info.dual_solution_status)) print('Basis validity = ', h.basisValidityToString(info.basis_validity))

3.3心得体会(轻松一下)

开源:很棒

求解时间:很快

使用感受:心态爆炸

如果你有耐心看到这里,那么感谢您。作为回礼,我将展示一些高级的HiGHS的用法,目前文档中没有写完,好像也没有写的计划。

4.HiGHS使用方法初探

4.1HiGHS特点

在官方给出的文档中我们可以看出,与Cplex、COPT、SCIP等其他求解器不同的是,HiGHS求解器在整个建模过程中仅仅维护了一个模型。在此过程中我们也可以发现一些问题和不足:

  • 变量名称无法定义
  • 变量无法直接调用,也就无法通过表达式等方式添加到模型中。
  • 模型建立的时候,变量作为了一个列进行添加,通俗来讲,仅能通过添加的次序作为变量的索引建立模型。
  • 无法定义整数型、布尔型等类型的变量。

4.2解决方法

对于以上问题,笔者给出了自己的解决方法,如下所示。

首先,应当完善变量的索引值列表,手动记录:

x={}#x变量索引字典,可添加类似x[i,j]状态的变量。 vdx=0#当前变量的数量、也可以是新添加变量的添加次序索引 A,B=4,6#比如添加一个4x6的二维变量X[i][k] for i in range(A): for k in range(B): h.addVar(0,1)#添加一个0~1的连续变量 x[i,k]=vdx vdx+=1 #那么此时,x[i,k]中就记录了vdx的值,即变量的索引值。

当获取了索引之后,我们便可以更方便的修改所有x变量的类型,需要调用changeColsIntegrality()函数,这个函数还是我用help(h)查找类中方法得到的,甚至没有用法。

#修改所有x变量的类型由连续型变为整数型 h.changeColsIntegrality(len(x),[x[i] for i in x],[1 for i in range(len(x))]) #其中第一个参数为改变类型的变量的数量,第二个参数为变量的索引,第三个参数为变量的类型代码。

这第三个参数的变量类型代码我也在其类里面找到了,如下所示:

#可使用如下命令看到内部的变量类型。 help(highspy.highs_bindings.HighsVarType)

连续变量:kContinuous = <HighsVarType.kContinuous: 0>
整型变量:kInteger = <HighsVarType.kInteger: 1>
半连续变量:kSemiContinuous = <HighsVarType.kSemiContinuous: 2>
半整型变量:kSemiInteger = <HighsVarType.kSemiInteger: 3>

怕大家也和我一样不太懂这个半是什么意思,给出IBM CPLEX的解释:

给出IBM的解释:

半连续变量:

何为半连续变量? 定义半连续变量。 半连续变量是缺省情况下可以采用值 0 或任何介于其半连续下限 (sclb) 与其上限 (ub) 之间的值的变量。 半连续下限 (sclb) 必须是有限值。 上限 (ub) 不必是有限值。 半连续下限 (sclb) 必须大于或等于 0。

当有了索引列表,我们就可以使用表达式的方法了:

#我们假设还定义了另一个变量y,要实现x[i]+y[j]<=10这一表达式。 lsh=[]#表达式的索引 for i in x: if x[i]%2==1:#假定的条件,取奇数索引建立模型。 lsh+=[x[i]] for i in y: if y[i]%2==0:#同理,但已经是不同的变量相加了。 lsh+=[y[i]] value=[1 for i in range(len(lsh))]#随便定义一下约束里面的系数。 #此处调用 h.addRow(inf,10,len(lsh),lsh,value)#前两个参数就不多解释了,第三个参数是约束中的变量数量,第四个参数是变量索引,第五个参数是变量前的系数。

如上所示,再加上for循环逐行添加,是不是用起来更舒服了呢?

今天的文章 HiGHS开源求解器Pyhton调用方法分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2025-01-07 17:11
下一篇 2025-01-07 17:06

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/104255.html