Pyomo中线性规划接口的使用

article/2025/7/5 10:31:27

      之前在 Pyomo介绍-CSDN博客 中以饮食为例介绍过Pyomo的使用,执行以下命令:

pyomo solve --solver=glpk test_pyomo_linear_programming.py ../test_data/diet.dat

      直接执行以上命令,不便之处有以下几点:

      (1).不能直接解析python文件,不便于后期与FastAPI集成;

      (2).不支持传入额外参数;

      (3).不能直接获取需要的结果,需要额外解析results.yml

      针对以上问题,对原始代码进行了重新实现,包括:支持解析dat文件和json文件、支持输入参数、结果可直接通过print打印输出:

      1.解析dat文件的实现如下:

def parse_dat(file):# creating a model objectmodel = ConcreteModel()# load data filedata = DataPortal()data.load(filename=file)# define sets and parametersmodel.F = Set(initialize=data['F'])model.N = Set(initialize=data['N'])model.c = Param(model.F, initialize=data['c'], within=PositiveReals)model.a = Param(model.F, model.N, initialize=data['a'], within=NonNegativeReals)model.V = Param(model.F, initialize=data['V'], within=PositiveReals)model.Nmin = Param(model.N, initialize=data['Nmin'], within=NonNegativeReals, default=0.0)model.Nmax = Param(model.N, initialize=data['Nmax'], within=NonNegativeReals, default=float('inf'))model.Vmax = Param(initialize=data['Vmax'], within=PositiveReals)return model

     diet.dat文件内容如下:

param:  F:                          c     V  :="Cheeseburger"                 1.84   4.0  "Ham Sandwich"                 2.19   7.5  "Hamburger"                    1.84   3.5  "Fish Sandwich"                1.44   5.0  "Chicken Sandwich"             2.29   7.3  "Fries"                         .77   2.6  "Sausage Biscuit"              1.29   4.1  "Lowfat Milk"                   .60   8.0 "Orange Juice"                  .72  12.0 ;param Vmax := 75.0;param:  N:       Nmin   Nmax :=Cal      2000      .Carbo     350    375Protein    55      .VitA      100      .VitC      100      .Calc      100      .Iron      100      . ;param a:Cal  Carbo Protein   VitA   VitC  Calc  Iron :="Cheeseburger"               510     34     28     15      6    30    20"Ham Sandwich"               370     35     24     15     10    20    20"Hamburger"                  500     42     25      6      2    25    20"Fish Sandwich"              370     38     14      2      0    15    10"Chicken Sandwich"           400     42     31      8     15    15     8"Fries"                      220     26      3      0     15     0     2"Sausage Biscuit"            345     27     15      4      0    20    15"Lowfat Milk"                110     12      9     10      4    30     0"Orange Juice"                80     20      1      2    120     2     2 ;

      2.解析json文件的实现如下:

def parse_json(file):model = ConcreteModel()data = DataPortal()data.load(filename=file)model.F = Set(initialize=data['sets']['F'])model.N = Set(initialize=data['sets']['N'])model.c = Param(model.F, initialize=data['params']['c'], within=PositiveReals)def parse_a(model, food, nutr):return data['params']['a'][food][nutr]model.a = Param(model.F, model.N, initialize=parse_a, within=NonNegativeReals)model.V = Param(model.F, initialize=data['params']['V'], within=PositiveReals)model.Nmin = Param(model.N, initialize=data['params']['Nmin'], within=NonNegativeReals, default=0.0)def parse_Nmax(model, nutr):val = data['params']['Nmax'][nutr]return val if val != "inf" else math.inf model.Nmax = Param(model.N, initialize=parse_Nmax, within=NonNegativeReals)model.Vmax = Param(initialize=data['params']['Vmax'], within=PositiveReals)return model

      diet.json文件内容如下:

{"sets": {"F": ["Cheeseburger","Ham Sandwich","Hamburger","Fish Sandwich","Chicken Sandwich","Fries","Sausage Biscuit","Lowfat Milk","Orange Juice"],"N": ["Cal","Carbo","Protein","VitA","VitC","Calc","Iron"]},"params": {"c": {"Cheeseburger": 1.84,"Ham Sandwich": 2.19,"Hamburger": 1.84,"Fish Sandwich": 1.44,"Chicken Sandwich": 2.29,"Fries": 0.77,"Sausage Biscuit": 1.29,"Lowfat Milk": 0.6,"Orange Juice": 0.72},"V": {"Cheeseburger": 4.0,"Ham Sandwich": 7.5,"Hamburger": 3.5,"Fish Sandwich": 5.0,"Chicken Sandwich": 7.3,"Fries": 2.6,"Sausage Biscuit": 4.1,"Lowfat Milk": 8.0,"Orange Juice": 12.0},"Vmax": 75.0,"Nmin": {"Cal": 2000.0,"Carbo": 350.0,"Protein": 55.0,"VitA": 100.0,"VitC": 100.0,"Calc": 100.0,"Iron": 100.0},"Nmax": {"Cal": "inf","Carbo": 375.0,"Protein": "inf","VitA": "inf","VitC": "inf","Calc": "inf","Iron": "inf"},"a": {"Cheeseburger": {"Cal": 510.0,"Carbo": 34.0,"Protein": 28.0,"VitA": 15.0,"VitC": 6.0,"Calc": 30.0,"Iron": 20.0},"Ham Sandwich": {"Cal": 370.0,"Carbo": 35.0,"Protein": 24.0,"VitA": 15.0,"VitC": 10.0,"Calc": 20.0,"Iron": 20.0},"Hamburger": {"Cal": 500.0,"Carbo": 42.0,"Protein": 25.0,"VitA": 6.0,"VitC": 2.0,"Calc": 25.0,"Iron": 20.0},"Fish Sandwich": {"Cal": 370.0,"Carbo": 38.0,"Protein": 14.0,"VitA": 2.0,"VitC": 0.0,"Calc": 15.0,"Iron": 10.0},"Chicken Sandwich": {"Cal": 400.0,"Carbo": 42.0,"Protein": 31.0,"VitA": 8.0,"VitC": 15.0,"Calc": 15.0,"Iron": 8.0},"Fries": {"Cal": 220.0,"Carbo": 26.0,"Protein": 3.0,"VitA": 0.0,"VitC": 15.0,"Calc": 0.0,"Iron": 2.0},"Sausage Biscuit": {"Cal": 345.0,"Carbo": 27.0,"Protein": 15.0,"VitA": 4.0,"VitC": 0.0,"Calc": 20.0,"Iron": 15.0},"Lowfat Milk": {"Cal": 110.0,"Carbo": 12.0,"Protein": 9.0,"VitA": 10.0,"VitC": 4.0,"Calc": 30.0,"Iron": 0.0},"Orange Juice": {"Cal": 80.0,"Carbo": 20.0,"Protein": 1.0,"VitA": 2.0,"VitC": 120.0,"Calc": 2.0,"Iron": 2.0}}}
}

      注:pyomo对json二维参数model.a需特殊处理

      3.支持的输入参数如下:

def parse_args():parser = argparse.ArgumentParser(description="pyomo glpk diet")parser.add_argument("--file", required=True, type=str, help="*.dat file or *.json file")parser.add_argument("--number", type=int, default=5, help="must select number of food types from all food types")args = parser.parse_args()return args

      4.主体实现如下:

def main(file, number):if Path(file).suffix.lower() == ".dat":model = parse_dat(file)elif Path(file).suffix.lower() == ".json":model = parse_json(file)else:raise ValueError(colorama.Fore.RED + f"unsupported file format: {file}")# define variablesmodel.x = Var(model.F, within=NonNegativeIntegers)model.y = Var(model.F, within=Binary)# define the cost objectivemodel.cost = Objective(expr=sum(model.c[i]*model.x[i] for i in model.F), sense=minimize)# define constraintdef nutrient_rule(model, j):value = sum(model.a[i,j]*model.x[i] for i in model.F)return inequality(model.Nmin[j], value, model.Nmax[j])model.nutrient_limit = Constraint(model.N, rule=nutrient_rule)def volume_rule(model):return sum(model.V[i]*model.x[i] for i in model.F) <= model.Vmaxmodel.volume = Constraint(rule=volume_rule)def select_rule(model):return sum(model.y[i] for i in model.F) == numbermodel.select = Constraint(rule=select_rule)def linking_upper_rule(model, f):return model.x[f] <= model.y[f] * 1e6model.linking_upper = Constraint(model.F, rule=linking_upper_rule)def linking_lower_rule(model, f):return model.x[f] >= model.y[f]model.linking_lower = Constraint(model.F, rule=linking_lower_rule)# model.pprint() # print model structure# solve the modelsolver = SolverFactory('glpk')results = solver.solve(model)# print(f"results: {results}")if results.solver.termination_condition != TerminationCondition.optimal:raise ValueError(colorama.Fore.RED + f"no optimal solution was found")# print resultprint(f"total cost: {value(model.cost):.2f}")count = 0print("selected food:")for f in model.F:v = int(value(model.x[f]))if v != 0:print(f"  {f}: {v}")count += 1if count != number:raise ValueError(colorama.Fore.RED + f"solution result is wrong, number of food types does not match: {count}:{number}")print("nutrients:")for n in model.N:actual = sum(value(model.a[f,n] * model.x[f]) for f in model.F)print(f"  {n}: actual value: {actual:.2f}; boundary:[{value(model.Nmin[n])},{value(model.Nmax[n])}]")

      模型构建方式:

      (1).AbstractModel:模型定义时不包含具体数据。

      (2).ConcreteModel:模型定义时直接包含具体数据。

      DataPortal类:加载数据到Pyomo模型,支持多种文件格式,如.dat, .json, .csv, Excel等。

      建模组件:Set, Param, Var, Constraint, Objective等。

      SolverFactory类:创建求解器实例,这里使用的是开源求解器glpk。

      5.入口函数实现如下:

if __name__ == "__main__":colorama.init(autoreset=True)args = parse_args()start = time.perf_counter()main(args.file, args.number)end = time.perf_counter()print(f"elapsed time: {end-start:.2f} seconds")print(colorama.Fore.GREEN + "====== execution completed ======")

      6.执行结果如下:与之前的结果一致

      GitHub:https://github.com/fengbingchun/Python_Test


http://www.hkcw.cn/article/tiQdCwJuOI.shtml

相关文章

打开一个新的Maven工程要做的事情

新导入项目变成maven 1、检查环境配置 2.看有没有maven 3.在idea中配置maven 4、让配置文件添加到maven项目中 变成这样基本就成功了 调出service界面 可以同时选中启动多个项目 这里可以同时关闭多个项目

GNURadio实现MIMO OFDM文件传输

文章目录 前言一、理论基础二、使用方法1、打开虚拟机2、输入密码3、运行 grc 文件4、运行 三、流图及运行结果1、MIMO_simulation.grc2、MIMO_tx.grc3、MIMO_rx.grc 四、资源自取 前言 使用 GNU Radio Companion 驱动 USRP N320 实现 MIMO OFDM 收发测试。&#xff08;Ubuntu…

达梦数据库 Windows 系统安装教程

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…

【Day43】

DAY 43 复习日 作业&#xff1a; kaggle找到一个图像数据集&#xff0c;用cnn网络进行训练并且用grad-cam做可视化 进阶&#xff1a;并拆分成多个文件 今天代码见个人 Gitee仓库&#xff1a;LOVE/Python学习库https://gitee.com/love_hub/python-learning-library Github仓库&a…

贪心算法应用:装箱问题(BFD算法)详解

贪心算法应用&#xff1a;装箱问题(BFD算法)详解 1. 装箱问题与BFD算法概述 1.1 装箱问题定义 装箱问题(Bin Packing Problem)是组合优化中的经典问题&#xff0c;其定义为&#xff1a; 给定n个物品&#xff0c;每个物品有大小wᵢ (0 < wᵢ ≤ C)无限数量的箱子&#xf…

mysql(十五)

目录 子查询 1.准备工作 2--创建表格 3--插入数据 2.where 子查询单列单个数据 格式 查询 3.where 子查询单列多个数据(in) 格式 查询 使用子查询 4.from 多行多数据 格式 查询 子查询 将select的查询的返回结果 当成另外一个selet语句的内容去使用。 子查询放在()里面 注意…

Unity 环境搭建

Unity是一款游戏引擎&#xff0c;可用于开发各种类型的游戏和交互式应用程序。它由Unity Technologies开发&#xff0c;并在多个平台上运行&#xff0c;包括Windows、macOS、Linux、iOS、Android和WebGL。Unity也支持虚拟现实(VR)和增强现实(AR)技术&#xff0c;允许用户构建逼…

从0开始学习R语言--Day15--非参数检验

非参数检验 如果在进行T检验去比较两组数据差异时&#xff0c;假如数据里存在异常值&#xff0c;会把数据之间的差异拉的很大&#xff0c;影响正常的判断。那么这个时候&#xff0c;我们可以尝试用非参数检验的方式来比较数据。 假设我们有A&#xff0c;B两筐苹果&#xff0c…

NX847NX855美光固态闪存NX862NX865

NX847NX855美光固态闪存NX862NX865 美光固态闪存技术深度解析&#xff1a;NX847、NX855、NX862、NX865的多维探索 一、技术架构与核心优势 美光NX系列固态闪存的卓越性能源于其底层技术的创新突破。以G9 NAND技术为核心的产品线&#xff08;如NX865&#xff09;&#xff0c;…

秋招Day12 - 计算机网络 - UDP

说说TCP和UDP的区别&#xff1f; TCP使用无边界的字节流传输&#xff0c;可能发生拆包和粘包&#xff0c;接收方并不知道数据边界&#xff1b;UDP采用数据报传输&#xff0c;数据报之间相互独立&#xff0c;有边界。 应用场景方面&#xff0c;TCP适合对数据的可靠性要求高于速…

Baklib知识中台重塑企业知识生态

Baklib四库体系构建知识中枢 Baklib通过独创的四库体系&#xff08;显性知识库、隐性经验库、场景案例库、智能模型库&#xff09;&#xff0c;构建起企业知识管理的核心枢纽。显性知识库集中存储制度文档、产品手册等结构化信息&#xff0c;隐性经验库则通过问答社区、专家笔…

字节跳动社招面经 —— BSP驱动工程师(5)

接前一篇文章&#xff1a;字节跳动社招面经 —— BSP驱动工程师&#xff08;4&#xff09; 本文内容参考&#xff1a; ARM64架构启动流程_arm64 linux kernel 启动流程-CSDN博客 特此致谢&#xff01; 上一回讲解了“嵌入式充电站”发的一篇文章字节跳动社招面经——BSP驱动工…

超越与沉浸:关于意识觉醒的量子化生存艺术

一、现象世界的认知架构&#xff1a;从AR渲染到神经编译 人类意识系统犹如搭载生物算法的增强现实&#xff08;AR&#xff09;设备&#xff0c;每秒将4000万比特的原始感官数据&#xff0c;通过神经编译引擎压缩成40比特的认知全息图。在这个过程中&#xff1a; 海马体材质库自…

自主设计一个DDS信号发生器

DDS发生器 DDS信号发生器是直接数字频率合成技术&#xff0c;采用直接数字频率合成(Direct Digital Synthesis&#xff0c;简称DDS)技术&#xff0c;把信号发生器的频率稳定度、准确度提高到与基准频率相同的水平&#xff0c;并且可以在很宽的频率范围内进行精细的频率调节。采…

浏览器网站禁止黏贴,但是要交作业怎么快速黏贴

出现的问题&#xff1a; 写这篇博客的原因&#xff1a;学校最近要求使用 iwrite 写英语作文&#xff0c;但是浏览器禁止黏贴&#xff0c;我们自己只能手动输入&#xff0c;但是作为程序猿的我想到了一个很好的解决方案。 解决思路&#xff1a; 我们直接在浏览器的控制台的源代码…

CAN通讯协议中各种参数解析

1.各种参数缩写 2.多帧传输时间参数解析 - Sender&#xff08;左侧&#xff09; 指的是 多帧数据的发送者&#xff0c;也就是&#xff1a; ECU&#xff08;被测系统 / 响应方&#xff09; - Receiver&#xff08;右侧&#xff09; 指的是 多帧数据的接收者&#xff0c;也就是…

第十二节:第五部分:集合框架:Set集合的特点、底层原理、哈希表、去重复原理

Set系列集合特点 哈希值 HashSet集合的底层原理 HashSet集合去重复 代码 代码一&#xff1a;整体了解一下Set系列集合的特点 package com.itheima.day20_Collection_set;import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.…

deepseek原理和项目实战笔记2 -- deepseek核心架构

混合专家&#xff08;MoE&#xff09; ​​混合专家&#xff08;Mixture of Experts, MoE&#xff09;​​ 是一种机器学习模型架构&#xff0c;其核心思想是通过组合多个“专家”子模型&#xff08;通常为小型神经网络&#xff09;来处理不同输入&#xff0c;从而提高模型的容…

迈向分布式智能:解析MCP到A2A的通信范式迁移

智能体与外部世界的桥梁之言&#xff1a; 在深入探讨智能体之间的协作机制之前&#xff0c;我们有必要先厘清一个更基础的问题&#xff1a;**单个智能体如何与外部世界建立连接&#xff1f;** 这就引出了我们此前介绍过的 **MCP&#xff08;Model Context Protocol&…

TCP/IP协议精华总结pdf分享

hi &#xff0c;大家好&#xff0c;应小伙伴们的要求&#xff0c;上次分享了个人的一些学习和职场经验&#xff0c;其中网络协议PDF文档是我之前学习协议的时候总结一些精华知识&#xff0c;网络属于基本功&#xff0c;是互联网必备知识&#xff0c;我深信掌握好核心20%知识&am…