运筹系列76:mps文件的读取与展示

Posted IE06

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了运筹系列76:mps文件的读取与展示相关的知识,希望对你有一定的参考价值。

1. mps文件规则

通过一个例子来认识:
max x1 + 2 x2 + 3 x3 + x4
s.t. − x1 + x2 + x3 + 10 x4 ≤ 20
x1 − 3 x2 + x3 ≤ 30
x2 - 3.5 x4 = 0
0 ≤ x1 ≤ 40,x2 ≥ 0,x3 ≥ 0,2 ≤ x4 ≤3

对应的mps文件为:

NAME       MindOptExample  #NAME表示这个优化模型的名字,可不写内容
ROWS        #ROWS定义各行名字,包括目标函数与约束条件
 N  obj       #N表示自由行,obj是对目标函数的命名,可任意取名
 L  c1          #L表示该行小于等于, c1是对该行的命名,可任意取名
 L  c2      
 E  c3          #E表示该行等于
COLUMNS  #COLUMS定义各列名字
    x1               obj                 -1   c1                  -1
    x1                c2                   1  
    x2                obj                 -2   c1                   1
    x2                c2                  -3   c3                   1
    x3                obj                 -3   c1                   1
    x3                c2                   1    
    MARK0000  'MARKER'             'INTORG'
    x4                obj                 -1   c1                  10
    x4                c3                -3.5
    MARK0001  'MARKER'             'INTEND'
RHS  #RHS定义约束条件等号右边的值
    rhs               c1                  20   c2                  30   	            
BOUNDS  #BOUNDS定义决策变量的上界或下界
 UP bnd       x1                  40  #UP 表示上界
 LO bnd       x4                   2  #LO 表示下界
 UP bnd       x4                   3
ENDATA   #ENDATA表示MPS文件结束

2. 文件解析

使用pysmps解析文件,例如上面的例子的结果是:

前四行是命名行,分别是:项目名、目标函数名、行名(约束条件名)、列名(变量名)
接下来两行是变量类型和约束条件类型
接下来两行是目标函数和约束条件的参数
接下来两行是rhs列表和rhs对应的值
接下来两行是bound列表和bound对应的值
解析函数为:

import re
import numpy as np
from pysmps import smps_loader as smps


def displayMps(file_path, dis_name = True, dis_bound = True, dis_integral = True):
    m = smps.load_mps(file_path)
    # variable names
    obj_type = 'Min '
    ss = []
    xs = [symbols('%s_%s' % tuple(re.split('(\\d+)', v)[:2])) for v in  m[3]]

    # objective
    cons = m[6]
    if np.all(m[6]<=0):
        obj_type = 'Max '
        cons = -m[6]
    obj = simplify(sum(xs*cons))
    ss.append(Math(latex(dis_name*('%s: '%m[1]))+latex(obj_type)+latex(obj)))

    # constraints
    rhs = list(m[9].values())[0]
    for i in range(len(m[2])):
        if m[5][i]=='L':
            eq = simplify(sum(xs*m[7][i])) <= rhs[i]
        elif m[5][i]=='G':
            eq = simplify(sum(xs*m[7][i])) >= rhs[i]
        elif m[5][i]=='E':
            eq = Eq(simplify(sum(xs*m[7][i])), rhs[i])
        ss.append(Math(latex(dis_name*('%s: '%m[2][i]))+latex(eq)))

    # bounds
    if dis_bound:
        bnd_list = []
        bnd=list(m[11].values())[0]
        for j in range(len(m[3])):
            if bnd['LO'][j]>0:
                eq = xs[j] >= bnd['LO'][j]
                bnd_list.append(latex(eq))
            if bnd['UP'][j]!=np.inf:
                eq = xs[j] <= bnd['UP'][j]
                bnd_list.append(latex(eq))
        ss.append(Math(','.join(bnd_list)))

    # integral
    if dis_integral:
        ids = np.where(np.array(m[4])=='integral')[0]
        if len(ids)>0:
            ss.append(Math(''+','.join([latex(v) for v in list(np.array(xs)[ids])])+'\\in  Z'))
    
    for s in ss:
        display(s)
        
    return "NAME:%s, ROWS:%d, COLUMNS:%d" % (m[0], len(m[1]),len(m[2]))

displayMps('../CLionProjects/test2/1.mps')

解析结果如下:

以上是关于运筹系列76:mps文件的读取与展示的主要内容,如果未能解决你的问题,请参考以下文章

运筹系列76:mps文件的读取与展示

运筹系列71:CBC和CLP的python接口Cylp

运筹系列68:TSP问题Held-Karp下界的julia实现

19.scala的类型上下界

与网络流相关算法

了解上界和下界?在 Java 泛型中