You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Scipy milp功能读取MPS格式文件?

解决Scipy MILP读取MPS文件的问题

方法1:使用第三方库mps-reader

这是专门用于读取MPS格式文件的轻量Python库,能直接将MPS数据转换成适配Scipy MILP的结构:

  1. 安装库:
pip install mps-reader
  1. 读取并转换为Scipy MILP参数:
from mps_reader import read_mps
from scipy.optimize import milp, LinearConstraint

# 读取MPS文件
mps_data = read_mps("your_problem.mps")

# 提取目标函数系数
c = mps_data["obj"]

# 构建约束矩阵与上下界
A = mps_data["A"]
lb = mps_data["lb"]
ub = mps_data["ub"]
constraints = LinearConstraint(A, lb, ub)

# 提取整数变量标记(0表示连续,1表示整数)
integrality = mps_data["int_vars"]

# 调用Scipy MILP求解
result = milp(c=c, constraints=constraints, integrality=integrality)
print(result.x)

方法2:手动解析MPS文件(无需额外依赖)

如果不想安装第三方库,可以基于MPS文件的标准格式手动解析核心内容。MPS文件主要包含NAME、ROWS、COLUMNS、RHS、BOUNDS、ENDATA等段,核心是提取目标系数、约束矩阵、变量上下界和整数标记:

from scipy.optimize import milp, LinearConstraint
import numpy as np

def read_mps_manual(file_path):
    c = []
    A_rows = []
    A_cols = []
    A_data = []
    rhs = {}
    bounds = {}
    int_vars = []
    row_types = {}
    var_names = []
    
    with open(file_path, 'r') as f:
        section = None
        for line in f:
            line = line.strip()
            if not line:
                continue
            # 识别段落
            if line.startswith('NAME'):
                section = 'NAME'
            elif line.startswith('ROWS'):
                section = 'ROWS'
            elif line.startswith('COLUMNS'):
                section = 'COLUMNS'
            elif line.startswith('RHS'):
                section = 'RHS'
            elif line.startswith('BOUNDS'):
                section = 'BOUNDS'
            elif line.startswith('ENDATA'):
                break
            
            # 处理ROWS段:记录约束类型(目标是N,约束是L/G/E)
            if section == 'ROWS':
                parts = line.split()
                row_type, row_name = parts[0], parts[1]
                row_types[row_name] = row_type
            # 处理COLUMNS段:提取目标系数和约束矩阵元素
            elif section == 'COLUMNS':
                parts = line.split()
                var_name = parts[0]
                if var_name not in var_names:
                    var_names.append(var_name)
                    int_vars.append(0)  # 默认连续变量,后续BOUNDS段标记整数
                # 处理第一个行和系数
                row1, val1 = parts[1], float(parts[2])
                if row1 == 'OBJ':
                    c.append(val1)
                else:
                    A_rows.append(list(row_types.keys()).index(row1))
                    A_cols.append(var_names.index(var_name))
                    A_data.append(val1)
                # 处理第二个行和系数(如果有)
                if len(parts) > 3:
                    row2, val2 = parts[3], float(parts[4])
                    if row2 == 'OBJ':
                        c.append(val2)
                    else:
                        A_rows.append(list(row_types.keys()).index(row2))
                        A_cols.append(var_names.index(var_name))
                        A_data.append(val2)
            # 处理RHS段:提取约束右侧值
            elif section == 'RHS':
                parts = line.split()
                rhs_name = parts[1]
                val = float(parts[2])
                rhs[rhs_name] = val
                if len(parts) >3:
                    rhs_name2 = parts[3]
                    val2 = float(parts[4])
                    rhs[rhs_name2] = val2
            # 处理BOUNDS段:提取变量上下界和整数标记
            elif section == 'BOUNDS':
                parts = line.split()
                bound_type = parts[0]
                var_name = parts[2]
                var_idx = var_names.index(var_name)
                if bound_type == 'LO':
                    bounds[var_idx] = {'lb': float(parts[3]), 'ub': bounds.get(var_idx, {}).get('ub', np.inf)}
                elif bound_type == 'UP':
                    bounds[var_idx] = {'lb': bounds.get(var_idx, {}).get('lb', -np.inf), 'ub': float(parts[3])}
                elif bound_type == 'FX':
                    bounds[var_idx] = {'lb': float(parts[3]), 'ub': float(parts[3])}
                elif bound_type == 'INT':
                    int_vars[var_idx] = 1
    
    # 构建约束矩阵
    A = np.zeros((len(row_types)-1, len(var_names)))  # 减去OBJ行
    for r, c_idx, val in zip(A_rows, A_cols, A_data):
        A[r, c_idx] = val
    
    # 构建约束上下界
    lb = []
    ub = []
    for row_name in row_types:
        if row_name == 'OBJ':
            continue
        rt = row_types[row_name]
        rh = rhs.get(row_name, 0)
        if rt == 'L':
            lb.append(-np.inf)
            ub.append(rh)
        elif rt == 'G':
            lb.append(rh)
            ub.append(np.inf)
        elif rt == 'E':
            lb.append(rh)
            ub.append(rh)
    
    # 构建变量上下界(默认-∞到∞)
    var_lb = [-np.inf]*len(var_names)
    var_ub = [np.inf]*len(var_names)
    for idx, b in bounds.items():
        var_lb[idx] = b['lb']
        var_ub[idx] = b['ub']
    
    return {
        'c': np.array(c),
        'A': A,
        'constraint_lb': np.array(lb),
        'constraint_ub': np.array(ub),
        'var_lb': np.array(var_lb),
        'var_ub': np.array(var_ub),
        'integrality': np.array(int_vars)
    }

# 使用示例
mps_data = read_mps_manual("your_problem.mps")
constraints = LinearConstraint(mps_data['A'], mps_data['constraint_lb'], mps_data['constraint_ub'])
result = milp(
    c=mps_data['c'],
    constraints=constraints,
    integrality=mps_data['integrality'],
    bounds=(mps_data['var_lb'], mps_data['var_ub'])
)
print(result.x)

注:手动解析代码仅适配MPS基础格式,复杂扩展格式(如分段约束、特殊变量类型)需额外调整。


内容的提问来源于stack exchange,提问作者Simd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 14:30:25