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.2-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.2-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.2-cp312-cp312-win_amd64.whl (2.2 MB view details)

Uploaded CPython 3.12Windows x86-64

discopt-0.2.2-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.2-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.2-cp312-cp312-macosx_11_0_arm64.whl (2.1 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

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

Uploaded CPython 3.12macOS 10.12+ x86-64

discopt-0.2.2-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.2-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.2-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.2-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.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.2.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 add60df422a4a9e2eef57b201bf52551de8d9c8fd1264cbac53e68eb62600b58
MD5 ac4f2a724c74ea7caee8f789219d25e4
BLAKE2b-256 005f8809d817f5829b5dc395b70af2650c98584c864cdb1ff75ecf57e6051108

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for discopt-0.2.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 46e3210c7ba7e7ab6e786e8ce4bfcafef873b6ccbbefd83113ae7a08d3ee03ad
MD5 7eb2b9827ae0943d9b280b8462ffa531
BLAKE2b-256 873079159947d1149335afd5931f31fcd93578d41b4e32e6baa5f45ff060325f

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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.2-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: discopt-0.2.2-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.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 09358637bc19deb572546b9a799037df6e6c1f7a24d90ec206d476ec1eba29dc
MD5 567d379c9942fc680ce84d1b6f19928a
BLAKE2b-256 e575b65b8d68ba99da1ed86492465830301e2245ad007300390f5ccc30e4504d

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c5120edcac25f609e75d54711c31977363525e88486d78744f1f24d6037aacdb
MD5 14be48a57f36defb51ae80680aa4dd3f
BLAKE2b-256 5a502b96030bfbc8de6bdd9bccc3c53cd7f2070f1d9d692b0e9df1f38baf1f2f

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for discopt-0.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4a1311888e68aff1ffcde14e09e35a41ae7842e4dae9ea052d4d0ff48ee0f703
MD5 f9b91440e9cb8ff9a72461ad3e68095b
BLAKE2b-256 c6a4e542bbada5b142adc3bccc8960773bdc034b9b032636a715185eb5e91162

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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.2-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for discopt-0.2.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f41bec2a0eca420cda316f878396e501c58ac6e2667127bb54c711d661dd9a61
MD5 92430a3ab93f97a2888cb304e8a15372
BLAKE2b-256 27c4549beae1e353e186eea988074b446e6ffb496f36ef2a8ee3a13f5a2326e2

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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.2-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.2.2-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 3209a0c2db7f07e55fa10dc7aac1d7ff3bf0e83030581ff225702dfef7a682e7
MD5 2d35be1f56ed0f8437997e0b9bb15a07
BLAKE2b-256 dd94c37cd413b4248ef50340eff7def19c15620f0e79a690cc62689ca9906f5d

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3d5e9a280eb799d32bee250de93abfde608de8474d6e650d5079b03f510349cc
MD5 017bbe5d8aa3ded4cb7caacbe930c4b8
BLAKE2b-256 7c66d2b5907f879c29b1d5793067a40268c7d56fe2f7bdec108c8d7738ca1654

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for discopt-0.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 90ec0cac4047ab4f483c70a3bc9d204acaa08433d3fdad7f3598337ec583dadc
MD5 b4619ad0a5f4dd986325cb74f15fe26f
BLAKE2b-256 165740943c00fdc7ca0a1fff94be6fd6e39691ccb52d3c8dfee8da0ca378e2da

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ad527c61f502f52500e65ce1459d482419b74d2bb6cb44e47efac8f5c1c1e10c
MD5 62a64fca9ccd1fc66668e95bd71694b6
BLAKE2b-256 8a75ea3a9922e2cd05bd75f971efb3c18bfad083e1430a490730eaf91039766a

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for discopt-0.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 c618528ce6c9bca5730b6bb0f3522add5af473db3c87ec0c257c7b366ef2392d
MD5 cdddfd325062f779dc8c3fe152f9ceb0
BLAKE2b-256 13e596b171a4526fcbb4c8cf5783b52088a2d7ac3437328566827c5c97eeb78c

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.2.2-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