分支限界法程序

#队列式分支限界法

import math

import queue

class Node:

    def __init__(self,cp,cw,myid):

        self.cp = cp

        self.cw = cw

        self.id = myid

def bound(node):

    global c,goods

    cleft = c - node.cw

    b = node.cp

    i =int(math.log2(node.id)) + 1#round(math.log2(node.id))求出节点深度,节点深度+1为所处的层次数,剩余物品为层次数....n+1

    while(i<n and goods[i][1]<=cleft):

        cleft -= goods[i][1]

        b +=goods[i][2]

        i +=1

    if(i<n):

        b += goods[i][2]/goods[i][1]*cleft;

    return b   

def queue_branch(capacity):

    global goods,n

    bestp = 0

    best = 0

    que =queue.Queue()

    node = Node(0,0,1)#根节点,当前重量cw为0,当前价值cp为0,根节点编号id为1

    que.put(node)

    while(not que.empty()):

        current_node = que.get()

        depth = int(math.log2(current_node.id))

        if depth == n:#叶子表示找到了一个比当前解更好的一个解,记录之

            bestp = current_node.cp

            best = current_node.id

        else:

            if current_node.cw + goods[depth][1] <= capacity:

                if(current_node.cp + goods[depth][2]> bestp):

                    bestp = current_node.cp + goods[depth][2]

                    best = current_node.id * 2#记录当前最优的节点编号

                alive_node = Node(current_node.cp + goods[depth][2],current_node.cw + goods[depth][1],current_node.id*2)

                que.put(alive_node)

            up = bound(current_node)

            if up > bestp:

                alive_node = Node(current_node.cp,current_node.cw,current_node.id * 2 + 1)

                que.put(alive_node)

    return bestp,best

def get_bestx(best):

    global n,goods

    bestx=[0 for i in range(n)]

    i = best

    depth = int(math.log2(best))

    while i>1:

        depth = int(math.log2(i))

        s,y = divmod(i,2)#s为商,是父节点的编号,y为余数,余数是0,则为左孩子,记录1,反之,记录0

        if y == 0:

            bestx[goods[depth-1][0]]=1

        else:

            bestx[goods[depth-1][0]]=0

        i = s

    return bestx

if  __name__ == '__main__':

    n=5 #问题规模

    c=10#背包容量

    #c = 20

    goods = [[0,2,6],[1,2,3],[2,6,5],[3,5,4],[4,4,6]]

    #goods = [[0,5,7],[1,4,9],[2,8,15],[3,12,21],[4,13,24]]

    goods.sort(key = lambda x:x[2]/x[1],reverse = True)

    bestp,best = queue_branch(c)

    bestx =  get_bestx(best)

    print("最大价值为:", bestp)

print("最优解为:", bestx)

#优先队列式

import math

import heapq

class Node:

    def __init__(self,cp,cw,myid,up):

        self.up = up#价值上界,按照价值上界构造极大堆

        self.cp = cp

        self.cw = cw

        self.id = myid

    def __gt__(self,other):

        return self.up > other.up

    def __eq__(self, other):

        if(other == None):

            return False

        if(not isinstance(other, HeapNode)):

            return False

        return self.up == other.up

def bound(node):

    global c,goods

    cleft = c - node.cw

    b = node.cp

    i =int(math.log2(node.id)) + 1#round(math.log2(node.id))求出节点深度,节点深度+1为所处的层次数,剩余物品为层次数....n+1

    while(i<n and goods[i][1]<=cleft):

        cleft -= goods[i][1]

        b +=goods[i][2]

        i +=1

    if(i<n):

        b += goods[i][2]/goods[i][1]*cleft;

    return b   

def first_queue_branch(capacity):

    global goods,n

    bestp=0

    best=0

    heap = []

    node = Node(0,0,1,0)#根节点,当前重量cw为0,当前价值cp为0,根节点编号id为1

    node.up = bound(node)

    heapq.heappush(heap,node)

    while(len(heap)>0):

        current_node = heapq.heappop(heap)

        depth = int(math.log2(current_node.id))

        if depth == n:#叶子表示找到了一个比当前解更好的一个解,记录之

            bestp = current_node.cp

            best = current_node.id

        else:

            if current_node.cw + goods[depth][1] <= capacity:

                if(current_node.cp + goods[depth][2]> bestp):

                    bestp = current_node.cp + goods[depth][2]

                    best = current_node.id * 2#记录当前最优的节点编号

                alive_node = Node(current_node.cp + goods[depth][2],current_node.cw + goods[depth][1],current_node.id*2,current_node.up)

                heapq.heappush(heap,alive_node)

            up = bound(current_node)

            if up > bestp:

                alive_node = Node(current_node.cp,current_node.cw,current_node.id * 2 + 1,up)

                heapq.heappush(heap,alive_node)

    return bestp,best

def get_bestx(best):

    global n,goods

    bestx=[0 for i in range(n)]

    i = best

    depth = int(math.log2(best))

    while i>1:

        depth = int(math.log2(i))

        s,y = divmod(i,2)#s为商,是父节点的编号,y为余数,余数是0,则为左孩子,记录1,反之,记录0

        if y == 0:

            bestx[goods[depth-1][0]]=1

        else:

            bestx[goods[depth-1][0]]=0

        i = s

    return bestx

if  __name__ == '__main__':

    n=5#问题规模

    c = 20#背包容量

    goods = [[0,5,7],[1,4,9],[2,8,15],[3,12,21],[4,13,24]]#物品编号,物品重量,物品价值

    goods.sort(key = lambda x:x[2]/x[1],reverse = True)

    bestp,best = first_queue_branch(c)

    bestx =  get_bestx(best)

    print("最大价值为:",bestp)

    print("最优解为:",bestx)

#队列式分支限界法,限界条件为cl<bestL

import math

import queue

class Node:

    def __init__(self,cl,level,x):#cl:当前路径长度,level:当前节点层次,g_n:问题规模

        self.cl = cl#当前路径长度

        self.level = level#节点的层次

        self.x = x#部分解

       

def traveling(a,start,g_n):

    que =queue.Queue()

    node = Node(0,2,[i for i in range(g_n+1)])#

    que.put(node)

    bestx =None#最大价值

    bestl = NoEdge

    while(not que.empty()):

        current_node = que.get()

        level = current_node.level

        cl = current_node.cl

        if level == g_n:#叶子表示找到了一个比当前解更好的一个解,记录之

            if (a[current_node.x[g_n-1]][current_node.x[g_n]] != NoEdge and  a[current_node.x[g_n]][1] != NoEdge and (cl + a[current_node.x[g_n-1]][current_node.x[g_n]] + a[current_node.x[g_n]][1] < bestl or bestl == NoEdge)):

                bestx = current_node.x[:]

                bestl = cl + a[current_node.x[g_n-1]][current_node.x[g_n]] + a[current_node.x[g_n]][1]

        else:

            for j in range(level,g_n+1):

                if (a[current_node.x[level-1]][current_node.x[j]] != NoEdge and (cl < bestl or bestl == NoEdge)):

                    current_node.x[level], current_node.x[j] = current_node.x[j], current_node.x[level]

                    que.put(Node(cl + a[current_node.x[level-1]][current_node.x[level]],level+1,current_node.x[:]))

                    current_node.x[level], current_node.x[j] = current_node.x[j], current_node.x[level]

    return bestx,bestl

   

if __name__ == '__main__':

    import sys

    NoEdge = sys.maxsize

    #a = [[NoEdge,NoEdge,NoEdge,NoEdge,NoEdge],[NoEdge,NoEdge,30,50,4],[NoEdge,30,NoEdge,5,15],[NoEdge,50,5,NoEdge,3],[NoEdge,4,15,3,NoEdge]]

    a = [[NoEdge,NoEdge,NoEdge,NoEdge,NoEdge,NoEdge],[NoEdge,NoEdge,10,NoEdge,4,12],[NoEdge,10,NoEdge,15,8,5],[NoEdge,NoEdge,15,NoEdge,7,30],[NoEdge,4,8,7,NoEdge,6],[NoEdge,12,5,30,6,NoEdge]]

    g_n = len(a) - 1

    bestx,bestl = traveling(a,1,g_n)

    print("最短路径长度为:", bestl)

    print("最优旅行路线为:", bestx)

#优先队列式分支限界法,限界条件为cl<bestl

import heapq

class Node:

    def __init__(self,cl,level,x):#cl:当前路径长度,level:当前节点层次,g_n:问题规模

        self.cl = cl#当前路径长度

        self.level = level#节点的层次

        self.x = x#部分解

       

    def __lt__(self,other):

        return self.cl < other.cl

    def __eq__(self, other):

        if(other == None):

            return False

        if(not isinstance(other, HeapNode)):

            return False

        return self.cl == other.cl

def traveling(a,start,g_n):

    heap = []

    bestx =None#最大价值

    bestl = NoEdge

    node = Node(0,2,[i for i in range(g_n+1)])#

    heapq.heappush(heap,node)

    while(len(heap)>0):

        current_node = heapq.heappop(heap)

        level = current_node.level

        cl = current_node.cl

        if level == g_n:#叶子表示找到了一个比当前解更好的一个解,记录之

            if (a[current_node.x[g_n-1]][current_node.x[g_n]] != NoEdge and  a[current_node.x[g_n]][1] != NoEdge and (cl + a[current_node.x[g_n-1]][current_node.x[g_n]] + a[current_node.x[g_n]][1] < bestl or bestl == NoEdge)):

                bestx = current_node.x[:]

                bestl = cl + a[current_node.x[g_n-1]][current_node.x[g_n]] + a[current_node.x[g_n]][1]

        else:

            for j in range(level,g_n+1):

                if (a[current_node.x[level-1]][current_node.x[j]] != NoEdge and (cl < bestl or bestl == NoEdge)):

                    current_node.x[level], current_node.x[j] = current_node.x[j], current_node.x[level]

                    heapq.heappush(heap,Node(cl + a[current_node.x[level-1]][current_node.x[level]],level+1,current_node.x[:]))

                    current_node.x[level], current_node.x[j] = current_node.x[j], current_node.x[level]

    return bestx,bestl

if __name__ == '__main__':

    import sys

    NoEdge = sys.maxsize

    #a = [[NoEdge,NoEdge,NoEdge,NoEdge,NoEdge],[NoEdge,NoEdge,30,50,4],[NoEdge,30,NoEdge,5,15],[NoEdge,50,5,NoEdge,3],[NoEdge,4,15,3,NoEdge]]

    a = [[NoEdge,NoEdge,NoEdge,NoEdge,NoEdge,NoEdge],[NoEdge,NoEdge,10,NoEdge,4,12],[NoEdge,10,NoEdge,15,8,5],[NoEdge,NoEdge,15,NoEdge,7,30],[NoEdge,4,8,7,NoEdge,6],[NoEdge,12,5,30,6,NoEdge]]

    g_n = len(a) - 1

    traveling(a,1,g_n)

    print("最短路径长度为:", bestl)

    print("最优旅行路线为:", bestx)

import heapq

class Node:

    def __init__(self,cl,level,rl,x):#cl:当前路径长度,level:当前节点层次,g_n:问题规模

        self.cl = cl#当前路径长度

        self.level = level#节点的层次

        self.bl = self.cl + rl #路径长度下界

        self.x = x#部分解

       

    def __lt__(self,other):

        return self.bl < other.bl

    def __eq__(self, other):

        if(other == None):

            return False

        if(not isinstance(other, HeapNode)):

            return False

        return self.bl == other.bl

def lower_bound(a):

    n = len(a)

    Minout = []

    rl = 0

    for i in range(1,n):#计算最小出边及其路径长度和

        minout = min(a[i])

        rl += minout

        Minout.append(minout)

    return rl,Minout

  

def traveling(a,start,g_n):

    rl,Minout = lower_bound(a)

    heap = []

    bestx =None#最大价值

    bestl = NoEdge

    node = Node(0,2,rl,[i for i in range(g_n+1)])#

    heapq.heappush(heap,node)

    while(len(heap)>0):

        current_node = heapq.heappop(heap)

        level = current_node.level

        cl = current_node.cl

        rl = current_node.bl - cl

        if level == g_n:#叶子表示找到了一个比当前解更好的一个解,记录之

            if (a[current_node.x[g_n-1]][current_node.x[g_n]] != NoEdge and  a[current_node.x[g_n]][1] != NoEdge and (cl + a[current_node.x[g_n-1]][current_node.x[g_n]] + a[current_node.x[g_n]][1] < bestl or bestl == NoEdge)):

                bestx = current_node.x[:]

                bestl = cl + a[current_node.x[g_n-1]][current_node.x[g_n]] + a[current_node.x[g_n]][1]

        else:

            rl -= Minout[level-1]

            for j in range(level,g_n+1):

                if (a[current_node.x[level-1]][current_node.x[j]] != NoEdge and (cl + rl < bestl or bestl == NoEdge)):

                    current_node.x[level], current_node.x[j] = current_node.x[j], current_node.x[level]

                    heapq.heappush(heap,Node(cl + a[current_node.x[level-1]][current_node.x[level]],level+1,rl,current_node.x[:]))

                    current_node.x[level], current_node.x[j] = current_node.x[j], current_node.x[level]

    return bestx,bestl

if __name__ == '__main__':

    import sys

    NoEdge = sys.maxsize

    #a = [[NoEdge,NoEdge,NoEdge,NoEdge,NoEdge],[NoEdge,NoEdge,30,50,4],[NoEdge,30,NoEdge,5,15],[NoEdge,50,5,NoEdge,3],[NoEdge,4,15,3,NoEdge]]

    a = [[NoEdge,NoEdge,NoEdge,NoEdge,NoEdge,NoEdge],[NoEdge,NoEdge,10,NoEdge,4,12],[NoEdge,10,NoEdge,15,8,5],[NoEdge,NoEdge,15,NoEdge,7,30],[NoEdge,4,8,7,NoEdge,6],[NoEdge,12,5,30,6,NoEdge]]

    g_n = len(a) - 1

    bestx,bestl = traveling(a,1,g_n)

    print("最短路径长度为:", bestl)

    print("最优旅行路线为:", bestx)

#队列式分支限界法

import queue

class Node:

    def __init__(self,row,col):

        self.row = row

        self.col = col

def findpath(start,finish):

    global grid,offset

    pathLen = 0

    if(start.row==finish.row) and (start.col==finish.col):#起点与终点相同,不用布线

        pathLen = 0

    # return

    here = start

    grid[start.row][start.col]=0

    que = queue.Queue()

    que.put(start)

    while(True):

        here = que.get()

        for i in range(4):#沿着扩展结点的右、下、左、上四个方向扩展

            nbr = Node(here.row + offset[i].row,here.col + offset[i].col)

            #print("nbr.row = "+str(nbr.row))

            #print("nbr.col =" +str(nbr.col))

            if(grid[nbr.row][nbr.col] == -1):#如果这个方格还没有扩展

                grid[nbr.row][nbr.col] = grid[here.row][here.col] + 1

                if((nbr.row == finish.row) and (nbr.col==finish.col)):

                    break  #如果到达终点结束

                que.put(nbr)#此邻结点放入队列

        if((nbr.row==finish.row) and (nbr.col==finish.col)):

            break #完成布线

        if que.empty():

            return

def build_path(grid,start,finish):

    global offset

    pathlen=grid[finish.row][finish.col]

    path = []

    here=finish

    for j in range(pathlen-1,-1,-1):

        path.insert(0,here)

        for i in range(4):#四个方向扩展

            nbr = Node(here.row+offset[i].row,here.col+offset[i].col)

            if (grid[nbr.row][nbr.col]==j):

                break

        here=nbr  #往回推进

    path.insert(0,start)

    return path ,pathlen

if __name__ == "__main__":

    n = 9#行数

    m = 7#列数

    grid = [[ -1 for j in range(m+2)]for i in range(n+2)]

    grid[1][6] = -2

    grid[2][3] = -2

    grid[3][3] = -2

    grid[3][5] = -2

    grid[3][6] = -2

    grid[4][3] = -2

    grid[5][6] = -2

    grid[6][5] = -2

    grid[6][4] = -2

    grid[6][6] = -2

    grid[7][6] = -2

    grid[9][3] = -2

    grid[9][5] = -2

    offset = [Node(0,1),Node(1,0),Node(0,-1),Node(-1,0)]

    start = Node(3,2)

    finish = Node(6,7)

    for i in range(n+2):# 方格阵列的上下“围墙”

        grid[i][0] = -2

        grid[i][m+1] = -2

    for i in range(m+2):

        grid[0][i] = -2

        grid[n+1][i] = -2

    findpath(start,finish)

    path,pathlen = build_path(grid,start,finish)

    print("布线长度为:", pathlen)

    print("布线方案为:")

    for i in range(len(path)):

        print("path["+str(i)+"].row=" + str(path[i].row)+"     path["+str(i)+"].col=" + str(path[i].col))

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值