Error when removing constraints, constr_by_name does not return the right constraint
See original GitHub issueHi I was trying to iterative eliminate constraints and I found a rare behavior, maybe I’m doing something wrong. but when I extract a constraint using constr_by_name
I’m receiving the wrong constraint
This is the code to reproduce the error:
from mip import Model
import numpy as np
from mip.constants import CONTINUOUS
import logging
logger = logging.getLogger(__name__)
def build_infeasible_cont_model(num_constraints:int = 10, num_infeasible_sets:int = 20) -> Model:
# build an infeasible model, based on many redundant constraints
mdl = Model(name='infeasible_model_continuous')
var = mdl.add_var(name='var', var_type=CONTINUOUS, lb=-1000, ub=1000)
for idx,rand_constraint in enumerate(np.linspace(1,1000,num_constraints)):
crt = mdl.add_constr(var>=rand_constraint, name='lower_bound_{}'.format(idx))
logger.debug('added {} to the model'.format(crt))
num_constraint_inf = int(num_infeasible_sets/num_constraints)
for idx,rand_constraint in enumerate(np.linspace(-1000,-1,num_constraint_inf)):
crt = mdl.add_constr(var<=rand_constraint, name='upper_bound_{}'.format(idx))
logger.debug('added {} to the model'.format(crt))
mdl.emphasis = 1 # feasibility
mdl.preprocess = 1 # -1 automatic, 0 off, 1 on.
# mdl.pump_passes TODO configure to feasibility emphasis
return mdl
import sys
if __name__ == "__main__":
# logger config
handler = logging.StreamHandler(sys.stdout)
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)
# model experiment
model = build_infeasible_cont_model()
logger.debug(model.status)
model.optimize()
logger.debug(model.status)
model_copy = model.copy()
for inc_crt in model.constrs:
logger.debug('removing temporally {}'.format(inc_crt.name))
aux_model_inc_crt = model_copy.constr_by_name(inc_crt.name)
logger.debug('removing temporally {}'.format(aux_model_inc_crt.name))
model_copy.remove(aux_model_inc_crt)
The logger should return something like
removing temporally lower_bound_0 removing temporally lower_bound_0 removing temporally lower_bound_1 removing temporally lower_bound_1 removing temporally lower_bound_2 removing temporally lower_bound_2 removing temporally lower_bound_3 removing temporally lower_bound_3 removing temporally lower_bound_4 removing temporally lower_bound_4
but Instead is returning:
removing temporally lower_bound_0 removing temporally lower_bound_0 removing temporally lower_bound_1 removing temporally lower_bound_2 removing temporally lower_bound_2 Traceback (most recent call last): File “/home/pablo/github/python-mip-infeasibility/get_name_error.py”, line 47, in <module> logger.debug(‘removing temporally {}’.format(aux_model_inc_crt.name)) AttributeError: ‘NoneType’ object has no attribute ‘name’
It seams like when Im removing objects the constr_by_name
method is not working properly, because I´m sending the right str
but it’s returning a different constraint.
how can I correctly identify a constraint in a mutable model ? is there a unique idx
that does not change when I remove a constraint ? why the method constr_by_name
is returning the wrong constraint ?
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (3 by maintainers)
w.r.t. adding vars one by one, it should be relatively fast, since model updates like that are cached in the C interface and then performed in batch.
understood now