#队列式分支限界法
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))