Starting from scratch-Machine Learning study notes (9)-python implementation of dynamic programming 01 knapsack algorithm

​ Here I will first quote the explanation of the 01 knapsack algorithm in dd Daniel's nine lectures on knapsack.

​ The so-called 01 knapsack problem can be described as: there are N items and a knapsack with a capacity of V. The cost of the ith item is c[i] and the value is w[i]. Find which items to put into the backpack maximize the sum of the values.

​ This is the most basic backpack problem. The characteristic is that there is only one item of each type, and you can choose to put it or not.

Case 1: The i-th item is not put in, and the value obtained at this time is: f[ii][v]

Case 2: The i-th item is put in, and the value obtained at this time is: f[i-1][vc[i]]+w[i]

​ Its state transition equation is:

f [ i ] [ v ] = m a x { f [ i 1 ] [ v ] , f [ i 1 ] [ v c [ i ] ] + w [ i ] }

This equation is very important, and basically all equations related to knapsack are derived from it. So it is necessary to explain it in detail: the sub-problem "put the first i item into a knapsack of capacity v", if only the strategy of the i-th item (put or not) is considered, then it can be transformed into a Only the question of the first i-1 items is involved. If the i-th item is not put, then the problem is transformed into "put the first i-1 items into the knapsack of capacity v", and the value is f[i-1][v]; if the i-th item is put, then The problem is transformed into "the first i-1 items are put into the remaining backpack with a capacity of vc[i]", and the maximum value that can be obtained at this time is f[i-1][vc[i]] plus The value w[i] obtained by putting in the i-th item.

A typical knapsack algorithm:

def deploy_01bag(count_all, capacity, goods):
    '''
    典型01背包算法
    :param count_all:   int, 输入的物品总数
    :param capacity:    int, 背包的容量
    :param goods:       list, 用于装包的物品参数list[[物品的id,物品占据的容量,
                            物品的价值],[],[]...]
    :return:            返回装包方式,list[物品id1,物品id2,...]  最大价值 int
    '''

    bag = [[0 for col in range(capacity + 1)] for raw in range(count_all + 1)]
    result = []
    # 计算背包问题
    for i in range(1, count_all + 1):
        for j in range(1, capacity + 1):
            bag[i][j] = bag[i - 1][j]
            if j >= goods[i - 1][1]:
                bag[i][j] = max(bag[i][j], bag[i - 1][j - goods[i - 1][1]] + goods[i - 1][2])

    # 递推出装入背包的物体
    big = bag[i][j]
    j = capacity
    for i in range(count_all, 0, -1):
        if bag[i][j] > bag[i - 1][j]:
            result.append(goods[i - 1][0])
            j = j - goods[i - 1][1]

    return result, big

if __name__ == "__main__":
    capacity = 10
    goods = [[1, 2, 6],\
             [2, 2, 3],\
             [3, 6, 5],\
             [4, 5, 4],\
             [5, 4, 6]]

    result, big = deploy_01bag(len(goods), capacity, goods)

    print("背包最能装下的最大价值为:{0}\n装包的物品有:{1}".format(big, result))

The output is:

The maximum value that the backpack can hold is: 15
packs of items are: [5, 2, 1]

Another example:

​ To give a specific example, in the 2018 Huawei Software Elite Challenge, the topic was to predict the number of virtual machines used in a certain period of time in the future, and to give a deployment plan to make the resource occupancy rate of each physical server. maximum. There are two main types of physical server resources. One is CPU, the other is MEM (memory), and its value is fixed. When it is required to optimize the CPU, the resource occupancy rate of the CPU must be maximized, and the total MEM of the placed virtual machines must not exceed the MEM of the physical server.

In this way, the deployment problem here is a knapsack problem. But it is a little different from the 01 knapsack problem. where the 01 knapsack problem is to maximize the sum of the values ​​placed given the capacity. But there is no limit to this size. However, in this question. If we want to optimize the CPU, then the total capacity of the backpack is the MEM size of the physical server. Our optimization purpose is to maximize the CPU (value), and this maximum value cannot exceed the CPU value of the physical server.

Therefore, when we are iterating on the backpack, we also need to judge that the value cannot exceed a certain fixed value in the loop.

def deploy_flavor_use_01bag(count_all, predict, server_CPU, server_MEM, target):
    """
    01背包算法装包
    :param count_all:   int 输入的虚拟机总数
    :param predict:     list[list,list...] [型号,CPU,MEM]将每种虚拟机的型号参数数目写出来,
                            如[[10, 8, 8], [10, 8, 8], [10, 8, 8], [7, 4, 4], [7, 4, 4], \
                            [7, 4, 4], [7, 4, 4], [7, 4, 4], [7, 4, 4]]
    :param server_CPU:  int 物理服务器的CPU大小
    :param server_MEM:  int 物理服务器的Memory的大小
    :param target:      int 优化类型 1:CPU, 0:MEM
    :return:            list[list, list...] 每台物理服务器的装包方式  int 每台服务器最大装包结果
    """
    if target:
        server = server_MEM
        limit_factor = server_CPU
        capacity = 2 #every MEM
        weight = 1 #every CPU
    else:
        server = server_CPU
        limit_factor = server_MEM
        capacity = 1 #every CPU
        weight = 2 #every MEM
    bag = [[0 for col in range(server + 1)] for raw in range(count_all + 1)]
    result = []
    # 计算背包问题
    for i in range(1, count_all + 1):
        for j in range(1, server + 1):
            bag[i][j] = bag[i - 1][j]
            if j >= predict[i - 1][capacity]:
                bag[i][j] = max(bag[i][j], bag[i - 1][j - predict[i - 1][capacity]] + predict[i - 1][weight])
            if bag[i][j] > limit_factor:
                n = j - 1
                for m in range(i, 0, -1):
                    if bag[m][n] > bag[m - 1][n]:
                        result.append(predict[m - 1][0])
                        n = n - predict[m - 1][capacity]
                return result, bag[i][j - 1]

    # 递推出装入背包的物体
    big = bag[i][j]
    j = server
    for i in range(count_all, 0, -1):
        if bag[i][j] > bag[i - 1][j]:
            result.append(predict[i - 1][0])
            j = j - predict[i - 1][capacity]

    return result, big

Finally, through the reverse push, the placement plan is output.

For more algorithm implementation, see my Github , if you find it useful, please don't forget to click Star~~~

Reference blog:

01 Knapsack problem (dynamic programming) python implementation

Nine lectures on dd Daniel's backpack - a summary of backpack problems

Detailed explanation of backpack 01 backpack, complete backpack, and multiple backpacks

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324823463&siteId=291194637