NeuroMANCER: differentiable constrained optimization and control on top of PyTorch
Pytorch-based framework for solving parametric constrained optimization problems, physics-informed system identification, and parametric model predictive control.
At a glance
- What is it?
- NeuroMANCER is a PyTorch library from PNNL that combines symbolic constraint definitions with neural modules for learning to optimize, model and control. It is strongest when the problem has physics or safety constraints you can write down, and weakest when you just want a standard supervised model.
- Who is it for?
- Adopt NeuroMANCER if your problem is a parametric constrained optimization or a control task where the constraints can be written symbolically and you already work in PyTorch. Do not adopt it if you need mixed-integer guarantees at runtime, if your team cannot commit to PyTorch, or if a plain supervised regressor would pass your acceptance test.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap NeuroMANCER is aimed at: constraints that survive training
Most PyTorch models learn a mapping from inputs to outputs and leave the constraints to whoever consumes the output. If the output is a control action for a building thermal system or a setpoint for a power converter, an unconstrained prediction can be physically infeasible even when its loss is low. NeuroMANCER is built for the case where the decision variable itself is the thing being learned, and where domain rules have to be part of the training graph rather than a post-processing step.
The README frames the library around three tasks: Learning To Optimize, Learning To Model, and Learning To Control. The intended user is an engineer or researcher who already has a model of the physics, or a set of operating constraints, and wants to embed that knowledge into a differentiable program. The project targets parametric problems, meaning the optimizer is trained once and then evaluated across many problem instances rather than re-solving from scratch for each one. That is the core value proposition: amortizing the cost of solving a constrained program by learning the solution map.
Symbolic variables, Node, and the System container
The mechanism is a symbolic programming layer that sits above ordinary PyTorch modules. The README example shows the pattern. A neural architecture is built with nm.modules.blocks.MLP, taking insize, outsize, a linear map from nm.slim.maps, a nonlinearity such as torch.nn.ReLU, and hidden sizes. That module is then wrapped in nm.system.Node(func, ['p'], ['x'], name='map'), where the two lists name the input and output variables. The Node is the unit of composition: it declares which symbolic variables it consumes and which it produces.
Decision variables are created separately with nm.constraint.variable("x"), and the README indexes the result to pull out individual components, for example x[:, [0]] and x[:, [1]]. Constraints and objectives are expressed over those variables, and the resulting graph is assembled into a System. The README notes that v1.5.6 adds a SystemPreview class described as a drop-in replacement for System that enables preview horizon functionality, which matters for control problems where the controller should see future reference values.
The data flow is therefore: symbolic variables carry problem data and decision values, Nodes map between them using neural modules or physics equations, constraints and objectives are declared over the same variables, and the whole structure is differentiated end to end. Losses are composed from PenaltyLoss classes according to the README, which is how soft constraints enter the objective. The library also lists differentiable convex optimization layers for safety constraints, so a hard constraint can in principle be enforced by a solver layer rather than only penalized.
Installing and running the first constrained optimization example
Installation is a single command: pip install neuromancer. The README points to INSTALLATION.md for manual installation, which is where you would look if you need a specific PyTorch build or a development checkout. The package is on PyPI, and the repository's default branch is master.
The fastest way to see the abstractions is the tutorial series linked from the README, which has Colab badges so you can run them without cloning anything. Part 1 compares linear regression in plain PyTorch against NeuroMANCER. Part 2 covers variables, constraints and objectives. Part 3 covers modules, the Node class and the System class. There is also a quick example in the README itself that builds an MLP with hsizes=[80] * 4, wraps it as a Node mapping p to x, declares decision variables x and y from nm.constraint.variable("x"), and assembles the constrained optimization problem. The README's own example is cut off partway through the constraint definitions, so the tutorials are the real reference for the full formulation.
Domain examples are organized by task. The v1.5.6 release notes list new notebooks for neural differential algebraic equations via operator splitting, mixed-integer DPC for a thermal system, grid-responsive DPC for building energy systems, and DPC with a preview horizon. Each is available as a Colab notebook, which is a low-friction way to check whether the formulation matches your problem before you install anything.
Where the abstraction leaks: integer decisions and solver guarantees
The mixed-integer DPC example is the one to read closely before assuming NeuroMANCER gives you combinatorial guarantees. A learned policy that produces near-integer values is not the same as a branch-and-bound solve that proves optimality. If your application needs a certified feasible action at every timestep, a learned controller is the wrong layer for that guarantee, regardless of how the constraints are written.
The second limitation is architectural. Everything is PyTorch. The symbolic layer, the Node and System classes, and the loss composition all assume a torch computation graph. If your existing pipeline is in JAX, CasADi, or a Julia stack, adopting NeuroMANCER means either rewriting the surrounding code or running two frameworks side by side. The README does not describe an export path to a standalone solver or a C runtime, so deployment of a trained policy is a separate engineering problem the documentation does not solve for you.
The third limitation is documentation depth. The README is a tour of features and examples rather than a specification. The SystemPreview class is introduced in the release notes with one sentence, and the README example stops before showing how constraints are actually declared. That is fine for exploration and thin for production sign-off. Expect to read source code and notebooks to answer questions about how a specific constraint is lowered into the training objective.
How this differs from a general differentiable optimization layer
The closest comparison is a differentiable optimization layer such as cvxpylayers, which wraps a disciplined convex program and returns gradients through the solution. NeuroMANCER uses the same idea, and the README lists differentiable convex optimization layers among the methods it supports, but the surrounding framework is different. cvxpylayers assumes you already have a convex program in a DSL and want to differentiate through it. NeuroMANCER assumes you are building a learning system, so it supplies the neural modules, the symbolic variable layer, the Node and System composition, the penalty loss machinery, and the training loop conventions around them.
That breadth is also the trade-off. If your problem is genuinely convex and you only need gradients through the solver, a thinner layer keeps the dependency surface smaller. NeuroMANCER earns its footprint when the problem mixes learned components with declared constraints and you want both expressed in one graph. The physics-informed side reinforces this: the README lists neural ODEs, neural Koopman operators, SINDy, Function Encoders and Kolmogorov-Arnold Networks as available methods, which means the library is positioning itself as a general differentiable programming toolkit for dynamical systems rather than a single-purpose solver wrapper.
Release cadence, licence status and what to verify before adopting
The release history shows active maintenance rather than a frozen artifact: v1.5.4 in July 2025, then v1.5.5 and v1.5.6 both dated 2025-09-26, with the repository's last push recorded as 2026-09-03. Patch releases arriving on the same day suggest small, quick fixes rather than long release trains. The v1.5.6 notes mention a fixed mlflow dependency conflict in Google Colab, which is the kind of packaging issue that affects users who run the notebooks in hosted environments.
The licence situation needs attention before you build on it. The repository metadata reports NOASSERTION, meaning the licence could not be automatically classified, while the README carries a BSD badge pointing at LICENSE.md. Those two signals are not the same thing, and for a government-lab project the actual terms in LICENSE.md are what govern your use. Read that file. This is a factual gap in the metadata, not a legal opinion, and it is the first thing a procurement or legal reviewer will ask about.
On upgrade cost, the library is at v1.5.x and the release notes describe new classes and new examples rather than breaking API changes, but the README does not publish a deprecation policy or a compatibility matrix against PyTorch versions. If you pin a NeuroMANCER version, pin the PyTorch version with it. The unit tests are described as brought up to date in v1.5.6, which is a signal that test coverage tracks the current release rather than every historical one.
Editorial conclusion
Adopt NeuroMANCER if your problem is a parametric constrained optimization or a control task where the constraints can be written symbolically and you already work in PyTorch. Do not adopt it if you need mixed-integer guarantees at runtime, if your team cannot commit to PyTorch, or if a plain supervised regressor would pass your acceptance test. Before committing, verify the licence text in LICENSE.md, since the repository metadata reports NOASSERTION while the README badge says BSD, and run the Part 2 variables and constraints notebook end to end on your own data shape.
Community notes