python解决分支限界法解决分配问题

#-*- coding:utf-8 -*-
import numpy as np
import os

#打印二维数组的函数,用以显示计算过程
def printTable(Data):
    for i in range(len(Data[0])):
        for y in range(len(Data)):
            if y == len(Data) -1 :
                dot = '\n'
            else:
                dot =' '
            print(Data[y][i], end=dot)

#分支算法执行类
class Worker:
    maxi = 0  #上界通过贪心算法找出近似值
    pt_nodes = []  #存放可扩展的节点
    pt_flag = 0  #标记队列是否被使用,用于结束算法
    n = 0  #数据矩阵的大小 n*n
    min_leaf_node = None  #消耗最小的叶子节点

    #初始化
    def __init__(self, matrix):
        self.n = len(matrix)
        self.get_up_limit()

    #贪心算法获取花费时间的数据上界
    def get_up_limit(self):

        #初始化n个作业被分配情况
        worker_mark = [0] * self.n
        for i in range(self.n):
            worker_mark.append(0)

        #利用贪心算法,从第1个作业开始寻找到完成它花费时间最少的工作人员,并记录,最终取得近似最优解
        for i in range(self.n):    #循环遍历n个作业
            temp = matrix[i]    #获得第i个作业被不同的n个工作人员完成的时间数组temp
            min_cost = float("inf")    #初始化最小时间为inf
            index = 0    #初始化第i个作业未被分配
            for k in range(self.n):    #循环n个工作人员,找到完成作业i时间最小的工作人员
                if worker_mark[k] == 0 and min_cost > temp[k]:    #如果第k个工人未被分配作业并且第i个作业被第k个人员完成的时间小于最小时间时
                    min_cost = temp[k]    #将当前完成时间赋给最小时间值
                    index = k    #记录第i个作业被第k个工人完成获得当前最小时间花费
            worker_mark[index] = 1  #标记被分配作业的工作人员k
            self.maxi += min_cost  #累积计算上限值

    #队列式(FIFO)分支界限算法,得到并输出最终结果
    def branch_limit(self):
        for i in range(self.n):    #循环n个工作人员
            time = matrix[0][i]    #得到第i个工作人员完成不同作业的时间
            if time <= self.maxi:    #如果完成时间小于最大值
                node = Node()    #则创建节点
                #初始化节点
                node.deep = 0    
                node.cost = time    
                node.worker = i    
                self.pt_nodes.append(node)    #将节点放入队列

            while (1):
                if len(self.pt_nodes) == 0:    #如果队列为空
                    break    #结束循环
                temp = self.pt_nodes.pop(0)    #队列非空,则遵守先进先出,弹出一个节点
                present_node = temp    #将当前节点看作父节点
                total_cost = temp.cost    #获得遍历至当前节点的总时间花费
                present_deep = temp.deep    #得到当前节点的深度

                #初始化工人分配标记数组
                worker_mark = []
                for i in range(self.n):
                    worker_mark.append(0)

                #检查本节点下的作业分配情况
                worker_mark[temp.worker] = 1    #将被分配的工人标记为1
                while temp.father is not None:    #如果当前节点有父节点
                    temp = temp.father    #则取出当前节点的父节点
                    worker_mark[temp.worker] = 1    #将父节点的标记置为1

                if present_deep + 1 == self.n:    #如果遍历深度达到n
                    if self.min_leaf_node is None:    #遍历至最后一个叶子节点不存在
                        self.min_leaf_node = present_node    #则取当前节点为叶子节点
                    else:    
                        if self.min_leaf_node.cost > present_node.cost:    #如果叶子节点时间花费大于父节点
                            self.min_leaf_node = present_node    #则取父节点为叶子节点
                else:
                    #否则获取当前节点的子节点
                    children = matrix[present_deep + 1]
                    #检查本节点的子节点是否满足进入队列的要求
                    for k in range(self.n):
                        if children[k] + total_cost <= self.maxi and worker_mark[k] == 0:    #如果时间花费小于最小值,并且第k个人未被分配工作
                            node = Node()   #则创建节点
                            node.deep = present_deep + 1
                            node.cost = children[k] + total_cost    #将当前时间加上总时间花费计入新的创建节点中
                            node.worker = k    #添加节点参数
                            node.father = present_node    #添加节点父节点
                            self.pt_nodes.append(node)    #将节点放入队列

        #输出算法执行的结果
        temp = self.min_leaf_node
        print('\n总花费时间最短为:\n' + str(temp.cost) + '\n工作分配如下所示:')
        print('第'+str(temp.worker+1) + '位工人被分配了第'+str(temp.deep+1) + '份工作')
        while temp.father is not None:    #如果存在父节点
            temp = temp.father    #返回父节点
            print('第' + str(temp.worker + 1) + '位工人被分配了第' + str(temp.deep + 1) + '份工作')

#分支节点类
class Node:
    def __init__(self):
        self.deep = 0  #标记该节点的深度
        self.cost = 0  #标记到达该节点的总时间花费
        self.father = None  #标记该节点的父节点
        self.worker = None  #本节点的该任务由第几位工人完成

file_name = ['input_assgin05_01.dat','input_assgin05_02.dat','input_assgin05_03.dat',
             'input_assgin05_04.dat','input_assgin05_05.dat']
for file_name in file_name:
    a = np.loadtxt(file_name)  #读取存数文档
    n = int( a[0][0] )  #读取小区数目
    matrix = [[0 for col in range(n)] for row in range(n)]   #初始化存储作业人员完成作业的时间花费
    #存储作业人员完成作业的时间花费至二维数组p中
    for i in range(n):
        for j in range(n):
            matrix[i][j]=a[i+1][j]
    print('\n###############################')
    print ('{0}文件中的测试结果:'.format(file_name))
    print('\n'+str(n)+'个工人完成'+str(n)+'个作业的时间表为:')
    printTable(matrix)
    #  初始化算法执行类
    worker = Worker(matrix)
    #  执行分支界限算法
    worker.branch_limit()
os.system("pause")




输入方式:

 百度云盘自取

 链接:https://pan.baidu.com/s/1hPrCHWV0848UZlgub7oYCg

提取码:1111

我发了另外一篇博客资源需要的直接跳转(我设置的0积分,大家随便拿)https://download.csdn.net/download/ccy423/87124111

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值