Knapsack problem with repeating components for lowest value, to fill (or slightly over) in Python

廉价感情. 提交于 2019-12-10 11:24:28

问题


I'm actually trying to find the lowest cost to supply custom medication doses from vials - however while researching, I found the knapsack problem is the best way to describe the issue, in way that is currently understood.

Breakdown of problem *A dose is prescribed based on clinical need. *The vials commercially available to make up the dose (and their respective dose) are then considered. The same size vial can be used more than once. *The vial / size combination may provide excess (i.e. provide a higher dose than is required) - as that combination works out cheaper than meeting the dose itself, or providing a smaller overage. Therefore overage or wastage is allowed provided the combinations yields the prescribed dose, even if there is wastage. *The output should display the qty/ vial combination used and the cost of that combinations.

Example of vials available are 50mg costs $15, 100mg costs $32 and 200mg costs $64

Lets say that a dose of 220mg is prescribed. Some of the possible options to make up the dose are as follows (remembering that the amount of wastage is not relevant provided it provides the cheapest option to make up the dose required.

5 x 50mg = 250mg (30mg over) = $75
3 x 50mg + 1 x 100mg = 250mg (30mg over) = $77
2 x 100mg + 1 x 200mg = 400mg (180mg over) = $128
1 x 50mg + 1 x 200mg = 250mg (30mg over) = $79
3 x 100mg = 300mg (80mg over) = $96

Therefore, we can see that the cheapest option is row1 5x 50mg at $75

If anyone could point me in the right direction then I'd be grateful!

The code below only uses each component once - but I'm lost on how to modify to get it to recycle them.

items = [("ITEM01", 100, 10000), ("ITEM02", 24, 576), \
    ("ITEM03", 24, 576), ("ITEM04", 51, 2500), ("ITEM05", 155, 25)]
S = sum([item[1] for item in items])    #sums all the weights in the list of items
dp = [None for i in range(S + 1)]       #list within which cycles through each integer of weights creates a list of "None,"
dp[0] = []                              #removes the first none from the list

for item in items:                      #for each element in the list of available vials
    for i in range(S, -1, -1):          #counts down from sum of all weights of available vial sizes DOWN TO zero (0) 
        if dp[i] is not None and i + item[1] <= S and \     
    (                                                               #if the long list of Nones - does not read None
        dp[i + item[1]] is None
        or
        sum(set_item[2] for set_item in dp[i]) + item[2]
            > sum(set_item[2] for set_item in dp[i + item[1]])
    ):
            dp[i + item[1]] = dp[i] + [item]

desired_sum = 200                   #desired weight 
i = j = desired_sum                 # desired sum becomes i and it also becomes j

while i >= 0 and j <= S:            #while desired sum(i) is over 0 and less then sum of weight of all vials in the list.
    if dp[i] is not None:           #if the none list entry at that point is NOT none
        print (dp[i])               #print element from that list that isn't 'None'
        break
    elif dp[j] is not None:         #if None list at desired_weight index is not None
        print (dp[j])               #print the element that isn't none
        break
    else:
        i -= 1                      #else diverge i and j which are originally the same
        j += 1

来源:https://stackoverflow.com/questions/58724841/knapsack-problem-with-repeating-components-for-lowest-value-to-fill-or-slightl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!