Python Interface and Modeling Environment for SCIP
PySCIPOpt is a Python interface and modeling environment for the SCIP Optimization Suite, a powerful mixed-integer programming (MIP) and mixed-integer nonlinear programming (MINLP) solver. It allows users to formulate and solve optimization problems using Python syntax. The library is actively maintained with frequent releases, often coinciding with new major versions of the underlying SCIP solver.
Common errors
-
Failed building wheel for pyscipopt / Cannot open include file: 'scip/scip.h': No such file or directory
cause This typically occurs during installation when the underlying SCIP Optimization Suite development files are not found or linked correctly, especially in environments where SCIP is not bundled or `SCIPOPTDIR` is not set.fixEnsure you have the SCIP Optimization Suite installed. If not bundled by PySCIPOpt (versions < 4.4.0) or for source builds, manually install SCIP and set the environment variable `SCIPOPTDIR` to the base directory of your SCIP installation (e.g., `export SCIPOPTDIR=/path/to/SCIPOptSuite`). Then retry `pip install pyscipopt`. -
ModuleNotFoundError: No module named 'pyscipopt'
cause The `pyscipopt` package was either not installed, installed in a different Python environment, or the current environment is not activated.fixRun `pip install pyscipopt` (preferably within a virtual environment) or activate the correct Python environment where it was installed. -
Segmentation fault / Crash when modifying model after optimization
cause Changes were attempted on the model (e.g., adding variables/constraints) after an `optimize()` call without properly resetting the model's internal state.fixCall `model.freeTransform()` before making any modifications to the model after it has been optimized. For a full reset, use `model.freeProb()`. -
TypeError: unsupported operand type(s) for <: 'int' and 'Expr'
cause Incorrect syntax used for defining ranged constraints, attempting `lhs <= expression <= rhs` directly.fixUse explicit parentheses for ranged constraints: `model.addCons(lhs <= (expression <= rhs))`.
Warnings
- breaking PySCIPOpt v6.0.0 introduced compatibility with SCIP 10, which includes significant changes to the underlying SCIP solver. This update removed some old methods (e.g., `chgAndConsCheckFlagWhenUpgr`, `chgAndConsRemovableFlagWhenUpgr`) and changed how nonlinear constraints are handled internally, which may affect existing code relying on older SCIP versions or specific API calls.
- gotcha Modifying a model after it has been optimized without calling `freeTransform()` can lead to unexpected crashes or incorrect behavior. SCIP retains transformed problem data by default.
- gotcha Accessing dual values from the solution can be unreliable in default SCIP configurations. Accurate dual values are only guaranteed when presolving, propagation, and primal heuristics are disabled, and the problem has no bound constraints.
- gotcha Python's operator overloading does not support chained comparisons for ranged constraints (e.g., `lhs <= expr <= rhs`). This syntax will not work as expected in PySCIPOpt.
- gotcha Prior to v4.4.0, PySCIPOpt did not bundle the SCIP Optimization Suite. Installation via pip or source for older versions required manual installation of SCIP and setting the `SCIPOPTDIR` environment variable to point to its installation. Newer versions typically bundle SCIP, but this variable might still be needed for custom builds or specific environments.
Install
-
pip install pyscipopt -
conda install -c conda-forge pyscipopt
Imports
- Model
from pyscipopt import Model
Quickstart
from pyscipopt import Model, SCIP_STATUS
# Create a SCIP model
model = Model("Simple_LP")
# Add variables
x = model.addVar("x", vtype="CONTINUOUS", lb=0.0)
y = model.addVar("y", vtype="CONTINUOUS", lb=0.0)
# Set the objective function: Maximize x + 2y
model.setObjective(x + 2*y, "maximize")
# Add constraints
model.addCons(x + y <= 10, "c1")
model.addCons(2*x + y <= 15, "c2")
# Optimize the model
model.optimize()
# Check the solution status and print results
if model.getStatus() == SCIP_STATUS.OPTIMAL:
print(f"Optimal solution found.")
print(f"Objective value: {model.getObjVal()}")
print(f"x: {model.getVal(x)}")
print(f"y: {model.getVal(y)}")
else:
print(f"Problem could not be solved to optimality. Status: {model.getStatus()}")
# Clean up the model (important for repeated modifications/solves)
model.freeProb()