本文参考Google OR-Tools官网文档介绍OR-Tools的使用方法。实际生活中有很多组合优化问题,例如最短路径、背包问题、人员排班等,这些组合优化问题一般属于规模较大的整数规划或者约束满足问题,一般没有直接的算法获得绝对最优解,只能通过启发式或元启发式算法获得相对最佳解。OR-Tools针对路径问题、背包问题和流问题提供了专用接口,相对于通用的求解器有更高的计算效率。
1 TSP问题
路径优化问题的目标都是在一个复杂的网络中找一个效能最高的路径,这个网络可以用下面这个节点图来示意
按照优化的目标是针对节点还是边,路径优化问题可以分成两类:节点路径优化( node-routing)和边路径优化(arc-routing)。节点路径优化的目标是以最短的路径长度访问到每个节点,而边路径优化的目标是以最短的路径长度实现访问图中的每条边。
旅行商(TSP)问题就是一个非常经典的node-routing问题,在这个问题下,图中每个节点代表了一个城市,而节点之间的边表示两座城市间的行程;每条边赋予一个权值,代表了两座城市间的距离;目标就是为旅行商找一条行程最短的路线来访问到每座城市。在这个标准的TSP问题定义上还可以附加各种额外条件来符合现实情况:
- 非对称距离,也就是节点图是有向图,从A到B和从B到A的距离不相同
- Prize-Collecting TSP,访问一个城市可能有收益,离开一个城市则可能有额外的支出
- 时间窗,有些城市要在规定的时间内访问
下面我们先了解一些解决以TSP为例的路径问题的算法,再使用OR-Tools演示一下。
2 算法相关
2.1 启发式算法
启发(heuristic)这个词带有联想、经验的意思,这也正是启发式算法的思想,是带有领域知识的非精确算法,启发式算法一般要依赖于问题领域,不同的问题因为环境的不同启发式算法的形式也不同。对于TSP问题,一种最简单和直接的启发式算法是最邻近优先(Nearest Neighbor)法,就是每次都访问离当前位置最近的城市,这种算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2):
- 随机选择一个城市;
- 找当前最近的未访问城市最为下一个访问的城市;
- 是否还有未访问的城市?如果有,再进行2;
- 返回到初始城市
这种算法得到的解通常来说只有最优解的10%到15%。或者可以用一种更好的启发式算法,最短边贪心算法,就是不断选择最短的边来构造路径:
- 所有的边排序
- 选择最短的边加入路径,如果这边不会导致某个城市有三个及以上的度(就是节点有三个及以上的边连接),并且不会使某些城市构成回路
- 是否有N条边在路径中,如果是,则停止,否则再进行2
贪心算法的时间复杂度为 O ( n 2 l o g 2 ( n ) ) O(n^2log_2(n)) O(n2log2(n)),解的优良程度大概是最优解的15%到20%。除了这两种典型的启发式算法,还有其他很多种实现,就不列举了。
启发式算法的最大优点就是计算速度非常快,但是缺点也很明显,解的质量不高,因为本质上所有的启发式算法都属于局部最优算法,在随机初始化后只会沿这个方向发展,到达局部最优点后就停止了。
2.2 元启发式算法
元启发式算法有时也称为智能优化算法,宽泛的来说也属于启发式算法,不过因为相对朴素的启发式算法有很大程度的改进因此一般单独划分出来讨论。元启发式算法的一大特点是面向全局的优化,会利用各种手段跳出局部最优来尝试寻找更好的解;另一个特点是通常会参考现实世界的物理过程来具体实现,从大多数元启发式算法的名字就可以直接体现,例如模拟退火算法、遗传算法、蚁群算法和霍普菲尔德神经网络等等。
在这篇文章里我们介绍一下模拟退火算法。它是受加热金属的退火过程所启发而提出的一种逼近算法,该算法在1983年由Kirkpatrick等人提出,并且最初设计这个算法就是为了解决TSP问题的。
模拟退火参考了一个物理现象:在某个温度下,金属分子停留在能量小的状态的概率比停留在能量大的状态的概率要大。更加具体的物理背景是这样的,在温度 T T T下,金属物体的分子可能会处于若干种状态,停留在状态 r r r的概率满足Boltzmann分布:
P { E ‾ = E ( r ) } = 1 Z ( T ) e x p ( − E ( r ) k B T ) \begin{aligned} P\{\overline{E} = E(r)\}= \frac{1}{Z(T)} exp(-\frac{E(r)}{k_BT}) \end{aligned} P{
E=E(r)}=Z(T)1exp(−kBTE(r))
其中 E ‾ \overline{E} E表示分子能量的随机变量, E ( r ) E(r) E(r)表示在状态 r r r下的能量, k B > 0 k_B>0 kB>0为Boltzmann常量,而 Z ( T ) Z(T) Z(T)为概率分布的标准化因子
Z ( T ) = ∑ r ∈ D e x p ( − E ( r ) k B T ) \begin{aligned} Z(T)= \sum_{r \in D}^{ }exp(- \frac{E(r)}{k_BT}) \end{aligned} Z(T)=r∈D∑exp(−kBTE(r))
其中 D D D是状态空间。根据分子能量的Boltzmann分布方程,分子不同状态的能量与温度的关系具有以下的特性:
- 温度很高时( T → ∞ T\to\infty T→∞),概率 P { E ‾ = E ( r ) } P\{\overline{E} = E(r)\} P{