pyomo icon indicating copy to clipboard operation
pyomo copied to clipboard

Sometimes constraints are not satisfied with NL Writer V2 with export_defined_variables=True

Open grahamsparrow-8451 opened this issue 1 year ago • 0 comments

Summary

There are cases when constraints are not satisfied in MINLP problems when using latest main (4a5bf8a2417246dc000df56576df9925d3497f90), but the problem is reported as feasible and optimal after solve. The problem only occurs for some solvers that use NL Writer and with export_defined_variables=True.

The following example shows the problem, but only couenne gives the wrong answer. See #3235 for some more discussion of this. I have also seen the same issue for mindpty using ipopt and cbc, but for some reason this example works fine for mindtpy and I have not yet managed to replicate the mindtpy issue on a manageably small problem.

Steps to reproduce the issue

The following code replicates the problem

from pyomo.environ import *

def create_model():
    model = ConcreteModel()

    model.p1 = Var(within=PositiveReals, bounds=(1, 2))
    model.p2 = Var(within=PositiveReals, bounds=(1, 2))
    model.t1 = Var(within=Boolean, bounds=(0, 1))
    model.t2 = Var(within=Boolean, bounds=(0, 1))

    model.f_expr = Expression(expr = 
        (model.p1*model.t1 + model.p2*model.t2) 
    )

    model.const_t = Constraint(expr=(model.t1 + model.t2 == 1))

    model.const2 = Constraint(expr=(model.f_expr <= 1.0))
    # just maximize the the expression we are constraining to <= 1
    model.OBJ = Objective(expr=model.f_expr, sense=maximize)

    return model

def solve(solver, export_defined_variables):
    model = create_model()
    opt = SolverFactory(solver)
    try:
        name = opt.name
        sol = opt.options.solver
    except AttributeError:
        name = opt.__class__.__name__
        sol = ""
    try:
        if solver == "mindtpy":
            if not export_defined_variables:
                # not sure how to switch this off for mindtpy
                return
            optResult = opt.solve(model, mip_solver="cbc")
        else:
            optResult = opt.solve(model, export_defined_variables=export_defined_variables)

        solverOutput = optResult["Solver"][0]
        termCond = solverOutput["Termination condition"]
        if termCond != "optimal":
            raise Exception(f"Termination condition: {termCond}")

    except Exception as e:
        print(f"{name}:{sol}:export_defined_variables:{export_defined_variables} {e}")    
        return
    print(f"{name}:{sol}:export_defined_variables:{export_defined_variables} {value(model.OBJ)}")

for export_defined_variables in [False, True]:
    for solver in ["ipopt", "scip", "bonmin", "couenne", "mindtpy"]:
        solve(solver, export_defined_variables)

Output:

ipopt:None:export_defined_variables:False 1.0000000089123255
scip:None:export_defined_variables:False 1.0
asl:bonmin:export_defined_variables:False 1.0000000099900264
asl:couenne:export_defined_variables:False 1.0000000099900361
ipopt:None:export_defined_variables:True 1.0000000089123255
scip:None:export_defined_variables:True 1.0
asl:bonmin:export_defined_variables:True 1.0000000099900264
asl:couenne:export_defined_variables:True 2.0
MindtPySolver::export_defined_variables:True 1.0000000081382578

Information on your system

Pyomo version: main (4a5bf8a2417246dc000df56576df9925d3497f90) Python version: 3.11.6 Operating system: Red Hat Enterprise Linux release 8.8 (Ootpa) How Pyomo was installed (PyPI, conda, source): PyPI Solver (if applicable): see above, all solvers were downloaded from the AMPL Portal (https://portal.ampl.com/user/ampl/download)

grahamsparrow-8451 avatar Apr 23 '24 11:04 grahamsparrow-8451