简介
OR-Tools 是一种用于组合优化的开源软件,该软件力求从一组可能的大量解决方案中找出某个问题的最佳解决方案。以下是 OR 工具可以解决的一些问题示例:
- 线性规划:线性目标函数在线性约束条件下的优化问题
- 整数规划:线性目标函数在变量为整数约束下的优化问题
- 车辆路线:根据给定的限制条件(例如,“这辆卡车承载的重量不能超过 20,000 磅”或“所有送货都必须在两小时内完成”)。
- 调度:为一组复杂的任务找到最佳调度,其中一些任务需要先完成,然后才能在一组固定的机器或其他资源上执行。
- 箱装:将各种不同尺寸的对象装入具有最大容量的固定数量的箱中。
在大多数情况下,此类问题具有大量可能的解决方案,计算机过多无法搜索所有解决方案。为了解决这个问题,OR-Tools 使用了先进的算法来缩小搜索集的范围,以寻找最佳(或最接近)的解决方案。
学习文档:https://developers.google.com/optimization/introduction/python?hl=zh-cn
安装
Google 以 C++ 创建了 OR 工具,但也可以将其与 Python、Java 或 C#(在 .NET 平台上)结合使用。
如果您已有 Python(Linux、macOS 或 Windows 上的版本为 3.8 及更高版本)和 Python 软件包管理器 PIP,则可以按如下方式安装 OR-Tools:
python -m pip install --upgrade --user ortools
确认是否安装成功,运行
pip show ortools
安装其他语言版本,可以参见官方文档:https://developers.google.com/optimization/install?hl=zh-cn
线性规划用法示例
目标为最大化 3x + 4y
,但需遵循以下限制条件:
x + 2y
≤ 143x - y
≥ 0x - y
≤ 2
目标函数 3x + 4y
和约束条件均由线性表达式给出,这使得此问题成为线性问题。
这些约束条件定义了可行区域,即下方显示的三角形,包括其内部。
解决 LP 问题的基本步骤
要解决 LP 问题,您的程序应包含以下步骤:
- 导入线性求解器封装容器,
- 声明 LP 求解器,
- 定义变量
- 定义约束条件,
- 定义目标,
- 调用 LP 求解器;
- 展示解决方案
使用 MPSolver 的解决方案
以下部分展示了一个使用 MPSolver 封装容器和 LP 求解器来解决问题的程序。
注意:如需运行以下程序,您需要安装 OR-Tools。
主要的 OR-Tools 线性优化求解器是 Glop,这是 Google 的内部线性编程求解器。它运行速度快、内存高效且数值稳定。
导入线性求解器封装容器
导入(或包含)OR-Tools 线性求解器封装容器(MIP 求解器和线性求解器的接口),如下所示。
from ortools.linear_solver import pywraplp
声明 LP 求解器
MPsolver
是多个不同求解器(包括 Glop)的封装容器。以下代码声明了 GLOP 求解器。
solver = pywraplp.Solver.CreateSolver("GLOP")
if not solver:
return
注意:将 GLOP
替换为 PDLP
以使用替代 LP 求解器。如需详细了解如何选择求解器,请参阅高级 LP 求解器;如需了解如何安装第三方求解器,请参阅安装指南。
创建变量
首先,创建变量 x 和 y,它们的值介于 0 到无穷大之间。
x = solver.NumVar(0, solver.infinity(), "x")
y = solver.NumVar(0, solver.infinity(), "y")
print("Number of variables =", solver.NumVariables())
定义限制条件
接下来,定义对变量的约束条件。为每个约束条件指定一个唯一的名称(例如 constraint0
),然后定义该约束条件的系数。
# Constraint 0: x + 2y <= 14.
solver.Add(x + 2 * y <= 14.0)
# Constraint 1: 3x - y >= 0.
solver.Add(3 * x - y >= 0.0)
# Constraint 2: x - y <= 2.
solver.Add(x - y <= 2.0)
print("Number of constraints =", solver.NumConstraints())
定义目标函数
以下代码定义了目标函数 3x + 4y
,并指定这是一个最大化问题。
# Objective function: 3x + 4y.
solver.Maximize(3 * x + 4 * y)
调用求解器
以下代码会调用求解器。
print(f"Solving with {solver.SolverVersion()}")
status = solver.Solve()
显示解决方案
以下代码将显示解决方案。
if status == pywraplp.Solver.OPTIMAL:
print("Solution:")
print(f"Objective value = {solver.Objective().Value():0.1f}")
print(f"x = {x.solution_value():0.1f}")
print(f"y = {y.solution_value():0.1f}")
else:
print("The problem does not have an optimal solution.")
程序会返回问题解
Number of variables = 2
Number of constraints = 3
Solution:
x = 6.0
y = 4.0
Optimal objective value = 34.0
下图展示了问题的解
绿色虚线通过将目标函数设置为等于其最佳值 34 来定义。任何方程式为 3x + 4y = c
的直线都平行于虚线,且 34 是该直线与可行区域相交的 c 的最大值。