多个背包的优化问题无法正常工作

Posted

技术标签:

【中文标题】多个背包的优化问题无法正常工作【英文标题】:Optimization problem with multiple knapsack does not work correctly 【发布时间】:2021-12-29 16:16:33 【问题描述】:

我正在尝试解决 Python 中的多个背包问题,该问题包括将物品放入 5 个箱中,并且限制是每个箱(袋)必须包含具有相同聚类的物品(因此我们不能在其中找到具有不同聚类的两个对象同一个箱子)并最大化箱子中包装的物品的总KPI

这是数据框数据:

index   Cluster PageId  OsId    BrowserId   Impressions VideoComplete   Clicks  VolumePred  KPIPred ConversionPred  pond
0          1    0      1016529     11          16           43            16         1       175.0     0.025703     1
1          2    0      1016529     11          17            1             1         0         4.0     0.100000     1
2         12    0      1068379     11          12            1             0         0         4.0     0.150000     1
3         21    0      1074581     11          16           82            36         2       334.0     0.024457     1
4         22    0      1074581     12          14            3             2         0        12.0     0.035648     1
... ... ... ... ... ... ... ... ... ... ... ... ...
310     1392    9       955767     11          11          264           170        12      1076.0     0.056217     1
311     1396    9       955767     11          17           42            32         2       171.0     0.118330     1
312     1397    9       955767     12          12            7             1         2        29.0     0.234646     1
313     1398    9       955767     12          14           31            17         1       126.0     0.026832     1
314     1405    9       988119     11          16           66            49         1       269.0     0.019075     1

解决它:

我创建了第一个分配矩阵 A:项目 像这样的垃圾箱:

      item     0   1   2   3   4   5   6   7   8   9   10   11   12   13   14   
 bins
 0   
 1    
 2    
 3    
 4 
              <=1 <=1 <=1 ...................................      <=1 <=1 <=1 


data1 = 
pond = data['pond']
Cluster = data['Cluster']
OsId = data['OsId']
BrowserId = data['BrowserId']
PageId = data['PageId']
volume = data['VolumePred']
conversion = data['ConversionPred']
KPI = data['KPIPred']

assert len(OsId) == len(BrowserId) == len(PageId) == len(conversion)

data1['Cluster']  = Cluster
data1['pond'] = pond
data1['OsId'] = OsId
data1['BrowserId'] = BrowserId
data1['PageId'] = PageId
data1['conversion'] = conversion
data1['volume'] = volume
data1['KPI'] = KPI
data1['items'] = list(range(len(BrowserId)))
data1['num_items'] = len(OsId)
number_bags = 5 #All have the same capacity of 50 pounds

data1['bag_capacities'] = [50,50,50,50,50]#pounds
data1['bag_PageId'] = [50,50,50,50,50] #while this equals bag_capacities, I made it its own variable in case
data1['conversion_capacities'] = [5,5,5,5,5]
#data1['bag_capacities'] = [50,50,50,50,50] #while this equals bag_capacities, I made it its own variable in case

#I wanted to change the OsId at a later data1
data1['bags'] = list(range(number_bags))

assert len(data1['bag_capacities']) == number_bags
assert len(data1['bag_capacities']) == len(data1['bag_PageId']) == len(data1['conversion_capacities'])
print("OsId: ",*data1['OsId'])
print('BrowserId:',*data1['BrowserId'])
print('PageId:',*data1['PageId'])
print('conversioniation Levels:', *data1['conversion'])
print("Number of Items:", data1['num_items'])
print("Number of Knapsacks:" , number_bags)
print('Knapsack Capacities: 50 Pounds, 50 cubic inches, 5 Levels of conversioniation')

变量 1

#x[i,j] for item i in knapsack j
x = 
for i in data1['items']:
    for j in data1['bags']:
        x[(i,j)] = solver.IntVar(0,1,'x_%i_%i' % (i, j))

然后,我添加了第二个矩阵:Assignment-matrix B item-classes bins:

data2=


unique_cluster = set(np.array(Cluster))

partition = [np.where(Cluster == i)[0] for i in unique_cluster]
data2['class'] = list(unique_cluster)
data2['bags'] = list(range(number_bags))

#x[i,j] for item i in knapsack j
x2 = 
for i in data2['class']:
    for j in data2['bags']:
        x2[(i,j)] = solver.IntVar(0,1,'x_%i_%i' % (i, j))
  

然后,我精确地列出了约束:

#Constraint for an item being placed in 1 knapsack
for i in data1['items']:
    
    solver.Add(sum(x[i,j] for j in data1['bags'])<=1)
 
 #Knapsack Capacity Constraint
for j in data1['bags']:
   
    solver.Add(sum(x[(i,j)]*data1['pond'][i] 
                 for i in data1['items']) == 5)    
 
 #Constraint for a class of item is  being placed in 1 knapsack
for i in data2['class']:
    solver.Add(sum(x2[i,j] for j in data2['bags'])<=1)

A=np.where(Cluster == 0)[0].tolist()

for b in data1['bags']:
    for c in data2['class']:
        print(b,c)
        u=len(np.where(Cluster == c)[0].tolist())

        print(c,b)
        
        solver.Add(sum(x[z,b]
                       for z in np.where(Cluster == c)[0].tolist()) <= (x2[c,b]*u))
  
                   

然后,我确定优化目标:

objective = solver.Objective()
for i in data1['items']:
    
    for j in data1['bags']:
        objective.SetCoefficient(x[(i,j)], data1['KPI'][i])
        
objective.SetMaximization()
        

分辨率

solv = solver.Solve()
if solv == pywraplp.Solver.OPTIMAL:
    #print('Total Packed Value:', objective.Value())
    total = 0
    kpi_moyen = 0
    kpi=0
    total_conversion = 0
    nombre_impression = 5
    
    
    for j in data1['bags']:
        bag_value = 0
        bag_weight = 0
        bag_volume= 0
        bag_rad = 0
        bag_conversion=0
        max = 0
        i_max=0
     
      
       
        print('\n','Bag', j+1 , '\n')
        
        for i in data1['items']:
                    
           
            if((x[i,j].solution_value()>0)):
                print('OsId',data1['OsId'][i], 
                      'Cluster', data1['Cluster'][i],
                      'BrowserId', data1['BrowserId'][i], 
                      'PageId', data1['PageId'][i],
                      'conversion', data1['conversion'][i],
                      'volume', data1['volume'][i],
                      'KPI', data1['KPI'][i]
                     )
                bag_value += data1['volume'][i]
                print(bag_value)
                bag_weight += data1['KPI'][i]
                bag_conversion += data1['conversion'][i]
                
        print('Packed Knapsack Volume Value: ', bag_value)
        print('impression number', nombre_impression)
        print('Packed Knapsack KPI: ', bag_weight/nombre_impression)
        kpi = bag_weight/nombre_impression
        total= total+bag_value
        kpi_moyen = kpi_moyen+kpi
        total_conversion= total_conversion+bag_conversion
        
  
   
        
    print("#######################################################")
    print("#######################################################")
    print("#######################################################")
    
    
    print("Le volume total", total)   
    print("KPI Moyen", kpi_moyen/5)
    
    
    
else:
    print("There is no optimal solution") 

最后,我得到了这五个装有物品的箱子:

> Bag 1 
> 
> OsId 11 Cluster 0 BrowserId 12 PageId 1149586 conversion 3.0 volume
> 4.0 KPI 0.6890546435965691
> 4.0 

OsId 99 Cluster 0 BrowserId 16 PageId 1154705 conversion 3.0 volume 8.0 KPI 0.3472222222222222
> 12.0 

OsId 11 Cluster 0 BrowserId 17 PageId 789615 conversion 3.0 volume 4.0 KPI 0.6564351851851853
> 16.0 

OsId 11 Cluster 0 BrowserId 11 PageId 955761 conversion 9.0 volume 37.0 KPI 0.2541666666666666
> 53.0 

OsId 99 Cluster 7 BrowserId 16 PageId 917224 conversion 4.0 volume 12.0 KPI 0.3292739040060469

> 65.0 Packed Knapsack Volume Value:  65.0 impression number 5 Packed Knapsack KPI:  0.45523052433533806
> 
>  Bag 2 
> 
> OsId 99 Cluster 12 BrowserId 16 PageId 941080 conversion 2.0 volume
> 4.0 KPI 0.5508680555555555
> 4.0 

OsId 12 Cluster 9 BrowserId 16 PageId 1018637 conversion 4.0 volume 12.0 KPI 0.321111111111111
> 16.0 

OsId 11 Cluster 9 BrowserId 17 PageId 1154705 conversion 13.0 volume 33.0 KPI 0.3886526452221044
> 49.0 

OsId 99 Cluster 9 BrowserId 12 PageId 955761 conversion 11.0 volume 33.0 KPI 0.3366657218442933
> 82.0 

OsId 12 Cluster 9 BrowserId 12 PageId 955767 conversion 7.0 volume 29.0 KPI 0.2346455795175744

> 111.0 Packed Knapsack Volume Value:  111.0 impression number 5 Packed Knapsack KPI:  0.3663886226501277
> 
>  Bag 3 
> 
> OsId 99 Cluster 4 BrowserId 16 PageId 1109643 conversion 1.0 volume
> 4.0 KPI 0.3055555555555556
> 4.0 

OsId 11 Cluster 4 BrowserId 11 PageId 1149586 conversion 6.0 volume 8.0 KPI 0.7676237922705315
> 12.0 

OsId 11 Cluster 4 BrowserId 15 PageId 1149586 conversion 8.0 volume 33.0 KPI 0.2383133975812547
> 45.0 

OsId 12 Cluster 4 BrowserId 16 PageId 1154705 conversion 10.0 volume 41.0 KPI 0.2528392857142857
> 86.0 

OsId 12 Cluster 4 BrowserId 14 PageId 955767 conversion 4.0 volume 20.0 KPI 0.2225
> 106.0 

Packed Knapsack Volume Value:  106.0 impression number 5 Packed Knapsack KPI:  0.35736640622432553
> 
>  Bag 4 
> 
> OsId 11 Cluster 15 BrowserId 17 PageId 1109643 conversion 5.0 volume
> 12.0 KPI 0.3877777777777778
> 12.0 

OsId 11 Cluster 15 BrowserId 17 PageId 1187774 conversion 3.0 volume 12.0 KPI 0.236237684729064
> 24.0 

OsId 11 Cluster 15 BrowserId 11 PageId 955765 conversion 10.0 volume 41.0 KPI 0.2319838228361533
> 65.0 

OsId 11 Cluster 18 BrowserId 17 PageId 1074581 conversion 5.0 volume 16.0 KPI 0.300344742063492
> 81.0 

OsId 11 Cluster 18 BrowserId 16 PageId 1148073 conversion 3.0 volume 4.0 KPI 0.6833333333333333

> 85.0 Packed Knapsack Volume Value:  85.0 impression number 5 Packed Knapsack KPI:  0.36793547214796407
> 
>  Bag 5 
> 
> OsId 11 Cluster 21 BrowserId 12 PageId 1016529 conversion 3.0 volume
> 8.0 KPI 0.3541076152683295
> 8.0 

OsId 11 Cluster 21 BrowserId 12 PageId 1068379 conversion 3.0 volume 4.0 KPI 0.6711734693877551
> 12.0 

OsId 12 Cluster 21 BrowserId 16 PageId 911433 conversion 5.0 volume 16.0 KPI 0.3160714285714284
> 28.0 

OsId 11 Cluster 21 BrowserId 12 PageId 941080 conversion 2.0 volume 8.0 KPI 0.2876372053872053
> 36.0 

OsId 12 Cluster 21 BrowserId 14 PageId 941080 conversion 2.0 volume 8.0 KPI 0.275
> 44.0

问题是我在同一个袋子或垃圾箱中发现了多个集群,例如在袋子 1 中,我们发现了集群 0 和 7 的项目。

我该如何解决这个问题?

【问题讨论】:

欢迎来到Stack Overflow.。虽然展示你的工作成果是有益的,但转储所有代码却适得其反。请编辑您的问题以显示一个最小的可重现集,其中包括样本输入、预期输出、实际输出以及重现问题所需的相关代码。请参阅Minimal Reproducible Example,了解如何最好地帮助我们。 在你的背包容量限制中不应该是&lt;=5而不是==5吗? 【参考方案1】:

您的“对一类物品的限制被放置在 1 个背包中”

for i in data2['class']:
    solver.Add(sum(x2[i,j] for j in data2['bags'])<=1)

确保每个班级都放在某个背包中。它不能保证每个背包只装一个类。

我想你必须添加

# Only one class per knapsack Constraint
for j in data1['bags']:
    solver.Add(sum(x2[(i,j)] 
                 for i in data2['class']) <= 1)

改为。

【讨论】:

感谢您的回复,它有效。我有另一个问题,因为你知道背包问题。我的问题:是否有一种自动方法来确定袋子的数量。这里 i 精确是 5 。谢谢! 看起来您目前正在最大化可放入 5 个袋子中的 KPI。相反,您可以尽量减少行李数量作为目标;然后,您必须添加一个约束,例如“至少 n 个 KPI 总数”或“至少 m 个对象总数”,否则最佳解决方案显然是 0 个袋子。 汉金斯 新年快乐!感谢您的指导性回应。但我不知道如何写我的目标:我想最大化袋子的数量。你能帮我吗?谢谢! 你的意思是尽量减少包的数量,不是吗?您对 KPI 数量或需要放入袋子的物品数量的下限是多少,例如“定义的所有项目都必须放入袋中”还是“至少 100 个 KPI 必须放入袋中”? 最后一个问题是针对@buddy。

以上是关于多个背包的优化问题无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

简单的 for 循环在某些手机上无法正常工作。优化不好?

数学建模MATLAB应用实战系列(136)-优化算法:0-1背包算法(附MATLAB代码)

多重背包二进制优化

01背包的优化问题

51nod 1086 背包问题 V2(二进制优化多重背包)

背包问题入门(单调队列优化多重背包