The Decomposition Algorithm

Example 13.4 Resource Allocation Problem

This example describes a model for selecting tasks to be run on a shared resource (Gamrath, 2010). Consider a set $I$ of tasks and a resource capacity $C$. Each item $i \in I$ has a profit $p_ i$, a resource utilization level $w_ i$, a starting period $s_ i$, and an ending period $e_ i$. The time horizon considered is from the earliest starting time to the latest ending time of all tasks. With each task, associate a binary variable $x_ i$, which, if set to $1$, indicates that the task is running from its start time until just before its end time. A task consumes capacity if it is running. The goal is to select which tasks to run in order to maximize profit while not exceeding the shared resource capacity. Let $S = \{ s_ i \;  | \;  i \in I\} $ define the set of start times for all tasks, and let $L_ s = \{ i \in I \;  | \; \  s_ i \leq s < e_ i\} $ define the set of tasks that are running at each start time $s \in S$. The problem can be modeled as a mixed integer linear programming problem as follows:

$\displaystyle  $
$\displaystyle \text {maximize}  $
$\displaystyle  \sum _{i \in I} p_ i x_ i $
$\displaystyle  $
$\displaystyle \text {subject to}  $
$\displaystyle  \sum _{i \in L_ s} w_ i x_ i  $
$\displaystyle  \leq C  $
$\displaystyle  $
$\displaystyle  s \in S  $
$\displaystyle  $
$\displaystyle  \text {(capacity)} $
$\displaystyle  $
$\displaystyle  $
$\displaystyle  x_ i  $
$\displaystyle  \in \left\{ 0,1\right\}   $
$\displaystyle  $
$\displaystyle  i \in I  $

In this formulation, constraints (capacity) ensure that the running tasks do not exceed the resource capacity. To illustrate, consider the following five-task example with data: $p_ i=\left(6,8,5,9,8\right)$, $w_ i=\left(8,5,3,4,3\right)$, $s_ i=\left(1,3,5,7,8\right)$, $e_ i=\left(5,8,9,17,10\right)$, and $C=10$. The formulation leads to a constraint matrix that has a staircase structure that is determined by tasks coming on and offline:

\[  \begin{array}{rlllllllllll} \mbox{maximize} &  6 x_1 &  + &  8 x_2 &  + &  5 x_3 &  + &  9 x_4 &  + &  8 x_5 \\ \mbox{subject to} &  8 x_1 & & & & & & & & &  \leq &  10 \\ &  8 x_1 &  + &  5 x_2 & & & & & & &  \leq &  10 \\ & & &  5 x_2 &  + &  3 x_3 & & & & &  \leq &  10 \\ & & &  5 x_2 &  + &  3 x_3 &  + &  4 x_4 & & &  \leq &  10 \\ & & & &  + &  3 x_3 &  + &  4 x_4 &  + &  3 x_5 &  \leq &  10 \\ & \multicolumn{11}{l}{x_ i \in \{ 0,1\}  \quad i \in I}\\ \end{array}  \]

Lagrangian Decomposition

This formulation clearly has no decomposable structure. However, you can use a common modeling technique known as Lagrangian decomposition to bring the model into block-angular form. Lagrangian decomposition works by first partitioning the constraints into blocks. Then, each original variable is split into multiple copies of itself, one copy for each block in which the variable has a nonzero coefficient in the constraint matrix. Constraints are added to enforce the equality of each copy of the original variable. Then, the original constraints can be written in block-angular form by using the duplicate variables.

To apply Lagrangian decomposition to the resource allocation problem, define a set $B$ of blocks and let $S_ b$ define the set of start times for a given block $b$, such that $S = \cup _{b \in B}S_ b$. Given this partition of start times, let $B_ i$ define the set of blocks in which task $i \in I$ is scheduled to be running. Now, for each task $i \in I$, define duplicate variables $x_ i^ b$ for each $b \in B_ i$. Let $m_ i$ define the minimum block index for each class of variable that represents task $i$. The problem can now be modeled in block-angular form as follows:

$\displaystyle  $
$\displaystyle \text {maximize}  $
$\displaystyle  \sum _{i \in I} p_ i x_ i^{m_ i} $
$\displaystyle  $
$\displaystyle \text {subject to}  $
$\displaystyle  x_ i^ b  $
$\displaystyle  = x_ i^{m_ i}  $
$\displaystyle  $
$\displaystyle  i \in I, \  b \in B_ i \setminus \{ m_ i\}   $
$\displaystyle  $
$\displaystyle  \text {(linking)}  $
$\displaystyle  $
$\displaystyle  $
$\displaystyle  \sum _{i \in L_ s} w_ i x_ i^ b  $
$\displaystyle  \leq C  $
$\displaystyle  $
$\displaystyle  b \in B, \  s \in S_ b  $
$\displaystyle  $
$\displaystyle  \text {(capacity)} $
$\displaystyle  $
$\displaystyle  $
$\displaystyle  x_ i^ b  $
$\displaystyle  \in \left\{ 0,1\right\}   $
$\displaystyle  $
$\displaystyle  i \in I, \  b \in B_ i  $

In this formulation, constraints (linking) ensure that the duplicate variables are equal to the original variables. Now, the five-task example has been transformed from a staircase structure to a block-angular structure:

\[  \begin{array}{r*{18}{r}} \mbox{maximize} &  6 x_1^1 &  + &  8 x_2^1 &  + & & &  5 x_3^2 &  + &  9 x_4^2 &  + & & & & &  8 x_5^3 \\ \mbox{subject to} & & &  x_2^1 &  - &  x_2^2 & & & & & & & & & & &  = &  0 \\ & & & & & & &  x_3^2 &  - & & &  x_3^3 & & & & &  = &  0 \\ & & & & & & & & &  x_4^2 & & &  - &  x_4^3 & & &  = &  0 \\ &  8 x_1^1 & & & & & & & & & & & & & & &  \leq &  10 \\ &  8 x_1^1 &  + &  5 x_2^1 & & & & & & & & & & & & &  \leq &  10 \\ & & & & &  5 x_2^2 &  + &  3 x_3^2 & & & & & & & & &  \leq &  10 \\ & & & & &  5 x_2^2 &  + &  3 x_3^2 &  + &  4 x_4^2 & & & & & & &  \leq &  10 \\ & & & & & & & & & & &  3 x_3^3 &  + &  4 x_4^3 &  + &  3 x_5^3 &  \leq &  10 \\ & \multicolumn{11}{l}{x_ i^ b \in \{ 0,1\}  \quad i \in I, \  b \in B_ i}\\ \end{array}  \]

To show how to apply Lagrangian decomposition in PROC OPTMODEL, consider the following data set TaskData from Caprara, Furini, and Malaguti (2010) which consists of $|I|=2697$ tasks:

data TaskData;
   input profit weight start end;
   datalines;
100 74    1   12 
 98 32    1    9 
 73 27    1   22 
 98 51    1   31 
...
 23 40 2684 2689 
 36 85 2685 2687 
 65 44 2686 2689 
 18 36 2687 2689 
 88 57 2688 2689 
;

Using the MILP Solver Directly in PROC OPTMODEL

The following PROC OPTMODEL statements read in the data and solve the original staircase formulation by calling the MILP solver directly:

%macro SetupData(task_data=, capacity=);
   set TASKS;
   num capacity=&capacity;
   num profit{TASKS}, weight{TASKS}, start{TASKS}, end{TASKS};

   read data &task_data into TASKS=[_n_] profit weight start end;
   /* the set of start times */

   set STARTS = setof{i in TASKS} start[i];
   /* the set of tasks i that are active at a given start time s */
   set TASKS_START{s in STARTS}
      = {i in TASKS: start[i] <= s < end[i]};
%mend SetupData;

%macro ResourceAllocation_Direct(task_data=, capacity=);
   proc optmodel;
      %SetupData(task_data=&task_data,capacity=&capacity);
      
      /* select task i to come online from period [start to end) */
      var x{TASKS} binary;
      
      /* maximize the total profit of running tasks */
      max TotalProfit = sum{i in TASKS} profit[i] * x[i];
      
      /* enforce that the shared resource capacity is not exceeded */
      con CapacityCon{s in STARTS}:
         sum{i in TASKS_START[s]} weight[i] * x[i] <= capacity;
         
      solve;
   quit;
%mend ResourceAllocation_Direct;   

%ResourceAllocation_Direct(task_data=TaskData, capacity=100);

The problem summary and solution summary are displayed in Output 13.4.1.

Output 13.4.1: Problem Summary and Solution Summary

The OPTMODEL Procedure

Problem Summary
Objective Sense Maximization
Objective Function TotalProfit
Objective Type Linear
   
Number of Variables 2697
Bounded Above 0
Bounded Below 0
Bounded Below and Above 2697
Free 0
Fixed 0
Binary 2697
Integer 0
   
Number of Constraints 2688
Linear LE (<=) 2688
Linear EQ (=) 0
Linear GE (>=) 0
Linear Range 0
   
Constraint Coefficients 26880

Solution Summary
Solver MILP
Algorithm Branch and Cut
Objective Function TotalProfit
Solution Status Optimal within Relative Gap
Objective Value 62524.000013
Iterations 14874
Best Bound 62529.119605
Nodes 325
   
Relative Gap 0.0000818753
Absolute Gap 5.1195920763
Primal Infeasibility 5.5114845E-7
Bound Infeasibility 6.1076486E-8
Integer Infeasibility 6.1076486E-8


The iteration log, which contains the problem statistics, the progress of the solution, and the optimal objective value, is shown in Output 13.4.2.

Output 13.4.2: Log

NOTE: There were 2697 observations read from the data set WORK.TASKDATA.              
NOTE: Problem generation will use 16 threads.                                         
NOTE: The problem has 2697 variables (0 free, 0 fixed).                               
NOTE: The problem has 2697 binary and 0 integer variables.                            
NOTE: The problem has 2688 linear constraints (2688 LE, 0 EQ, 0 GE, 0 range).         
NOTE: The problem has 26880 linear constraint coefficients.                           
NOTE: The problem has 0 nonlinear constraints (0 LE, 0 EQ, 0 GE, 0 range).            
NOTE: The OPTMODEL presolver is disabled for linear problems.                         
NOTE: The MILP presolver value AUTOMATIC is applied.                                  
NOTE: The MILP presolver removed 0 variables and 0 constraints.                       
NOTE: The MILP presolver removed 0 constraint coefficients.                           
NOTE: The MILP presolver modified 0 constraint coefficients.                          
NOTE: The presolved problem has 2697 variables, 2688 constraints, and 26880           
      constraint coefficients.                                                        
NOTE: The MILP solver is called.                                                      
          Node  Active    Sols    BestInteger      BestBound      Gap    Time         
             0       1       3  54182.0000000         145710   62.82%       4         
             0       1       3  54182.0000000  73230.2096818   26.01%       4         
             0       1       6  60619.0000000  69933.6883758   13.32%       7         
             0       1       7  61305.0000021  68114.1525673   10.00%      10         
             0       1       7  61305.0000021  66617.2266845    7.97%      13         
             0       1       7  61305.0000021  65606.3087011    6.56%      17         
             0       1       7  61305.0000021  64688.1924916    5.23%      22         
             0       1       7  61305.0000021  64178.3437213    4.48%      23         
             0       1       7  61305.0000021  63788.4375982    3.89%      23         
             0       1       7  61305.0000021  63555.2698638    3.54%      24         
             0       1       7  61305.0000021  63375.5809702    3.27%      24         
             0       1       7  61305.0000021  63246.3722859    3.07%      25         
             0       1       7  61305.0000021  63135.2853095    2.90%      25         
             0       1       7  61305.0000021  63060.2975525    2.78%      25         
             0       1       7  61305.0000021  62998.5109991    2.69%      25         
             0       1       7  61305.0000021  62939.7852238    2.60%      26         
             0       1       7  61305.0000021  62916.8478192    2.56%      26         
             0       1       7  61305.0000021  62878.7708461    2.50%      26         
             0       1       7  61305.0000021  62846.9075970    2.45%      26         
             0       1       7  61305.0000021  62828.4374813    2.42%      27         
             0       1       7  61305.0000021  62818.0388114    2.41%      27         
             0       1       7  61305.0000021  62809.0758271    2.39%      27         
             0       1       7  61305.0000021  62804.5910528    2.39%      27         
             0       1       8  61488.0000000  62804.5910528    2.10%      27         
             0       1       8  61488.0000000  62804.5910528    2.10%      28         
NOTE: The MILP solver added 1260 cuts with 8646 cut coefficients at the root.         
           100      97       8  61488.0000000  62756.0802643    2.02%      85         
           105     101       9  61566.0000000  62742.8502536    1.88%      89         
           126     121      12  62476.0000000  62737.6251206    0.42%      98         
           157     146      13  62486.0000137  62731.3965146    0.39%     101         
           174     144      14  62501.0000132  62718.2341516    0.35%     103         
           195     146      15  62504.0000131  62695.8606054    0.31%     107         
           200     148      15  62504.0000131  62694.7921811    0.30%     108         
           223     141      16  62507.0000129  62683.1519312    0.28%     112         
           230     119      17  62517.0000128  62679.5328475    0.26%     113         
           268      60      18  62524.0000130  62571.9031406    0.08%     115         
           300      28      18  62524.0000130  62546.4671512    0.04%     115         
           324       6      18  62524.0000130  62529.1196051    0.01%     115         
NOTE: Optimal within relative gap.                                                    
NOTE: Objective = 62524.                                                              


Using the Decomposition Algorithm in PROC OPTMODEL

To transform this data into block-angular form, first sort the task data to help reduce the number of duplicate variables needed in the reformulation as follows:

proc sort data=TaskData; 
   by start end; 
run;

Then, create the partition of constraints into blocks of size block_size as follows:

%macro ResourceAllocation_Decomp(task_data=, capacity=, block_size=);
   proc optmodel;
      %SetupData(task_data=&task_data,capacity=&capacity);
      /* partition into blocks of size blocks_size */
      num block_size = &block_size; 
      num num_blocks = ceil( card(TASKS) / block_size );
      set BLOCKS     = 1..num_blocks;

      /* the set of starts s for which task i is active */
      set STARTS_TASK{i in TASKS} = {s in STARTS: start[i] <= s < end[i]};

      /* partition the start times into blocks of size block_size */
      set STARTS_BLOCK{BLOCKS} init {};
      num block_id    init 1;
      num block_count init 0;
      for{s in STARTS} do;
         STARTS_BLOCK[block_id] = STARTS_BLOCK[block_id] union {s};
         block_count = block_count + 1;
         if(mod(block_count, block_size) = 0) then 
             block_id = block_id + 1;
      end;         

Then, the following PROC OPTMODEL statements define the block-angular formulation and solve the problem by using the decomposition algorithm, the PRESOLVER=BASIC option, and block_size=40. Because this reformulation is equivalent to the original staircase formulation, disabling some of the advanced presolver techniques ensures that the model maintains block-angularity.

      /* blocks in which task i is online */
      set BLOCKS_TASK{i in TASKS} = 
         {b in BLOCKS: card(STARTS_BLOCK[b] inter STARTS_TASK[i]) > 0};

      /* minimum block id in which task i is online */
      num min_block{i in TASKS} = min{b in BLOCKS_TASK[i]} b;

      /* select task i to come online from period [start to end) 
         in each block */
      var x{i in TASKS, b in BLOCKS_TASK[i]} binary;
      
      /* maximize the total profit of running tasks */
      max TotalProfit = sum{i in TASKS} profit[i] * x[i,min_block[i]];
      
      /* enforce that task selection is consistent across blocks */
      con LinkDupVarsCon{i in TASKS, b in BLOCKS_TASK[i] diff {min_block[i]}}:
         x[i,b] = x[i,min_block[i]];
         
      /* enforce that the shared resource capacity is not exceeded */
      con CapacityCon{b in BLOCKS, s in STARTS_BLOCK[b]}:
         sum{i in TASKS_START[s]} weight[i] * x[i,b] <= capacity;
         
      /* define blocks for decomposition algorithm */ 
      for{b in BLOCKS, s in STARTS_BLOCK[b]} CapacityCon[b,s].block = b;
      
      solve with milp / presolver=basic decomp=();
   quit;
%mend ResourceAllocation_Decomp;

%ResourceAllocation_Decomp(task_data=TaskData, capacity=100, block_size=40);

The problem summary and solution summary are displayed in Output 13.4.3. Compared to the original formulation, the number of variables and constraints is increased by the number of duplicate variables.

Output 13.4.3: Problem Summary and Solution Summary

The OPTMODEL Procedure

Problem Summary
Objective Sense Maximization
Objective Function TotalProfit
Objective Type Linear
   
Number of Variables 3300
Bounded Above 0
Bounded Below 0
Bounded Below and Above 3300
Free 0
Fixed 0
Binary 3300
Integer 0
   
Number of Constraints 3291
Linear LE (<=) 2688
Linear EQ (=) 603
Linear GE (>=) 0
Linear Range 0
   
Constraint Coefficients 28086

Solution Summary
Solver MILP
Algorithm Decomposition
Objective Function TotalProfit
Solution Status Optimal within Relative Gap
Objective Value 62524.000009
Iterations 53
Best Bound 62526.501053
Nodes 5
   
Relative Gap 0.0000399998
Absolute Gap 2.5010445286
Primal Infeasibility 8.9999997E-7
Bound Infeasibility 5.7842335E-8
Integer Infeasibility 9.4285709E-8


The iteration log, which contains the problem statistics, the progress of the solution, and the optimal objective value, is shown in Output 13.4.4.

Output 13.4.4: Log

NOTE: There were 2697 observations read from the data set WORK.TASKDATA.              
NOTE: Problem generation will use 16 threads.                                         
NOTE: The problem has 3300 variables (0 free, 0 fixed).                               
NOTE: The problem has 3300 binary and 0 integer variables.                            
NOTE: The problem has 3291 linear constraints (2688 LE, 603 EQ, 0 GE, 0 range).       
NOTE: The problem has 28086 linear constraint coefficients.                           
NOTE: The problem has 0 nonlinear constraints (0 LE, 0 EQ, 0 GE, 0 range).            
NOTE: The MILP presolver value BASIC is applied.                                      
NOTE: The MILP presolver removed 0 variables and 0 constraints.                       
NOTE: The MILP presolver removed 0 constraint coefficients.                           
NOTE: The MILP presolver modified 0 constraint coefficients.                          
NOTE: The presolved problem has 3300 variables, 3291 constraints, and 28086           
      constraint coefficients.                                                        
NOTE: The MILP solver is called.                                                      
NOTE: The Decomposition algorithm is used.                                            
NOTE: The DECOMP method value USER is applied.                                        
NOTE: The decomposition subproblems consist of 68 disjoint blocks.                    
NOTE: The decomposition subproblems cover 3300 (100.00%) variables and 2688 (81.68%)  
      constraints.                                                                    
NOTE: The deterministic parallel mode is enabled.                                     
NOTE: The Decomposition algorithm is using up to 16 threads.                          
      Iter         Best       Master         Best       LP       IP   CPU  Real       
                  Bound    Objective      Integer      Gap      Gap  Time  Time       
NOTE: Starting phase 1.                                                               
         1       0.0000       0.0000            . 0.00e+00        .     4     0       
NOTE: Starting phase 2.                                                               
         .  145710.0000    1076.0000    1076.0000   99.26%   99.26%     4     0       
         3  145710.0000    2134.0000    2134.0000   98.54%   98.54%    11     2       
         9  122196.5339   57100.0074    2134.0000   53.27%   98.25%    26     6       
        10  122196.5339   59262.1719    2134.0000   51.50%   98.25%    29     6       
         .  122196.5339   60495.5101   46176.0000   50.49%   62.21%    30     7       
        12   67392.1689   60960.2971   46176.0000    9.54%   31.48%    40     9       
        14   64578.1085   61696.2311   46176.0000    4.46%   28.50%    47    10       
        17   63360.1939   62093.7197   46176.0000    2.00%   27.12%    60    12       
        18   63291.2501   62150.9167   46176.0000    1.80%   27.04%    65    13       
        19   63107.2180   62226.8333   46176.0000    1.40%   26.83%    69    14       
        20   63040.2686   62244.5093   46176.0000    1.26%   26.75%    74    14       
         .   63040.2686   62324.2667   57872.0000    1.14%    8.20%    75    16       
        21   62852.9000   62324.2667   57872.0000    0.84%    7.92%    82    17       
        22   62845.6667   62382.0000   57872.0000    0.74%    7.91%    87    18       
        23   62638.6667   62425.0000   57872.0000    0.34%    7.61%    92    18       
        24   62608.6667   62440.6667   57872.0000    0.27%    7.57%    97    19       
        26   62583.3334   62528.3333   57872.0000    0.09%    7.53%   106    20       
        27   62535.0001   62528.3333   57872.0000    0.01%    7.46%   111    21       
        29   62532.3334   62528.3333   57872.0000    0.01%    7.45%   121    22       
NOTE: The Decomposition algorithm stopped on the continuous RELOBJGAP option.         
         .   62532.3334   62528.3333   62445.0000    0.01%    0.14%   121    23       
NOTE: Starting branch and bound.                                                      
         Node  Active   Sols         Best         Best      Gap     CPU    Real       
                                  Integer        Bound             Time    Time       
            0       1      5   62445.0000   62532.3334    0.14%     121      23       
            4       2      7   62524.0000   62526.5011    0.00%     239      39       
NOTE: The Decomposition algorithm used 16 threads.                                    
NOTE: The Decomposition algorithm time is 39.90 seconds.                              
NOTE: Optimal within relative gap.                                                    
NOTE: Objective = 62524.                                                              


Using a Hybrid Method in PROC OPTMODEL

The decomposition algorithm solves the problem in fewer nodes due to the stronger bound obtained by the reformulation. However, it takes longer than the direct method to find a good feasible solution. The fact that the direct method seems to quickly find good feasible solutions but has weaker bounds motivates the use of a hybrid algorithm. In the macro %ResourceAllocation_Decomp, replace the statement,

      solve with milp / presolver=basic decomp=();

with the following statements:

      solve with milp / relobjgap=0.1;
      solve with milp / presolver=basic primalin decomp=();

These statements use the direct method with RELOBJGAP=0.1 to find a good starting solution and then use that result to seed the initial columns of the decomposition algorithm.

The solution summaries are displayed in Output 13.4.5.

Output 13.4.5: Solution Summaries

The OPTMODEL Procedure

Solution Summary
Solver MILP
Algorithm Branch and Cut
Objective Function TotalProfit
Solution Status Optimal within Relative Gap
Objective Value 61365.000002
Iterations 2198
Best Bound 68114.152567
Nodes 1
   
Relative Gap 0.0990859067
Absolute Gap 6749.1525652
Primal Infeasibility 0
Bound Infeasibility 0
Integer Infeasibility 1.1794872E-8

Solution Summary
Solver MILP
Algorithm Decomposition
Objective Function TotalProfit
Solution Status Optimal within Relative Gap
Objective Value 62524.000007
Iterations 29
Best Bound 62529.333388
Nodes 3
   
Relative Gap 0.0000852941
Absolute Gap 5.3333812158
Primal Infeasibility 8.9990996E-7
Bound Infeasibility 7.3809532E-8
Integer Infeasibility 7.3809532E-8


The iteration log, which contains the problem statistics, the progress of the solution, and the optimal objective value, is shown in Output 13.4.6.

Output 13.4.6: Log

NOTE: There were 2697 observations read from the data set WORK.TASKDATA.              
NOTE: Problem generation will use 16 threads.                                         
NOTE: The problem has 3300 variables (0 free, 0 fixed).                               
NOTE: The problem has 3300 binary and 0 integer variables.                            
NOTE: The problem has 3291 linear constraints (2688 LE, 603 EQ, 0 GE, 0 range).       
NOTE: The problem has 28086 linear constraint coefficients.                           
NOTE: The problem has 0 nonlinear constraints (0 LE, 0 EQ, 0 GE, 0 range).            
NOTE: The MILP presolver value AUTOMATIC is applied.                                  
NOTE: The MILP presolver removed 603 variables and 603 constraints.                   
NOTE: The MILP presolver removed 1206 constraint coefficients.                        
NOTE: The MILP presolver modified 0 constraint coefficients.                          
NOTE: The presolved problem has 2697 variables, 2688 constraints, and 26880           
      constraint coefficients.                                                        
NOTE: The MILP solver is called.                                                      
          Node  Active    Sols    BestInteger      BestBound      Gap    Time         
             0       1       3  54609.0000000         145710   62.52%       4         
             0       1       3  54609.0000000  73230.2096818   25.43%       4         
             0       1       6  60619.0000000  69933.6883758   13.32%       7         
             0       1       7  61365.0000021  68114.1525673    9.91%      10         
NOTE: The MILP solver added 390 cuts with 2060 cut coefficients at the root.          
NOTE: Optimal within relative gap.                                                    
NOTE: Objective = 61365.                                                              
NOTE: The MILP presolver value BASIC is applied.                                      
NOTE: The MILP presolver removed 0 variables and 0 constraints.                       
NOTE: The MILP presolver removed 0 constraint coefficients.                           
NOTE: The MILP presolver modified 0 constraint coefficients.                          
NOTE: The presolved problem has 3300 variables, 3291 constraints, and 28086           
      constraint coefficients.                                                        
NOTE: The MILP solver is called.                                                      
NOTE: The Decomposition algorithm is used.                                            
NOTE: The DECOMP method value USER is applied.                                        
NOTE: The decomposition subproblems consist of 68 disjoint blocks.                    
NOTE: The decomposition subproblems cover 3300 (100.00%) variables and 2688 (81.68%)  
      constraints.                                                                    
NOTE: The deterministic parallel mode is enabled.                                     
NOTE: The Decomposition algorithm is using up to 16 threads.                          
      Iter         Best       Master         Best       LP       IP   CPU  Real       
                  Bound    Objective      Integer      Gap      Gap  Time  Time       
NOTE: Starting phase 1.                                                               
         1       0.0000       0.0000            . 0.00e+00        .     3     0       
NOTE: Starting phase 2.                                                               
         .  145710.0000   61418.0000   61418.0000   57.85%   57.85%     4     0       
         3  145710.0000   61455.0000   61455.0000   57.82%   57.82%    11     2       
         4  145710.0000   61493.0000   61493.0000   57.80%   57.80%    14     3       
         6  127317.6055   61493.0000   61493.0000   51.70%   51.70%    19     4       
         7  127317.6055   61572.0000   61572.0000   51.64%   51.64%    22     4       
         9   87503.5259   62019.0000   61572.0000   29.12%   29.63%    29     6       
        10   65254.6113   62118.0000   61572.0000    4.81%    5.64%    33     6       
         .   65254.6113   62286.0000   62200.0000    4.55%    4.68%    33     6       
        12   63697.5000   62389.6667   62200.0000    2.05%    2.35%    41     8       
        13   63404.5001   62516.3333   62200.0000    1.40%    1.90%    45     8       
        14   63346.5001   62522.8333   62200.0000    1.30%    1.81%    49     9       
        15   62946.3334   62523.8333   62200.0000    0.67%    1.19%    54    10       
        16   62851.8334   62525.3333   62200.0000    0.52%    1.04%    58    10       
        17   62688.8334   62525.3333   62200.0000    0.26%    0.78%    62    11       
        18   62598.8334   62525.3333   62200.0000    0.12%    0.64%    67    11       
        19   62541.3334   62528.3333   62200.0000    0.02%    0.55%    71    12       
        20   62541.3334   62528.3333   62200.0000    0.02%    0.55%    75    13       
         .   62541.3334   62528.3333   62484.0000    0.02%    0.09%    75    13       
        21   62529.3334   62528.3333   62484.0000    0.00%    0.07%    79    13       
NOTE: The Decomposition algorithm stopped on the continuous RELOBJGAP option.         
NOTE: Starting branch and bound.                                                      
         Node  Active   Sols         Best         Best      Gap     CPU    Real       
                                  Integer        Bound             Time    Time       
            0       1      7   62484.0000   62529.3334    0.07%      80      14       
            2       2      8   62524.0000   62529.3334    0.01%     104      18       
NOTE: The Decomposition algorithm used 16 threads.                                    
NOTE: The Decomposition algorithm time is 18.58 seconds.                              
NOTE: Optimal within relative gap.                                                    
NOTE: Objective = 62524.                                                              


By using this hybrid method, you can take advantage of the direct method, which finds a good feasible solution quickly, and the strong bounds provided by the decomposition algorithm. The overall time to solve the model by using the hybrid method is faster than either of the other two.

The Tradeoff between Coverage and Subproblem Difficulty

The reformulation of this resource allocation problem provides a nice example of the potential tradeoffs in modeling a problem for use with the decomposition algorithm. As seen in Example 13.2, the strength of the bound is an important factor in the overall performance of the algorithm, but it is not always correlated to the magnitude of the subproblem coverage. In this example, the block size determines the number of blocks. Moreover, it determines the number of linking variables that are needed in the reformulation. At one extreme, if the block size is set to be $|S|$, then the number of blocks is 1, and the number of copies of original variables is 0. Using one block would be equivalent to the original staircase formulation and would not yield a model conducive to decomposition. As the number of blocks is increased, the number of linking variables increases (the size of the master problem), the strength of the decomposition bound decreases, and the difficulty of solving the subproblems decreases. In addition, as the number of blocks and their relative difficulty change, the efficent utilization of your machine’s parallel architecture can be affected.

The previous section used a block size of 40. The following statement calls the decomposition algorithm and uses a block size of 130:

%ResourceAllocation_Decomp(task_data=TaskData, capacity=100, block_size=130);

The solution summary is displayed in Output 13.4.7.

Output 13.4.7: Solution Summary

The OPTMODEL Procedure

Solution Summary
Solver MILP
Algorithm Decomposition
Objective Function TotalProfit
Solution Status Optimal within Relative Gap
Objective Value 62523.000017
Iterations 17
Best Bound 62523.001039
Nodes 1
   
Relative Gap 1.6347585E-8
Absolute Gap 0.0010221001
Primal Infeasibility 7.8333358E-8
Bound Infeasibility 2.1999998E-8
Integer Infeasibility 2.4615249E-7


The iteration log, which contains the problem statistics, the progress of the solution, and the optimal objective value, is shown in Output 13.4.8.

Output 13.4.8: Log

NOTE: There were 2697 observations read from the data set WORK.TASKDATA.              
NOTE: Problem generation will use 16 threads.                                         
NOTE: The problem has 2877 variables (0 free, 0 fixed).                               
NOTE: The problem has 2877 binary and 0 integer variables.                            
NOTE: The problem has 2868 linear constraints (2688 LE, 180 EQ, 0 GE, 0 range).       
NOTE: The problem has 27240 linear constraint coefficients.                           
NOTE: The problem has 0 nonlinear constraints (0 LE, 0 EQ, 0 GE, 0 range).            
NOTE: The MILP presolver value BASIC is applied.                                      
NOTE: The MILP presolver removed 0 variables and 0 constraints.                       
NOTE: The MILP presolver removed 0 constraint coefficients.                           
NOTE: The MILP presolver modified 0 constraint coefficients.                          
NOTE: The presolved problem has 2877 variables, 2868 constraints, and 27240           
      constraint coefficients.                                                        
NOTE: The MILP solver is called.                                                      
NOTE: The Decomposition algorithm is used.                                            
NOTE: The DECOMP method value USER is applied.                                        
NOTE: The decomposition subproblems consist of 21 disjoint blocks.                    
NOTE: The decomposition subproblems cover 2877 (100.00%) variables and 2688 (93.72%)  
      constraints.                                                                    
NOTE: The deterministic parallel mode is enabled.                                     
NOTE: The Decomposition algorithm is using up to 16 threads.                          
      Iter         Best       Master         Best       LP       IP   CPU  Real       
                  Bound    Objective      Integer      Gap      Gap  Time  Time       
NOTE: Starting phase 1.                                                               
         1       0.0000       0.0000            . 0.00e+00        .     7     1       
NOTE: Starting phase 2.                                                               
         .  145710.0000       0.0000       0.0000  100.00%  100.00%     7     1       
         2  126790.2482       0.0000       0.0000  100.00%  100.00%    14     3       
         3  126790.2482   12735.0000   12735.0000   89.96%   89.96%    21     4       
         7  102615.1164   57591.6667   12735.0000   43.88%   87.59%    46     9       
         9   64261.1000   61854.1000   12735.0000    3.75%   80.18%    58    12       
        10   63394.2500   62212.7500   12735.0000    1.86%   79.91%    63    13       
         .   63394.2500   62382.5000   61668.0000    1.60%    2.72%    63    13       
        11   62875.5000   62382.5000   61668.0000    0.78%    1.92%    69    14       
        13   62622.0000   62444.0000   61668.0000    0.28%    1.52%    81    16       
        14   62604.0000   62464.5000   61668.0000    0.22%    1.50%    86    17       
        15   62579.5000   62496.5000   61668.0000    0.13%    1.46%    92    18       
        16   62547.0000   62508.5000   61668.0000    0.06%    1.41%    98    19       
        17   62524.0000   62523.0000   62523.0000    0.00%    0.00%   104    20       
NOTE: The continuous bound was improved to 62523 due to objective granularity.        
        17   62523.0010   62523.0010   62523.0000    0.00%    0.00%   104    20       
         Node  Active   Sols         Best         Best      Gap     CPU    Real       
                                  Integer        Bound             Time    Time       
            0       0      4   62523.0000   62523.0010    0.00%     104      20       
NOTE: The Decomposition algorithm used 16 threads.                                    
NOTE: The Decomposition algorithm time is 20.73 seconds.                              
NOTE: Optimal within relative gap.                                                    
NOTE: Objective = 62523.                                                              


This version of the model provides a stronger bound and yields better overall performance.