diff --git a/.gitignore b/.gitignore index 6d34ac5..28a795a 100644 --- a/.gitignore +++ b/.gitignore @@ -115,3 +115,4 @@ dmypy.json # Cython debug symbols cython_debug/ +.DS_Store diff --git a/data/950_glass4_Method2.log b/data/950_glass4_Method2.log new file mode 100644 index 0000000..af91cea --- /dev/null +++ b/data/950_glass4_Method2.log @@ -0,0 +1,116 @@ + +Gurobi 9.5.0 (mac64[arm], gurobi_cl) logging started Mon Jan 10 14:49:20 2022 + +Set parameter Method to value 2 +Set parameter LogFile to value "950_glass4_Method2.log" +Using license file /Users/vandervelden/gurobi.lic + +Gurobi Optimizer version 9.5.0 build v9.5.0rc5 (mac64[arm]) +Copyright (c) 2021, Gurobi Optimization, LLC + +Read MPS format model from file glass4.mps +Reading time = 0.00 seconds +glass4: 396 rows, 322 columns, 1815 nonzeros +Thread count: 8 physical cores, 8 logical processors, using up to 8 threads +Optimize a model with 396 rows, 322 columns and 1815 nonzeros +Model fingerprint: 0x18b19fdf +Variable types: 20 continuous, 302 integer (0 binary) +Coefficient statistics: + Matrix range [1e+00, 8e+06] + Objective range [1e+00, 1e+06] + Bounds range [1e+00, 8e+02] + RHS range [1e+00, 8e+06] +Presolve removed 6 rows and 6 columns +Presolve time: 0.01s +Presolved: 390 rows, 316 columns, 1803 nonzeros +Variable types: 19 continuous, 297 integer (297 binary) +Found heuristic solution: objective 3.133356e+09 +Root barrier log... + +Ordering time: 0.00s + +Barrier statistics: + AA' NZ : 2.456e+04 + Factor NZ : 5.555e+04 (roughly 1 MB of memory) + Factor Ops : 1.105e+07 (less than 1 second per iteration) + Threads : 8 + + Objective Residual +Iter Primal Dual Primal Dual Compl Time + 0 3.85701553e+09 -2.44746138e+10 3.25e+03 7.29e-07 8.27e+08 0s + 1 2.73108698e+09 -1.05530373e+11 1.02e-12 4.66e-09 1.10e+08 0s + 2 1.32418625e+09 -6.98135861e+09 2.27e-13 9.31e-10 8.42e+06 0s + 3 8.00844488e+08 6.20408532e+08 2.27e-13 6.10e-10 1.83e+05 0s + 4 8.00638297e+08 7.99663215e+08 2.84e-13 3.09e-10 9.89e+02 0s + 5 8.00007332e+08 7.99985170e+08 2.27e-13 5.73e-09 2.25e+01 0s + 6 8.00002838e+08 8.00001226e+08 2.84e-13 1.83e-13 1.63e+00 0s + 7 8.00002402e+08 8.00002387e+08 3.41e-13 1.86e-09 1.51e-02 0s + 8 8.00002400e+08 8.00002400e+08 3.41e-13 3.47e-09 1.51e-05 0s + 9 8.00002400e+08 8.00002400e+08 2.27e-13 6.04e-14 1.51e-11 0s + +Barrier solved model in 9 iterations and 0.05 seconds (0.02 work units) +Optimal objective 8.00002400e+08 + + +Root relaxation: objective 8.000024e+08, 281 iterations, 0.03 seconds (0.01 work units) + + Nodes | Current Node | Objective Bounds | Work + Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time + + 0 0 8.0000e+08 0 72 3.1334e+09 8.0000e+08 74.5% - 0s + 0 0 8.0000e+08 0 72 3.1334e+09 8.0000e+08 74.5% - 0s + 0 0 8.0000e+08 0 72 3.1334e+09 8.0000e+08 74.5% - 0s + 0 0 8.0000e+08 0 73 3.1334e+09 8.0000e+08 74.5% - 0s + 0 0 8.0000e+08 0 73 3.1334e+09 8.0000e+08 74.5% - 0s +H 0 0 2.300022e+09 8.0000e+08 65.2% - 0s + 0 2 8.0000e+08 0 73 2.3000e+09 8.0000e+08 65.2% - 0s +H 71 120 2.233354e+09 8.0000e+08 64.2% 9.8 0s +H 85 120 2.200021e+09 8.0000e+08 63.6% 8.5 0s +H 179 316 2.000018e+09 8.0000e+08 60.0% 5.6 0s +H 202 316 1.900018e+09 8.0000e+08 57.9% 5.5 0s +H 417 520 1.900017e+09 8.0000e+08 57.9% 5.1 0s +* 2167 1924 86 1.900017e+09 8.0000e+08 57.9% 5.9 0s +H 2225 1831 1.900017e+09 8.0000e+08 57.9% 6.0 0s +H 2256 1767 1.900017e+09 8.0000e+08 57.9% 6.0 0s +H 2354 1748 1.875017e+09 8.0000e+08 57.3% 5.8 0s +H 2359 1663 1.700016e+09 8.0000e+08 52.9% 5.8 0s +H 3590 2080 1.700016e+09 8.0000e+08 52.9% 5.0 0s +H 3599 2002 1.700016e+09 8.0000e+08 52.9% 5.1 0s +H 3643 1927 1.680016e+09 8.0000e+08 52.4% 5.1 0s +H 5143 2113 1.680016e+09 8.0000e+08 52.4% 4.9 0s +H 6422 2524 1.680016e+09 8.0000e+08 52.4% 4.7 0s +* 6439 2515 101 1.666682e+09 8.0000e+08 52.0% 4.7 0s +H 6791 3058 1.666681e+09 8.0000e+08 52.0% 4.8 0s +* 8953 3889 99 1.666681e+09 8.0000e+08 52.0% 4.5 0s +* 8954 3889 99 1.666681e+09 8.0000e+08 52.0% 4.5 0s +H14998 7347 1.666681e+09 8.0000e+08 52.0% 4.3 1s +H15037 7237 1.650015e+09 8.0000e+08 51.5% 4.3 1s +H15324 6303 1.575014e+09 8.0000e+08 49.2% 4.3 1s +H30400 10662 1.575014e+09 9.0000e+08 42.9% 4.5 2s + 38484 12515 infeasible 81 1.5750e+09 9.0000e+08 42.9% 6.8 5s +*40024 11851 87 1.550015e+09 9.0000e+08 41.9% 7.4 5s +*40290 11407 77 1.540015e+09 9.0000e+08 41.6% 7.5 5s +*76153 18875 90 1.500024e+09 9.7501e+08 35.0% 9.5 8s +*101369 29869 80 1.500015e+09 1.0000e+09 33.3% 9.6 9s + 106588 32924 1.3000e+09 55 44 1.5000e+09 1.0000e+09 33.3% 9.6 10s +*131449 42063 74 1.500013e+09 1.0000e+09 33.3% 9.4 11s +*132241 42219 80 1.500013e+09 1.0000e+09 33.3% 9.4 11s +*145183 34082 74 1.400013e+09 1.0000e+09 28.6% 9.4 11s +H147243 17900 1.200013e+09 1.0000e+09 16.7% 9.5 11s + +Cutting planes: + Gomory: 16 + Implied bound: 16 + Projected implied bound: 2 + MIR: 11 + Flow cover: 31 + RLT: 6 + Relax-and-lift: 26 + +Explored 160585 nodes (1440238 simplex iterations) in 12.31 seconds (16.88 work units) +Thread count was 8 (of 8 available processors) + +Solution count 10: 1.20001e+09 1.40001e+09 1.50001e+09 ... 1.57501e+09 + +Optimal solution found (tolerance 1.00e-04) +Best objective 1.200012600000e+09, best bound 1.200003400000e+09, gap 0.0008% diff --git a/data/950_klein1_infeasible.log b/data/950_klein1_infeasible.log new file mode 100644 index 0000000..f83eca1 --- /dev/null +++ b/data/950_klein1_infeasible.log @@ -0,0 +1,28 @@ + +Gurobi 9.5.0 (mac64[arm], gurobi_cl) logging started Mon Jan 10 14:51:39 2022 + +Set parameter LogFile to value "950_klein1_infeasible.log" +Using license file /Users/vandervelden/gurobi.lic + +Gurobi Optimizer version 9.5.0 build v9.5.0rc5 (mac64[arm]) +Copyright (c) 2021, Gurobi Optimization, LLC + +Read MPS format model from file klein1.mps +Reading time = 0.00 seconds +KLEIN1: 54 rows, 54 columns, 696 nonzeros +Thread count: 8 physical cores, 8 logical processors, using up to 8 threads +Optimize a model with 54 rows, 54 columns and 696 nonzeros +Model fingerprint: 0xa5520c92 +Coefficient statistics: + Matrix range [1e+00, 2e+03] + Objective range [0e+00, 0e+00] + Bounds range [0e+00, 0e+00] + RHS range [8e+00, 5e+01] +Presolve time: 0.00s +Presolved: 54 rows, 54 columns, 696 nonzeros + +Iteration Objective Primal Inf. Dual Inf. Time + 0 0.0000000e+00 1.400000e+02 0.000000e+00 0s + +Solved in 116 iterations and 0.00 seconds (0.00 work units) +Infeasible model diff --git a/data/950_qafiro.log b/data/950_qafiro.log new file mode 100644 index 0000000..f5c3472 --- /dev/null +++ b/data/950_qafiro.log @@ -0,0 +1,54 @@ + +Gurobi 9.5.0 (mac64[arm], gurobi_cl) logging started Mon Jan 10 14:50:39 2022 + +Set parameter LogFile to value "950_qafiro.log" +Using license file /Users/vandervelden/gurobi.lic + +Gurobi Optimizer version 9.5.0 build v9.5.0rc5 (mac64[arm]) +Copyright (c) 2021, Gurobi Optimization, LLC + +Read LP format model from file qafiro.lp +Reading time = 0.00 seconds +: 27 rows, 32 columns, 83 nonzeros +Thread count: 8 physical cores, 8 logical processors, using up to 8 threads +Optimize a model with 27 rows, 32 columns and 83 nonzeros +Model fingerprint: 0x74babdfc +Model has 6 quadratic objective terms +Coefficient statistics: + Matrix range [1e-01, 2e+00] + Objective range [3e-01, 1e+01] + QObjective range [2e+00, 1e+01] + Bounds range [0e+00, 0e+00] + RHS range [4e+01, 5e+02] +Presolve removed 16 rows and 18 columns +Presolve time: 0.00s +Presolved: 11 rows, 14 columns, 36 nonzeros +Presolved model has 6 quadratic objective terms +Ordering time: 0.00s + +Barrier statistics: + Free vars : 2 + AA' NZ : 3.300e+01 + Factor NZ : 9.100e+01 + Factor Ops : 8.190e+02 (less than 1 second per iteration) + Threads : 1 + + Objective Residual +Iter Primal Dual Primal Dual Compl Time + 0 3.04762508e+05 -6.19194374e+05 3.78e+03 3.64e+02 1.01e+06 0s + 1 9.19074541e+04 -6.50581821e+05 1.08e+03 1.04e+02 3.06e+05 0s + 2 3.42696482e+04 -7.22766898e+05 9.36e+00 1.07e+00 3.44e+04 0s + 3 2.02825275e+04 -4.44313760e+04 4.38e-01 5.01e-02 2.72e+03 0s + 4 3.88511497e+03 -5.56534324e+03 4.38e-07 5.01e-08 3.94e+02 0s + 5 5.77516824e+02 -6.68382750e+02 4.14e-13 4.62e-14 5.19e+01 0s + 6 8.31403688e+01 -9.23266283e+01 1.07e-14 2.66e-15 7.31e+00 0s + 7 1.15818327e+01 -1.34624295e+01 3.11e-15 1.33e-15 1.04e+00 0s + 8 3.72931523e-01 -2.52864393e+00 8.88e-16 1.76e-15 1.21e-01 0s + 9 -1.48959224e+00 -1.69620250e+00 1.67e-16 5.55e-16 8.61e-03 0s + 10 -1.59068065e+00 -1.59088807e+00 2.22e-16 5.41e-16 8.64e-06 0s + 11 -1.59078169e+00 -1.59078190e+00 3.92e-16 1.17e-15 8.65e-09 0s + 12 -1.59078179e+00 -1.59078179e+00 3.89e-16 1.17e-15 8.66e-12 0s + +Barrier solved model in 12 iterations and 0.01 seconds (0.00 work units) +Optimal objective -1.59078179e+00 + diff --git a/data/tsp_100_optimal.log b/data/tsp_100_optimal.log new file mode 100644 index 0000000..684ffb2 --- /dev/null +++ b/data/tsp_100_optimal.log @@ -0,0 +1,52 @@ +Gurobi 9.1.2 (mac64[arm]) logging started Mon Jan 10 14:57:17 2022 + +Changed value of parameter LogFile to tsp.log + Prev: Default: +Changed value of parameter LazyConstraints to 1 + Prev: 0 Min: 0 Max: 1 Default: 0 +Gurobi Optimizer version 9.1.2 build v9.1.2rc0 (mac64[arm]) +Thread count: 8 physical cores, 8 logical processors, using up to 8 threads +Optimize a model with 100 rows, 4950 columns and 9900 nonzeros +Model fingerprint: 0x0313d8d5 +Variable types: 0 continuous, 4950 integer (4950 binary) +Coefficient statistics: + Matrix range [1e+00, 1e+00] + Objective range [1e+00, 1e+02] + Bounds range [1e+00, 1e+00] + RHS range [2e+00, 2e+00] +Presolve time: 0.00s +Presolved: 100 rows, 4950 columns, 9900 nonzeros +Variable types: 0 continuous, 4950 integer (4950 binary) + +Root relaxation: objective 7.780982e+02, 144 iterations, 0.00 seconds + + Nodes | Current Node | Objective Bounds | Work + Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time + + 0 0 778.09821 0 22 - 778.09821 - - 0s + 0 0 789.44882 0 14 - 789.44882 - - 0s + 0 0 790.55756 0 18 - 790.55756 - - 0s + 0 0 791.44578 0 20 - 791.44578 - - 0s + 0 0 791.44578 0 20 - 791.44578 - - 0s + 0 2 799.12705 0 14 - 799.12705 - - 0s +* 1345 1214 101 856.7701003 803.53288 6.21% 4.3 0s +H 1611 1066 847.9450046 803.62810 5.23% 4.5 0s +H 1646 1004 829.6838079 813.74207 1.92% 4.4 0s +H 1657 962 824.4134445 820.19170 0.51% 4.5 0s + +Cutting planes: + Gomory: 10 + MIR: 1 + Flow cover: 3 + Zero half: 6 + Lazy constraints: 3 + +Explored 1688 nodes (8621 simplex iterations) in 1.14 seconds +Thread count was 8 (of 8 available processors) + +Solution count 4: 824.413 829.684 847.945 856.77 + +Optimal solution found (tolerance 1.00e-04) +Best objective 8.244134444902e+02, best bound 8.244134444902e+02, gap 0.0000% + +User-callback calls 3955, time in user-callback 0.35 sec diff --git a/data/tsp_500_interrupted.log b/data/tsp_500_interrupted.log new file mode 100644 index 0000000..d462913 --- /dev/null +++ b/data/tsp_500_interrupted.log @@ -0,0 +1,56 @@ + +Gurobi 9.1.2 (mac64[arm]) logging started Mon Jan 10 14:57:48 2022 + +Changed value of parameter LogFile to tsp.log + Prev: Default: +Changed value of parameter LazyConstraints to 1 + Prev: 0 Min: 0 Max: 1 Default: 0 +Gurobi Optimizer version 9.1.2 build v9.1.2rc0 (mac64[arm]) +Thread count: 8 physical cores, 8 logical processors, using up to 8 threads +Optimize a model with 500 rows, 124750 columns and 249500 nonzeros +Model fingerprint: 0xa0347fad +Variable types: 0 continuous, 124750 integer (124750 binary) +Coefficient statistics: + Matrix range [1e+00, 1e+00] + Objective range [1e+00, 1e+02] + Bounds range [1e+00, 1e+00] + RHS range [2e+00, 2e+00] +Presolve time: 0.10s +Presolved: 500 rows, 124750 columns, 249500 nonzeros +Variable types: 0 continuous, 124750 integer (124750 binary) + +Starting sifting (using dual simplex for sub-problems)... + + Iter Pivots Primal Obj Dual Obj Time + 0 0 infinity 0.0000000e+00 0s + +Sifting complete + + +Root relaxation: objective 1.616131e+03, 780 iterations, 0.02 seconds + + Nodes | Current Node | Objective Bounds | Work + Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time + + 0 0 1616.13138 0 76 - 1616.13138 - - 0s + 0 0 1626.80849 0 54 - 1626.80849 - - 1s + 0 0 1627.53253 0 48 - 1627.53253 - - 1s + 0 0 1629.11256 0 49 - 1629.11256 - - 1s + 0 0 1630.18968 0 52 - 1630.18968 - - 2s + 0 0 1630.29259 0 65 - 1630.29259 - - 2s + 0 0 1630.29259 0 65 - 1630.29259 - - 2s + +Cutting planes: + MIR: 5 + Zero half: 42 + Lazy constraints: 7 + +Explored 1 nodes (885 simplex iterations) in 5.21 seconds +Thread count was 8 (of 8 available processors) + +Solution count 0 + +Solve interrupted +Best objective -, best bound 1.630292589993e+03, gap - + +User-callback calls 2483, time in user-callback 1.14 sec diff --git a/data/tsp_500_timelimit.log b/data/tsp_500_timelimit.log new file mode 100644 index 0000000..31591d7 --- /dev/null +++ b/data/tsp_500_timelimit.log @@ -0,0 +1,58 @@ + +Gurobi 9.1.2 (mac64[arm]) logging started Mon Jan 10 14:58:18 2022 + +Changed value of parameter LogFile to tsp.log + Prev: Default: +Changed value of parameter LazyConstraints to 1 + Prev: 0 Min: 0 Max: 1 Default: 0 +Changed value of parameter TimeLimit to 5.0 + Prev: inf Min: 0.0 Max: inf Default: inf +Gurobi Optimizer version 9.1.2 build v9.1.2rc0 (mac64[arm]) +Thread count: 8 physical cores, 8 logical processors, using up to 8 threads +Optimize a model with 500 rows, 124750 columns and 249500 nonzeros +Model fingerprint: 0xa0347fad +Variable types: 0 continuous, 124750 integer (124750 binary) +Coefficient statistics: + Matrix range [1e+00, 1e+00] + Objective range [1e+00, 1e+02] + Bounds range [1e+00, 1e+00] + RHS range [2e+00, 2e+00] +Presolve time: 0.10s +Presolved: 500 rows, 124750 columns, 249500 nonzeros +Variable types: 0 continuous, 124750 integer (124750 binary) + +Starting sifting (using dual simplex for sub-problems)... + + Iter Pivots Primal Obj Dual Obj Time + 0 0 infinity 0.0000000e+00 0s + +Sifting complete + + +Root relaxation: objective 1.616131e+03, 780 iterations, 0.02 seconds + + Nodes | Current Node | Objective Bounds | Work + Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time + + 0 0 1616.13138 0 76 - 1616.13138 - - 0s + 0 0 1626.80849 0 54 - 1626.80849 - - 1s + 0 0 1627.53253 0 48 - 1627.53253 - - 1s + 0 0 1629.11256 0 49 - 1629.11256 - - 1s + 0 0 1630.18968 0 52 - 1630.18968 - - 2s + 0 0 1630.29259 0 65 - 1630.29259 - - 2s + 0 0 1630.29259 0 65 - 1630.29259 - - 2s + +Cutting planes: + MIR: 5 + Zero half: 42 + Lazy constraints: 7 + +Explored 1 nodes (885 simplex iterations) in 5.00 seconds +Thread count was 8 (of 8 available processors) + +Solution count 0 + +Time limit reached +Best objective -, best bound 1.630292589993e+03, gap - + +User-callback calls 2369, time in user-callback 1.14 sec diff --git a/test.ipynb b/test.ipynb new file mode 100644 index 0000000..e69de29 diff --git a/tests/helpers.py b/tests/helpers.py index b742abe..2820cdc 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,6 +1,6 @@ import grblogtools as glt def read_single(filename): - summary = glt.get_dataframe([f'data/{filename}']) + summary, timelines = glt.get_dataframe([f'data/{filename}'], timelines=True) rows = summary.to_dict(orient='records') - return rows[0] + return rows[0], timelines diff --git a/tests/test_barrier.py b/tests/test_barrier.py new file mode 100644 index 0000000..7ac9cab --- /dev/null +++ b/tests/test_barrier.py @@ -0,0 +1,36 @@ +from helpers import * +from pytest import approx + +def test_qafiro(): + row, timelines = read_single('950_qafiro.log') + root = timelines['rootlp'] + t = type(root) + barrier = root.to_dict(orient='records') + + assert len(barrier) == 13 + + line = barrier[0] + assert line['PObj'] == approx(3.04762508e+05, abs=1e-2) + assert line['DObj'] == approx(-6.19194374e+05, abs=1e-2) + assert line['PRes'] == 3.78e+03 + assert line['DRes'] == 3.64e+02 + assert line['Compl'] == 1.01e+06 + assert line['Time'] == 0 + + line = barrier[12] + assert line['PObj'] == approx(-1.59078179e+00, abs=1e-2) + assert line['DObj'] == approx(-1.59078179e+00, abs=1e-2) + assert line['PRes'] == approx(3.89e-16, abs=1e-18) + assert line['DRes'] == approx(1.17e-15, abs=1e-13) + assert line['Compl'] == approx(8.66e-12, abs=1e-14) + assert line['Time'] == 0 + +def test_barrier_and_tree_search(): + row, timelines = read_single('950_glass4_Method2.log') + + barrier = timelines['rootlp'] + assert len(barrier.index) == 10 + + tree = timelines['nodelog'] + assert len(tree.index) == 41 + diff --git a/tests/test_cuts.py b/tests/test_cuts.py index b79997e..298d7fa 100644 --- a/tests/test_cuts.py +++ b/tests/test_cuts.py @@ -1,6 +1,6 @@ from helpers import * def test_cuts(): - row = read_single('912-glass4-0.log') + row, timelines = read_single('912-glass4-0.log') cuts = { key: row[key] for key in row.keys() if key.startswith('Cuts: ') } assert len(cuts) == 8 \ No newline at end of file diff --git a/tests/test_modeltypes.py b/tests/test_modeltypes.py new file mode 100644 index 0000000..2c2b489 --- /dev/null +++ b/tests/test_modeltypes.py @@ -0,0 +1,7 @@ +from numpy import NaN, isnan +from helpers import * +from pytest import approx + +def test_tree_search(): + row, timelines = read_single('912-glass4-0.log') + assert row['ModelType'] == 'MIP' \ No newline at end of file diff --git a/tests/test_norel.py b/tests/test_norel.py new file mode 100644 index 0000000..c1413de --- /dev/null +++ b/tests/test_norel.py @@ -0,0 +1,26 @@ +from numpy import NaN, isnan +from helpers import * +from pytest import approx + +def test_tree_search(): + row, timelines = read_single('912-NoRelHeurWork60-glass4-0.log') + norel = timelines['norel'] + + assert len(norel.index) == 15 + rows = norel.to_dict(orient='records') + + row = rows[0] + assert isnan(row['Incumbent']) + + row = rows[1] + assert row['Time'] == 10 + assert row['Incumbent'] == approx(1.450014e+09) + + row = rows[3] + assert row['Time'] == 21 + assert row['Incumbent'] == approx(1.200013e+09) + + row = rows[14] + assert row['Time'] == 93 + assert row['Incumbent'] == approx(1.200013e+09) + assert row['BestBd'] == approx(8.00002e+08) \ No newline at end of file diff --git a/tests/test_numerics.py b/tests/test_numerics.py new file mode 100644 index 0000000..09be702 --- /dev/null +++ b/tests/test_numerics.py @@ -0,0 +1,15 @@ +from numpy import NaN, isnan +from helpers import * +from pytest import approx + +def test_numerics_general(): + row, timelines = read_single('912-glass4-0.log') + + assert row['MinCoeff'] == 1 + assert row['MaxCoeff'] == 8e6 + assert row['MinObjCoeff'] == 1 + assert row['MaxObjCoeff'] == 1e6 + assert row['MinBound'] == 1 + assert row['MaxBound'] == 8e2 + assert row['MinRHS'] == 1 + assert row['MaxRHS'] == 8e6 \ No newline at end of file diff --git a/tests/test_treesearch.py b/tests/test_treesearch.py new file mode 100644 index 0000000..da78caf --- /dev/null +++ b/tests/test_treesearch.py @@ -0,0 +1,41 @@ +from numpy import NaN, isnan +from helpers import * +from pytest import approx + +def test_tree_search(): + row, timelines = read_single('912-glass4-0.log') + tree = timelines['nodelog'] + assert len(tree.index) == 35 + + rows = tree.to_dict(orient='records') + + heur = rows[33] + assert heur['CurrentNode'] == 187961 + assert heur['RemainingNodes'] == 3679 + assert heur['Incumbent'] == 1.200013e+09 + assert heur['BestBd'] == 1.2000e+09 + assert heur['Gap'] == 0 + assert heur['ItPerNode'] == 7.3 + assert heur['Time'] == 35 + + pruned = rows[30] + assert pruned['CurrentNode'] == 177203 + assert pruned['RemainingNodes'] == 30607 + assert pruned['Incumbent'] == 1.4e+09 + assert pruned['BestBd'] == 1.2e+09 + assert pruned['Gap'] == approx(0.143, 1e-5) + assert pruned['ItPerNode'] == 7.4 + assert pruned['Time'] == 35 + + final = rows[34] + + # Explored 188145 nodes (1383139 simplex iterations) in 35.66 seconds + assert final['Time'] == 35.66 + assert final['CurrentNode'] == 188145 + assert isnan(final['RemainingNodes']) + + # Best objective 1.200012600000e+09, best bound 1.200007800000e+09, gap 0.0004% + assert final['Incumbent'] == approx(1.200012e9) + assert final['BestBd'] == approx(1.200008e9) + assert final['Gap'] == 0.000004 + \ No newline at end of file