Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Simple problem with non-optimal solution #166

@Plug11

Description

@Plug11

I have a problem which I have simplified to a simple case with two continuous and one binary variable. There are no constraints (other than variable bounds) and while the objective is nonconvex, it is monotonic. I get the correct optimal solution with bonmin and MindtPy, but not consistently with SHOT. When I say not consistently, I mean that the results are sensitive to the exact algebraic representation I use in Pyomo.

I am very interested in using SHOT both for convex and nonconvex MINLP problems. Any thoughts on this would be greatly appreciated :-)

I am using a build of the following commit:

commit 033622c6f9989d48caf7eefe430d292286544711
Merge: 77da53f edd04d7
Author: Stefan Vigerske <[email protected]>
Date:   Mon Jun 27 14:50:10 2022 +0200

and I tried using both CBC and CPLEX MIP solvers (with slightly different results).

The following is the output from the different solvers (objective and variable values), for various different representations of the same problem. Note: when y==1.0 [optimum value], the value of the objective does not depend on x1. However this does not seem be the cause of this issue. I tried adding a small offset, so that the objective is always influenced by x1 and this caused bonmin and MindtPy to always give the same value for x1, as expected, but the behaviour of SHOT was still the same):

{'min': False, 'divide': False}
    SHOT_CBC:  OBJ: 2.0, x1: 0.5, x2: 0.1, y: 0.0
    SHOT_CPLEX:OBJ: 6.5, x1: 0.6, x2: 0.2, y: 1.0
    bonmin:    OBJ: 13.0, x1: 0.6, x2: 0.1, y: 1.0
    MindtPy:   OBJ: 13.0, x1: 0.5, x2: 0.1, y: 1.0
{'min': False, 'divide': True}
    SHOT_CBC:  OBJ: 2.0, x1: 0.5, x2: 0.1, y: 0.0
    SHOT_CPLEX:OBJ: 6.5, x1: 0.6, x2: 0.2, y: 1.0
    bonmin:    OBJ: 13.0, x1: 0.6, x2: 0.1, y: 1.0
    MindtPy:   OBJ: 13.0, x1: 0.6, x2: 0.1, y: 1.0
{'min': True, 'divide': False}
    SHOT_CBC:  OBJ: -2.0, x1: 0.5, x2: 0.1, y: 0.0
    SHOT_CPLEX:OBJ: -2.0, x1: 0.5, x2: 0.1, y: 0.0
    bonmin:    OBJ: -13.0, x1: 0.6, x2: 0.1, y: 1.0
    MindtPy:   OBJ: -13.0, x1: 0.5, x2: 0.1, y: 1.0
{'min': True, 'divide': True}
    SHOT_CBC:  OBJ: -13.0, x1: 0.5, x2: 0.1, y: 1.0
    SHOT_CPLEX:OBJ: -13.0, x1: 0.5, x2: 0.1, y: 1.0
    bonmin:    OBJ: -13.0, x1: 0.6, x2: 0.1, y: 1.0
    MindtPy:   OBJ: -13.0, x1: 0.6, x2: 0.1, y: 1.0

and this is the self-contained code to replicate:

import pyomo.environ as pyo
import pyomo.contrib.mindtpy.MindtPy as mindtpy


def create_model(min=False, divide=False):

    model = pyo.ConcreteModel()

    model.x1 = pyo.Var(domain=pyo.NonNegativeReals, bounds=(0.5, 0.6))
    model.x2 = pyo.Var(domain=pyo.NonNegativeReals, bounds=(0.1, 0.2))
    model.y = pyo.Var(domain=pyo.Boolean, initialize=1)

    y_mult = 1.3
    if divide:
        obj = (1 - model.y) / model.x1 + model.y * y_mult / model.x2
    else:
        obj = (1 - model.y) * (model.x1 ** -1) + model.y * y_mult * (model.x2 ** -1)

    if min:
        model.OBJ = pyo.Objective(expr = -1 * obj, sense=pyo.minimize)
    else:
        model.OBJ = pyo.Objective(expr = obj, sense=pyo.maximize)

    return model


solvers = {}

shotCbc = pyo.SolverFactory("SHOT")
shotCbc.options["Dual.MIP.Solver"] = 2
solvers["SHOT_CBC"] = shotCbc

shotCplex = pyo.SolverFactory("SHOT")
shotCplex.options["Dual.MIP.Solver"] = 0
solvers["SHOT_CPLEX"] = shotCplex

solvers["bonmin"] = pyo.SolverFactory("bonmin")

mindtpy_solver = mindtpy.MindtPySolver()
mindtpy_solver.CONFIG["mip_solver"] = "cbc"
solvers["MindtPy"] = mindtpy_solver

params = [
    {"min": False, "divide": False}, 
    {"min": False, "divide": True}, 
    {"min": True, "divide": False}, 
    {"min": True, "divide": True}, 
]
results = {}
for p in params:
    cur_res = {}
    for name, sol in solvers.items():
        model = create_model(**p)
        sol.solve(model, tee=True)
        cur_res[name] = model
    results[str(p)] = cur_res

for p, res in results.items():
    print(p)
    for name, r in res.items():
        print(f"    {name}:{' '*(10-len(name))}OBJ: {pyo.value(r.OBJ):.1f}, x1: {pyo.value(r.x1):.1f}, x2: {pyo.value(r.x2):.1f}, y: {pyo.value(r.y):.1f}")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions