多个背包的优化问题不能正常工作

Optimization problem with multiple knapsack does not work correctly

我正在尝试解决 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:items <-> bins like this :

      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-类 <-> 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:

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 的物品。

我该如何解决这个问题?

您的“class 物品的约束被放置在 1 个背包中”

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

确保每个 class 都放入某个背包中。不保证每个背包只能装一个class.

我想你必须添加

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

相反。