如何在Pyomo中用含*通配符的.dat表格格式声明三维参数?
解决Pyomo加载MathProg表格格式三维参数的问题
Pyomo原生DataPortal.load()对MathProg中带通配符(*)的表头表格格式支持不完善,你可以通过以下方案保留原.dat文件格式,同时正确加载数据,无需修改模型的目标函数与约束。
方案1:自定义解析.dat文件并加载数据
这是最灵活的方案,完全适配你的原.dat格式,核心思路是手动解析表格内容,再将数据注入DataPortal。
具体实现
修改你的test.py,添加自定义解析逻辑:
# test.py import pyomo.environ as pyo def parse_mathprog_table(dat_file, param_name): param_data = {} with open(dat_file, 'r') as f: lines = [line.strip() for line in f if line.strip() and not line.startswith('#')] # 定位参数表格起始行 start_line_idx = next(i for i, line in enumerate(lines) if line.startswith(f'param {param_name}:')) # 提取表头(YEAR集合元素,保留*通配符) header = [y.strip() for y in lines[start_line_idx].split(':')[1].split() if y.strip()] # 逐行解析数据 for line in lines[start_line_idx+1:]: if line.startswith(';'): break parts = line.strip().split() # 拆分dimen=2的集合元素为元组 region = tuple(parts[0].split(',')) emission = tuple(parts[1].split(',')) values = parts[2:] # 匹配表头与数值,生成三维参数键值对 for year_str, val in zip(header, values): year = tuple(year_str.split(',')) param_data[(region, emission, year)] = float(val) return param_data # 模型定义部分保持不变 model = pyo.AbstractModel() model.REGION = pyo.Set(dimen=2) model.EMISSION = pyo.Set(dimen=2) model.YEAR = pyo.Set(dimen=2) model.AnnualEmissionLimit = pyo.Param( model.REGION, model.EMISSION, model.YEAR, default=99999 ) data = pyo.DataPortal(model=model) # 先加载集合数据(假设.dat中包含REGION/EMISSION/YEAR的定义) data.load(filename='A.dat', set=('REGION', 'EMISSION', 'YEAR')) # 自定义解析参数数据并注入DataPortal param_data = parse_mathprog_table('A.dat', 'AnnualEmissionLimit') data['AnnualEmissionLimit'] = param_data # 创建实例并验证 instance = model.create_instance(data) instance.pprint()
适配调整说明
- 若你的集合元素格式不是
R1,R2这类逗号分隔形式,需修改tuple(xxx.split(','))的分隔符逻辑。 - 若
*通配符代表“所有YEAR集合元素”,可在解析后结合instance.YEAR集合,批量生成对应键值对替换*。
方案2:尝试Pyomo原生tabular格式加载(有限支持)
若你的.dat格式可微调,可尝试指定加载格式为tabular:
data.load(filename='A.dat', format='tabular')
但注意Pyomo的tabular格式对通配符的支持远不如MathProg,若原文件的*无法被识别,仍需回到方案1。
内容的提问来源于stack exchange,提问作者Themistoklis Koutsellis
相关产品推荐
相关产品推荐

