Skip to main content

Hybrid MINLP solver combining Rust and JAX

Project description

discopt

CI codecov

discopt

A hybrid Mixed-Integer Nonlinear Programming (MINLP) solver combining a Rust backend, JAX automatic differentiation, and Python orchestration. Solves MINLP problems via NLP-based spatial Branch and Bound with JIT-compiled objective/gradient/Hessian evaluation.

Features

  • Algebraic modeling API -- continuous, binary, and integer variables with operator overloading
  • Spatial Branch and Bound -- Rust-powered node pool, branching, and pruning
  • JIT-compiled NLP evaluation -- objective, gradient, Hessian, and constraint Jacobian via JAX
  • Three NLP backends -- pure-JAX interior-point method (default, vmap-batched), ripopt (Rust IPM via PyO3), cyipopt (Ipopt)
  • Convex relaxations -- McCormick envelopes (21 functions including sigmoid/softplus/tanh), piecewise McCormick, alphaBB underestimators
  • Neural network embedding -- embed trained feedforward networks (ReLU, sigmoid, tanh, softplus) as MINLP constraints via big-M, full-space, and reduced-space strategies; interval arithmetic bound propagation; ONNX import (pip install discopt[nn])
  • Generalized disjunctive programming -- BooleanVar, propositional logic operators (land, lor, lnot, atleast, atmost, exactly), either_or(), if_then(); reformulated via big-M, multiple big-M (LP-tightened), hull, or Logic-based Outer Approximation (gdp_method="loa")
  • Presolve -- FBBT (interval arithmetic, probing, Big-M simplification), OBBT with LP warm-start
  • Cutting planes -- reformulation-linearization (RLT) and outer approximation (OA)
  • GNN branching policy -- bipartite graph neural network trained on strong branching data
  • Primal heuristics -- multi-start NLP, feasibility pump
  • Differentiable optimization -- parameter sensitivity via envelope theorem and KKT implicit differentiation
  • .nl file import -- read AMPL-format models via Rust parser
  • Dynamic optimization -- DAE collocation (Radau/Legendre) and finite differences for optimal control, parameter estimation, and PDE-constrained optimization
  • CUTEst interface -- NLP benchmarking against the CUTEst test set
  • LLM integration (optional) -- conversational model building, diagnostics, and reformulation suggestions
  • 1650+ tests -- 141 Rust + 1510+ Python

Quick Start

from discopt import Model

m = Model("example")
x = m.continuous("x", lb=0, ub=5)
y = m.continuous("y", lb=0, ub=5)
z = m.binary("z")

m.minimize(x**2 + y**2 + z)
m.subject_to(x + y >= 1)
m.subject_to(x**2 + y <= 3)

result = m.solve()
print(result.status)     # "optimal"
print(result.objective)  # 0.5
print(result.x)          # {"x": 0.5, "y": 0.5, "z": 0.0}

Architecture

Model.solve()  -->  Python orchestrator  -->  Rust TreeManager (B&B engine)
                        |                          |
                  JAX NLPEvaluator           Node pool / branching / pruning
                  NLP backends:              Zero-copy numpy arrays (PyO3)
                    ripopt  (Rust IPM, PyO3)
                    ipm     (pure-JAX, vmap batch)  [default]
                    cyipopt (Ipopt)

Rust backend (crates/discopt-core): Expression IR, Branch and Bound tree (node pool, branching, pruning), .nl file parser, FBBT/presolve (interval arithmetic, probing, Big-M simplification).

Rust-Python bindings (crates/discopt-python): PyO3 bindings with zero-copy numpy array transfer for the B&B tree manager, expression IR, batch dispatch, and .nl parser.

JAX layer (python/discopt/_jax): DAG compiler mapping modeling expressions to JAX primitives, JIT-compiled NLP evaluator (objective, gradient, Hessian, constraint Jacobian), McCormick convex/concave relaxations (21 functions), and a relaxation compiler with vmap support.

Solver wrappers (python/discopt/solvers): ripopt (Rust IPM via PyO3), cyipopt NLP wrapper for Ipopt, HiGHS LP and MILP wrappers with warm-start support.

CUTEst interface (python/discopt/interfaces/cutest.py): PyCUTEst-based evaluator for NLP benchmarking against the CUTEst test set.

Orchestrator (python/discopt/solver.py): End-to-end Model.solve() connecting all components. At each B&B node: solve continuous NLP relaxation with tightened bounds, prune infeasible nodes, fathom integer-feasible solutions, branch on most fractional variable.

NLP Backends

Backend Implementation Use Case
ipm (default) Pure-JAX IPM B&B inner loop; GPU-batched via jax.vmap
ripopt Rust IPM via PyO3 Single-problem NLP; fastest wall-clock
cyipopt Ipopt via cyipopt Single-problem NLP; most robust
result = model.solve(nlp_solver="ipm")      # Pure-JAX (default)
result = model.solve(nlp_solver="ripopt")   # Rust IPM
result = model.solve(nlp_solver="cyipopt")  # Ipopt

Benchmarks

Performance measured on Apple M4 Pro (CPU, JAX 0.8.2). "Warm" times exclude JIT compilation. All solvers produce matching objective values.

Problem Class discopt Comparison Notes
LP (n=100) 0.015s warm HiGHS 0.002s, scipy 0.002s Algebraic extraction, no autodiff
QP (n=100) 0.04s warm scipy SLSQP 0.02s Was 66s before algebraic extraction
MILP (n=25) 0.002s HiGHS MIP 0.002s B&B + LP relaxation, correct objectives
MIQP (n=10) 0.004s NLP path 4.9s QP-specialized path: 1000x+ speedup
NLP (n=20, Rosenbrock) IPM 1.1s warm, ripopt 0.42s, Ipopt 0.43s -- ripopt fastest single-solve; IPM best for batched B&B
MINLP (n=10) 0.9s (batch=1) 0.9s (batch=16) vmap batching helps with deeper B&B trees

See the benchmark notebooks for full scaling plots and details:

Installation

Requires Rust 1.84+, Python 3.10+, and Ipopt.

# Install Ipopt (macOS)
brew install ipopt

# Clone ripopt alongside discopt (path dependency at ../ripopt)
git clone <ripopt-repo-url> ../ripopt

# Build Rust-Python bindings (includes ripopt PyO3 bindings)
cd crates/discopt-python && maturin develop && cd ../..

# Run tests
cargo test -p discopt-core
JAX_PLATFORMS=cpu JAX_ENABLE_X64=1 pytest python/tests/ -v

Command-Line Interface

After installation, the discopt command is available on your PATH:

# Search arXiv for recent papers
discopt search-arxiv 'all:"spatial branch and bound"' --max-results 10 --start-date 2026-01-01

# Search OpenAlex
discopt search-openalex "McCormick relaxation" --from-date 2026-01-01 --to-date 2026-03-31

# Write a report from stdin
echo "report content" | discopt write-report reports/output.md

All subcommands output structured JSON, making them suitable for scripting and integration with other tools. The discoptbot literature scanner skill uses these subcommands to automatically find and summarize relevant new papers from arXiv and OpenAlex.

Documentation

Tutorial notebooks are available in docs/notebooks/:

  • Quickstart -- basic modeling and solving
  • MINLP Examples -- mixed-integer nonlinear programs
  • Advanced Features -- relaxations, presolve, cutting planes, branching policies
  • IPM vs Ipopt -- backend comparison
  • Batch IPM -- vmap-batched interior-point solving
  • Dynamic Optimization -- DAE collocation for optimal control, parameter estimation, and PDEs
  • Neural Network Embedding -- optimize over trained ML surrogates as MINLP constraints
  • Decision-Focused Learning -- differentiable optimization in ML pipelines
  • GDP Tutorial -- disjunctive programming, logical constraints, big-M/hull/LOA reformulations

Full documentation is built with Jupyter Book: jupyter-book build docs/

Project Statistics

Last updated: 2026-02-16

Category Count
Python source (python/discopt/) 65 files, ~27,200 lines
Rust source (crates/) 19 files, ~10,700 lines
Test code (python/tests/) 41 files, ~24,500 lines
Total source + tests 125 files, ~62,400 lines
Python tests 1,510+
Rust tests 141
Tutorial notebooks (docs/notebooks/) 21
Git commits 99

Development History

See ROADMAP.md for the full development roadmap and task history.

License

Eclipse Public License 2.0 (EPL-2.0)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

discopt-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

discopt-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

discopt-0.2.1-cp312-cp312-win_amd64.whl (2.2 MB view details)

Uploaded CPython 3.12Windows x86-64

discopt-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

discopt-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

discopt-0.2.1-cp312-cp312-macosx_11_0_arm64.whl (2.1 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

discopt-0.2.1-cp312-cp312-macosx_10_12_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

discopt-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

discopt-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

discopt-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

discopt-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

File details

Details for the file discopt-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d17ff9d03f1f478bcb6937fd807fe3bc7d837aebfc4abf14d0071342821b08d0
MD5 cd1cd69641291f2e01fd9e22eebcbdb1
BLAKE2b-256 dbf7ed8e130d9dd1dc363a6f7f6c2b847c115ea855fe7270cb0fef813ebc50df

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file discopt-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for discopt-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 bb19a2020d9b7150cb6d2979baa5826ff8640890f7bd6453e07c8a81d2d181f2
MD5 af875a1ac2d3c88c2830c9925b560f5b
BLAKE2b-256 ad768373377b9594d3258e641d3ffa751e214ddaa9d48b113ef780e79ebe9915

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file discopt-0.2.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: discopt-0.2.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 2.2 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for discopt-0.2.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 9e62a789a04741ba618ea7cc204c8d3e18eca383100b721380489467861d5009
MD5 13d8b3794a39ca40e7b2f7e9cd33f7c6
BLAKE2b-256 eaf12bac483f4a3ba5286858623f21c12e10ff9480b7972326cc69d80444f823

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp312-cp312-win_amd64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file discopt-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d0e6085992dba72b53e22aeb139fe761ce7dc0837ff1cd2c8cade03b9d145e61
MD5 e15a4ed551649e0b4319a45cccc64ea8
BLAKE2b-256 06250674298c9792e35cc1192d8389a4cd7bcc4de383281bd421848111c40c01

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file discopt-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for discopt-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 5a7f98ac439263f62dc318df1bc2112a0a5b9065bb30f34ba89f2527ded680f6
MD5 a26430a2b8c2aeb567c0630f30a35423
BLAKE2b-256 104e567cb27413d4af6200b0d6e1dafc615176835793b63014e47ec2cdc1226c

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file discopt-0.2.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for discopt-0.2.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 186fca917ebdafdf5ec932f82fa4855349c3f16df20f9ea0ae55da48c79294c4
MD5 2bba0eeceb206df8764db3752ac133ca
BLAKE2b-256 a157726c9595e13d0a370becffb349eac2097b4b02f356cee635eac8456efd5f

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file discopt-0.2.1-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.2.1-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 5fcb8121b87b372269664037c303b8ed0a21382e3335dfa9a6d4b2d57e72c634
MD5 673aeb963b9c651f9b58ddab619bccc2
BLAKE2b-256 410e7d4a4c2420a25ba8e3d9e3701d8345d734a19f62845c80efb832d51a3161

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp312-cp312-macosx_10_12_x86_64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file discopt-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 07693f96325e72713e09e08cb0121ee12abcdbbea320b072b0b4f7d6903cf717
MD5 8da6967081659f0cf2ee253e9c876e90
BLAKE2b-256 f7b411255617ac753b1789dfe825817a51e704edebc667c1e88ea1251cbcf771

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file discopt-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for discopt-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 33f6598070e891b1bb2b4336729ea9c2f8264f0bd75ee93850ffc23182b25bc6
MD5 e8f902f1c56ef0ba8fab573e2cd02b56
BLAKE2b-256 4102439910950380aab57d11119b00e5fd72c792c037b1efead70c716ae87321

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file discopt-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0e871379dd1ad4dfb1322d1f0855126d96f1bed2028f5d1719e7f355e601bb99
MD5 77bd8444cb99b7bc70f903ec1b236bc2
BLAKE2b-256 774e5fa007a4198c268b3ebd673caf68eec732a9e90262666e5d760716b01335

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file discopt-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for discopt-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e841820e63e572203905491de0d030d7655f63b2eed1fcc60bd8f71605770238
MD5 0a07380b8a459f05ec403ec0e5a8a7c9
BLAKE2b-256 f6c68f42a7ef7dd59d3eb08726251878ff1db011585d703765f2eb38a26a6c3a

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on jkitchin/discopt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page