求平衡输入输出比例的配方工厂数量计算算法
你遇到的问题本质是物料平衡约束下的整数规划问题,核心是找到满足所有产物完全消耗(或近似消耗)的最小整数工厂数量,下面分情况给出具体解法:
一、存在完美比例的精确解法
当配方之间能通过整数倍组合实现完全物料平衡时,可通过以下步骤求解:
1. 消除分数系数
先把所有配方的物料系数转为整数,避免浮点运算误差。比如你的水分离配方,3台的总产出是20单位H₂和30单位O₂,可将其作为一个“批量配方”来计算,后续再还原为单台数量。
2. 建立线性平衡方程
针对需要完全消耗的物料,列出方程。比如你的例子中,要让H₂完全被氨合成消耗:
(20/3) * x = 10 * y
化简后得到 2x = 3y,最小正整数解是x=3(水分离工厂数)、y=2(氨合成工厂数),此时H₂净流量为0,刚好完全消耗。
3. 多元配方的线性方程组求解
如果有多个配方和物料,可将问题转化为多元线性方程组,找非负整数解:
- 用线性代数方法先求解实数解,再通过辗转相除法(二元情况)或整数线性规划(多元情况)找到最小整数解。
二、无完美比例的近似解法
当无法找到完全平衡的整数解时,可采用以下方式找到最优近似解:
1. 优先保证关键物料平衡
先针对核心物料(比如你的例子中的H₂)计算近似整数解,再调整数量使过剩尽可能小。比如如果方程是(20/3)x = 11y,无整数解,可试算找到最接近平衡的组合:
- x=10时,H₂产出≈66.67;y=6时,H₂消耗66,过剩仅0.67,是较优的近似解。
2. 整数线性规划(ILP)
对于复杂场景,可定义目标函数(比如最小化所有物料的过剩总量),用ILP求解器找到最优整数解。常见的开源求解器有GLPK、Coin-OR,JavaScript中也有simplex-js这类工具可以先求实数解再调整为整数。
3. 启发式调整
先按实数解向上取整得到初始工厂数,再逐步调整部分配方的数量,减少过剩物料的总量。比如初始取整后某物料过剩较多,可增加消耗该物料的配方数量,直到过剩在可接受范围内。
三、代码实现思路(简化版)
以你的例子为例,先处理分数系数,再求解二元方程:
const waterSeparation = { name: 'water separation', h2: 20/3, o2: 10 }; const ammonia = { name: "ammonia", h2: -10, n2: -10, nh3: 10, }; // 求解H₂平衡的最小整数解 function findMinCounts() { // 方程化简后为 2x = 3y,取最小正整数解 return { waterSeparation: 3, ammonia: 2 }; } // 验证结果 const counts = findMinCounts(); const results = {}; // 计算水分离的物料变化 Object.keys(waterSeparation).forEach(key => { if (key === 'name') return; results[key] = (results[key] || 0) + waterSeparation[key] * counts.waterSeparation; }); // 计算氨合成的物料变化 Object.keys(ammonia).forEach(key => { if (key === 'name') return; results[key] = (results[key] || 0) + ammonia[key] * counts.ammonia; }); console.log(results); // { h2: 0, o2: 30, n2: -20, nh3: 20 }
这个结果中H₂完全消耗,O₂是过剩产物(如果需要消耗O₂,可加入对应的配方继续平衡)。
内容的提问来源于stack exchange,提问作者whiterook6

