Hello,
I have a binary integer program
Max cx
s.t. Ax = b
x in {0,1}
that can get instantiated in two ways:
(Way 1)
Create the LP relaxation
Max cx
s.t. Ax = b
0 <= x <= 1
That is, there is a call to CPXnewcols(env, lp, Ncol, obj, lb, ub, vartype, varname);
where vartype entries are all 'C' denoting continuous variables.
Solve this using call to
CPXprimopt()
Then, call
CPXchgctype(env, lp, number_changed, indices, ctype);//here ctype is a char* of all entries 'B' denoting binary variables
CPXchgprobtype(env, lp, CPXPROB_MILP);
After this, call to
CPXmipopt(env, lp)
gives a log that looks thus:
Version identifier: 12.10.0.0 | 2019-11-26 | 843d4de2ae
CPXPARAM_TimeLimit 7200
Probing fixed 686 vars, tightened 296 bounds.
Probing time = 0.03 sec. (12.91 ticks)
Cover probing fixed 1 vars, tightened 354 bounds.
Clique table members: 7599.
MIP emphasis: balance optimality and feasibility.
MIP search method: dynamic search.
Parallel mode: deterministic, using up to 8 threads.
Root relaxation solution time = 0.05 sec. (17.51 ticks)
Nodes Cuts/
Node Left Objective IInf Best Integer Best Bound ItCnt Gap
* 0+ 0 0.0000 0.00%
0 0 27600.3333 139 0.0000 27600.3333 474 ---
* 0+ 0 941.0000 27600.3333 ---
* 0+ 0 1033.0000 27600.3333 ---
0 0 14396.2409 139 1033.0000 Cuts: 913 725 ---
0 0 3173.5983 139 1033.0000 Cuts: 863 979 207.22%
0 0 2654.4265 139 1033.0000 Cuts: 706 1179 156.96%
0 0 1199.2878 139 1033.0000 Cuts: 454 1284 16.10%
0 0 1192.9676 139 1033.0000 Cuts: 521 1355 15.49%
0 0 1189.2662 139 1033.0000 Cuts: 151 1393 15.13%
0 0 1185.0240 139 1033.0000 Cuts: 91 1428 14.72%
0 0 1183.5318 139 1033.0000 Cuts: 50 1453 14.57%
0 0 1183.5318 139 1033.0000 Cuts: 57 1479 14.57%
0 0 1183.5276 139 1033.0000 Cuts: 30 1494 14.57%
0 0 1183.5276 139 1033.0000 Cuts: 245 1539 14.57%
* 0+ 0 1042.0000 1183.5276 13.58%
Detecting symmetries...
0 2 1183.5276 86 1042.0000 1173.1277 1539 12.58%
Elapsed time = 0.88 sec. (542.46 ticks, tree = 0.02 MB, solutions = 4)
* 24+ 2 1044.0000 1157.4561 10.87%
293 187 1054.5067 51 1044.0000 1134.1228 2606 8.63%
1073 688 1066.6562 60 1044.0000 1094.7462 7619 4.86%
1999 1300 1057.9912 58 1044.0000 1083.8762 18334 3.82%
2967 1854 1044.5000 44 1044.0000 1078.3558 26361 3.29%
4168 2403 1046.7143 38 1044.0000 1076.3747 34221 3.10%
5363 2945 1071.3246 49 1044.0000 1072.7077 45632 2.75%
6765 3544 1044.9365 45 1044.0000 1070.1413 57361 2.50%
7909 4055 1055.0520 70 1044.0000 1067.1077 67591 2.21%
9249 4548 1054.8801 49 1044.0000 1065.7896 78924 2.09%
14690 6779 1050.5365 51 1044.0000 1060.4964 117756 1.58%
Elapsed time = 5.95 sec. (3643.50 ticks, tree = 7.46 MB, solutions = 5)
20724 8609 1049.2143 44 1044.0000 1056.1878 155672 1.17%
26725 10006 1047.2019 52 1044.0000 1053.7070 190282 0.93%
33252 10815 1050.8780 52 1044.0000 1051.8889 217586 0.76%
39021 10649 1046.5000 45 1044.0000 1050.8790 244866 0.66%
44758 9767 1044.2500 47 1044.0000 1049.1667 266144 0.49%
50591 8413 1047.0000 37 1044.0000 1047.4889 296666 0.33%
56392 7662 1044.8889 56 1044.0000 1046.8878 320280 0.28%
...
As can be observed, it takes quite a bit of nodes to reduce the gap.
(Way 2)
In this way, I directly create the binary integer program thus:
Max cx
s.t. Ax = b
x in {0,1}
and solve it directly by a call to
CPXmipopt(env, lp)
That is, there is a call to
CPXnewcols(env, lp, Ncol, obj, lb, ub, vartype, varname);
where the values of vartype are 'B' indicating binary variables being added to the problem.
This solve the problem much quicker. See log:
Version identifier: 12.10.0.0 | 2019-11-26 | 843d4de2ae
CPXPARAM_TimeLimit 7200
Tried aggregator 3 times.
MIP Presolve eliminated 2596 rows and 791 columns.
MIP Presolve modified 8805 coefficients.
Aggregator did 51 substitutions.
Reduced MIP has 989 rows, 642 columns, and 3278 nonzeros.
Reduced MIP has 447 binaries, 0 generals, 0 SOSs, and 0 indicators.
Presolve time = 0.03 sec. (14.56 ticks)
Probing fixed 50 vars, tightened 27 bounds.
Probing time = 0.02 sec. (5.42 ticks)
Cover probing fixed 0 vars, tightened 53 bounds.
Tried aggregator 2 times.
MIP Presolve eliminated 116 rows and 64 columns.
MIP Presolve modified 379 coefficients.
Aggregator did 1 substitutions.
Reduced MIP has 872 rows, 577 columns, and 2861 nonzeros.
Reduced MIP has 390 binaries, 0 generals, 0 SOSs, and 0 indicators.
Presolve time = 0.03 sec. (2.02 ticks)
Probing time = 0.02 sec. (2.55 ticks)
Cover probing fixed 0 vars, tightened 26 bounds.
Tried aggregator 1 time.
Detecting symmetries...
MIP Presolve eliminated 1 rows and 0 columns.
MIP Presolve modified 355 coefficients.
Reduced MIP has 871 rows, 577 columns, and 2858 nonzeros.
Reduced MIP has 390 binaries, 0 generals, 0 SOSs, and 0 indicators.
Presolve time = 0.02 sec. (1.73 ticks)
Probing fixed 2 vars, tightened 6 bounds.
Probing time = 0.02 sec. (3.46 ticks)
Cover probing fixed 0 vars, tightened 7 bounds.
Clique table members: 2129.
MIP emphasis: balance optimality and feasibility.
MIP search method: dynamic search.
Parallel mode: deterministic, using up to 8 threads.
Root relaxation solution time = 0.00 sec. (2.67 ticks)
Nodes Cuts/
Node Left Objective IInf Best Integer Best Bound ItCnt Gap
0 0 1133.9133 123 1133.9133 185
0 0 1081.3978 123 Cuts: 317 316
* 0+ 0 1029.0000 1081.3978 5.09%
0 0 1059.3933 123 1029.0000 Cuts: 317 450 2.95%
0 0 1057.2601 123 1029.0000 Cuts: 285 551 2.75%
* 0+ 0 1042.0000 1057.2601 1.46%
0 0 1055.8400 123 1042.0000 Cuts: 255 645 1.33%
0 0 1053.8510 123 1042.0000 Cuts: 211 727 1.14%
Detecting symmetries...
0 0 1052.9856 123 1042.0000 Cuts: 200 812 1.05%
0 0 1052.8992 123 1042.0000 Cuts: 160 870 1.05%
0 0 1052.8992 123 1042.0000 Cuts: 84 902 1.05%
0 0 1052.8992 123 1042.0000 Cuts: 11 917 1.05%
0 0 1052.8992 123 1042.0000 Cuts: 42 943 1.05%
Detecting symmetries...
0 2 1052.8992 35 1042.0000 1052.8992 943 1.05%
Elapsed time = 0.45 sec. (161.64 ticks, tree = 0.02 MB, solutions = 2)
* 252 66 integral 0 1044.0000 1045.7143 1907 0.16%
Clique cuts applied: 11
Cover cuts applied: 2
Implied bound cuts applied: 122
Flow cuts applied: 8
Mixed integer rounding cuts applied: 77
Zero-half cuts applied: 1
Lift and project cuts applied: 2
Gomory fractional cuts applied: 11
Root node processing (before b&c):
Real time = 0.45 sec. (161.26 ticks)
Parallel b&c, 8 threads:
Real time = 0.06 sec. (28.45 ticks)
Sync time (average) = 0.02 sec.
Wait time (average) = 0.00 sec.
------------
Total (root+branch&cut) = 0.52 sec. (189.71 ticks)
Looking at the two logs, it appears that the preprocessing path taken by the two ways differ significantly. In (Way 2), the aggregator is called amongst others, for instance. Then, the path taken within the branch and bound tree also differs significantly.
Is there a way to figure out why this is happening and how this can be avoided?
In each instance, I call CPLEX using default parameters except for the time limit of 7200 seconds in both cases.
Thanks.
------------------------------
CPLEX User
------------------------------
#DecisionOptimization