簡體   English   中英

給定一個數字數組(整數或浮點數)和一個 integer M、output M 個子集,使得總和最高的子集最小化

[英]Given an array of numbers (integer or float) and an integer M, output M number of subsets such that the subset with the highest sum is minimised

親愛的 stackoverflow 社區,

目前,我正在嘗試解決一個優化問題,給定一個數字數組(整數或浮點數;非負數)和一個正數 integer M、output M 個子集(任何合適的長度),使得總和最高的子集子集之間的最小化。 子集中的元素可以是不連續的。

例如,給定數組 [1, 4, 5, 3] 和 integer M = 2,所需的 output 為 [1, 5] 和 [4, 3],其中最高子集總和為 7,已最小化。

另一個例子,給定數組 [3, 10, 7, 2] 和 integer M = 3,所需的 output 是 [3, 2], [7], 和 [10] 甚至 [3, 7], [ 2] 和 [10] 其中最小化的最高子集總和為 10。

有沒有人經歷過這樣的優化? 我相信這是 Kadane 算法的變體。

非常感謝任何鏈接、偽代碼、pythonic 代碼等。

我想到了以下程序來解決問題:

  1. 按升序排列數組
  2. 初始化 M 個空子集
  3. 在 while 循環中,將最小和最大的可用元素添加到每個子集中,直到父數組中沒有剩余元素可供選擇

這可以看作是分配問題的變體:

v[i]成為我們的數據數組,讓j=1..M表示子集。 引入二進制變量x[i,j] ∈ {0,1}具有:

 x[i,j] = 1 if value i is assigned to subset j
          0 otherwise

我們的優化模型看起來像:

 min z
 z >= sum(i, v[i]*x[i,j])  ∀j  "largest sum"  
 sum(j, x[i,j]) = 1        ∀i   "assign each value to a subset"
 x[i,j] ∈ {0,1}

這是一個線性混合整數規划問題,可以使用任何 MIP 求解器求解。

使用隨機數據的結果:

----     34 PARAMETER results  

            value        sub1        sub2        sub3        sub4        sub5        sub6        sub7        sub8        sub9       sub10

i1         17.175      17.175
i2         84.327                                                                  84.327
i3         55.038                                                      55.038
i4         30.114      30.114
i5         29.221                                                                  29.221
i6         22.405                  22.405
i7         34.983                                                                                          34.983
i8         85.627                                                                                                      85.627
i9          6.711                                                                                           6.711
i10        50.021                                                                                                                  50.021
i11        99.812                                          99.812
i12        57.873                                                                              57.873
i13        99.113                              99.113
i14        76.225                  76.225
i15        13.069                                                                              13.069
i16        63.972                                                                                                                  63.972
i17        15.952                  15.952
i18        25.008                                                                                                      25.008
i19        66.893      66.893
i20        43.536                                                                              43.536
i21        35.970                                                                                          35.970
i22        35.144                                                                                          35.144
i23        13.149                                          13.149
i24        15.010                              15.010
i25        58.911                                                      58.911
total                 114.181     114.582     114.123     112.961     113.949     113.548     114.478     112.809     110.635     113.993

筆記:

  • 通常,解決方案不是唯一的。
  • 添加禁止空子集的約束很容易。 (可能發生在更多偏斜的數據集上)。

這個問題可以轉化為一個不平衡分配問題(任務多於工人),如下所示:

 import random from ortools.linear_solver import pywraplp # Number of tasks num_tasks = 10 # Number of workers num_workers = 3 # Randomly generate a cost matrix # If workers have different costs per task cost_matrix = [[random.uniform(1, 10) for j in range(num_workers)] for i in range(num_tasks)] # If worker have the same cost per task cost_matrix = [[random.uniform(1, 10) for j in range(num_workers)]] * num_tasks print(f"Cost Matrix is: \n {cost_matrix} \n") # Create a solver solver = pywraplp.Solver('AssignmentProblem', pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) # Create variables x = {} for i in range(num_tasks): for j in range(num_workers): x[i, j] = solver.IntVar(0, 1, f'x_{i}_{j}') # Create the objective function solver.Minimize(solver.Sum([cost_matrix[i][j] * x[i, j] for i in range(num_tasks) for j in range(num_workers)])) # Add constraints for i in range(num_tasks): solver.Add(solver.Sum([x[i, j] for j in range(num_workers)]) == 1) for j in range(num_workers): solver.Add(solver.Sum([x[i, j] for i in range(num_tasks)]) >= 1) # Solve the problem status = solver.Solve() # Print the solution if status == pywraplp.Solver.OPTIMAL: print("Optimal solution found:") print("Minimum cost,". solver.Objective():Value()) for i in range(num_tasks): for j in range(num_workers), if x[i. j]:solution_value() == 1: print(f"Task {i} is assigned to worker {j} with cost {cost_matrix[i][j]}") else: print("No solution found!")

哪個產量:

 Cost Matrix is: [[3.460201798841283, 2.8943294622750626, 1.3556528058162691], [3.460201798841283, 2.8943294622750626, 1.3556528058162691], [3.460201798841283, 2.8943294622750626, 1.3556528058162691], [3.460201798841283, 2.8943294622750626, 1.3556528058162691], [3.460201798841283, 2.8943294622750626, 1.3556528058162691], [3.460201798841283, 2.8943294622750626, 1.3556528058162691], [3.460201798841283, 2.8943294622750626, 1.3556528058162691], [3.460201798841283, 2.8943294622750626, 1.3556528058162691], [3.460201798841283, 2.8943294622750626, 1.3556528058162691], [3.460201798841283, 2.8943294622750626, 1.3556528058162691]] Optimal solution found: Minimum cost. 17.1997537076465 Task 0 is assigned to worker 2 with cost 1.3556528058162691 Task 1 is assigned to worker 2 with cost 1.3556528058162691 Task 2 is assigned to worker 0 with cost 3.460201798841283 Task 3 is assigned to worker 2 with cost 1.3556528058162691 Task 4 is assigned to worker 2 with cost 1.3556528058162691 Task 5 is assigned to worker 1 with cost 2.8943294622750626 Task 6 is assigned to worker 2 with cost 1.3556528058162691 Task 7 is assigned to worker 2 with cost 1.3556528058162691 Task 8 is assigned to worker 2 with cost 1.3556528058162691 Task 9 is assigned to worker 2 with cost 1.3556528058162691

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM