Python interface and modeling environment for SCIP optimization solver
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Central model management that provides the foundation for all optimization workflows in PySCIPOpt. The Model class handles problem setup, solving, and solution access for linear programming, mixed integer programming, and constraint programming problems.
Create and configure optimization models with various settings for different problem types and solving approaches.
class Model:
def __init__(self, problemName='model', defaultPlugins=True, sourceModel=None,
origcopy=False, globalcopy=True, enablepricing=False,
createscip=True, threadsafe=False):
"""
Create a new optimization model.
Parameters:
- problemName (str): Name for the problem
- defaultPlugins (bool): Include default SCIP plugins
- sourceModel (Model): Source model for copying
- origcopy (bool): Copy original model state
- globalcopy (bool): Perform global copy
- enablepricing (bool): Enable column generation
- createscip (bool): Create SCIP instance
- threadsafe (bool): Enable thread safety
"""Core functions for problem lifecycle management including creation, transformation, and cleanup.
def createProbBasic(self, problemName='model'):
"""
Create basic problem structure.
Parameters:
- problemName (str): Name for the problem
"""
def freeProb(self):
"""Free problem data and reset to initial state."""
def freeTransform(self):
"""Free transformation data while keeping original problem."""
def includeDefaultPlugins(self):
"""Include default SCIP plugins for standard optimization."""Comprehensive variable creation and management for different variable types and properties.
def addVar(self, name='', vtype='C', lb=0.0, ub=None, obj=0.0,
pricedVar=False, pricedVarScore=1.0):
"""
Add a variable to the model.
Parameters:
- name (str): Variable name
- vtype (str): Variable type ('C' continuous, 'I' integer, 'B' binary)
- lb (float): Lower bound (default: 0.0)
- ub (float): Upper bound (default: infinity)
- obj (float): Objective coefficient
- pricedVar (bool): Is this a priced variable for column generation
- pricedVarScore (float): Priority score for priced variables
Returns:
Variable: The created variable object
"""
def getVars(self):
"""
Get all variables in the model.
Returns:
list: List of all Variable objects
"""
def addVarLocks(self, var, nlocksdown, nlocksup):
"""
Add locks to prevent variable from being deleted.
Parameters:
- var (Variable): Variable to lock
- nlocksdown (int): Number of down locks
- nlocksup (int): Number of up locks
"""Add and manage constraints with various properties and settings.
def addCons(self, cons, name='', initial=True, separate=True,
enforce=True, check=True, propagate=True, local=False,
modifiable=False, dynamic=False, removable=False,
stickingatnode=False):
"""
Add a constraint to the model.
Parameters:
- cons: Constraint expression or ExprCons object
- name (str): Constraint name
- initial (bool): Should constraint be in initial LP relaxation
- separate (bool): Should constraint be subject to separation
- enforce (bool): Should constraint be enforced during node processing
- check (bool): Should constraint be checked for feasibility
- propagate (bool): Should constraint be subject to propagation
- local (bool): Is constraint only valid for current subtree
- modifiable (bool): Can constraint be modified during solution process
- dynamic (bool): Can constraint be added during solution process
- removable (bool): Can constraint be removed during solution process
- stickingatnode (bool): Should constraint remain at node even if it can be removed
Returns:
Constraint: The created constraint object
"""
def addConss(self, conss, **kwargs):
"""
Add multiple constraints to the model.
Parameters:
- conss (list): List of constraints
- **kwargs: Additional constraint properties (same as addCons)
Returns:
list: List of created Constraint objects
"""
def addConsCoeff(self, cons, var, coeff):
"""
Add coefficient to existing linear constraint.
Parameters:
- cons (Constraint): Constraint to modify
- var (Variable): Variable to add
- coeff (float): Coefficient value
"""Set and modify objective functions with different optimization senses.
def setObjective(self, coeffs, sense='minimize', clear='true'):
"""
Set the objective function.
Parameters:
- coeffs: Objective expression (Expr, dict, or list)
- sense (str): Optimization sense ('minimize' or 'maximize')
- clear (str): Clear existing objective ('true' or 'false')
"""
def setMinimize(self):
"""Set optimization sense to minimization."""
def setMaximize(self):
"""Set optimization sense to maximization."""
def getObjective(self):
"""
Get current objective expression.
Returns:
Expr: Current objective expression
"""
def getObjectiveSense(self):
"""
Get current optimization sense.
Returns:
str: 'minimize' or 'maximize'
"""
def setObjlimit(self, objlimit):
"""
Set objective limit for early termination.
Parameters:
- objlimit (float): Objective value limit
"""
def getObjlimit(self):
"""
Get current objective limit.
Returns:
float: Current objective limit
"""
def addObjoffset(self, offset, solutions=False):
"""
Add offset to objective function.
Parameters:
- offset (float): Offset value to add
- solutions (bool): Apply offset to existing solutions
"""Core solving functionality with different solving methods and output control.
def optimize(self):
"""
Solve the optimization problem.
This is the main solving method that runs the complete SCIP
optimization process including presolving, LP solving, and
branch-and-bound.
"""
def solve(self):
"""
Alternative solving method (alias for optimize).
"""
def hideOutput(self):
"""
Suppress solver output during optimization.
"""Retrieve optimization results, variable values, and solution information.
def getBestSol(self):
"""
Get the best solution found.
Returns:
Solution: Best solution object, or None if no solution found
"""
def getObjVal(self):
"""
Get objective value of best solution.
Returns:
float: Objective value
Raises:
Exception: If no solution available
"""
def getVal(self, var):
"""
Get variable value in best solution.
Parameters:
- var (Variable): Variable to query
Returns:
float: Variable value in solution
Raises:
Exception: If no solution available or variable not found
"""
def getStatus(self):
"""
Get current solver status.
Returns:
str: Status string ('optimal', 'infeasible', 'unbounded',
'timelimit', 'nodelimit', etc.)
"""Access detailed solving statistics and performance information.
def getTotalTime(self):
"""
Get total solving time including presolving.
Returns:
float: Total time in seconds
"""
def getSolvingTime(self):
"""
Get pure solving time excluding presolving.
Returns:
float: Solving time in seconds
"""
def getReadingTime(self):
"""
Get time spent reading problem files.
Returns:
float: Reading time in seconds
"""
def getPresolvingTime(self):
"""
Get time spent in presolving.
Returns:
float: Presolving time in seconds
"""
def getNNodes(self):
"""
Get number of processed branch-and-bound nodes.
Returns:
int: Number of processed nodes
"""
def getNTotalNodes(self):
"""
Get total number of branch-and-bound nodes.
Returns:
int: Total number of nodes
"""
def getGap(self):
"""
Get optimality gap (relative difference between best bounds).
Returns:
float: Gap as percentage (0.0 = optimal, 1.0 = 100% gap)
"""
def getDepth(self):
"""
Get current depth in branch-and-bound tree.
Returns:
int: Current tree depth
"""
def getCurrentNode(self):
"""
Get current node in branch-and-bound tree.
Returns:
Node: Current node object
"""Read and write optimization problems in various formats.
def readProblem(self, filename, extension=None):
"""
Read problem from file.
Parameters:
- filename (str): Path to problem file
- extension (str): File format extension (auto-detected if None)
Supported formats: .lp, .mps, .cip, .zpl, .pip, .osil, .wbo, .opb
"""
def writeProblem(self, filename='model.cip', trans=False, genericnames=False):
"""
Write problem to file.
Parameters:
- filename (str): Output filename with extension
- trans (bool): Write transformed problem
- genericnames (bool): Use generic variable/constraint names
"""Access numerical constants and tolerance checking functions.
def infinity(self):
"""
Get SCIP's infinity value.
Returns:
float: Infinity value used by SCIP
"""
def epsilon(self):
"""
Get SCIP's epsilon (smallest meaningful difference).
Returns:
float: Epsilon value
"""
def feastol(self):
"""
Get feasibility tolerance.
Returns:
float: Feasibility tolerance
"""
def isZero(self, value):
"""
Test if value is considered zero.
Parameters:
- value (float): Value to test
Returns:
bool: True if value is zero within tolerance
"""
def isFeasZero(self, value):
"""
Test if value is feasibly zero.
Parameters:
- value (float): Value to test
Returns:
bool: True if value is feasibly zero
"""
def isInfinity(self, value):
"""
Test if value is infinity.
Parameters:
- value (float): Value to test
Returns:
bool: True if value is infinity
"""
def isEQ(self, val1, val2):
"""
Test if two values are equal within tolerance.
Parameters:
- val1 (float): First value
- val2 (float): Second value
Returns:
bool: True if values are equal within tolerance
"""
def isFeasEQ(self, val1, val2):
"""
Test if two values are feasibly equal.
Parameters:
- val1 (float): First value
- val2 (float): Second value
Returns:
bool: True if values are feasibly equal
"""
def isLE(self, val1, val2):
"""
Test if first value is less than or equal to second.
Parameters:
- val1 (float): First value
- val2 (float): Second value
Returns:
bool: True if val1 <= val2 within tolerance
"""
def isGE(self, val1, val2):
"""
Test if first value is greater than or equal to second.
Parameters:
- val1 (float): First value
- val2 (float): Second value
Returns:
bool: True if val1 >= val2 within tolerance
"""from pyscipopt import Model
# Create model
model = Model("linear_program")
# Add variables
x1 = model.addVar(name="x1", lb=0)
x2 = model.addVar(name="x2", lb=0)
# Add constraints
model.addCons(2*x1 + x2 <= 4, name="constraint1")
model.addCons(x1 + 2*x2 <= 4, name="constraint2")
# Set objective
model.setObjective(x1 + x2, "maximize")
# Solve
model.optimize()
# Get results
if model.getStatus() == 'optimal':
print(f"Optimal value: {model.getObjVal()}")
print(f"x1 = {model.getVal(x1)}")
print(f"x2 = {model.getVal(x2)}")from pyscipopt import Model
# Create model
model = Model("integer_program")
# Add integer variables
x = model.addVar(name="x", vtype="I", lb=0, ub=10)
y = model.addVar(name="y", vtype="I", lb=0, ub=10)
# Add binary variable
z = model.addVar(name="z", vtype="B")
# Add constraints
model.addCons(3*x + 2*y <= 15, name="resource")
model.addCons(x + y >= 2*z, name="logic")
# Set objective
model.setObjective(2*x + 3*y + z, "maximize")
# Solve
model.optimize()
# Check solution
if model.getStatus() == 'optimal':
print(f"Solution: x={model.getVal(x)}, y={model.getVal(y)}, z={model.getVal(z)}")
print(f"Gap: {model.getGap():.2%}")
print(f"Nodes: {model.getNNodes()}")PySCIPOpt may raise exceptions in various scenarios:
getObjVal() and getVal() raise exceptions when called before a solution is found or when the problem is infeasiblereadProblem() or writeProblem()from pyscipopt import Model
model = Model("error_handling_example")
# Safe solution access
try:
model.optimize()
if model.getStatus() == 'optimal':
obj_val = model.getObjVal()
print(f"Optimal value: {obj_val}")
elif model.getStatus() == 'infeasible':
print("Problem is infeasible")
elif model.getStatus() == 'timelimit':
print("Time limit reached")
if model.getNSols() > 0:
print(f"Best solution found: {model.getObjVal()}")
else:
print(f"Solver status: {model.getStatus()}")
except Exception as e:
print(f"Optimization error: {e}")
# Safe parameter setting
try:
model.setParam("limits/time", 300.0)
model.setParam("display/verblevel", 2)
except Exception as e:
print(f"Parameter error: {e}")
# Safe file operations
try:
model.readProblem("problem.lp")
except FileNotFoundError:
print("Problem file not found")
except Exception as e:
print(f"File reading error: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-pyscipopt