42、动态规划-资源分配问题

import random as rd
import matplotlib.pyplot as plt
import functools
import math
import copy
import time
from pyscipopt import Model, quicksum

#资源分配问题,例如n台机器分给m个工厂

def sub_LL_print(L, digit):
    s = "["
    for i in range(len(L)):
        s = s + str(L[i])
        temp = L[i]
        digit_temp = 1
        while temp//10>0:
            digit_temp += 1
            temp = temp//10
        for j in range(digit-digit_temp):
            s += " "
        if i < len(L)-1:
            s += ",  "
    s += "]"
    return s

def LL_print(name, LL):
    LL1 = [[int(LL[i][j]) for j in range(len(LL[i]))] for i in range(len(LL))]
    num_max = max([max(LL1[i]) for i in range(len(LL1))])
    digit = 1
    while num_max//10>0:
        digit += 1
        num_max = num_max // 10

    print("\n"+name+":")
    print("["+sub_LL_print(LL[0], digit)+",")
    for i in range(1,len(LL)-1):
        print(" "+sub_LL_print(LL[i], digit)+",")
    print(" " + sub_LL_print(LL[-1], digit) + "]")

def G_generate(m, n):

    G = [[0 for j in range(n+1)] for i in range(m)]

    for i in range(m):
        for j in range(1,n+1):
            G[i][j] = G[i][j-1] + int(rd.random() * 5)

    return G

def IP(dG, time_limit):

    m = len(dG)
    n = len(dG[0])-1

    model = Model("Resource_allocation_IP")
    A = [[model.addVar(vtype="B", name="A[%s,%s]" % (i, j)) for j in range(n+1)] for i in range(m)]

    # 以总成本最小为目标
    model.setObjective(quicksum(dG[i][j]*A[i][j] for i in range(m) for j in range(n+1)), "maximize")

    # A[i][j] >= A[i][j+..]
    for i in range(m):
        for j in range(n):
            for k in range(j+1, n+1):
                model.addCons(A[i][j] - A[i][k] >= 0)

    model.addCons(quicksum(A[i][j] for i in range(m) for j in range(1,n+1)) == n)

    # 设置求解时间
    model.setRealParam("limits/time", time_limit)
    model.optimize()
    print("\ngap:",model.getGap())

    # 拿结果
    A1 = [[round(model.getVal(A[i][j])) for j in range(n + 1)] for i in range(m)]

    return A1

def DP(dG):

    m = len(dG)
    n = len(dG[0])-1

    # 局部结果,A[i][j]表示j个机器分给第i个工厂的情况下,
    A = [[0 if i > 0 else sum(dG[i][:j+1]) for j in range(n+1)] for i in range(m)]
    A_detail = [[[0 if i > 0 or k > 0 else j for k in range(m)] for j in range(n+1)] for i in range(m)]

    for i in range(1,m):
        gi = [sum(dG[i][:j+1]) for j in range(n+1)]
        for j in range(1, n+1):
            idex = 0
            for k in range(1, j+1):
                if A[i-1][idex] + gi[j - idex] < A[i-1][k] + gi[j - k]:
                    idex = k
            A[i][j] = A[i-1][idex] + gi[j - idex]
            A_detail[i][j] =  [A_detail[i-1][idex][k] if k != i else j - idex for k in range(m)]

    R = A_detail[m-1][n]

    A1 = [[1 if j <= R[i] else 0 for j in range(n+1)] for i in range(m)]

    return A1

def allocation(dG, time_limit = 100):

    A_IP = IP(dG, time_limit)
    A_DP = DP(dG)

    return A_IP, A_DP

if __name__ == "__main__":

    #工厂数、机器数
    m,n = 3,5

    #每个工厂有不同机器数目能产生的盈利
    G = G_generate(m, n)
    LL_print("G", G)

    #每台机器的边际效用
    dG = [[0 if j == 0 else G[i][j] - G[i][j - 1] for j in range(n + 1)] for i in range(m)]
    LL_print("dG", dG)

    # 求解,得到每个工厂分配的机器数
    A_IP, A_DP = allocation(dG, 100)
    LL_print("A_IP", A_IP)
    LL_print("A_DP", A_DP)

    # 每个工厂分配的机器数汇总
    R_IP = [sum(A_IP[i][1:]) for i in range(m)]
    R_DP = [sum(A_DP[i][1:]) for i in range(m)]
    print("\nR_IP:\n", R_IP)
    print("\nR_DP:\n", R_DP)

    # 价值
    g_IP = sum([sum(dG[i][:(R_IP[i] + 1)]) for i in range(m)])
    g_DP = sum([sum(dG[i][:(R_DP[i] + 1)]) for i in range(m)])
    print("\ng_IP:\n", g_IP)
    print("\ng_DP:\n", g_DP)


 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验课程:算法分析与设计 实验名称:用动态规划法求解资源分配问题 (验证型实验) 实验目标: (1)掌握用动态规划方法求解实际问题的基本思路。 (2)进一步理解动态规划方法的实质,巩固设计动态规划算法的基本步骤。 实验任务: (1)设计动态规划算法求解资源分配问题,给出算法的非形式描述。 (2) 在Windows环境下用C 语言实现该算法。计算10个实例,每个实例中n=30, m=10, Ci j为随机产生于范围(0,103)内的整数。记录各实例的数据及执行结果(即最优分配方案、最优分配方案的值)、运行时间。 (3)从理论上分析算法的时间和空间复杂度,并由此解释相应的实验结果。 实验设备及环境: PC;C/C++等编程语言。 实验主要步骤: (1) 根据实验目标,明确实验的具体任务; (2) 分析资源分配问题,获得计算其最优值的递推计算公式; (3) 设计求解问题的动态规划算法,并编写程序实现算法; (4) 设计实验数据并运行程序、记录运行的结果; (5) 分析算法的时间和空间复杂度,并由此解释释相应的实验结果; 问题分析: 问题描述: 某厂根据计划安排,拟将n台相同的设备分配给m个车间,各车间获得这种设备后,可以为国家提供盈利Ci j(i台设备提供给j号车间将得到的利润,1≤i≤n,1≤j≤m) 。问如何分配,才使国家得到最大的盈利? 算法基本思想: 本问题是一简单资源分配问题,由于具有明显的最优子结构,故可以使用动态规划求解,用状态量f[i][j]表示用i台设备分配给前j个车间的最大获利,那么显然有f[i][j] = max{ f[k][j–1] + c[i-k][j] },0<=k<=i。再用p[i][j]表示获得最优解时第j号车间使用的设备数为i-p[i][j],于是从结果倒推往回求即可得到分配方案。程序实现时使用顺推,先枚举车间数,再枚举设备数,再枚举状态转移时用到的设备数,简单3重for循环语句即可完成。时间复杂度为O(n^2*m),空间复杂度为O(n*m),倘若此题只需求最大获利而不必求方案,则状态量可以减少一维,空间复杂度优化为O(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值