Skip to main content

grbcompat

PyPI CI License: MIT

A Python package that lets you run gurobipy-based optimization models on the free, open-source HiGHS solver — with no changes to your existing code.

Why

Gurobi is a best-in-class commercial solver, but it requires a licence. HiGHS is a high-quality open-source LP/MIP solver. This wrapper translates the gurobipy API into HiGHS calls at runtime, so you can:

  • Run models on HiGHS during development without a Gurobi licence.
  • Switch freely between solvers to compare results or costs.
  • Keep a single codebase that works with either solver.

Requirements

  • Python ≥ 3.11
  • highspy ≥ 1.7 (installed automatically)
  • A Gurobi licence is not required to use this wrapper.

Installation

pip install grbcompat

Or, to work from source:

git clone <repo-url>
cd grbcompat
uv sync --dev

Usage

Pattern A — Drop-in replacement (one extra line)

Add a single install() call before any import gurobipy statement. Every subsequent import gurobipy in that process resolves to the HiGHS-backed wrapper. Your existing code stays untouched.

import grbcompat
grbcompat.install()          # ← the only change

import gurobipy as gp                # now backed by HiGHS
from gurobipy import GRB

m = gp.Model("my_model")
x = m.addVar(lb=0, name="x")
y = m.addVar(lb=0, name="y")

m.setObjective(x + 2 * y, GRB.MINIMIZE)
m.addConstr(x + y >= 1, "demand")
m.optimize()

print(f"x={x.X:.4f}  y={y.X:.4f}  obj={m.ObjVal:.4f}")

Pattern B — Side-by-side solvers

Import the wrapper directly under its own name. Both solver namespaces are fully independent and can be used in the same script simultaneously.

import grbcompat as highs    # backed by HiGHS (free)
import gurobipy as gp                # backed by Gurobi (licensed)

from grbcompat import GRB as HGRB

# Build the same LP with both solvers
def build(Mod, G):
    m = Mod()
    x = m.addVar(lb=0.0, name="x")
    y = m.addVar(lb=0.0, name="y")
    m.addConstr(x + y >= 4, "demand")
    m.setObjective(2 * x + 3 * y, G.MINIMIZE)
    m.optimize()
    return m, x, y

m_h, x_h, y_h = build(highs.Model, HGRB)
m_g, x_g, y_g = build(gp.Model, gp.GRB)

print(f"HiGHS:  obj={m_h.ObjVal:.4f}  x={x_h.X:.4f}  y={y_h.X:.4f}")
print(f"Gurobi: obj={m_g.ObjVal:.4f}  x={x_g.X:.4f}  y={y_g.X:.4f}")

Supported gurobipy API

Model

Method / Property Notes
addVar(lb, ub, obj, vtype, name) All types: CONTINUOUS, INTEGER, BINARY
addVars(*indices, lb, ub, obj, vtype, name) Scalar, list, range, or cartesian-product indices; lb/ub can be dicts
addConstr(lhs, sense, rhs, name) TempConstr from <=/>=/==, or explicit sense/rhs
addConstrs(generator, name) Returns a tupledict
addLConstr(...) Alias for addConstr
setObjective(expr, sense) GRB.MINIMIZE / GRB.MAXIMIZE
optimize()
update() No-op (changes applied immediately)
reset() Clears solution without rebuilding the model
write(filename) Writes .lp, .mps, or other HiGHS-supported formats
setParam(name, value) Alias for model.Params.<name> = value
setAttr(attr, value) Supports ModelSense, ObjCon
getAttr(attr, objects) Batch-reads X, Pi, Slack, RC, LB, UB, …
getVars() / getConstrs()
getVarByName(name) / getConstrByName(name)
ObjVal, ObjBound, MIPGap After optimize()
Status, Runtime
NumVars, NumConstrs
ModelName, ModelSense Readable and writable
Context manager (with Model() as m)

Var

Attribute / Property Notes
X Primal value (after optimize())
RC Reduced cost
LB, UB, Obj, VType, VarName Readable and writable; changes take effect immediately
+, -, *, /, unary - Returns LinExpr
<=, >=, == Returns TempConstr for use in addConstr

Constr

Attribute / Property Notes
Pi Dual value / shadow price (after optimize())
Slack Constraint slack (after optimize())
ConstrName, Sense, RHS RHS is writable; change takes effect at next optimize()

LinExpr

Full arithmetic support: +, -, *, /, unary -, sum() built-in, ==/<=/>= to produce constraints.
Methods: size(), getCoeff(i), getVar(i), getConstant(), add(), addTerms(), getValue().

tupledict

Returned by addVars and addConstrs. Supports select(*pattern), sum(*pattern), prod(coeff_dict, *pattern).

GRB constants

GRB.MINIMIZE / GRB.MAXIMIZE
GRB.CONTINUOUS / GRB.INTEGER / GRB.BINARY / GRB.SEMICONT / GRB.SEMIINT
GRB.LESS_EQUAL / GRB.GREATER_EQUAL / GRB.EQUAL
GRB.INFINITY
GRB.OPTIMAL / GRB.INFEASIBLE / GRB.UNBOUNDED / GRB.INF_OR_UNBD
GRB.TIME_LIMIT / GRB.ITERATION_LIMIT / GRB.SOLUTION_LIMIT / …
GRB.Status.*   # mirrors the top-level codes
GRB.Attr.*     # attribute name strings

Params

Set solver parameters via attribute assignment. gurobipy names are translated to their HiGHS equivalents automatically.

gurobipy name HiGHS option Type
TimeLimit time_limit float
MIPGap mip_rel_gap float
MIPGapAbs mip_abs_gap float
FeasibilityTol primal_feasibility_tolerance float
OptimalityTol dual_feasibility_tolerance float
IntFeasTol mip_feasibility_tolerance float
OutputFlag output_flag bool
Threads threads int
Seed random_seed int
NodeLimit mip_max_nodes int
IterationLimit simplex_iteration_limit int

Unknown parameter names are forwarded directly to HiGHS.

Compatibility stubs

GurobiError, Env, disposeDefaultEnv — accepted and silently ignored so that licence-management code in existing scripts does not break.

Module-level functions

grbcompat.quicksum(iterable)      # → LinExpr
grbcompat.multidict(data)         # → [keys, dict1, dict2, …]
grbcompat.install()               # patches sys.modules['gurobipy']

Running the tests

uv sync --dev
uv run pytest

The test suite has 388 tests across 10 files:

File Tests Coverage
test_constants.py 28 All GRB constants and status codes
test_expr.py 47 LinExpr arithmetic, merging, TempConstr
test_var.py 52 All Var properties, setters, operators
test_constr.py 22 Constr metadata, duals, slacks, RHS setter
test_tupledict.py 31 select, sum, prod, addVars integration
test_params.py 16 All mapped params, unknown-param error
test_model_core.py 81 addVar/Vars, addConstr/Constrs, setObjective, I/O
test_model_lp.py 32 LP correctness, duals, re-optimization
test_model_mip.py 15 Binary, integer, mixed-integer programs
test_api_compat.py 55 install() isolation, gurobipy usage patterns
test_gurobi_comparison.py 29 Cross-solver comparison (skipped without Gurobi licence)

Cross-solver comparison tests

If you have a valid Gurobi licence, the comparison tests run automatically and verify that HiGHS and Gurobi produce identical results (within 1e-4 tolerance) for LP objectives, primal values, dual values, slacks, solve status, and MIP objectives:

pytest tests/test_gurobi_comparison.py -v

Without a licence they are skipped with a clear message — no configuration needed.


Limitations

  • Quadratic objectives and constraints (QuadExpr, QConstr) are not supported. HiGHS does support QP but the translation layer is not yet implemented.
  • Model.remove() (removing individual variables or constraints) is not implemented.
  • Callbacks (Model.optimize(callback)) are not supported.
  • Multi-objective and scenario features are not supported.
  • HiGHS and Gurobi may return different optimal bases for degenerate problems; primal solution values can differ while objective values agree.

How it works

When you call install(), the package registers itself under sys.modules['gurobipy']. Subsequent import gurobipy statements in the same process return the wrapper instead of the real package.

Internally, each Model creates a highspy.Highs instance. Variable and constraint operations translate directly to HiGHS column/row operations applied immediately (no lazy batching). model.update() is a no-op.

The solver-status integer codes (GRB.OPTIMAL = 2, etc.) match gurobipy's values exactly, so any code that branches on model.Status works correctly with either solver.


License

MIT

Metadata

Release files for grbcompat 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for grbcompat 0.1.2
File Size Uploaded Provenance Actions
grbcompat-0.1.2.tar.gz 90.8 kB Without provenance Details for grbcompat-0.1.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for grbcompat 0.1.2
File Interpreter ABI Platform Actions
grbcompat-0.1.2-py3-none-any.whl Python 3 none any Details for grbcompat-0.1.2-py3-none-any.whl

Total release size: 122.3 kB

Release files / grbcompat-0.1.2.tar.gz

Download URL grbcompat-0.1.2.tar.gz
Size 90.8 kB
Tags Source
SHA-256 checksum
How to use checksums
2e04cd3392bbf4b3f10a10acf2f64681738ba66e198ec42406afb5858c5ccfb8
BLAKE2b-256 checksum
How to use checksums
7f34b964edab987010522340dc59ee8d0f056411f08f35d709a9ec7553850c06
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / grbcompat-0.1.2-py3-none-any.whl

Download URL grbcompat-0.1.2-py3-none-any.whl
Size 31.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d4f0f449ec926b18da7112f749e02293d6a7f50eafc68d7dc3713e68ffac168d
BLAKE2b-256 checksum
How to use checksums
f48c2043ef50fab04780fda1b7e8097f59e120442448dde52774b444f89aee3b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for grbcompat 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page