Solvers¶
Declare an optimization problem with problem and ProblemSpec, then select an installed backend
with solver. The result is a Solver that you call with the problem parameters.
The official plugins register "piqp", "ipopt", "sqp" and "fatrop".
Fatrop accepts stage-structured nonlinear programs. With
solver(ocp.stage_problem(), "fatrop"), it uses the builder's mapped stage
Functions and recorded layout, including global variables carried as constant
states. Ordinary problems use whole-problem oracles and stage detection.
Use x0= for an initial guess or warm= for a previous result, and .stats()
to inspect the latest numerical solve. Its .function exposes the full input signature
for integrations that need a Function.
See the solver guide for a complete example and
solver backends for backend-specific options.
Problem construction and statistics are useful in application code. Plugin descriptors and graph queries support solver integrations and compiler extensions.
Problem construction¶
Bounded
dataclass
¶
A named constraint group with an optional lower and upper bound.
Source code in src/scaly/solvers/problem.py
bounded ¶
Declare a lower- and/or upper-bounded inequality group.
A numerical bound converts to the expression's dtype when NumPy's same_kind rule allows it,
as the arguments of a numerical call do. An expression bound must have the expression's dtype.
Source code in src/scaly/solvers/problem.py
NO_LB
module-attribute
¶
A scalar expression that leaves one variable block unbounded below.
NO_UB
module-attribute
¶
A scalar expression that leaves one variable block unbounded above.
ProblemSpec
dataclass
¶
The objective, constraint groups, and box bounds returned by a problem body.
lb and ub have the variables’ tree structure. Scalar expression leaves broadcast over
their variable blocks. Use NO_LB or NO_UB for an open side of one leaf.
Source code in src/scaly/solvers/problem.py
Problem
dataclass
¶
problem ¶
problem(*, vars: Tree[Any, Any], params: Tree[Any, Any] | None = None, name: str | None = None) -> Callable[[Callable[..., ProblemSpec[Any]]], Problem[Any, Any, Any, Any]]
Trace a backend-free problem over declared variables and parameters.
Source code in src/scaly/solvers/problem.py
Optimal control problems¶
See the optimal control guide.
DiscreteOCP
dataclass
¶
A discrete-time optimal-control problem over N stages, stated by its stage Functions.
It minimizes sum_k l(x_k, u_k) + Vf(x_N) subject to x_{k+1} = F(x_k, u_k), x_0 equal to
the parameter initial_state, the path constraints and control bounds at every stage k < N,
the state bounds at every stage after the first, and the terminal constraints on x_N.
dynamics takes the state and the control, two vectors, and returns the next state. The stage
cost and the path constraints take the same two, and the terminal cost and constraints take the
state. A Function's further inputs are matched by name across Functions: a name in
global_vars is a decision variable shared by every stage, a name in stage_params a
parameter with one row per stage, N + 1 of them, and any other name a parameter. path and
terminal each take one StageConstraint or a sequence of them. x_bounds and
u_bounds are (lo, hi) pairs, each side None, a number or an array.
problem() and stage_problem() lower it to a Problem, and pack and unpack
convert between trajectories and their variables.
problem ¶
The general form: variables z of shape (N, nx + nu), one row [x_k, u_k] per stage,
x_N, then each global variable, shared by every stage.
stage_problem ¶
The stage form: each global variable becomes part of the state, held constant from stage to stage, so every stage depends on its own variables only. The problem records the sizes of its stages and its stage Functions for the solvers that read them.
pack ¶
The variables of problem(), or of stage_problem(), for states xs of shape
(N + 1, nx), controls us of shape (N, nu) and one value per global variable. Each
broadcasts, so pack(x0, 0.0) holds the initial state with zero controls.
unpack ¶
(xs, us, *global values) from the variables of problem(), or of stage_problem(),
taking the global variables from its last stage.
StageConstraint
dataclass
¶
The constraint lo <= fn(...) <= hi on one stage.
fn takes the state and the control for a path constraint, which holds at every stage before
the last, and the state alone for a terminal constraint. Its further inputs are matched by name, as
for the costs. A side is None, a number, or an array of the output's size, and lo == hi
makes an equality.
Source code in src/scaly/solvers/ocp.py
Solver selection¶
solver ¶
solver(problem: Problem[SV, NV, SP, NP], backend: str, /, *, name: str | None = None, options: dict[str, Any] | None = None) -> Solver[SV, NV, SP, NP]
Build a typed Solver for one backend-free problem.
Options are checked at construction. Runtime tuning is supplied to each numerical
call and shares the generated module and cache entry. PIQP's sparse and SQP's
qp select a fixed compiled matrix interface.
Source code in src/scaly/solvers/solver.py
Solver
dataclass
¶
A compiled solver called with its parameters. The initial point and multipliers default to zero.
function is the plain Function with the full five-group signature, for code generation
and symbolic composition. Its four outputs are its first four
inputs, so passing a previous result as warm warm-starts the next call.
Source code in src/scaly/solvers/solver.py
solver_loadable ¶
Return whether the discovered solver can be dlopened and has headers for JIT/AOT codegen.
Source code in src/scaly/solvers/paths.py
SolverLibraryError ¶
Bases: ToolchainError
Raised when a solver's shared library or C headers cannot be located or loaded.
Compiling or calling a function that reaches the solver raises it. The message lists the
locations searched, as scaly_toolchain reports them.
Source code in src/scaly/solvers/paths.py
qp_problem ¶
qp_problem(n: int, n_eq: int, n_ineq: int) -> Problem[Expr, np.ndarray, QPData[Expr], QPData[np.ndarray]]
Return the typed matrix-data form of a quadratic problem.
Source code in src/scaly/solvers/qp.py
NotQuadratic ¶
Plugin interfaces¶
These are the names a solver plugin builds on. Solver plugins explains how they fit together.
SolverBackend ¶
Bases: Protocol
The full solver plugin protocol: packaging metadata plus the C wrapper template. Solves always run through the generated C wrapper, and plugins ship no Python solve path.
Source code in src/scaly/solvers/registry.py
prepare_options ¶
Validate options, supply defaults, and split compilation choices from runtime tuning.
render_wrapper ¶
Emit the C wrapper for one solver ConcreteFunction (see docs/dev/solver_plugins.md).
Must define static void <ctx.raw_symbol>(...) with the descriptor's
in*/out* signature followed by double* w and one option-array pointer,
drive the solver's
C API with the oracle kernels (ctx.raw_symbol_of), and fill
ctx.stats_symbol on every call.
Source code in src/scaly/solvers/registry.py
NlpSolverBackend ¶
Bases: SolverBackend, Protocol
Solver backend protocol for NLP plugins, including Hessian layout and stage oracles.
Source code in src/scaly/solvers/registry.py
SolverWrapperCtx
dataclass
¶
Codegen kit handed to a plugin's render_wrapper hook.
symbol is the solver's mangled C identifier (prefix for any static the
template declares), raw_symbol the function the template must define,
stats_symbol the scaly_solver_stats static it must fill (declared by
core, one per solver). raw_symbol_of resolves the C symbol of an oracle
/ derivative ConcreteFunction from the descriptor.
Source code in src/scaly/codegen/solver.py
SolverDescriptor
dataclass
¶
Everything a solver plugin's generated C wrapper needs to drive a solve.
The solver Function retains this record for runtime options and statistics.
stage_layout
cached
property
¶
The supplied stage layout, or a layout detected and checked on first access.
StageLayout
dataclass
¶
State/control sizes and original constraint rows for stages 0..N.
Variables are ordered [x_0, u_0, ..., x_N, u_N]. dynamics[k] contains
the nx[k+1] equality rows into stage k+1, in next-state order.
eq[k] and ineq[k] contain the remaining constraints of stage k.
All row indices refer to the stacked [equalities; inequalities] vector.
The number of local constraints is the length of the corresponding tuple.
Next-state Jacobian blocks are structurally diagonal, without a guarantee
about their coefficients.
Source code in src/scaly/solvers/stages.py
StageOracles
dataclass
¶
Mapped dense derivatives in recorded stage order, with row-major stage blocks.
grad returns the stacked objective gradient. jac returns the dynamics,
initial, path and terminal Jacobians, each in local [x, u] order.
hess takes the objective scale and stacked constraint multipliers after the
ordinary inputs. It returns stage and terminal Lagrangian blocks, each a dense
Hessian followed by its gradient row. A stage excludes the incoming transition's
linear -xnext term. Box bounds are handled by the plugin.
Source code in src/scaly/solvers/model.py
ExternalOracle
dataclass
¶
A C-ABI oracle supplied by a plugin consumer instead of an Scaly graph.
source must define raw_symbol with the same flat-buffer convention
as generated Scaly kernels: one const double* per input, one double*
per output, and a trailing double* workspace argument. workspace_size
declares the number of doubles available through that final argument.
Source code in src/scaly/solvers/model.py
descriptor_function ¶
descriptor_function(descriptor: SolverDescriptor, input_tree: Tree[Any, Any] | None = None, output_tree: Tree[Any, Any] | None = None) -> Function[Any, Any, Any, Any]
Build a Function calling the plugin's concrete extern bridge.
Source code in src/scaly/solvers/model.py
Statistics¶
SolverStats
dataclass
¶
The statistics of one numerical solve, as returned by Solver.stats().
The fields mirror the generated scaly_solver_stats struct, whose layout and meaning are
described on the generated-interface page of How it works. Diagnostics
a backend does not report are zero.
Source code in src/scaly/solvers/stats.py
to_solver_status ¶
Summarize these statistics. ok holds for OK and ACCEPTABLE.
Source code in src/scaly/solvers/stats.py
SolverStatus
dataclass
¶
A short solve summary from SolverStats.to_solver_status(): the status, iterations and oracle evaluation counts.
Source code in src/scaly/solvers/stats.py
ScalySolveStatus ¶
Bases: IntEnum
Backend-neutral solve outcome, as reported in the generated statistics struct.
Each backend maps its own native status onto these, so calling code does not have to know
which solver ran. OK and ACCEPTABLE are the successful ones.
Source code in src/scaly/solvers/stats.py
Graph queries¶
is_solver_function ¶
Return whether fun is a solver's own concrete graph.
solver_callees ¶
Return the inner Functions a solver ConcreteFunction depends on at codegen time.