将一个简化模型表述为线性规划问题

编程语言 2026-07-09

我在尝试把下面这个简单模型实现为线性规划问题,期待知道我是否有遗漏。

考虑以下简单模型,包含三个工厂A、B、C,生产产品foo和 bar。

foo bar
A 80 20
B 20 40
C 10 5

我们要使foo和 bar系统的总产量分别增加50和 25。

工厂不能降低产出。

每个工厂的foo与 bar的比例是固定的(例如工厂A 每产出20单位bar,就产出80单位foo)。

我们希望将各工厂产出的相对变化降至最低。

如果我理解正确,这个问题可以用线性规划来解决。

目标函数是 : minimize z = sum(x_i^*/w_i),其中 x_i^* 是每个工厂的新产出,w_i 是每个工厂的基线产出。注意 x_i^* 是变量,而 w_i 是固定的。

接下来,要在 linprog 中实现这个目标函数,我们需要把目标函数改写为 c^t @ x 的形式:

minimize z = sum(1/w_i * x_i^*) ,such that c^t = [1/w_a, 1/w_b, 1/w_c], and x = [x_a^*, x_b^*, x_c^*]

此外,我们需要添加一个约束:新的产出是 foo = 50bar = 25。为此,我们对初始表进行转置,得到形式:

array([[80, 20, 10],[20, 40, 5]]) @ [x_a^*, x_b^*, x_c^*] = [50, 25]

请注意,由于需要严格匹配这个新产出,我们使用 A_eqb_eq(而不是 A_ubb_ub)。

此外,请注意,我们无需定义比例 foobar 固定的约束,因为决策变量关心每个工厂的总产出,而不是按产品单独的产出。

最后,通过将约束表述为产出变化量(而不是 foo = 110 + 50 = 160bar = 65+ 25 = 90 的新产出),可以利用 linprog 对决策变量非负性所设定的默认上下界。换句话说,我们不需要显式添加工厂不能降低产出的约束。

我相信这就包括所有需要的内容:

import numpy as np
import pandas as pd
from scipy.optimize import linprog

# Toy model.
df_base = pd.DataFrame([[80, 20], [20, 40], [10, 5]])

# Additional output of foo and bar.
df_scen_s = pd.DataFrame(np.array([50, 25]))

# Get total output per factory: w1, w2, w3.
df_base_s = df_base.sum(axis=1)

# Get coefficients: 1/w1, 1/w2, 1/w3.
df_base_s_inv = 1 / df_base_s

# Linear objective function.
ar_c = df_base_s_inv.values

# Constraint to match new output exactly.
ar_base = df_base.T.values
ar_scen_s = df_scen_s.values

result = linprog(ar_c, A_eq=ar_base, b_eq=ar_scen_s)

print(result.x)

>>> [0.53571429 0.35714286 0.        ]

从中可以看出,工厂A 的产出提高了54%,工厂B 提高了36%,而工厂C 不受影响(产出保持在100%)。

如果把这个toy model转换成线性规划问题的理解是正确的,我观察到如下几点:

看起来产出变化并没有在工厂之间分配(也就是说工厂C 不受影响)。如果我想要让变化在工厂之间分配,我认为需要修改目标函数,但我暂时还不清楚该如何做。

我怀疑这是否真的可以通过线性规划实现,还是需要使用如二次规划等其他方法,例如目标函数可能类似于 minimize z = sum(((x_i^*-w_i)/w_i)^2)),即最小二乘和。

编辑1:

我对目标函数的直觉如下:在绝对变化量方面,工厂A 受影响最小,其次是B,最后是C。换句话说,如果把总产出增加10个单位,A的产出将增加10%,B增加17%,C增加67%。这将使我们更偏向先提升工厂A 的产出,再提升B,最后是C。

为了检验直觉,我把目标函数改为 c^t @ x = [1, 1, 1] @ x。换言之,现在每个工厂的产出变化同样“糟糕”。结果没有改变。

接着,我对工厂A 的产出进行了强烈惩罚:c^t @ x = [10, 1, 1] @ x。结果变为 [0, 0, 5],也就是说工厂A 和B 仍保持在100%,而工厂C 的产出增加了500%。

这个新目标函数可以这样理解。假设不是要最小化各工厂的相对变化,而是要最小化总成本,其中工厂A 的运行成本非常高,工厂B 和C 同样便宜。这样,我们就更倾向把所有增加的产出分配给工厂C。

此外,若理解正确,这也凸显了线性规划在解空间的顶点处寻找解的特性;通过对工厂A 施以重惩罚,我迫使求解器跳到另一个顶点。

此外,在这种情况下,目标函数似乎相当稳健——对目标系数的改动似乎对结果影响不大,只有在极端情况下才会影响。

编辑2:

看来我对目标的理解需要修正。也就是说,在我最初的解释中,x_i^* 是每个工厂的新产出。

然而,经过进一步分析,情况似乎并非如此。相反,x_i^* 描述了每个工厂的相对变化(算法的输出将 x_i^* 表示为分数)。

因此,系数变得多余,因为相对变化已经通过 x_i^* 表达。

更进一步地,应该把 c^t 改成 [1, 1, 1]

解决方案

我在这里假设必须使foo和 bar的产出分别恰好为160和 90。如果你能容忍其中一个产出过剩,那情况会不同。

要以不同方式分配这些变化,你需要问自己哪种分配方式会让你满意。这将指引你对模型进行必要的修改。

一种可能是要求三家工厂的相对变化(百分比增量)相同。这在理论上不可行;如果三家工厂的产量都提高45.45% 来达到foo的配额,就会导致bar的产量过剩。

另一种可能是尽量最小化任一工厂的最高百分比增幅与最低百分比增幅之间的差异。假设变量是各工厂的增量百分比,你可以再增加两个变量(记为 $x_{min}$ 与 $x_{max}$),设置约束使每个工厂的增量变量都 >= $x_{min}$ 且 <= $x_{max}$,并把目标改为最小化 $x_{max} - x_{min}$。该版本的解使工厂产量分别乘以1.48387、1.32258、1.48387,且最增幅与最小增幅之间的差距为16%。

还有其他可能性,同样取决于你对在各工厂之间分配变化时设定的「公平」或「良好」标准。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章