【运筹学】什么是优化问题:从现实决策到数学模型

优化问题

  • 前言
  • [1. 现实决策怎样变成优化问题](#1. 现实决策怎样变成优化问题)
    • [1.1 从小店的生产安排说起](#1.1 从小店的生产安排说起)
    • [1.2 什么情况下需要优化](#1.2 什么情况下需要优化)
  • [2. 建模前,先把问题说清楚](#2. 建模前,先把问题说清楚)
    • [2.1 哪些信息已知,哪些需要决定](#2.1 哪些信息已知,哪些需要决定)
    • [2.2 如何确定优化目标与业务边界](#2.2 如何确定优化目标与业务边界)
    • [2.3 为简化问题,需要作出哪些假设](#2.3 为简化问题,需要作出哪些假设)
  • [3. 把生产计划写成数学模型](#3. 把生产计划写成数学模型)
    • [3.1 整理数据并定义变量](#3.1 整理数据并定义变量)
    • [3.2 写出利润与资源消耗的表达式](#3.2 写出利润与资源消耗的表达式)
    • [3.3 组成完整模型,并逐项检查含义](#3.3 组成完整模型,并逐项检查含义)
  • [4. 从模型回到现实决策](#4. 从模型回到现实决策)
    • [4.1 什么是可行方案与最优方案](#4.1 什么是可行方案与最优方案)
    • [4.2 如何解释求解结果](#4.2 如何解释求解结果)
    • [4.3 数据和假设变化时,结论为何可能改变](#4.3 数据和假设变化时,结论为何可能改变)
  • 后记
  • [附录:用 Python 求解生产计划](#附录:用 Python 求解生产计划)

前言

生产多少产品、怎样安排配送、如何分配有限的工作时间,都是现实中的决策问题。我们通常希望找到更好的方案,但更好需要有明确的衡量标准,方案也必须满足资源和业务要求。把这些信息整理清楚,才能进一步讨论如何寻找最合适的选择。

在上一篇 《目标函数、决策变量和约束条件分别是什么?》 中,我们认识了优化模型的三个基本要素。本文沿用这些概念,以一家小店安排面包和蛋糕的生产为例,重点介绍如何从现实描述出发,逐步建立一个优化问题,以及得到模型结果后该怎样理解它。

1. 现实决策怎样变成优化问题

1.1 从小店的生产安排说起

假设一家小店每天制作面包和蛋糕。店主需要决定两种产品各做多少份:做得太少,可能错过销售机会;做得太多,又会占用原料和制作时间。两种产品的单份利润和资源消耗也不同,因此不能只比较哪一种更赚钱,就决定全部生产哪一种。

我们可以先把店主面临的问题表述为:在现有原料、工作时间和预计销量的范围内,怎样安排面包与蛋糕的生产数量,才能使当天的总利润尽可能高? 这句话明确了要作出的选择、衡量方案的标准,以及选择受到的限制。不同的生产数量组合,就是不同的备选方案。

1.2 什么情况下需要优化

当一个问题存在可以选择的方案,并且我们能说清楚怎样评价方案的好坏时,就可以考虑用优化的方法分析 。

如果还存在必须遵守的资源或业务限制,就需要先找出满足这些限制的方案,再从中寻找表现最好的方案。例如,小店即使想获得更高利润,也不能使用超过库存的原料,或安排超过当天可用工作时间的制作任务。一个利润看起来很高、却无法实际完成的生产计划,并不是可接受的答案。

不过,并非所有想做得更好的想法都能立即写成优化问题。如果店主尚未确定要提高利润、减少浪费,还是缩短制作时间,就无法判断哪个方案更好;如果原料用量和可用工时都不清楚,也难以判断方案能否实施。因此,建立优化问题的第一步,是把决策、评价标准和现实边界说清楚。下一节,我们将沿着这三个方向整理小店的具体信息。

2. 建模前,先把问题说清楚

上一节把小店的问题概括为:安排面包和蛋糕的生产数量,使当天总利润尽可能高。要把这句话写成数学模型,还需要明确哪些信息是已知的、哪些量由店主决定,以及模型暂时忽略哪些现实细节。

2.1 哪些信息已知,哪些需要决定

先看小店每天需要掌握的数据。每种产品的单份利润、原料用量和制作时间,可以根据配方与经营记录估计;当天可用的原料、工作时间和预计销量,也需要提前确定。这些数据在建立当天的模型时被视为已知参数。

店主真正需要决定的是面包和蛋糕各生产多少份。我们暂时把这两个数量记为 x x x 和 y y y。它们的具体取值尚未确定,会随着生产方案变化,因此是决策变量。

2.2 如何确定优化目标与业务边界

同一份生产计划,可以从不同角度评价:总利润是否更高、剩余原料是否更少、制作任务是否能更早完成。优化目标,就是我们希望通过调整方案尽可能改善的评价标准。为了让模型能够比较方案,店主需要先确定这次最关心什么。本文选择使当天总利润最大作为目标。

接下来要列出方案必须满足的条件。业务边界,就是现实中限制方案选择范围的条件,例如资源数量、工作时间、销量上限和生产规则。小店不能消耗超过库存的原料,也不能安排超过当天工作时间的制作任务;如果预计销量有限,生产数量还应受到销量上限约束。此外,面包和蛋糕不能生产负数份,实际制作时也通常需要按整数份安排。

目标和限制回答的是两个不同的问题:总利润用于比较哪个可实施方案更好;资源、销量等限制用于判断方案能否实施。

2.3 为简化问题,需要作出哪些假设

现实经营中,销量可能波动,原料也可能有损耗。模型不必一开始就包含所有细节,但需要说明当前版本如何处理它们。为了先看清建模过程,本文作出以下假设:

  • 单份产品的利润、原料用量和制作时间在当天保持不变;
  • 两种产品使用同一类有限原料,制作时间从同一份可用工时中扣除;
  • 预计销量作为当天能够售出的数量上限;
  • 暂不考虑原料损耗、批量制作带来的效率变化,以及卖不完的产品如何处理。

这些假设决定了模型能解释到什么程度。例如,若实际销量远低于预计值,即使求出了模型中的最优生产数量,店主也可能无法获得模型计算的利润。假设不是对现实的保证,而是这次分析采用的边界。

整理到这里,我们已经知道要决定什么、依据什么比较方案,以及哪些条件必须满足。下一节就可以为这些信息填入具体数据,写出完整的数学模型。

3. 把生产计划写成数学模型

前面已经明确了小店的问题边界。现在给出一组具体数据,假设:

项目 面包 蛋糕
单份利润 3 元 5 元
每份面粉用量 1 千克 2 千克
每份制作时间 1 小时 2 小时
每日预计销量 40 份 30 份

小店每天有 50 千克面粉和 40 小时制作时间可用。下面把这些业务信息逐步转换为数学表达式。

3.1 整理数据并定义变量

设:

  • x x x:每天生产的面包数量;
  • y y y:每天生产的蛋糕数量。

这里的 x x x 和 y y y 就是决策变量。由于产品需要按份生产,它们通常取非负整数:

x ≥ 0 , y ≥ 0 x\geq 0,\qquad y\geq 0 x≥0,y≥0

如果暂时只研究连续模型,也可以先把它们看成非负实数。但在实际生产中,最终还要结合产品是否允许拆分来确定变量类型。

3.2 写出利润与资源消耗的表达式

每份面包利润为 3 元,每份蛋糕利润为 5 元。因此,两种产品带来的总利润为:

3 x + 5 y 3x+5y 3x+5y

店主希望总利润尽可能高,所以目标函数可以写成:

max ⁡ Z = 3 x + 5 y \max Z=3x+5y maxZ=3x+5y

接下来写约束条件。

生产 x x x 份面包需要使用 x x x 千克面粉,生产 y y y 份蛋糕需要使用 2 y 2y 2y 千克面粉。面粉总用量不能超过 50 千克:

x + 2 y ≤ 50 x+2y\leq 50 x+2y≤50

制作时间方面,每份面包需要 1 小时,每份蛋糕需要 2 小时,而每天最多有 40 小时:

x + 2 y ≤ 40 x+2y\leq 40 x+2y≤40

根据预计销量,面包最多生产 40 份,蛋糕最多生产 30 份:

x ≤ 40 , y ≤ 30 x\leq 40,\qquad y\leq 30 x≤40,y≤30

3.3 组成完整模型,并逐项检查含义

将目标函数、约束条件和变量取值范围合并,可以得到小店的生产计划模型:

max ⁡ Z = 3 x + 5 y s.t. x + 2 y ≤ 50 , x + 2 y ≤ 40 , x ≤ 40 , y ≤ 30 , x ≥ 0 , y ≥ 0 , x , y ∈ Z . \begin{aligned} \max\quad & Z=3x+5y\\ \text{s.t.}\quad &x+2y\leq 50,\\ &x+2y\leq 40,\\ &x\leq 40,\\ &y\leq 30,\\ &x\geq 0,\ y\geq 0,\\ &x,y\in\mathbb{Z}. \end{aligned} maxs.t.Z=3x+5yx+2y≤50,x+2y≤40,x≤40,y≤30,x≥0, y≥0,x,y∈Z.

其中, s . t . s.t. s.t. 是 subject to 的缩写,表示满足以下条件。

读这个模型时,可以按三个问题检查:

  1. 决定什么?
    决定 x x x 和 y y y,也就是面包与蛋糕的生产数量。
  2. 希望什么最好?
    让总利润 Z = 3 x + 5 y Z=3x+5y Z=3x+5y尽可能大。
  3. 必须满足什么?
    不超过面粉、工时和预计销量上限,并且生产数量不能为负数。

这里的两个资源约束恰好有相同的左侧表达式,但右侧不同。由于工时上限为 40 小时,比面粉约束允许的 50 个单位更紧,因此在这组数据中,面粉约束可能不会成为主要限制。保留它仍然有意义,因为如果资源数据发生变化,它可能影响最终方案。

tips 写出公式后,不要只检查符号是否正确,还要检查每一项的单位是否一致。例如, x + 2 y x+2y x+2y 表示面粉用量时,单位是千克;表示制作时间时,单位是小时。两条约束形式相同,但业务含义不同。

到这里,现实中的生产安排已经被转换为一个数学优化问题。下一节将进一步讨论:满足这些约束的方案如何称为可行解,为什么其中某一个方案可以被称为最优解,以及求解结果应如何回到现实决策中。

4. 从模型回到现实决策

模型写好以后,还需要判断哪些生产计划可以执行,以及哪个计划最符合目标。这个过程不能只看目标函数,还要同时检查所有约束条件。

4.1 什么是可行方案与最优方案

对于前面的模型,如果一组 ( x , y ) (x,y) (x,y) 同时满足:

x + 2 y ≤ 50 , x + 2 y ≤ 40 , x ≤ 40 , y ≤ 30 x+2y\leq 50,\quad x+2y\leq 40,\quad x\leq 40,\quad y\leq 30 x+2y≤50,x+2y≤40,x≤40,y≤30

并且 x , y x,y x,y 是非负整数,那么这组生产数量就是一个可行解。例如:

x = 20 , y = 10 x=20,\qquad y=10 x=20,y=10

此时面粉用量为 20 + 2 × 10 = 40 20+2\times10=40 20+2×10=40 千克,制作时间也是 40 小时,且没有超过销量上限,因此它是可执行的生产计划。

可行解可能有很多个,但它们带来的利润不一定相同。把所有可行解的目标函数值进行比较后,使利润最大的方案称为最优解。

4.2 如何解释求解结果

在当前数据下,工时约束为:

x + 2 y ≤ 40 x+2y\leq 40 x+2y≤40

面包每占用 1 小时可获得 3 元利润,蛋糕每占用 2 小时可获得 5 元利润,相当于每小时获得 2.5 元。因此,在工时最紧张的情况下,生产面包更有利。

模型的最优方案是:

x = 40 , y = 0 x=40,\qquad y=0 x=40,y=0

对应的最大利润为:

Z = 3 × 40 + 5 × 0 = 120 Z=3\times40+5\times0=120 Z=3×40+5×0=120

这个结果表示:按照当前利润、资源和销量假设,全部生产 40 份面包,能够获得 120 元利润。

需要注意,模型并不是在说面包永远比蛋糕好。它只是在当前数据下比较两种方案。如果蛋糕售价提高、制作时间减少,或者面包的销量上限降低,最优生产计划都可能改变。

4.3 数据和假设变化时,结论为何可能改变

优化结果依赖于输入数据和建模假设。比如:

  • 如果蛋糕单份利润从 5 元提高到 7 元,蛋糕的单位工时收益会增加;
  • 如果面包最多只能卖 20 份,剩余工时可能需要安排生产蛋糕;
  • 如果两种产品不共用同一种面粉,资源约束就需要重新拆分;
  • 如果销量具有较大不确定性,固定的销量上限可能不足以描述实际情况。

因此,求解器给出的数值是在当前模型下的最优方案。实际执行前,还应检查数据是否可靠、假设是否合理,以及结果是否符合经营经验。必要时,可以修改参数并重新求解,这也是优化建模中的敏感性分析思路。

后记

一个现实问题要成为优化问题,通常需要完成三步:先明确需要作出的决策,再确定评价方案的目标,最后列出方案必须满足的限制。将这三部分写成数学表达式后,模型就可以交给图解法、求解器或程序进行分析。

但模型的最优解并不是脱离现实的唯一答案。它只在给定数据和假设下成立。实际应用中,还需要检查数据是否准确、约束是否完整,并根据销量、成本和资源变化及时更新模型。优化的价值,不只是找到一个数字,更是把现实决策中的目标、条件和取舍表达清楚。


附录:用 Python 求解生产计划

前文建立了小店的生产计划模型。下面用 Python 求解,检验在给定数据下应生产多少份面包和蛋糕。

python 复制代码
import numpy as np
from scipy.optimize import Bounds, LinearConstraint, milp

# x:面包数量;y:蛋糕数量
# milp 求最小值,因此将"最大化 3x + 5y"写为"最小化 -3x - 5y"
objective = np.array([-3, -5])

# 依次表示面粉、工时、面包销量和蛋糕销量约束
coefficients = np.array([
    [1, 2],
    [1, 2],
    [1, 0],
    [0, 1],
])
limits = np.array([50, 40, 40, 30])

result = milp(
    c=objective,
    integrality=[1, 1],  # 两种产品都按整数份生产
    bounds=Bounds([0, 0], [np.inf, np.inf]),
    constraints=LinearConstraint(coefficients, -np.inf, limits),
)

if result.success:
    bread, cake = map(int, np.rint(result.x))
    profit = 3 * bread + 5 * cake

    print(f"面包:{bread} 份")
    print(f"蛋糕:{cake} 份")
    print(f"最大利润:{profit} 元")
else:
    print(f"求解失败:{result.message}")
相关推荐
有范先生9 小时前
即食米饭和传统自热米饭比强在哪里
其他
老吴的商业笔记1 天前
GEO系统贴牌前如何评估源码架构、私有化部署与技术选型落地路径
其他
迪康coolmu1 天前
出差终端数据安全落地实战:基于迪康端点安全一体化管理系统的四道防线实践
运维·服务器·经验分享·笔记·其他·安全·php
goodzz2221 天前
地板参数拉满,静电、异响、散热差?问题藏在施工里
其他
成都蜀味缘餐饮技术培训学校2 天前
手撕烤兔技术培训实战指南,秘制腌料配方比例与调制手法
大数据·经验分享·笔记·其他·微信公众平台
魅惑骄傲滴超人5 天前
工业串口屏十大品牌解析:ASIC自研、组态生态与EMC能
其他
别问!问就是全会6 天前
Jupyter Notebook 安装包下载|单元格分块运行,图表直接内嵌
ide·python·其他·jupyter
echoarts6 天前
服务器连不上?FileZilla 改被动模式就好了
运维·服务器·其他
pixelpilot6 天前
Deta Surf:把笔记、文件和网页塞进同一个 AI 工作台
笔记·其他