1、1第六章 分支限界法n理解分支限界法的剪枝搜索策略。n掌握分支限界法的算法框架n队列式(FIFO)分支限界法n优先队列式分支限界法 2第五章 分支限界法n通过应用范例学习分支限界法的设计策略。n单源最短路径问题n装载问题;n布线问题n0-1背包问题;n最大团问题;n旅行售货员问题n电路板排列问题n批处理作业调度问题3分支限界法的基本思想分支限界法与回溯法(1)求解目标:回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。 (2)搜索方式的不同:回溯法以深度优先的方式搜索解空间树;而分支限界法
2、则以广度优先或以最小耗费优先的方式搜索解空间树。 4分支限界法的基本思想 分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。对已处理的各结点根据限界函数估算目标函数的可能取值,从中选取使目标函数取得极值(极大/极小)的结点优先进行广度优先搜索不断调整搜索方向,尽快找到解。特点:特点:限界函数常基于问题的目标函数,适用于求解最优化问题。5分支限界法的基本思想 此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。 在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生
3、其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。6分支限界法的基本思想常见的两种分支限界法(1)队列式(FIFO)分支限界法 按照队列先进先出(FIFO)原则选取下一个结点为扩展结点。 (2)优先队列式分支限界法 按照优先队列中规定的优先级选取优先级最高的结点成为当前扩展结点。7解空间树的动态搜索(1)回溯求解0/1背包问题,虽剪枝减少了搜索空间,但整个搜索按深度优先机械进行,是盲目搜索(不可预测本结点以下的结点进行的如何)。(2)回溯求解TSP也是盲目的(虽有目标函数,也只有找到一个可行解后才有意义)8解空间树的动态搜索分支限界法首
4、先确定一个合理的限界函数,并根据限界函数确定目标函数的界down, up;然后按照广度优先策略遍历问题的解空间树,在某一分支上,依次搜索该结点的所有孩子结点,分别估算这些孩子结点的目标函数的可能取值(对最小化问题,估算结点的down,对最大化问题,估算结点的up)。如果某孩子结点的目标函数值超出目标函数的界,则将其丢弃(从此结点生成的解不会比目前已得的更好),否则入待处理表。90/1背包的分支限界法过程1. 问题描述物品 重(w) 价(v) 价/重(v/w) 1 4 40 10 2 7 42 6 3 5 25 5 4 3 12 4容量w=10贪心法的解(1,0,0,0),价值为40,可作为0/
5、1背包的下界。100/1背包的分支限界法过程2. 求解过程上界ub可用最好情况来代替ub=w*(v1/w1)=10*10=100目标函数的界40, 100,一般解空间树中第i层的各结点,代表对物1i的选择,可这样定限界函数:ub=V+(W-w)*(vi+1/wi+1)可参考板书视图已装入价值已装入价值剩余容量剩余容量剩下物品最大单位价值剩下物品最大单位价值vi+1/wi+1的积的积110/1背包的分支限界法过程2. 总结从0/1背包问题的搜索过程可看出:与回溯法相比,分支限界法可根据限界函数不断调整搜索方向,选择最可能得最优解的子树优先进行搜索找到问题的解。12分支限界法的设计思路设求解最大化
6、问题,解向量为X=(x1,xn),xi的取值范围为Si,|Si|=ri。在使用分支限界搜索问题的解空间树时,先根据限界函数估算目标函数的界down, up,然后从根结点出发,扩展根结点的r1个孩子结点,从而构成分量x1的r1种可能的取值方式。对这r1个孩子结点分别估算可能的目标函数bound(x1),其含义:以该结点为根的子树所有可能的取值不大于bound(x1),即:bound(x1)bound(x1,x2) bound(x1,xn)13分支限界法的设计思路n若某孩子结点的目标函数值超出目标函数的下界,则将该孩子结点丢弃;否则,将该孩子结点保存在待处理结点表PT中。n再取PT表中目标函数极大
7、值结点作为扩展的根结点,重复上述。n直到一个叶子结点时的可行解X=(x1,xn),及目标函数值bound(x1,xn)。14单源最短路径问题1. 问题描述 下面以一个例子来说明单源最短路径问题:在下图所给的有向图G中,每一边都有一个非负边权。要求图G的从源顶点s到目标顶点t之间的最短路径。15单源最短路径问题1. 问题描述下图是用优先队列式分支限界法解有向图G的单源最短路径问题产生的解空间树。其中,每一个结点旁边的数字表示该结点所对应的当前路长。16单源最短路径问题2. 算法思想 解单源最短路径问题的优先队列式分支限界法用一极小堆来存储活结点表。其优先级是结点所对应的当前路长。17单源最短路径
8、问题2. 算法思想n算法从图G的源顶点s和空优先队列开始。结点s被扩展后,它的儿子结点被依次插入堆中。此后,算法从堆中取出具有最小当前路长的结点作为当前扩展结点,并依次检查与当前扩展结点相邻的所有顶点。如果从当前扩展结点i到顶点j有边可达,且从源出发,途经顶点i再到顶点j的所相应的路径的长度小于当前最优路径长度,则将该顶点作为活结点插入到活结点优先队列中。n这个结点的扩展过程一直继续到活结点优先队列为空时为止。18单源最短路径问题3. 剪枝策略在算法扩展结点的过程中,一旦发现一个结点的下界不小于当前找到的最短路长,则算法剪去以该结点为根的子树。 在算法中,利用结点间的控制关系进行剪枝。从源顶点
9、s出发,2条不同路径到达图G的同一顶点。由于两条路径的路长不同,因此可以将路长长的路径所对应的树中的结点为根的子树剪去。 19单源最短路径问题3. 剪枝策略下图是用优先队列式分支限界法解有向图G的单源最短路径问题产生的解空间树的剪枝情况。经过不同的路径到达相同的顶点ABA优于B,B可剪枝20单源最短路径问题 while (true) for (int j = 1; j = n; j+) if (cE.ijinf)&(E.length+cE.ijdistj) / 顶点i到顶点j可达,且满足控制约束 distj=E.length+cE.ij; prevj=E.i; / 加入活结点优先队列 MinH
10、eapNode N; N.i=j; N.length=distj; H.Insert(N); try H.DeleteMin(E); / 取下一扩展结点 catch (OutOfBounds) break; / 优先队列空 顶点顶点i和和j间有边,且此路间有边,且此路径长小于原先从源点到径长小于原先从源点到j的路径长的路径长 21单源最短路径问题nDijakstra算法:每一步的选择为当前步的最优,复杂度为O(n2)。n分支限算法:每一步的扩散为当前耗散度的最优。n队列式分支限界法的搜索解空间树的方式类似于解空间树的宽度优先搜索,不同的是队列式分支限界法不搜索以不可行结点(已经被判定不能导致可
11、行解或不能导致最优解的结点)为根的子树。按照规则,这样的结点不被列入活结点表。nA-E-Q-M Dijakstra算法和分支限法在解决该问题的异同:22单源最短路径问题n优先队列式分支限界法的搜索方式是根据活结点的优先级确定下一个扩展结点。结点的优先级常用一个与该结点有关的数值p来表示。最大优先队列规定p值较大的结点点的优先级较高。在算法实现时通常用一个最大堆来实现最大优先队列,体现最大效益优先的原则。类似地,最小优先队列规定p值较小的结点的优先级较高。在算法实现时,常用一个最小堆来实现,体现最小优先的原则。采用优先队列式分支定界算法解决具体问题时,应根据问题的特点选用最大优先或最小优先队列,
12、确定各个结点点的p值。Dijakstra算法和分支限法在解决该问题的异同:23装载问题1. 问题描述有一批共n个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集装箱i的重量为Wi,且211ccwnii装载问题要求确定是否有一个合理的装载方案可将这n个集装箱装上这2艘轮船。如果有,找出一种装载方案。 容易证明:如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。 (1)首先将第一艘轮船尽可能装满;(2)将剩余的集装箱装上第二艘轮船。 24装载问题2. 队列式分支限界法 在算法的while循环中,首先检测当前扩展结点的左儿子结点是否为可行结点。如果是则将其加入到活结点队列中。然后将其
13、右儿子结点加入到活结点队列中(右儿子结点一定是可行结点)。2个儿子结点都产生后,当前扩展结点被舍弃。25装载问题2. 队列式分支限界法活结点队列中的队首元素被取出作为当前扩展结点,由于队列中每一层结点之后都有一个尾部标记-1,故在取队首元素时,活结点队列一定不空。当取出的元素是-1时,再判断当前队列是否为空。如果队列非空,则将尾部标记-1加入活结点队列,算法开始处理下一层的活结点。26装载问题2. 队列式分支限界法while (true) / 检查左儿子结点 if (Ew + wi = c) / xi = 1 判断是否可以装上船 EnQueue(Q, Ew + wi, bestw, i, n)
14、; / 右儿子结点总是可行的 左孩子是选择,右孩子是不选,总有其它方案. EnQueue(Q, Ew, bestw, i, n); / xi = 0 Q.Delete(Ew); / 取下一扩展结点 if (Ew = -1) / 同层结点尾部 if (Q.IsEmpty() return bestw; Q.Add(-1); / 同层结点尾部标志 Q.Delete(Ew); / 取下一扩展结点 i+; / 进入下一层 27装载问题3. 算法的改进 结点的左子树表示将此集装箱装上船,右子树表示不将此集装箱装上船。设bestw是当前最优解;ew是当前扩展结点所相应的重量;r是剩余集装箱的重量。则当ew
15、+rbestw时,可将其右子树剪去,因为此时若要船装最多集装箱,就应该把此箱装上船。 另外,为了确保右子树成功剪枝,应该在算法每一次进入左子树的时候更新bestw的值。28装载问题3. 算法的改进/ 检查左儿子结点 Type wt = Ew + wi; / 左儿子结点的重量 if (wt bestw) bestw = wt; / 加入活结点队列 if (i bestw & i 0; j-) bestxj = bestE-LChild; bestE = bestE-parent; 31装载问题5. 优先队列式分支限界法n解装载问题的优先队列式分支限界法用最大优先队列存储活结点表。活结点x在优先队
16、列中的优先级定义为从根结点到结点x的路径所相应的载重量再加上剩余集装箱的重量之和。n优先队列中优先级最大的活结点成为下一个扩展结点。以结点x为根的子树中所有结点相应的路径的载重量不超过它的优先级。子集树中叶结点所相应的载重量与其优先级相同。n在优先队列式分支限界法中,一旦有一个叶结点成为当前扩展结点,则可以断言该叶结点所相应的解即为最优解。此时可终止算法。 32布线问题1. 算法思想布线问题:印刷电路板将布线区域划分成nm个方格如图a所示。精确的电路布线问题要求确定连接方格a的中点到方格b的中点的最短布线方案。在布线时,电路只能沿直线或直角布线,如图b所示。为了避免线路相交,已布了线的方格做了
17、封锁标记,其它线路不允穿过被封锁的方格。 33布线问题1. 算法思想一个布线的例子:图中包含障碍。起始点为a,目标点为b。34布线问题1. 算法思想 解此问题的队列式分支限界法从起始位置a开始将它作为第一个扩展结点。与该扩展结点相邻并且可达的方格成为可行结点被加入到活结点队列中,并且将这些方格标记为1,即从起始方格a到这些方格的距离为1。 接着,算法从活结点队列中取出队首结点作为下一个扩展结点,并将与当前扩展结点相邻且未标记过的方格标记为2,并存入活结点队列。这个过程一直继续到算法搜索到目标方格b或活结点队列为空时为止。即加入剪枝的广度优先搜索。35布线问题Position offset4;
18、offset0.row = 0; offset0.col = 1; / 右 offset1.row = 1; offset1.col = 0; / 下 offset2.row = 0; offset2.col = -1; / 左 offset3.row = -1; offset3.col = 0; / 上定义移动方向的定义移动方向的相对位移相对位移 for (int i = 0; i = m+1; i+) grid0i = gridn+1i = 1; / 顶部和底部 for (int i = 0; i = n+1; i+) gridi0 = gridim+1 = 1; / 左翼和右翼设置边界的
19、围墙设置边界的围墙36布线问题for (int i = 0; i NumOfNbrs; i+) nbr.row = here.row + offseti.row; nbr.col = here.col + offseti.col; if (gridnbr.rownbr.col = 0) / 该方格未标记 gridnbr.rownbr.col = gridhere.rowhere.col + 1; if (nbr.row = finish.row) & (nbr.col = finish.col) break; / 完成布线 Q.Add(nbr); 找到目标位置后,可以通过回溯方法找到这条最短路
20、径。370-1背包问题算法的思想 首先,要对输入数据进行预处理,将各物品依其单位重量价值从大到小进行排列。 在下面描述的优先队列分支限界法中,结点的优先级由已装袋的物品价值加上剩下的最大单位重量价值的物品装满剩余容量的价值和。 算法首先检查当前扩展结点的左儿子结点的可行性。如果该左儿子结点是可行结点,则将它加入到子集树和活结点优先队列中。当前扩展结点的右儿子结点一定是可行结点,仅当右儿子结点满足上界约束时才将它加入子集树和活结点优先队列。当扩展到叶结点时为问题的最优值。380-1背包问题上界函数/ n表示物品总数,cleft为剩余空间while (i = n & wi = cleft) cle
21、ft -= wi; /wi表示i所占空间 b += pi; /pi表示i的价值 i+;if (i bestn时,右子树中可能含有最优解,此时将右儿子结点加入到子集树中并插入到活结点优先队列中。43最大团问题3. 算法思想 算法的while循环的终止条件是遇到子集树中的一个叶结点(即n+1层结点)成为当前扩展结点。 对于子集树中的叶结点,有upperSizecliqueSize。此时活结点优先队列中剩余结点的upperSize值均不超过()当前扩展结点的upperSize值,从而进一步搜索不可能得到更大的团,此时算法已找到一个最优解。否则还要找。44旅行售货员问题1. 问题描述 某售货员要到若干
22、城市去推销商品,已知各城市之间的路程(或旅费)。他要选定一条从驻地出发,经过每个城市一次,最后回到驻地的路线,使总的路程(或总旅费)最小。 路线是一个带权图。图中各边的费用(权)为正数。图的一条周游路线是包括V中的每个顶点在内的一条回路。周游路线的费用是这条路线上所有边的费用之和。 旅行售货员问题的解空间可以组织成一棵树,从树的根结点到任一叶结点的路径定义了图的一条周游路线。旅行售货员问题要在图G中找出费用最小的周游路线。 45旅行售货员问题2. 算法描述 算法开始时创建一个最小堆,用于表示活结点优先队列。堆中每个结点的子树费用的下界lcost值是优先队列的优先级。接着算法计算出图中每个顶点的
23、最小费用出边并用minout记录。如果所给的有向图中某个顶点没有出边,则该图不可能有回路,算法即告结束。如果每个顶点都有出边,则根据计算出的minout作算法初始化。 算法的while循环体完成对排列树内部结点的扩展。对于当前扩展结点,算法分2种情况进行处理:46旅行售货员问题2. 算法描述 1、首先考虑s=n-2的情形,此时当前扩展结点是排列树中某个叶结点的父结点。如果该叶结点相应一条可行回路且费用小于当前最小费用,则将该叶结点插入到优先队列中,否则舍去该叶结点。 2、当sn-2时,算法依次产生当前扩展结点的所有儿子结点。由于当前扩展结点所相应的路径是x0: s,其可行儿子结点是从剩余顶点x
24、s+1: n-1中选取的顶点xi,且(xs,xi)是所给有向图G中的一条边。对于当前扩展结点的每一个可行儿子结点,计算出其前缀(x0:s, xi)的费用cc和相应的下界lcost。当lcostbestc时,将这个可行儿子结点插入到活结点优先队列中。 47旅行售货员问题2. 算法描述 算法中while循环的终止条件是排列树的一个叶结点成为当前扩展结点。当s=n-1时,已找到的回路前缀是x0:n-1,它已包含图G的所有n个顶点。因此,当s=n-1时,相应的扩展结点表示一个叶结点。此时该叶结点所相应的回路的费用等于cc和lcost的值。剩余的活结点的lcost值不小于已找到的回路的费用。它们都不可能
25、导致费用更小的回路。因此已找到的叶结点所相应的回路是一个最小费用旅行售货员回路,算法可以结束。 算法结束时返回找到的最小费用,相应的最优解由数组v给出。 48旅行售货员问题3. 算法举例 参见一个五结点的TSP实例。32983475246197638513C49电路板排列问题算法描述 算法开始时,将排列树的根结点置为当前扩展结点。在do-while循环体内算法依次从活结点优先队列中取出具有最小cd值的结点作为当前扩展结点,并加以扩展。 首先考虑s=n-1的情形,当前扩展结点是排列树中的一个叶结点的父结点。x表示相应于该叶结点的电路板排列。计算出与x相应的密度并在必要时更新当前最优值和相应的当前
26、最优解。 当sn-1时,算法依次产生当前扩展结点的所有儿子结点。对于当前扩展结点的每一个儿子结点node,计算出其相应的密度node.cd。当node.cdbestd时,将该儿子结点N插入到活结点优先队列中。50电路板排列问题算法描述do / 结点扩展 if (E.s = n - 1) / 仅一个儿子结点 int ld = 0; / 最后一块电路板的密度 for (int j = 1; j = m; j+) ld += BE.xnj; if (ld bestd) / 密度更小的电路板排列 delete bestx; bestx = E.x; bestd = max(ld, E.cd); s=n
27、-1的情况,计算出此时的的情况,计算出此时的密度和密度和bestd进行比较。进行比较。51电路板排列问题算法描述else / 产生当前扩展结点的所有儿子结点 for (int i = E.s + 1; i = n; i+) BoardNode N; N.now = new int m+1; for (int j = 1; j = m; j+) / 新插入的电路板 N.nowj = E.nowj + BE.xij; 52电路板排列问题算法描述int ld = 0; / 新插入电路板的密度 for (int j = 1; j 0 & totalj != N.nowj) ld+; N.cd = ma
28、x(ld, E.cd); if (N.cd bestd) / 可能产生更好的叶结点 N.x = new int n+1; N.s = E.s + 1; for (int j = 1; j =r+1时依非减序排列,S1则取得极小值(机器1没有空闲时间)。同理如果选择Pk使t2pk 依非减序排列,则S2取得极小值(机器2没有空闲时间) 。 ,max212SSFfMii这可以作为优先队列式分支限界法中的限界函数。 57批处理作业调度问题3. 算法描述 算法的while循环完成对排列树内部结点的有序扩展。在while循环体内算法依次从活结点优先队列中取出具有最小bb值(完成时间和下界)的结点作为当前扩
29、展结点,并加以扩展。 首先考虑E.s=n的情形,当前扩展结点E是排列树中的叶结点。E.sf2是相应于该叶结点的完成时间和。当E.sf2 bestc时更新当前最优值bestc和相应的当前最优解bestx。 当E.sn时,算法依次产生当前扩展结点E的所有儿子结点。对于当前扩展结点的每一个儿子结点node,计算出其相应的完成时间和的下界bb。当bb bestc时,将该儿子结点插入到活结点优先队列中。而当bb bestc时,可将结点node舍去。 58批处理作业调度问题3. 算法描述 while (E.s = n ) if (E.s = n ) / 叶结点 if (E.sf2 bestc) bestc
30、 = E.sf2; for (int i = 0; i n; i+) bestxi = E.xi; delete E.x; 当当E.sf2bestc时,更新当前最优时,更新当前最优值值bestc和相应的最优解和相应的最优解bestx59批处理作业调度问题3. 算法描述 else / 产生当前扩展结点的儿子结点 for (int i = E.s; i n; i+) Swap(E.xE.s,E.xi); int f1,f2; int bb=Bound(E,f1,f2,y); if (bb bestc ) MinHeapNode N; N.NewNode(E,f1,f2,bb,n); H.Insert(N); Swap(E.xE.s,E.xi); delete E.x; / 完成结点扩展当当bbbestc时,将儿子结点时,将儿子结点插入到活结点优先队列中插入到活结点优先队列中