新余市网站建设_网站建设公司_在线客服_seo优化
2026/1/8 1:38:57 网站建设 项目流程

原文:towardsdatascience.com/linear-programming-optimization-foundations-2f12770f66ca

线性规划是一种强大的优化技术,它被用于许多领域的决策改进。这是关于线性规划的多部分系列的第一部分,将涵盖与线性规划相关的重要主题。这篇文章将是简单的,旨在在探讨更高级的线性规划主题之前介绍基础知识。

在这篇文章中,我们将:

  1. 讨论构成线性规划问题的要素

  2. 了解线性规划的工作原理及其为何强大

  3. 在 Python 中运行线性规划示例

我个人认为,例子是学习技术主题的有效途径。因此,我们将贯穿整篇文章使用一个简单的例子。我将在下一节介绍这个例子。

在我们深入探讨之前,如果你对优化的基本概念和术语不是很熟悉,我写了一篇关于优化的入门文章,我鼓励你在继续之前阅读(这篇文章中有许多通用的优化术语,我没有定义)。

优化直观基础

设置我们的例子

我们将遵循一个愚蠢的例子,为本文中我们将涵盖的概念提供背景。我们将想象我们是非常简单的人,我们只吃两样东西——苹果🍏和巧克力棒🍫。我们想要平衡我们的健康和口味享受。这就是我们例子的背景,在接下来的章节中,我将介绍线性规划的概念,并将其应用于这个例子。到那时,我们将进行完整的优化,帮助我们决定应该吃多少苹果和多少巧克力棒!

什么是线性规划?

线性规划是一种优化技术,它通过线性方程或不等式的约束条件最小化或最大化线性目标函数(这里有大量的术语,不用担心,我们很快就会在直观的例子中解释)。"线性规划"这个名字比我们现在通常认为的编程(即计算机编程)要早,线性规划是在二战时期开发和使用的。它被广泛用于管理操作程序——例如,将物资从工厂运送到前线。所以,“规划”指的是计划或调度,而不是计算机。这是一个历史背景,这样你就不会总是想知道“规划”部分何时出现!

虽然它最初是为了解决操作/后勤问题而开发的,但有许多巧妙的方法可以使线性规划适用于广泛的多种问题类型!

一个线性规划问题由以下 3 部分组成:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4e3a195fb4778e23671ac88eecce82fb.png

由作者提供

让我们为我们的苹果和巧克力棒示例设置这三个部分。

类型:我们希望最大化从食物中获得的享受——因此这是一个最大化问题。

目标函数:幸运的是,我们非常了解自己,可以量化我们对苹果和巧克力棒的喜爱程度——我们甚至更有运气,因为我们的喜爱程度是一个适合线性规划问题的线性函数 😅!

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3e34c1e9d10d0eb31e7dcbd1130a6fed.png

作者图片

这个函数可以用来计算我们吃多少苹果和巧克力棒可以获得多少享受。我们吃一个苹果获得 1 单位的享受,吃一个巧克力棒获得 3 单位的享受。

约束条件:虽然我们的饮食种类非常有限,但我们对我们健康有一点担忧。我们决定限制我们的(1)卡路里和(2)糖分摄入。由于我们想要控制两个变量,我们需要两个约束条件。我们需要设置线性函数来计算给定苹果和巧克力棒数量的卡路里和克糖。一旦我们设置了公式,我们将它们设置为不等式,基于我们想要限制的消费。我们决定我们不想吃超过 850 卡路里,也不想吃超过 100 克糖。

这里是我们的约束条件:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/9d13b7c38381d645b95ec67be1828e3a.png

苹果含有 95 卡路里和 15 克糖,巧克力棒含有 215 卡路里和 20 克糖 - 作者图片

好的,我们现在已经完全设置好了线性规划问题!以下是总结:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1c7e0a38f634eea01f3d1ebe228d050b.png

作者图片

我们非常幸运,我们所有的食物消费偏好和约束都是线性的。关于基本线性规划允许的约束类型和目标函数有很多规则。违反规则的内容如下:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/9f344225ae5fd6bbe27ee6b0f52e5cea.png

作者图片

线性规划可以扩展以允许许多这些违规行为——但允许上述元素会失去保证解决方案将是全局最优的。对于今天的示例,我们将保持在线性规划范围内!未来的文章将探讨我们如何使用修改后的线性规划框架,称为混合整数线性规划,来违反一些这些规则。

工作原理

我认为通过创建图形表示来理解线性规划的工作原理是最容易的。由于我们只有两个决策变量,我们可以制作出漂亮的二维图表(我们只吃两种食物是多么方便)。我们首先通过图表来表示我们的约束条件:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/a79c176ac3adedaa3ee791ef7ee99080.png

约束条件以视觉形式表示 – 作者图片

橙色和蓝色线条是我们的线性约束。我们只接受小于或等于这两条线的解。阴影区域是我们的可行解空间。线性规划问题的任务是找到解空间中最大化我们的目标函数(我们的食物享受)的位置。这可能会显得有些令人畏惧——我们的解空间是无限的(因为我们可以吃苹果和巧克力棒的分数部分)!不过不用担心,因为我们的所有函数都是线性的,我们可以使用一个技巧将我们的无限解空间减少到一个有限集合!

让我们稍微思考一下我们的解空间。它是被蓝色和橙色线条所包围的灰色区域。在寻找最优解时,我们寻找极端值——最低或最高。因此,最优解将在边界或灰色区域是有意义的,因为那是最极端的。现在,我们可以得出结论,我们的最优解将在我们的可行空间边界上。但这仍然是一个无限的空间。我们需要一个额外的技巧来得到一个有限解空间。让我们在我们的蓝色线条上随机选择一个点:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/eb38d11a155916ba33cfcb7d42f4f56e.png

作者图片

我们如何使这个点更加极端,同时保持在可行区域的边缘?我们可以将它滑动到可行区域左边的边缘,或者我们可以将它滑动到橙色线条与蓝色线条相交的右边。在那之后,橙色线条定义了可行区域而不是蓝色线条。这些点是这部分解空间的最极端点。如果我们对解空间的每个边缘或逻辑进行推理,我们会发现所有的交点都是边缘的最极端点。通过这个算法,我们通过只查看空间的角点来将我们的无限解空间减少到有限空间。如果我们的目标函数和约束条件是线性的,最优解将始终是角点之一!我们只需要查看所有角点的目标值,并选择具有最高或最低值的点!

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/5592ef9e18ac940f5225c7547f2d1943.png

作者图片

下面是线性规划算法在角点处寻找最优解的图形表示:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4a23b97c18d4c2d040e277aa89756909.png

作者图片

如我们之前讨论的,对于一个线性规划问题,目标函数和约束条件必须是线性的。现在,我们对线性规划问题的工作原理有了更好的理解,即检查约束条件的角点,我们处于一个很好的位置来理解线性违反如何导致问题。当引入非线性函数时,极点可以出现在角点之间,因为线不是单调递增或递减的。这取消了线性规划通过检查角点来使潜在解列表有限的“技巧”。

在下面的示例中,我们的卡路里约束是二次的(当然这在实际中没有任何意义——但为了示例,我们就这么假设吧!)最优解现在是抛物线的最大值,它不在角上。所以,如果我们尝试在这个约束集上使用角点方法,我们会得到一个次优解!总的来说,约束和目标函数需要是线性的,因为线性规划依赖于角点是极点,这意味着最优解总是在角上。正如我们下面看到的,当这一点不成立时,“技巧”并不能保证得到最优解。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3f7d34c75b6b3b911f36446308fbe4ea.png

非线性约束下最优解不仅限于角点 - 图片由作者提供

现在,我将花几分钟时间讨论两种 LP 算法会运行但不会返回最优解的情况。第一种情况是,满足所有约束条件的解空间为空。例如,如果我决定我想吃负数的糖,那么在卡路里约束以下和 X、Y 轴上的 0 以上将没有空间。下面是一个示例图表。这将导致一个“不可行”的结果。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/2a2debb31c2bec5f5a0953ea6513b98a.png

无可行区域 - 图片由作者提供

第二种情况是,解空间没有被约束完全包围。想象一下,如果我们想吃至少 850 卡路里和 100 克糖,而不是少于 850 卡路里和 100 克糖(这意味着我们改变了约束条件为≥),那么我们的解空间将是无界的。我们可以总是吃更多的巧克力棒和苹果,获得更多的享受。当然,这没有意义!我们会得到一个“无界”的结果——这意味着无法达到有意义的最优解。在排除了这两个注意事项之后,让我们用 Python 解决 LP 问题。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/084acf9b4f0124c0b38f51a14ef53417.png

无界线性规划问题示例 - 图片由作者提供

在 Python 中运行示例

现在我们将探讨如何使用名为 pulp 的包在 Python 中解决这个线性规划问题。在我们深入这些细节之前,我已经写了两篇关于线性规划的文章。一篇关于模拟的文章,间接展示了线性规划如何帮助虚构的房地产开发商优化利润。另一篇文章介绍了名为“地球搬运工距离”的分布比较度量,它在计算中使用了线性规划。下面是链接,您可以查看更多线性规划的应用示例!

模拟数据,真实学习:情景分析

使用地球迁移距离比较分布

好的,让我们继续编写我们一直在讨论的示例代码!代码编写并不太难。

在导入 pulp 包后,我们实例化一个 pulp.LpProblem 对象——在这里我们定义我们是在解决最大化问题还是最小化问题。

importpulp# Create the LP problemlp_problem=pulp.LpProblem("Apples and Candy Bars",pulp.LpMaximize)

在我们的问题实例化后,让我们使用 pulp.LpVariable 函数创建我们的决策变量,即苹果和巧克力棒。注意:可以将 lowBound 参数设置为 0,为决策变量添加非负约束。

# Define the decision variablesapples=pulp.LpVariable('apples',lowBound=0)candy_bars=pulp.LpVariable('candy_bars',lowBound=0)

现在,我们使用‘+=’运算符将我们的目标函数和约束条件添加到问题实例中。Pulp 没有参数来指示你是否直接添加目标函数或约束条件。相反,它将没有等式/不等式的函数解释为目标函数,而有等式/不等式的函数解释为约束条件。这有点令人困惑,但当你查看下面的代码片段时,希望你会明白。

# Add the objective function - level of enjoyment from specific diet# notice, no equality or inequality at the end of the functionlp_problem+=1*apples+3*candy_bars# Add calorie constraintlp_problem+=95*apples+215*candy_bars<=850# Add sugar constraintlp_problem+=15*apples+20*candy_bars<=100

好的,现在一切都已经设置好了!我们只需要在我们的 lp_problem 对象上调用 solve()方法并打印结果!

# Solve the problemlp_problem.solve()# Print the resultsprint(f"Status:{pulp.LpStatus[lp_problem.status]}")print(f"apples ={pulp.value(apples)}")print(f"candy bars ={pulp.value(candy_bars)}")print(f"Objective value ={pulp.value(lp_problem.objective)}")

这里是打印出的结果:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/a138630694f94ccf5e39edf706a88391.png

作者图片

“最优”状态意味着已经找到了最优解——如果没有找到可行解或者它是无界的,那么“状态”属性将向我们指示这一点。我们可以看到,最优解是吃 3.95 块巧克力棒和 0 个苹果,总共获得 11.86 的享受。这正是我们手动解决问题时找到的结果!

这里是代码的单一片段:

importpulp# Create the LP problemlp_problem=pulp.LpProblem("Apples and Candy Bars",pulp.LpMaximize)# Define the decision variablesapples=pulp.LpVariable('apples',lowBound=0)candy_bars=pulp.LpVariable('candy_bars',lowBound=0)# Add the objective function - level of enjoyment from specific dietlp_problem+=1*apples+3*candy_bars# Add calorie constraintlp_problem+=95*apples+215*candy_bars<=850# Add sugar constraintlp_problem+=15*apples+20*candy_bars<=100# Solve the problemlp_problem.solve()# Print the resultsprint(f"Status:{pulp.LpStatus[lp_problem.status]}")print(f"apples ={pulp.value(apples)}")print(f"candy bars ={pulp.value(candy_bars)}")print(f"Maximum enjoyment ={pulp.value(lp_problem.objective)}")

结论

到现在为止,你应该已经很好地理解了什么是线性规划问题,线性规划问题如何找到最优值,以及如何在 Python 中设置和解决它们!在未来的文章中,我们将详细介绍 LP 算法如何检查边缘(称为单纯形法)以及如何将整数变量(而不是仅连续变量)扩展到 LP 问题中。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询