HiGHS solver does not update the model correctly after variable fix/unfix
Summary
HiGHS solver does not update the model correctly after a sequence of variable fix/unfix. This only occurs when the treat_fixed_vars_as_params flag is True (the default option).
Steps to reproduce the issue
import pyomo.environ as pyo
from pyomo.contrib import appsi
m = pyo.ConcreteModel()
m.x = pyo.Var(domain = pyo.Binary)
m.y = pyo.Var(domain = pyo.Binary)
m.fx = pyo.Var(domain = pyo.NonNegativeReals)
m.fy = pyo.Var(domain = pyo.NonNegativeReals)
m.c1 = pyo.Constraint(expr = m.fx <= m.x)
m.c2 = pyo.Constraint(expr = m.fy <= m.y)
m.c3 = pyo.Constraint(expr = m.x + m.y <= 1)
m.obj = pyo.Objective(
expr = m.fx * 0.5 + m.fy * 0.4,
sense = pyo.maximize,
)
opt = appsi.solvers.Highs()
opt.config.load_solution = False
# opt.update_config.treat_fixed_vars_as_params = False
# solution 1 has m.x == 1 and m.y == 0
r = opt.solve(m)
print(r)
assert r.best_feasible_objective is not None
# solution 2 has m.x == 0 and m.y == 1
m.y.fix(1)
r = opt.solve(m)
print(r)
assert r.best_feasible_objective is not None
# solution 3 should be equal solution 1 but get infeasible
m.y.unfix()
m.x.fix(1)
r = opt.solve(m)
print(r)
assert r.best_feasible_objective is None
gives
termination_condition: TerminationCondition.optimal
best_feasible_objective: 0.5
best_objective_bound: 0.5
termination_condition: TerminationCondition.optimal
best_feasible_objective: 0.4
best_objective_bound: 0.4
termination_condition: TerminationCondition.infeasible
best_feasible_objective: None
best_objective_bound: inf
The expected behavior is that in the 3rd solve the solution obtained is the same as the first solve. This behavior is only achieved if the treat_fixed_vars_as_params flag is set to False.
Error Message
The highs log gives a hint : ERROR: Set supplied to Highs::deleteRows is not ordered
Information on your system
Pyomo version: 6.7.0 Python version: 3.9.16 Operating system: Win 11 How Pyomo was installed (PyPI, conda, source): pip Solver (if applicable): highspy 1.5.3
highspy 1.7.1 with Pyomo 6.7.3 gives the following result on a mac:
termination_condition: TerminationCondition.optimal
best_feasible_objective: 0.5
best_objective_bound: 0.5
termination_condition: TerminationCondition.optimal
best_feasible_objective: 0.4
best_objective_bound: 0.4
ERROR: Set supplied to Highs::deleteRows is not ordered
termination_condition: TerminationCondition.optimal
best_feasible_objective: 0.0
best_objective_bound: -0.0
@lpierezan I attempted to solve this problem and created this PR: https://github.com/Pyomo/pyomo/pull/3281