深入学习动规划
1.引言:
如下图所示,我们现在要求从A到E的最短路径,该如何做呢?
我们可以用深度优先搜索法来解决此问题,但是这个程序的效率如何呢?
我们可以看到,每次除了已经访问过的城市外,其他城市都要访问,所以时间复杂度为O(n!),这是一个“指数级”的算法,那么,还有没有更好的算法呢?
首先,我们来观察一下这个算法。在求从B1到E的最短距离的时候,先求出从C2到E的最短距离;而在求从B2到E的最短距离的时候,又求了一遍从C2到E的最短距离。也就是说,从C2到E的最短距离我们求了两遍。同样可以发现,在求从C1、C2到E的最短距离的过程中,从D1到E的最短距离也被求了两遍。而在整个程序中,从D1到E的最短距离被求了四遍。
如果在求解的过程中,同时将求得的最短距离"记录在案",随时调用,就可以避免这种情况。于是,可以改进该算法,将每次求出的从v到E的最短距离记录下来,在算法中递归地求MinDistance(v)时先检查以前是否已经求过了MinDistance(v),如果求过了则不用重新求一遍,只要查找以前的记录就可以了。这样,由于所有的点有n个,因此不同的状态数目有n个,该算法的数量级为O(n)。
这种高效算法,就是动态规划算法。
2.动态规划的基本概念
(1).决策过程的分类
根据过程的时间变量是离散的还是连续的,分为离散时间决策过程(即多阶段决策过程)和连续时间决策过程;
根据过程的演变是确定的还是随机的,分为确定性决策过程和随机性决策过程,
其中应用最广的是确定性多阶段决策过程。
(2).动态规划模型的基本要素
阶段:阶段(step)是对整个过程的自然划分。通常根据时间顺序或空间特征来划分阶段,以便按阶段的次序解优化问题
状态:状态(state)表示每个阶段开始时过程所处的自然状况。它应该能够描述过程的特征并且具有无后向性,即当某阶段的状态给定时,这个阶段以后过程的演变与该阶段以前各
阶段的状态无关,即每个状态都是过去历史的一个完整总结。通常还要求状态是直接或间接可以观测的。
决策:当一个阶段的状态确定后,可以作出各种选择从而演变到下一阶段的某个状态,这种选择手段称为决策(decision),在最优控制问题中也称为控制(control)。用uk(xk)表
示第k阶段处于状态xk时的决策变量,它是xk的函数,用Uk(xk)表示了xk的允许决策集合。
策略:由初始状态x1开始的全过程的策略记作p1n(x1),即p1n(x1)={u1(x1),u2(x2),...,un(xn)}。由第k阶段的状态xk开始到终止状态的后部子过程的策略记作pkn(xk),即pkn(xk)=
{uk(xk),uk+1(xk+1),...,un(xn)}
状态转移方程:在确定性过程中,一旦某阶段的状态和决策为已知,下阶段的状态便完全确定。用状态转移方程(equation of state)表示这种演变规律,写作
指标函数和最优函数:
指标函数(objective function)是衡量过程优劣的数量指标,它是关于策略的数量函数,从阶段k到阶段n的指标函数用Vkn(xk,pkn(xk))表示,k=1,2,...,n。
能够用动态规划解决的问题的指标函数应具有可分离性,即Vkn可表为xk,uk,Vk+1 n 的函数,记为:
其中函数是一个关于变量Vk+1 n单调递增的函数。这一性质保证了最优化原理(principle of optimality)的成立,是动态规划的适用前提。
过程在第j 阶段的阶段指标取决于状态xj和决策uj,用vj(xj,uj)表示。阶段k到阶段n的指标由vj(j=k,k+1,..n)组成,常见的形式有:
阶段指标之和,即
阶段指标之积,即
阶段指标之极大(或极小),即
这些形式下第k到第j阶段子过程的指标函数为Vkj(xk,uk,xk+1,...,xj+1)。可以发现,上述(3)-(5)三个指标函数的形式都满足最优性原理。
3.动态规划的基本方程
根据基本定理的推论可以得到动态规划的基本方程:
其中是决策过程的终端条件,
为一个已知函数。当xn+1只取固定的状态时称固定终端;当xn+1可在终端集合Xn+1中变动时称自由终端。最终要求的最优指标函数满足(10)式:
(9)式是一个递归公式,如果目标状态确定,当然可以直接利用该公式递归求出最优值(这种递归方法将在后文介绍,称作备忘录法),但是一般在实际应用中我们通常将该递归公式改为递推公式求解,这样一般效率会更高一些。
4.动态规划的适用条件
任何思想方法都有一定的局限性,超出了特定条件,它就失去了作用。同样,动态规划也并不是万能的。适用动态规划的问题必须满足最优化原理和无后效性。
5.动态规划的基本思想
动态规划的实质是分治思想和解决冗余,因此,动态规划是一种将问题实例分解为更小的、相似的子问题,并存储子问题的解而避免计算重复的子问题,以解决最优化问题的算法策略。
由此可知,动态规划法与分治法和贪心法类似,它们都是将问题实例归纳为更小的、相似的子问题,并通过求解子问题产生一个全局最优解。其中贪心法的当前选择可能要依赖已经作出的所有选择,但不依赖于有待于做出的选择和子问题。因此贪心法自顶向下,一步一步地作出贪心选择;而分治法中的各个子问题是独立的 (即不包含公共的子子问题),因此一旦递归地求出各子问题的解后,便可自下而上地将子问题的解合并成问题的解。但不足的是,如果当前选择可能要依赖子问题的解时,则难以通过局部的贪心策略达到全局最优解;如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题。
动态规划法的关键就在于,对于重复出现的子问题,只在第一次遇到时加以求解,并把答案保存起来,让以后再遇到时直接引用,不必重新求解。
6.动态规划的基本步骤:
设计一个标准的动态规划算法,通常可按以下几个步骤进行:
- 划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。注意这若干个阶段一定要是有序的或者是可排序的(即无后向性),否则问题就无法用动态规划求解。
- 选择状态:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。当然,状态的选择要满足无后效性。
- 确定决策并写出状态转移方程:之所以把这两步放在一起,是因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以,如果我们确定了决策,状态转移方程也就写出来了。但事实上,我们常常是反过来做,根据相邻两段的各状态之间的关系来确定决策。
- 写出规划方程(包括边界条件):动态规划的基本方程是规划方程的通用形式化表达式。一般说来,只要阶段、状态、决策和状态转移确定了,这一步还是比较简单的。
动态规划的主要难点在于理论上的设计,一旦设计完成,实现部分就会非常简单。根据动态规划的基本方程可以直接递归计算最优值,但是一般将其改为递推计算,实现的大体上的框架如下:
1. 对fn+1(xn+1)初始化; {边界条件}
2. for k:=n downto 1 do
3. for 每一个xk∈Xk do
4. for 每一个uk∈Uk(xk) do
begin
5. fk(xk):=一个极值; {∞或-∞}
6. xk+1:=Tk(xk,uk); {状态转移方程}
7. t:=φ(fk+1(xk+1),vk(xk,uk)); {基本方程(9)式}
8. if t比fk(xk)更优 then fk(xk):=t; {计算fk(xk)的最优值}
end;
9. t:=一个极值; {∞或-∞}
10. for 每一个x1∈X1 do
11. if f1(x1)比t更优 then t:=f1(x1); {按照10式求出最优指标}
12. 输出t;
但是,实际应用当中经常不显式地按照上面步骤设计动态规划,而是按以下几个步骤进行:
- 分析最优解的性质,并刻划其结构特征。
- 递归地定义最优值。
- 以自底向上的方式或自顶向下的记忆化方法(备忘录法)计算出最优值。
- 根据计算最优值时得到的信息,构造一个最优解。
步骤(1)--(3)是动态规划算法的基本步骤。在只需要求出最优值的情形,步骤(4)可以省略,若需要求出问题的一个最优解,则必须执行步骤(4)。此时,在步骤(3)中计算最优值时,通常需记录更多的信息,以便在步骤(4)中,根据所记录的信息,快速地构造出一个最优解。