Skip to main content

Hybrid MINLP solver combining Rust and JAX

Project description

discopt

CI codecov

img

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.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

discopt-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.1 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

discopt-0.2.0-cp312-cp312-win_amd64.whl (2.1 MB view details)

Uploaded CPython 3.12Windows x86-64

discopt-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

discopt-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.1 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

discopt-0.2.0-cp312-cp312-macosx_11_0_arm64.whl (2.0 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

discopt-0.2.0-cp312-cp312-macosx_10_12_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

discopt-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

discopt-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.1 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

discopt-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

discopt-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.1 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

File details

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

File metadata

File hashes

Hashes for discopt-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9b2460e387d3a2f51fdaa8faf49c9ead8de5f7b17608b38224e6c6f1511faab2
MD5 d746e0449777361d84354b457d3ddb83
BLAKE2b-256 c2638441f5053aaa64905ac19222065bd41433933a4a0dd11c9416ab624c2d77

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 30b7324f1c76d36cff8931e60e22216260381c5f470910a4a545242d5ca5f634
MD5 0274f373b2a636623a22aeef0a36a90c
BLAKE2b-256 19fadb83840d530cf8c933ad460e0510d97a04d28993e9e9cef881980b31048e

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: discopt-0.2.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 2.1 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.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 06e000f58be4f9e38ee71d04d79c02f9ffc2d666e9e1ebaa7c52c520cccb6b17
MD5 bcb979c545e6a2165aae5fdb2262ac78
BLAKE2b-256 1e4cfcd5446c90f021ee08d735fd273d37b9cdbbb15bbefc08f598e627c923b7

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 467570aa84f36b1957005b413de604fd4b8b39df4aacc23b6f52c63a4e002ecd
MD5 bbb7e1b4d33eb258fa319617dc601d6c
BLAKE2b-256 014a116dde487eb48eae6668500a57614feb38205a4e5e128ec324e91ceb21e2

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 825dd78199d81731f4017a7ddf135a8f270141787334061f883efa012d044a36
MD5 ff07f003fd3eb819421ad6b7ef9eba65
BLAKE2b-256 d3237e7f93cef399cd06236009eeea1110740462cba0706f9fcbb3d8e7426471

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.2.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 54f9b1e7a5a0fb2633ce4284306493ee8c5cd3f2fbb812b8d74c22cb21a9a8e0
MD5 8daecd4893f02b6e2b8b063ebecf5238
BLAKE2b-256 6278e4110369419931a27399a85077f0699e330436dc719a24a26ef7f15fdbff

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.2.0-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 6b11279cd3b3709b3f2aed828f35a26ca9899ee8e8986619583bd1b35d2ad48b
MD5 eba4e94c65132d76d84e55d3eba0c229
BLAKE2b-256 a3fb16dd99ecef06b5f06f2883654ca3022805d1450f10d47d6cee94b123a57b

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e493777250fec1e4a57b89fd78ac0eccaa2572448376b7eed1db17aae53da426
MD5 ac5a4b3b6103a4750e2a13ee8cb71841
BLAKE2b-256 a6b1afc45431fe02e7edbab20b727c6ba9a787285720e08d8255fcadc5b64fc5

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0ed1cf7f5363443e74b43089a7e402427eef71a7e0088d904e3ac6a91c069216
MD5 ea148ba6b2a96d9da671f1d73e7398da
BLAKE2b-256 9af9a4983501ca3feec906da6ac4133b5606324d23f5d34137ed4723f1ac977c

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fd09c2d010d4b5aa3c64dc3a1188bdbc85c152473facd7d995372ef391acb955
MD5 e36abb3ca2b2700cb37b925134d99350
BLAKE2b-256 cdacc078e8f0189f3259ac4dbafdd33a1a7ffbd35c31581ddb66f7fbbaf0ea21

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for discopt-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 2e54e61177740ac2a5e2eab93c3e660d951d9dad2fa1bb3b04ee39730cede01b
MD5 ec385c2036103932b20cf2f6129c24ac
BLAKE2b-256 aecb7c5ab052663b678a6f680b2c9651ba5adb38e12ab1166b3e8c18ed16c65d

See more details on using hashes here.

Provenance

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