High-performance Open-source Mixed-Integer Linear Optimization Solver (HiGHS) Python Interface
highspy is a thin set of pybind11 wrappers to HiGHS, a high-performance serial and parallel solver for large-scale sparse linear optimization, convex quadratic programming, and mixed-integer programming problems. It is currently at version 1.14.0 and maintains an active development and release cadence.
Warnings
- gotcha Direct iteration or element-wise access of returned array-like solution values (e.g., `solution.col_value`) can be very slow. It is highly recommended to convert these to Python lists first for efficient access.
- gotcha When constructing linear expressions, the `highs_linear_expression.__add__` method modifies the expression in-place. Reusing an expression object after it has been modified can lead to unexpected and hard-to-debug results.
- gotcha By default, HiGHS C++ logging is duplicated to `Highs.log`. In `highspy`, to redirect logging output to a specific file, you must explicitly set the 'log_file' option.
- gotcha Users integrating `highspy` with other modeling libraries like `python-mip` might encounter `FileNotFoundError: HiGHS not found` even after `highspy` is installed. This suggests a solver discovery issue in the integrating library.
- deprecated The `addVar` method within the direct `highspy` modeling interface was noted for clashes and potential confusion with internal methods. A new method, `addVariable`, is being introduced for clearer high-level modeling.
Install
-
pip install highspy
Imports
- Highs
import highspy h = highspy.Highs()
- HighsLp
from highspy import HighsLp lp = HighsLp()
- ObjSense
from highspy import ObjSense lp.sense_ = ObjSense.kMaximize
Quickstart
import highspy
import numpy as np
h = highspy.Highs()
# Define an LP problem (maximize 8x0 + 10x1 subject to constraints)
lp = highspy.HighsLp()
lp.num_col_ = 2
lp.num_row_ = 2
lp.sense_ = highspy.ObjSense.kMaximize
lp.col_cost_ = np.array([8, 10], dtype=np.double)
lp.col_lower_ = np.array([0, 0], dtype=np.double)
lp.col_upper_ = np.array([highspy.kHighsInf, highspy.kHighsInf], dtype=np.double)
lp.row_lower_ = np.array([-highspy.kHighsInf, -highspy.kHighsInf], dtype=np.double)
lp.row_upper_ = np.array([120, 210], dtype=np.double)
# Constraint matrix A (row-wise in this example for illustration)
# 0.3*x0 + 0.5*x1 <= 120
# 0.7*x0 + 0.5*x1 <= 210
lp.a_matrix_.start_ = np.array([0, 2, 4]) # Column starts (for column-wise storage, but example uses row-wise interpretation)
lp.a_matrix_.index_ = np.array([0, 1, 0, 1]) # Row indices for each element
lp.a_matrix_.value_ = np.array([0.3, 0.7, 0.5, 0.5], dtype=np.double)
h.passModel(lp)
# Solve the model
h.run()
# Extract and print solution
solution = h.getSolution()
info = h.getInfo()
model_status = h.getModelStatus()
print(f"Model status: {h.modelStatusToString(model_status)}")
if model_status == highspy.HighsModelStatus.kOptimal:
col_value = list(solution.col_value)
print(f"Optimal objective: {info.obj_val}")
print(f"x0 = {col_value[0]}, x1 = {col_value[1]}")
else:
print("No optimal solution found.")