coin-or / python-mip

Python-MIP: collection of Python tools for the modeling and solution of Mixed-Integer Linear programs
Eclipse Public License 2.0
513 stars 88 forks source link

upper bound not reported correctly in CBC Progress Callback #378

Open ngtuankhai opened 3 months ago

ngtuankhai commented 3 months ago

Describe the bug The CBC progress callback method doesn't report the correct values of ub (upper bound). While the lb (lower bound) is reported correctly (it increases over time from zero), the ub drops immediately from infinity to zero

To Reproduce

import mip
import tempfile

lp_str = '''
Minimize
 obj: xMAX

Subject To
 xMAX(b): xMAX - x(b) >= 0
 xMAX(d): xMAX - x(d) >= 0
 xMAX(f): xMAX - x(f) >= 0
 xMAX(g): xMAX - x(g) >= 0
 xMAX(l): xMAX - x(l) >= 0
 xMAX(n): xMAX - x(n) >= 0
 dc_a(g,b): x(g) - x(b) + 1000 t(g,b) >= 1
 dc_b(g,b): x(b) - x(g) - 1000 t(g,b) >= -999
 dc_a(g,d): x(g) - x(d) + 1000 t(g,d) >= 1
 dc_b(g,d): x(d) - x(g) - 1000 t(g,d) >= -999
 dc_a(g,f): x(g) - x(f) + 1000 t(g,f) >= 1
 dc_b(g,f): x(f) - x(g) - 1000 t(g,f) >= -999
 dc_a(g,n): x(g) - x(n) + 1000 t(g,n) >= 1
 dc_b(g,n): x(n) - x(g) - 1000 t(g,n) >= -999
 dc_a(g,l): x(g) - x(l) + 1000 t(g,l) >= 1
 dc_b(g,l): x(l) - x(g) - 1000 t(g,l) >= -999
 dc_a(b,f): x(b) - x(f) + 1000 t(b,f) >= 1
 dc_b(b,f): x(f) - x(b) - 1000 t(b,f) >= -999
 dc_a(b,n): x(b) - x(n) + 1000 t(b,n) >= 1
 dc_b(b,n): x(n) - x(b) - 1000 t(b,n) >= -999
 dc_a(b,l): x(b) - x(l) + 1000 t(b,l) >= 1
 dc_b(b,l): x(l) - x(b) - 1000 t(b,l) >= -999
 dc_a(f,l): x(f) - x(l) + 1000 t(f,l) >= 1
 dc_b(f,l): x(l) - x(f) - 1000 t(f,l) >= -999

Bounds
 x(b) <= 5
 x(d) <= 5
 x(f) <= 5
 x(g) <= 5
 x(l) <= 5
 x(n) <= 5

Binaries
 t(g,b) t(g,d) t(g,f) t(g,n)
 t(g,l) t(b,f) t(b,n)
 t(b,l) t(f,l)

Generals
 x(b) x(d) x(f) x(g) x(l) x(n)

End
'''

with tempfile.NamedTemporaryFile(suffix='.lp', delete=False) as tmp:
    # Store string to tmp file
    tmp.write(lp_str.encode('utf-8'))
    tmp.close()
    # Instantiate a problem model and have it read the tmp file
    test_mdl = mip.Model()
    test_mdl.read(path=tmp.name)

test_mdl.store_search_progress_log = True

test_mdl.optimize(max_seconds=300)

for second, (lb, ub) in test_mdl.search_progress_log.log:
    print(ub)

Expected behavior The ub should gradually decrease from infinity to a finite value.

Desktop: