python3 分支界限法解决作业分配问题

来源:互联网 发布:网络布线 报价 编辑:程序博客网 时间:2024/06/06 06:06
学号:S201625005姓名:梁勋联系电话:13126734215运行环境:MacOS serria 10.12.4 Beta (16E163f)程序语言:Python3分析设计:有n份作业分配给n个人去完成,每人完成一份作业。假定第i个人完成第j份作业需要花费cij时间,cij>0,1≦i,j≦n。试设计一个分支界限算法,将n份作业分配给n个人完成,使得总花费时间最少。这是一个寻找最优解的问题,通常的解决办法就是穷举出所有结果,找出最优解。分支界限算法是为了有效的避免穷举结果,这是一个广度优先的搜索操作数据结构:Node 类:        self.deep = 0  # 标记该节点的深度        self.cost = 0  # 标记到达该节点的总消费        self.father = None  # 标记该节点的父节点        self.value = 0  # 本节点的消费值        self.worker = None  # 本节点的该任务由第几位工人完成Node类用来存放分支树上的所有有效节点Worker 类:    max = 0  # 上界 通过贪心算法找出近似值    min = 0  # 下界 由每组的最小值组成    pt_nodes = []  # 存放可扩展的节点  FIFO    pt_flag = 0  # 标记队列是否被使用 用于结束算法    input_file = ''  # 输入文件名    output_file = ''  # 输出文件名    matrix = []  # 存放数据矩阵  行为单个任务 每个工人 完成所要的时间    n = 0  # 数据矩阵的大小 n*n    min_leaf_node = None  # 消耗最小的节点    function:        read_data_from_file  从文件中读取数据        get_low_limit 计算下界        get_up_limit  计算上界        branch_limit  执行分支界限算法        output_result  结果输出到文件算法思路:    1 将数据用n*n的矩阵来描述 M[i,j]表示第i个任务由第j位工人完成所耗时间    2 使用贪心算法计算一个近似的最优解作为上界    3 最小值求和法得到最优解的下界    4 针对第一个任务,检查每人的耗时是否超过上界,是则舍弃,否则创建节点加入队列    5 开始处理队列元素,先进先出,如果是子节点,判断是否是最优节点,否则 检查累积上下一个任务每人的耗时后是否超过上界,否则继续创建节点加入队列,是则舍弃    6 当队列处理完毕后,层层遍历最优节点的father节点,输出结果
代码如下:
#  分支算法执行类class Worker:    max = 0  # 上界 通过贪心算法找出近似值    min = 0  # 下界 由每组的最小值组成    pt_nodes = []  # 存放可扩展的节点    pt_flag = 0  # 标记队列是否被使用 用于结束算法    input_file = ''  # 输入文件名    output_file = ''  # 输出文件名    matrix = []  # 存放数据矩阵  行为单个任务 每个工人 完成所要的时间    n = 0  # 数据矩阵的大小 n*n    min_leaf_node = None  # 消耗最小的节点    #  初始化参数    def __init__(self, input_file, output_file):        self.input_file = input_file        self.output_file = output_file        self.read_data_from_file()        self.n = len(self.matrix)        self.get_low_limit()        self.get_up_limit()        # print(self.matrix)        # print(self.n)        # print(self.max)        # print(self.min)    #  从文件中读取数据 初始化数据矩阵    def read_data_from_file(self):        with open(self.input_file) as source:            for line in source:                data_cluster = line.split(',')                temp = []                for value in data_cluster:                    temp.append(int(value))                self.matrix.append(temp)    #  获取数据下界  最小值之和    def get_low_limit(self):        for i in range(self.n):            self.min += min(self.matrix[i])    #  获取数据上界  贪心算法    def get_up_limit(self):        #  初始化工人使用标记        worker_mark = []        for i in range(self.n):            worker_mark.append(0)        # 贪心算法 取得 近似最优解        for i in range(self.n):            temp = self.matrix[i]            min_value = 5000            index = 0            for k in range(self.n):                if worker_mark[k] == 0 and min_value > temp[k]:                    min_value = temp[k]                    index = k            worker_mark[index] = 1  # 标记工人是否被分配            self.max += min_value  # 累积上限值    #  分支界限算法    def branch_limit(self):        if self.pt_flag == 0:  # 从第一层开始            for i in range(self.n):                time = self.matrix[0][i]                if time <= self.max:  # 没达到上限,创建节点,加入队列                    node = Node()                    node.deep = 0                    node.cost = time                    node.value = time                    node.worker = i                    self.pt_nodes.append(node)            self.pt_flag = 1            while self.pt_flag == 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                while temp.father is not None:                    temp = temp.father                    worker_mark[temp.worker] = 1                if present_deep + 1 == self.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 = self.matrix[present_deep + 1]                    #  检查本节点的子节点是否符合进入队列的要求                    for k in range(self.n):                        if children[k] + total_cost <= self.max and worker_mark[k] == 0:                            node = Node()                            node.deep = present_deep + 1                            node.cost = children[k] + total_cost                            node.value = children[k]                            node.worker = k                            node.father = present_node                            self.pt_nodes.append(node)    #  输出算法执行的结果    def output_result(self):        file = open(self.output_file,'a')        temp = self.min_leaf_node        file.write('最少的消耗为:' + str(temp.cost) + '\n')        file.write('第'+str(temp.worker+1) + '位工人完成第'+str(temp.deep+1) + '份工作\n')        while temp.father is not None:            temp = temp.father            file.write('第' + str(temp.worker + 1) + '位工人完成第' + str(temp.deep + 1) + '份工作\n')        print('算法执行结果以及写入到文件:', self.output_file)#  分支节点类class Node:    def __init__(self):        self.deep = 0  # 标记该节点的深度        self.cost = 0  # 标记到达该节点的总消费        self.father = None  # 标记该节点的父节点        self.value = 0  # 本节点的消费值        self.worker = None  # 本节点的该任务由第几位工人完成#  主逻辑# input_file = 'input_assign05_01.dat'# input_file = 'input_assign05_02.dat'input_file = 'input_assign05_03.dat'# output_file = 'output_01.dat'# output_file = 'output_02.dat'output_file = 'output_03.dat'#  初始化算法执行类worker = Worker(input_file, output_file)#  执行分支界限算法worker.branch_limit()#  输出结果worker.output_result()
输入数据:
10,12,20,30,1823,30,8,12,2211,21,23,40,1633,34,23,19,2021,32,11,14,21

输出结果:
最少的消耗为:65第4位工人完成第5份工作第5位工人完成第4份工作第1位工人完成第3份工作第3位工人完成第2份工作第2位工人完成第1份工作
1 0
原创粉丝点击