Solvers¶
polar-high is solver-agnostic. HiGHS (via highspy) is the
no-license-needed default and ships in the base install. Four
commercial solvers — Gurobi, CPLEX, FICO Xpress, and
COPT — are supported on a bring-your-own-license basis: you
install the vendor's Python wrapper and provide your own license,
polar-high translates the model and dispatches the solve. We do
not ship solver binaries, generate license files, or store credentials.
See the multi-solver handoff spec
for the architectural rationale and the
"What NOT to do"
constraints baked into the design.
Detecting what is installed¶
polar_high.solvers.available_solvers is populated at import time by
attempting each vendor wrapper's Python import. It tells you which
wrappers are installed, not whether their license check will pass
— the license probe only fires when an env/model is constructed
inside the adapter.
from polar_high.solvers import available_solvers
print(available_solvers)
# Clean install: ['highs']
# With Gurobi: ['gurobi', 'highs']
# Full developer: ['gurobi', 'cplex', 'xpress', 'copt', 'highs']
solve(...) picks the first entry as the default if you don't pass
solver_name:
from polar_high.solvers import solve
result = solve(problem) # first available
result = solve(problem, solver_name="highs") # explicit
Installing a commercial solver¶
Each commercial adapter has a matching optional extra that pulls only
the Python wrapper (plus scipy where vectorized matrix loads
need it). The solver runtime and its license remain your
responsibility.
Gurobi¶
License discovery follows Gurobi's own rules — $HOME/gurobi.lic,
/opt/gurobi/, or the GRB_LICENSE_FILE env var. For WLS, Compute
Server, or Token Server contexts, build a gurobipy.Env and pass it
through:
import gurobipy as gp
from polar_high.solvers import solve
env = gp.Env(empty=True)
env.setParam("WLSACCESSID", "...")
env.setParam("WLSSECRET", "...")
env.setParam("LICENSEID", 12345)
env.start()
result = solve(problem, solver_name="gurobi", env=env)
Vendor docs: Gurobi licensing, gurobipy Env.
CPLEX¶
License discovery uses CPLEX's own mechanisms — ILOG_LICENSE_FILE
or CPLEX_STUDIO_LICENSE, an access.ilm adjacent to the install,
or IBM's ILM subscription credentials. The env= parameter is
reserved for future CPLEX subscription contexts.
Vendor docs: IBM CPLEX licensing, CPLEX Python API.
Xpress¶
The FICO Xpress wheel ships with a free community license built
in — small models work out of the box without any extra setup. For a
full / commercial license, point xpress.init(...) at your
xpauth.xpr file, or set the XPRESS / XPAUTH_PATH env var,
before calling solve(...).
Vendor docs: FICO Xpress community, Xpress Python.
COPT¶
License discovery follows COPT's own rules — copt.lic in the
install dir, COPT_LICENSE_DIR, or the bundled non-commercial
fallback for small models. For server or subscription deployments,
build a coptpy.Envr and pass it via env=.
Vendor docs: COPT manual.
COPT and HiGHS in the same Python process
COPT 8.x ships native code (coptpy.coptcore) that conflicts with
highspy once both are loaded into one interpreter: Highs.run()
segfaults after coptpy is imported. The conflict is on the solver
side only — highspy.Highs.writeModel is unaffected.
Since polar-high always imports highspy (it is the matrix
builder), the COPT adapter cannot use its in-memory Python path
when called from a polar_high process. It transparently
auto-routes through the file-based copt_cmd CLI in that case:
highspy writes the MPS, then a subprocess invokes copt_cmd
(no in-process coptpy load).
This requires the standalone copt_cmd binary on PATH. The
coptpy pip wheel does not ship it; install it from the
full COPT distribution. If
copt_cmd is missing the adapter raises SolverNotAvailableError
with a pointer to this section. As an alternative, invoke COPT
from a Python process that does not import polar_high — for
example, write the MPS via Problem.solve(write_mps=...) (or any
other route) and call coptpy directly.
No other commercial solver exhibits this conflict — Gurobi, CPLEX, and Xpress coexist with HiGHS in-process without issue.
File-based fallback: io_api='mps'¶
If you have a solver binary on PATH (e.g. an IT-managed install of
gurobi_cl or cplex) but not the matching Python wrapper —
common on locked-down corporate Python, mismatched Python versions,
or wheels missing for your platform — drop down to the MPS file
path:
from polar_high.solvers import IOMode, solve
result = solve(problem, solver_name="gurobi", io_api=IOMode.MPS)
polar-high writes a temporary MPS file via highspy, invokes the
solver's CLI binary on it, parses the resulting .sol file, and
returns the same SolverResult shape as the direct path. This is
slower on large models (round-trip through a file) and currently
LP-only on the writer side, but it covers cases the direct path
can't.
CLI binary names checked per solver: gurobi_cl, cplex,
optimizer (Xpress), copt_cmd. HiGHS deliberately refuses
io_api='mps' — the in-memory path is strictly better.
Passing solver options¶
Anything after solver_name= / io_api= / env= is forwarded as-is
to the underlying solver via its native parameter API:
The option keys are vendor-specific — TimeLimit is Gurobi's name;
CPLEX wants timelimit, Xpress uses maxtime, and so on. Consult
each vendor's reference for the supported parameter set.
Troubleshooting¶
The adapters wrap raw vendor exceptions into polar_high.solvers
types so you never see a bare gurobipy.GurobiError etc. reach your
code. Distinguishing the two failure modes:
SolverNotAvailableError— the Python wrapper is not importable. Install the corresponding optional extra.LicenseError— wrapper is installed but the license check failed. Fix per the messages below.SolverError— wrapper and license are fine, but the solver reported an error while solving (bad option, unsupported feature, etc.).
Common license errors, one per solver:
- Gurobi —
LicenseError: Gurobi license check failed (code 10009): ...Placegurobi.licat$HOMEor/opt/gurobi/, setGRB_LICENSE_FILE, or pass a configuredgurobipy.Envviaenv=.... WLS users build the env in code; the file path is not required. - CPLEX —
LicenseError: CPLEX license check failed (code 1016): ...Placeaccess.ilmnext to the CPLEX install, setCPLEX_STUDIO_LICENSEorILOG_LICENSE_FILE, or configure your subscription credentials. - Xpress —
LicenseError: Xpress license check failed: ...Configure your Xpress license (xpauth.xpr,XPRESS_LICENSE,XPAUTH_PATHenv vars), or callxpress.init('<path-to-xpauth.xpr>')before solving. The wheel's bundled FICO community license covers small problems and will not trigger this error. - COPT —
LicenseError: COPT license check failed (code ...): ...Placecopt.licin the COPT install dir, setCOPT_LICENSE_DIR, or pass a configuredcoptpy.Envrviaenv=....