Skip to content
coin-orPublic

About

A solver for mixed-integer nonlinear optimization problems

Topics

Resources

Code of conduct

Stars

135 stars

Watchers

9 watching

Forks

Repository files navigation

CMake License

The Supporting Hyperplane Optimization Toolkit

SHOT is a software for solving mathematical optimization problems of the mixed-integer nonlinear programming (MINLP) class. In addition to MINLP problems, SHOT can also be used for subclasses such as NLP and MI(QC)QP.

Python installation

SHOT builds on Linux, macOS, and natively on Windows x64 with MSVC. See the compilation instructions for supported solver configurations and platform-specific setup.

Install the open-source solver build (Cbc, Ipopt, and HiGHS) from PyPI:

pip install SHOTpy
import SHOTpy

solver = SHOTpy.Solver()
problem = SHOTpy.Problem(solver)

x = problem.addVariable("x", SHOTpy.VariableType.Real, 0.0, 10.0)
y = problem.addVariable("y", SHOTpy.VariableType.Integer, 0.0, 10.0)

problem.setObjective(SHOTpy.exp(x) + (y - 2.5)**2)
problem.addConstraint(x + y >= 3, "c")
problem.finalize()

solver.setProblem(problem)
solver.solveProblem()
print(solver.getModelReturnStatus(), solver.getPrimalSolution().point)

See the SHOTpy tutorial for nonlinear expressions, settings, file input, and callbacks.

The package also installs the SHOT executable as the command SHOT, which solves problem files and can be used as an AMPL solver, e.g., from Pyomo, JuMP, or AMPL (see command-line usage). To get only the command, install it as a tool with pipx install SHOTpy or uv tool install SHOTpy:

SHOT problem.nl -AMPL
SHOT problem.osil Termination.TimeLimit=60

Building with proprietary solvers

Public wheels do not include the CPLEX, Gurobi, GAMS, or CONOPT SDKs. If one of these products is installed and licensed locally, force an sdist build and pass its existing SHOT CMake options through pip. For example:

python -m pip install SHOTpy --no-binary SHOTpy --no-cache-dir --force-reinstall \
    --config-settings=cmake.define.HAS_GUROBI=on \
    --config-settings=cmake.define.GUROBI_DIR=/opt/gurobi1103/linux64

Use the same pattern with HAS_CPLEX/CPLEX_DIR or HAS_GAMS/GAMS_DIR. CPLEX_DIR can point to the CPLEX Studio installation root or its cplex subdirectory. GAMS_DIR must contain apifiles and the GAMS executable (on macOS, use the framework's versioned Resources directory). Multiple integrations can be enabled in the same build by passing each pair of settings.

Replace GUROBI_DIR with your local installation path. Verify the resulting build with python -c "import SHOTpy; print(SHOTpy.HAS_GUROBI)"; it should print True. The SHOT command installed by this build has the same solvers, e.g., SHOT problem.nl --mip=gurobi.

For CONOPT on Linux, macOS, or Windows x64, download and extract the CONOPT C++ SDK, then rebuild from this checkout (which includes the CONOPT integration):

python -m pip install . --no-cache-dir --force-reinstall \
    --config-settings=cmake.define.HAS_CONOPT=on \
    --config-settings=cmake.define.CONOPT_DIR=/absolute/path/to/conopt-sdk
python -c "import SHOTpy; assert SHOTpy.HAS_CONOPT"

CONOPT_DIR must contain include/conopt.hpp and the SDK's lib directory. Once a release containing this integration is available on PyPI, the same options can be passed to pip install SHOTpy --no-binary SHOTpy as above. Select CONOPT in Python with:

solver.updateSetting(
    "Primal.FixedInteger.Solver", int(SHOTpy.PrimalNLPSolver.Conopt)
)

This builds a local wheel linked to your external SDK. Keep the SDK at its configured location; CONOPT libraries are not installed into the wheel by this build. Do not run wheel repair tools (auditwheel, delocate, or delvewheel) on this local wheel, since they can copy external libraries into it. On Windows, build from an x64 Native Tools Command Prompt with the CBC_DIR, IPOPT_DIR, and CMAKE_ARGS=-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL settings used for the Windows wheels; SHOTpy then loads CONOPT from the configured SDK, without PATH changes. The public wheel build keeps CONOPT disabled. See the CONOPT instructions for licensing, demo limits, and solver settings.

The compiler toolchain and open-source dependencies described in the compilation instructions are still required for a source build.

Originally SHOT was intended for convex MINLP problems only, but as of version 1.0 it also has functionality to solve nonconvex MINLP problems as a heuristic method without providing any guarantees of global optimality. SHOT can solve certain nonconvex problem types to global optimality as well, and the bounds for the objective function value are guaranteed for nonconvex problems as well.

SHOT can be used

  • as a console application,
  • from GAMS — the easiest way to use SHOT is through GAMSPy,
  • on the NEOS Server,
  • from any modeling system that can use ASL, such as
  • through its own Python API (SHOTpy) — install with pip install SHOTpy or build with -DHAS_PYTHON=on (see docs/CompilationInstructions.md), or
  • using its API implemented in C++, both of which support callbacks for customizing SHOT's behavior (e.g. injecting primal solutions, warm-starting, or adding custom cuts).

SHOT requires a MILP solver: Cplex, Gurobi, Cbc or HiGHS. NLP subproblems can use Ipopt, Uno, the optional CONOPT C++ API, or SHOT's built-in NLP solver. If SHOT is interfaced with GAMS, any licensed NLP solver can be used.

The documentation is provided at the project website at https://www.shotsolver.dev.

SHOT is a COIN-OR project, and won the COIN-OR Cup 2018. Project manager is Andreas Lundell. A full list of contributors is available on the project website.

Dual bound through polyhedral (outer) approximation

SHOT is based on iteratively creating a tighter polyhedral approximation of the nonlinear feasible set by generating supporting hyperplanes or cutting planes. These linearized problems are then solved with a mixed-integer linear programming (MILP) solver such as CPLEX, Gurobi, Cbc or HiGHS. If CPLEX or Gurobi is used, the subproblems can also include quadratic and bilinear nonlinearities directly; then MIQP or MIQCQP subproblems are solved. The dual strategy can be run either as a multi-tree search (repeatedly re-solving the MIP relaxation) or, with CPLEX or Gurobi, as a single-tree (branch-and-cut) search that adds cuts via callbacks during one search tree; Cbc and HiGHS currently only support the multi-tree strategy.

The problem types that can be solved to global optimality depend on which MIP solver is used:

Problem type CPLEX Gurobi Cbc HiGHS
Convex MIQP ✓* ✓* ✓ ✓
Convex MIQCQP ✓* ✓* ✓ ✓
Convex MINLP ✓ ✓ ✓ ✓
Nonconvex MIQP ✓* ✓* ? ?
Nonconvex MIQCQP ? ✓* ? ?
Nonconvex MINLP ? ? ? ?

✓ = solved to global optimality, ? = no guarantee that a solution is found, * = the problem can be handled directly by the subsolver (native quadratic/bilinear support).

Primal bound using heuristics

The solution to the outer approximation problem provides a lower (dual) bound (when solving a minimization problem) to the original problem if the problem is convex. If the problem is nonconvex, convergence to the global optimal solution cannot be guaranteed (but might be achieved for certain classes of problems, cf. this paper.

To get an upper (primal) bound (when solving a minimization problem) on the optimal solution SHOT utilizes the following heuristics:

  • Solving nonlinear programming (NLP) problems where the integer variables have been fixed to valid values. This is done by calling an external NLP solver (e.g. Ipopt).
  • By checking solutions from the MIP solver's solution pool for points that fulfill also the nonlinearities in the original MINLP problem.
  • By performing root searches.

Termination

When the relative or absolute difference (objective gap) between the primal and dual bounds is less than a user-specified value, SHOT terminates with the current primal solution. If the original problem is convex, this is a global solution to the problem. If it is nonconvex, there is normally no guarantee that such a solution can be found, however SHOT will always in addition to the primal solution give a valid lower bound on the solution.

Compilation instructions

Instructions for compiling SHOT are available in docs/CompilationInstructions.md, and also at the project website.

Solver manual

Instructions for how to use SHOT, e.g. call it from different environments, are provided in docs/CommandLineUsage.md and on the project website. For troubleshooting solver behavior, see docs/DebuggingSHOT.md.

Publications

SHOT is best described in the paper:

Lundell, A. Kronqvist, J. and Westerlund, T. The supporting hyperplane optimization toolkit for convex MINLP. Journal of Global Optimization (2022). https://link.springer.com/article/10.1007/s10898-022-01128-0

The features for solving nonconvex MINLP problems are described in the papers:

Lundell, A. and Kronqvist, J., Polyhedral approximation strategies for nonconvex mixed-integer nonlinear programming in SHOT. Journal of Global Optimization (2021). https://doi.org/10.1007/s10898-021-01006-1

Lundell, A. and Kronqvist, J. On Solving Nonconvex MINLP Problems with SHOT (2019). In: Le Thi H., Le H., Pham Dinh T. (editors) Optimization of Complex Systems: Theory, Models, Algorithms and Applications. WCGO 2019. Advances in Intelligent Systems and Computing, vol 991. Springer, Cham.

Reformulation of nonseparable convex quadratic expressions (preprint):

Blomqvist, J., Tamm, E., Kronqvist, J. and Lundell, A. Decomposition-Based Reformulation of Nonseparable Quadratic Expressions in Convex MINLP. Optimization Online (2026). https://optimization-online.org/?p=34367

About

A solver for mixed-integer nonlinear optimization problems

Topics

Resources

Code of conduct

Stars

135 stars

Watchers

9 watching

Forks

Releases

Packages

Used by

Contributors

Languages