python实现分支限界算法的案例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python实现分支限界算法的案例相关的知识,希望对你有一定的参考价值。

参考技术A 分支限界法的基本思想:

求解目标:分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。

搜索方式:以广度优先或以最小耗费优先的方式搜索解空间树。分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。

在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。

此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。

分支限界法示例:

单源最短路径:

问题:给定一个带权 有向图 G=(V,E),其中每条边的权是一个实数。另外,还给定V中的一个顶点,称为源。现在要计算从源到其他所有各顶点的 最短路径 长度。这里的长度就是指路上各边权之和。

分析:

分支限界法的步骤如下:

1)按宽度优先策略遍历解空间树

2)在遍历过程中,对处理的每个结点i,根据界限函数,估计沿该结点向下搜索所可能达到的完全解的目标函数的可能取值范围—界限bound(i)=[dow(i), up(i)]

3) 从中选择使目标函数取的极小值的结点优先进行宽度优先搜索,从而不断调整搜索方向,尽快找到问题解。

在每次分支后,对凡是界限超出已知可行解值那些子集不再做进一步分支。这样,解的许多子集(即搜索树上的许多结点)就可以不予考虑了,从而缩小了搜索范围。

将这个图转化成树的形式,如下所示:

创建队列。 1.节点1入队列,Q={1}。

我们取出队头节点,作为扩散节点,更新他的后代的值。此题中更新节点2,3,4 的距离,并将他们加入队列,Q={1,2,3,4}。 完成后节点1出队。Q={2,3,4}。

2.同样,重复1的步骤,Q={3,4,5,6};

3.当我们取到节点3时,我们发现源点->节点3->节点6的距离为11,大于1-2-6这条路径的权重,所以1-3-6这条路径之后我们不再考虑。 这就是“限界”(称为”剪枝“)的思想。

4. 重复步骤,直到Q为空。优先队列法方法和FIFO方法类似,区别在于优先队列每次取队列元素中到源点距离最短的点。

# -*- coding: utf-8 -*-

"""

Created on Sun Mar  7 19:03:09 2021

@author: iron

"""

# Author:Iron

# 初始化图参数 用字典初始初始化这个图

G = 1: 2: 4, 3: 2,4:5,

    2: 5: 7, 6: 5,

    3: 6: 9,

    4: 5: 2, 7: 7,

    5: 8: 4,

    6: 10:6,

    7: 9: 3,

    8: 10:7,

    9: 10:8,

    10:

   

inf=9999

#保存源点到各点的距离,为了让顶点和下标一致,前面多了一个inf不用在意。

length=[inf,0,inf,inf,inf,inf,inf,inf,inf,inf,inf]

Q=[]

#FIFO队列实现

def branch(G,v0):

    Q.append(v0)

    dict=G[1]

    while len(Q)!=0:

          #队列头元素出队

          head=Q[0]

          #松弛操作,并且满足条件的后代入队

          for key in dict:

              if length[head]+G[head][key]<=length[key]:

                    length[key]=length[head]+G[head][key]

                    Q.append(key)

        #松弛完毕,队头出列

          del Q[0]

          if len(Q)!=0:

              dict=G[Q[0]]

'''

#优先队列法实现

def branch(G, v0):

    Q.append(v0)

    while len(Q) != 0:

          min=99999

          flag=0

          #找到队列中距离源点最近的点

          for v in Q:

              if min > length[v]:

                    min=length[v]

                    flag = v

          head = flag

          dict=G[head]

          #找到扩散点后进行松弛操作

          for key in dict:

              if length[head] + G[head][key] <= length[key]:

                    length[key] = length[head] + G[head][key]

                    Q.append(key)

          #松弛完毕后,该扩散点出队

          Q.remove(head)

'''

branch(G,1)

print(length)

运行结果:[9999, 0, 4, 2, 5, 7, 9, 12, 11, 15, 15]。

算法---分支限定0/1背包--蚁群算法

用蚁群算法解决01背包问题。

我本以为就是完全的蛮力法,但百度后觉得应该是这个

(4)分支限界-优先队列(STL) 

技术图片


// #  分支限界优先队列法
//  队列中的节点类型
struct NodeType
{//  分支限界节点
 int no;     //  节点编号
 int i;     //  当前节点在搜索空间的层次
 int w;     //  当前节点的总重量
 int v;     //  当前节点的总价值
 int x[MAXN];           //  当前节点包含的解向量
 double ub;    // 上界
 
 bool operator<(const NodeType& node) const
 {//  优先队列按此方式排序
  return ub < node.ub;         //  ub越大越优先出队
 }
};
/*  主干
 *  ->初始化根节点
 *  ->计算根节点上界及进队
 *  ->循环遍历队列,条件为非空:出一个节点,
       计算左孩子节点剪枝条件,满足的左孩子计算上界及进队;
       计算右孩子节点上界,符合上界条件的右孩子进队;
    (根据容量剪去左孩子,根据上界条件剪去右孩子)
 *
*/
void bfs();  
//  进队----不是叶子节点就直接进队,是叶子节点则判断是否更优解,是的话则更新最优解
void EnQueue(NodeType e,priority_queue<NodeType> &qu);
//  计算边界 就是根据剩余容量的大小,计算剩下全部物品装入的价值和装入部分物品的价值
//  (部分物品按照单位容量内价值高低的顺序装入---这有点贪心的思想了)
void bound(NodeType &e);
// !#  分支限界优先队列法

 

 


版权声明:本文为CSDN博主「D丶酒舞」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010323330/article/details/80302227

以上是关于python实现分支限界算法的案例的主要内容,如果未能解决你的问题,请参考以下文章

算法与程序设计:分支限界法

优先队列式分支限界法-最小重量机器设计问题

浅谈分支限界算法

动态规划回溯搜索分治算法分支限界算法

五大常用算法:分支限界法

计算机算法与分析——7.1分枝-限界法