- Let \(I = \{1,\dots,n\}\)
- We have two parameters \(a_i, b_i \ge 0\)
- Find a subset \(S\subset I\) that maximizes the following expression \[\max \left(\sum_{i \in S} a_i\right) \left(\sum_{i \notin S} b_i\right) \]
This is easily formulated as a Mixed Integer Quadratic Programming (MIQP) problem. We can write: 
| MIQP Model | 
|---|
| \[\begin{align}\max &\left(\sum_i a_i x_i \right) \left(\sum_i b_i (1-x_i) \right) \\ & x_i \in \{0,1\}\end{align}\] | 
Using a modeling system like GAMS we can directly implement this:
obj.. z =e= sum(i, a(i)*x(i)) * sum(i, b(i)*(1-x(i)));
It is interesting to see what different solvers do with this. The model can be reformulated by the solver in different ways, so we can potentially see very different behavior. I generated some random values (uniformly distributed) for the parameters: \[\begin{align} &n=100\\ & a_i \sim U(0,1)\\ & b_i \sim U(0,1)\end{align}\] This is already large enough to make it interesting. Complete enumeration is out of the question: \[2^{100} = 1267650600228229401496703205376\] The generated input data looks like:
---- 7 PARAMETER a i1 0.172, i2 0.843, i3 0.550, i4 0.301, i5 0.292, i6 0.224, i7 0.350, i8 0.856 i9 0.067, i10 0.500, i11 0.998, i12 0.579, i13 0.991, i14 0.762, i15 0.131, i16 0.640 i17 0.160, i18 0.250, i19 0.669, i20 0.435, i21 0.360, i22 0.351, i23 0.131, i24 0.150 i25 0.589, i26 0.831, i27 0.231, i28 0.666, i29 0.776, i30 0.304, i31 0.110, i32 0.502 i33 0.160, i34 0.872, i35 0.265, i36 0.286, i37 0.594, i38 0.723, i39 0.628, i40 0.464 i41 0.413, i42 0.118, i43 0.314, i44 0.047, i45 0.339, i46 0.182, i47 0.646, i48 0.561 i49 0.770, i50 0.298, i51 0.661, i52 0.756, i53 0.627, i54 0.284, i55 0.086, i56 0.103 i57 0.641, i58 0.545, i59 0.032, i60 0.792, i61 0.073, i62 0.176, i63 0.526, i64 0.750 i65 0.178, i66 0.034, i67 0.585, i68 0.621, i69 0.389, i70 0.359, i71 0.243, i72 0.246 i73 0.131, i74 0.933, i75 0.380, i76 0.783, i77 0.300, i78 0.125, i79 0.749, i80 0.069 i81 0.202, i82 0.005, i83 0.270, i84 0.500, i85 0.151, i86 0.174, i87 0.331, i88 0.317 i89 0.322, i90 0.964, i91 0.994, i92 0.370, i93 0.373, i94 0.772, i95 0.397, i96 0.913 i97 0.120, i98 0.735, i99 0.055, i100 0.576 ---- 7 PARAMETER b i1 0.051, i2 0.006, i3 0.401, i4 0.520, i5 0.629, i6 0.226, i7 0.396, i8 0.276 i9 0.152, i10 0.936, i11 0.423, i12 0.135, i13 0.386, i14 0.375, i15 0.268, i16 0.948 i17 0.189, i18 0.298, i19 0.075, i20 0.401, i21 0.102, i22 0.384, i23 0.324, i24 0.192 i25 0.112, i26 0.597, i27 0.511, i28 0.045, i29 0.783, i30 0.946, i31 0.596, i32 0.607 i33 0.363, i34 0.594, i35 0.680, i36 0.507, i37 0.159, i38 0.657, i39 0.524, i40 0.124 i41 0.987, i42 0.228, i43 0.676, i44 0.777, i45 0.932, i46 0.201, i47 0.297, i48 0.197 i49 0.246, i50 0.646, i51 0.735, i52 0.085, i53 0.150, i54 0.434, i55 0.187, i56 0.693 i57 0.763, i58 0.155, i59 0.389, i60 0.695, i61 0.846, i62 0.613, i63 0.976, i64 0.027 i65 0.187, i66 0.087, i67 0.540, i68 0.127, i69 0.734, i70 0.113, i71 0.488, i72 0.796 i73 0.492, i74 0.534, i75 0.011, i76 0.544, i77 0.451, i78 0.975, i79 0.184, i80 0.164 i81 0.025, i82 0.178, i83 0.061, i84 0.017, i85 0.836, i86 0.602, i87 0.027, i88 0.196 i89 0.951, i90 0.336, i91 0.594, i92 0.259, i93 0.641, i94 0.155, i95 0.460, i96 0.393 i97 0.805, i98 0.541, i99 0.391, i100 0.558
MIQP Solvers: Cplex, Gurobi and Baron
Cplex solves this very fast, all in the root node:
| 
       
  Nodes                                        
  Cuts/ 
   Node  Left    
  Objective  IInf  Best Integer    Best Bound    ItCnt    
  Gap 
*     0+    0                            0.0000     1807.5989              ---  
Found incumbent of value 0.000000 after 0.89 sec.
  (112.24 ticks) 
*     0+    0                          874.9563     1807.5989           106.59% 
Found incumbent of value 874.956296 after 0.89 sec.
  (112.41 ticks) 
      0     0     
  903.7995   100      874.9563      903.7995     3357   
  3.30% 
      0     0     
  896.6965   182      874.9563    Cuts: 1268     3752   
  0.00% 
      0     0     
  889.7657   772      874.9563    Cuts: 1337     4088   
  0.00% 
      0     0     
  882.7062  1112      874.9563 ZeroHalf: 1337     4432   
  0.00% 
      0     0 
      877.9208  2106     
  874.9563 ZeroHalf: 1337    
  4827    0.00% 
      0     0     
  875.4173   762      874.9563 ZeroHalf: 1098     5071   
  0.00% 
      0     0       
  cutoff            874.9563                   5112     ---  
Elapsed time = 10.70 sec. (3363.84 ticks, tree = 0.01
  MB, solutions = 2) | 
The solution looks like:
Gurobi has some real troubles with this model. After 10,000 seconds I stopped it:
---- 21 VARIABLE x.L selection (binary) i1 1.000, i2 1.000, i3 1.000, i8 1.000, i11 1.000, i12 1.000, i13 1.000, i14 1.000 i19 1.000, i20 1.000, i21 1.000, i25 1.000, i26 1.000, i28 1.000, i34 1.000, i37 1.000 i38 1.000, i39 1.000, i40 1.000, i47 1.000, i48 1.000, i49 1.000, i52 1.000, i53 1.000 i58 1.000, i60 1.000, i64 1.000, i67 1.000, i68 1.000, i70 1.000, i74 1.000, i75 1.000 i76 1.000, i79 1.000, i81 1.000, i83 1.000, i84 1.000, i87 1.000, i88 1.000, i90 1.000 i91 1.000, i92 1.000, i94 1.000, i96 1.000, i98 1.000, i100 1.000 ---- 21 PARAMETER count = 46.000 number of x(i)=1 VARIABLE z.L = 874.956 objective variable
Gurobi has some real troubles with this model. After 10,000 seconds I stopped it:
| 
    Nodes   
  |    Current Node    |    
  Objective Bounds      |     Work 
 Expl Unexpl |  Obj 
  Depth IntInf | Incumbent   
  BestBd   Gap | It/Node Time 
     0    
  0 1028.82147    0   88  
  -0.00000 1028.82147      -     -   
  0s 
H    0    
  0                     
  94.1937601 1028.82147  
  992%     -    0s 
H    0    
  0                    
  874.9562964 1028.82147 
  17.6%     -    0s 
     0    
  2 1028.82147    0   88 
  874.95630 1028.82147  17.6%     -   
  0s 
  5024 
  3355  981.36042   24  
  77  874.95630  989.02791 
  13.0%   2.4    5s 
H13738 10488                     874.9564248  978.66510 
  11.9%   2.4    8s 
 20782 16103 
  909.88622   55   44 
  874.95642  975.04173  11.4%  
  2.4   10s 
 43494 34084 
  943.11968   43   57 
  874.95642  968.63227  10.7%  
  2.4   15s 
 65078 50966 
  916.66669   49   50 
  874.95642  964.88315  10.3%  
  2.4   20s 
 89405 69894 
  904.98150   56   44 
  874.95642  962.21433  10.0%  
  2.4   25s 
 114800 89612 
  898.26415   51   50 
  874.95642  959.84933  9.70%  
  2.4   30s 
 136964 106525  911.88894  
  51   49  874.95642 
  958.31653  9.53%   2.4  
  35s 
 162025 125584  892.69915  
  52   48  874.95642 
  956.85312  9.36%   2.4  
  40s 
 184525 142823  922.61714  
  44   57  874.95642 
  955.79186  9.24%   2.4  
  45s 
 208972 161530  880.72495  
  54   46  874.95642 
  954.67328  9.11%   2.4  
  50s 
 231067 178124  885.81556  
  57   44  874.95642 
  953.79519  9.01%   2.4  
  55s 
 255408 196541  935.18869  
  46   54  874.95642 
  952.89911  8.91%   2.4  
  60s 
 278680 214033  899.07410  
  51   47  874.95642 
  952.12450  8.82%   2.4  
  65s 
 302859 232220  936.52130  
  37   64  874.95642 
  951.40827  8.74%   2.4  
  70s 
 328028 251086  910.60834  
  50   50  874.95642 
  950.70076  8.66%   2.4  
  75s 
 352051 268955  905.74964  
  54   45  874.95642 
  950.10317  8.59%   2.4  
  80s 
 376120 286723  902.67637  
  57   43  874.95642 
  949.57421  8.53%   2.4  
  85s 
 400406 304716  949.03348  
  26   77  874.95642 
  949.03348  8.47%   2.4  
  90s 
 422676 321239  882.35938  
  52   47  874.95642 
  948.53308  8.41%   2.4  
  95s 
. . . 
 13091984 8119359  883.24548  
  54   44  874.95642 
  919.65956  5.11%   2.4 9990s 
 13094401 8120718     cutoff  
  55       874.95642  919.65790 
  5.11%   2.4 9995s 
 13095972 8121550  897.09522  
  56   41  874.95642 
  919.65687  5.11%   2.4 10000s 
 13098502 8122984  908.84424  
  50   50  874.95642 
  919.65560  5.11%   2.4 10005s 
 13100870 8124293  874.95653  
  56   44  874.95642 
  919.65388  5.11%   2.4 10010s 
 13103160 8125658  883.98954  
  56   46  874.95642 
  919.65273  5.11%   2.4 10015s 
 13105665 8127116  889.74823  
  60   40  874.95642 
  919.65125  5.11%   2.4 10020s 
 13107878 8128361     cutoff  
  61       874.95642  919.64989 
  5.11%   2.4 10025s 
 13110794 8129992  880.12914  
  53   48  874.95642 
  919.64814  5.11%   2.4 10030s 
 13112818 8131096  891.49116  
  58   43  874.95642 
  919.64674  5.11%   2.4 10035s 
Sending CtrlC
  signal 
Explored 13114854
  nodes (31784166 simplex iterations) in 10037.84 seconds 
Thread count was 4
  (of 8 available processors) 
Solution count 4:
  874.956 874.956 94.1938 -0  
Solve interrupted 
Best objective
  8.749562757165e+02, best bound 9.196456216128e+02, gap 5.1076% 
MIQP status(11):
  Optimization was terminated by the user. | 
Gurobi finds the optimal solution quickly but it is not able to prove optimality.
Interestingly, the global solver Baron does a very good jobs on this:
| 
Preprocessing
  found feasible solution with value 
  0.00000000000      
 Doing local search 
 Preprocessing found feasible solution with
  value  874.943601492      
 Solving bounding LP 
 Starting multi-start local search 
 Preprocessing found feasible solution with
  value  874.956296356      
 Done with local search 
=========================================================================== 
  Iteration   
  Open nodes         Time (s)    Lower bound      Upper bound 
          1             0             1.00     874.956          874.956     
 Cleaning up 
                         *** Normal
  completion ***             
 Wall clock time:                     1.00 
 Total CPU time used:                 0.75 | 
Linearization
Let's see if we can make Gurobi look a little bit better. We can reformulate the model as a straight mixed-integer programming model:
| MIP Model | 
|---|
| \[\begin{align} \max & \sum_{i \ne j} a_i b_j y_{i,j} \\ & y_{i,j} \le x_i && \forall i \ne j \\ & y_{i,j} \le 1-x_j && \forall i \ne j \\ & 0 \le y_{i,j} \le 1 \\ & x_i \in \{0,1\} \end{align}\] | 
This model introduces \(100 \times 100 - 100 = 9,900\) extra continuous variables (and 19,800 additional constraints).
Derivation
We can rewrite \[\max \left(\sum_i a_i x_i \right) \left(\sum_i  b_i (1-x_i) \right) \] as \[\max \sum_{i,j} a_i b_j x_i (1-x_j)  \] We can linearize the product \[y_{i,j} = x_i (1-x_j)\] as \[\begin{align} &  y_{i,j} \le x_i \\ & y_{i,j} \le (1-x_j) \\ & y_{i,j} \ge x_i - x_j \\ & y_{i,j}, x_i \in \{0,1\}\end{align}\] You can verify the correctness of this by plugging in the possible values for \((x_i,x_j) = \{(0,0),(0,1),(1,0),(1,1)\}\). Finally we observe: 
- \(y_{i,j}\) can be relaxed to be continuous between 0 and 1. It will be integer automatically.
- We are really maximizing \(y_{i,j}\) so we can drop the last \(\ge\) constraints.
- We can skip the case where \(i=j\): the product \(x_i (1-x_i)\) is always zero.
This formulation proves to be quite beneficial for Gurobi: 
| 
    Nodes   
  |    Current Node    |    
  Objective Bounds      |     Work 
 Expl Unexpl |  Obj 
  Depth IntInf | Incumbent    BestBd  
  Gap | It/Node Time 
     0    
  0  903.79947    0 
  100   -0.00000  903.79947      -    
  -    2s 
H    0    
  0                      
  2.2104609  903.79947      -    
  -    3s 
H    0    
  0                    
  163.3432337  903.79947   453%    
  -    3s 
H    0    
  0                    
  177.4409096  903.79947   409%    
  -    3s 
H    0    
  0                    
  672.0256560  903.79947  34.5%    
  -    3s 
H    0    
  0                    
  690.8350810  903.79947  30.8%    
  -    3s 
     0    
  0  903.64085    0 
  100  690.83508  903.64085 
  30.8%     -    3s 
H    0    
  0                    
  787.7021585  903.64085  14.7%    
  -    3s 
     0    
  0  903.47324    0 
  100  787.70216  903.47324 
  14.7%     -    4s 
     0    
  0  903.30963    0 
  100  787.70216  903.30963 
  14.7%     -    4s 
     0    
  2  903.30963    0 
  100  787.70216  903.30963 
  14.7%     -    7s 
*    4    
  4               2     874.9562964  888.63188 
  1.56%   737    9s 
Cutting planes: 
  Gomory: 9 
Explored 7 nodes
  (16549 simplex iterations) in 9.53 seconds 
Thread count was 4
  (of 8 available processors) 
Solution count 8:
  874.956 787.702 690.835 ... -0 
Optimal solution
  found (tolerance 0.00e+00) 
Best objective
  8.749562963561e+02, best bound 8.749562963561e+02, gap 0.0000% 
MIP status(2):
  Model was solved to optimality (subject to tolerances). | 
Instead of doing this linearization by ourselves, we can also tell Gurobi to do this by using the option preqlinearize. (The behavior is not exactly the same, it solved in 12 seconds instead of 9). The automatic behavior is apparently not to apply the linearization. Too bad Gurobi does not realize it is in so much trouble and should reformulate the problem.
We can predict the optimal solution for our specific random data set quite easily:
Of course, this approach will only work for certain very "balanced" data sets. We exploited here that \(a_i\) and \(b_i\) are drawn from the same distribution. In addition, we have no cases where \(a_i=b_i\). I don't know about good heuristics for the more general case.
A related problem (or better: a special case) only looks at parameter \(a\):\[\max \left(\sum_{i \in S} a_i\right) \left(\sum_{i \notin S} a_i\right) \] This problem, as noted in the comments below, has an interesting linearization. The MIQP formulation is again straightforward: \[\begin{align}\max & \left(\sum_i a_i x_i \right) \left(\sum_i a_i (1-x_i) \right)\\ & x_i \in \{0,1\}\end{align} \] We can find the optimal solution by solving instead \[\min \left|\sum_i a_i x_i - \sum_i a_i (1-x_i) \right| \] I.e. make sure we divide into \(I\) into \(S\) and \(I-S\) as evenly as possible. The absolute value is easily linearized, yielding a MIP model.
Note that when we write \(A=\sum_i a_i\), we can state this as: \[\min \left| \sum_i a_i x_i - \frac{A}{2}\right|\]
Here are some performance figures for this problem:
So we see:
Cheating: a simple heuristic
We can predict the optimal solution for our specific random data set quite easily:
- if \(a_i\gt b_i\), set \(x_i=1\)
- if \(a_i\lt b_i\), set \(x_i=0\)
This correctly shows the optimal solution:
---- 18 heuristic solution ---- 18 VARIABLE x.L selection (binary) i1 1.000, i2 1.000, i3 1.000, i8 1.000, i11 1.000, i12 1.000, i13 1.000, i14 1.000 i19 1.000, i20 1.000, i21 1.000, i25 1.000, i26 1.000, i28 1.000, i34 1.000, i37 1.000 i38 1.000, i39 1.000, i40 1.000, i47 1.000, i48 1.000, i49 1.000, i52 1.000, i53 1.000 i58 1.000, i60 1.000, i64 1.000, i67 1.000, i68 1.000, i70 1.000, i74 1.000, i75 1.000 i76 1.000, i79 1.000, i81 1.000, i83 1.000, i84 1.000, i87 1.000, i88 1.000, i90 1.000 i91 1.000, i92 1.000, i94 1.000, i96 1.000, i98 1.000, i100 1.000 ---- 18 PARAMETER count = 46.000 number of x(i)=1 EQUATION obj.L = 874.956
Of course, this approach will only work for certain very "balanced" data sets. We exploited here that \(a_i\) and \(b_i\) are drawn from the same distribution. In addition, we have no cases where \(a_i=b_i\). I don't know about good heuristics for the more general case.
A related problem
A related problem (or better: a special case) only looks at parameter \(a\):\[\max \left(\sum_{i \in S} a_i\right) \left(\sum_{i \notin S} a_i\right) \] This problem, as noted in the comments below, has an interesting linearization. The MIQP formulation is again straightforward: \[\begin{align}\max & \left(\sum_i a_i x_i \right) \left(\sum_i a_i (1-x_i) \right)\\ & x_i \in \{0,1\}\end{align} \] We can find the optimal solution by solving instead \[\min \left|\sum_i a_i x_i - \sum_i a_i (1-x_i) \right| \] I.e. make sure we divide into \(I\) into \(S\) and \(I-S\) as evenly as possible. The absolute value is easily linearized, yielding a MIP model.
Note that when we write \(A=\sum_i a_i\), we can state this as: \[\min \left| \sum_i a_i x_i - \frac{A}{2}\right|\]
Here are some performance figures for this problem:
| Solver | Model | Time | Obj | Gap | 
|---|---|---|---|---|
| Cplex | MIQP | >3600 | 465.931 | 40% | 
| Gurobi | MIQP | >3600 | 465.931 | 65% | 
| Baron | MIQP | 2 | 465.931 | Optimal | 
| Cplex | MIP | 4 | 465.931 | Optimal | 
| Gurobi | MIP | 1 | 465.931 | Optimal | 
So we see:
- Cplex and Gurobi do not like the MIQP model at all. They stopped on a time limit before optimality was proven. This is worse performance than on the original problem with both \(a\) and \(b\).
- Baron does a really good job. Baron is a global NLP/MINLP solver, so it is somewhat surprising to me that it is doing so much better than more specialized MIQP solvers.
- The MIP formulations are easy to solve.
- The objective reported for the MIP models is not the MIP objective but rather \(\left(\sum_i a_i x_i \right) \left(\sum_i a_i (1-x_i) \right)\) evaluated at the solution point.
The Baron log is just very convincing:
| 
  Iteration   
  Open nodes         Time (s)    Lower bound      Upper bound 
*         1             1             2.00     465.931          1863.72     
          1             0             2.00    
  465.931          465.931     | 
Conclusion
MIQP models, including rather smallish ones, remain very difficult to solve, even with expensive commercial solvers. The only solver that is consistently doing a good job is Baron. For most solvers it pays off to look for linearizations.   
References
- Maximize the product of the sum of two subsets, https://cs.stackexchange.com/questions/71168/maximize-product-of-sum-of-two-subset
 
 
No comments:
Post a Comment