Skip to main content

Hybrid MINLP solver combining Rust and JAX

Project description

discopt

PyPI CI codecov DOI

discopt

PyPI Downloads

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 Distribution

discopt-0.3.0.tar.gz (650.2 kB view details)

Uploaded Source

Built Distributions

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

discopt-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

discopt-0.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

discopt-0.3.0-cp312-cp312-win_amd64.whl (2.8 MB view details)

Uploaded CPython 3.12Windows x86-64

discopt-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

discopt-0.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

discopt-0.3.0-cp312-cp312-macosx_11_0_arm64.whl (2.6 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

discopt-0.3.0-cp312-cp312-macosx_10_12_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

discopt-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

discopt-0.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

discopt-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

discopt-0.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

File details

Details for the file discopt-0.3.0.tar.gz.

File metadata

  • Download URL: discopt-0.3.0.tar.gz
  • Upload date:
  • Size: 650.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for discopt-0.3.0.tar.gz
Algorithm Hash digest
SHA256 72ead17bb6aff3e0a5101de52c5633b3cbb48fe5a2defdf7a601397a43818c17
MD5 399af549f6f5efd1c6067a4dd9ea3455
BLAKE2b-256 1cb6433fe21825485521d4af12f098a9fb585e731424055db5c629cac196a739

See more details on using hashes here.

Provenance

The following attestation bundles were made for discopt-0.3.0.tar.gz:

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.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for discopt-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8067187a55044a06757ac5922e01108a9d73e8d6f3855951c09820603240ff0d
MD5 8a57d7d77ad9cb3786a658c111e43312
BLAKE2b-256 59edf679ebe5553ed0688d2b2b441f4fa0a63bfd25bf58bded78b8492a792a46

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d22c5aa381ded802c9c9addd096f56da653e0a142251e1677a37821cbd3eef46
MD5 a1eb6988e4b06e3dde7264bed640d8e7
BLAKE2b-256 ae574fc304269866ea551a4145ec4ff3b41d33107ca5ed341b5fa2c252c17531

See more details on using hashes here.

Provenance

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

File metadata

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

File hashes

Hashes for discopt-0.3.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 b668ccb21f03ff4d4b33301e62a647d122729028d8cf0bc56917cef6a5bcf3e4
MD5 c54566ed4fa63804184dba3ef5122b81
BLAKE2b-256 67dc69a8c6626cb36fca63daba88b5c5c9634c66b4e3a36641a7913ea44de2d6

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 43a186d338f971acd644ba4b5c4774566c136d6af47bc14aecc2ca7f8cc11d30
MD5 a41be6362df4558a2933141d01c1860c
BLAKE2b-256 7dbb364784d3d1f188a1c83c85ee6c6998373aeb01e8124311655f979d345136

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 360b00de04c8fdbc63eadc35db4b0e543a45e0cb56376d0d1c62cbeffc7fc054
MD5 d5e5081e50409ef078947a501a5c9567
BLAKE2b-256 6da8f9bba18c5dc446e8f2bffee270a56255339cdbe38b864b709e5a50188b04

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.3.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8307c64517109f7b7ce22f8137972212fa94f791e8182b77d42f948f203c3e73
MD5 f247c7341eb6cf319ef110611b7251d0
BLAKE2b-256 5129aa7702240a18c9787b064c1ead0aab00160a0ca3dd4cba6714295de84e96

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.3.0-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 499784e93833461848bf29a27a5e24b9b074170540d8b4d587dafd0bc5985e95
MD5 8a7b2d55c55b4594928b1b88929261a6
BLAKE2b-256 92e8b211095ea15a693b43f9ff7ddf9333e8d5300e5eb7481375ef28bbcbc60b

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0b435fa0c7386c8e6a80d94ceb42b2956c0d1e65c06db626495872a3415d4d56
MD5 1223ad7a08558e03f529cf45493c5191
BLAKE2b-256 8b7a6e77be60f611fb09bcdc9bcf866c1d7654cb6c0c1336752f04972190f23a

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e656013bd9046b372d1d820f83c4c4751c2f2ff778e9279201e101569ca3a520
MD5 88c2f0bb1cd11d52be9300be9cb0da01
BLAKE2b-256 54013f34db7ea872168439001c5ee8257e4acbfd0ac0d5cea6e3c224e0e15ed6

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d223de50d0fbd5d8e12f3ca312c05ffdf6761776c959e817beca77abd6be2eff
MD5 65109dce4901c3fc3e5381956dd10b07
BLAKE2b-256 3579b1fedbe3d61f74412cff6fa623a7125b1cb5742a0b9d319a04c244d432c1

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4c854ec03dafd72b5c64f1c66e61a87b72b209f16d06e3611700b49816de19c8
MD5 f736a8679bb15964bb7f3beaf0e909e2
BLAKE2b-256 a2f4be1998fe15bb38c6b6b44cfe63a90b80282e8e006ef7a43bc34e5425895d

See more details on using hashes here.

Provenance

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