Optimization

Mathematical programs: the finite-dimensional NLP, and the result an optimizer returns.

class minilink.optimization.mathematical_program.MathematicalProgram(n_z, J, h=None, g=None, lower=None, upper=None, grad_J=None, hess_J=None, jac_h=None, jac_g=None, backend='numpy', metadata=<factory>)[source]

Pure finite-dimensional nonlinear program description.

The generic form is the textbook NLP minimize J(z) subject to h(z) = 0, g(z) >= 0, and optional box bounds lower <= z <= upper. The program stores pure callables of the decision vector z and no solver state such as an initial guess; backend casting, JAX compilation and SciPy-friendly wrappers live on the program evaluators the optimizers own.

Native function contract

The mathematical callables are backend-native functions. With NumPy input, they should return NumPy scalar/array expressions; with JAX input, they should return JAX scalar/array expressions. Do not cast with float(...) or force NumPy arrays inside these functions if JAX tracing may be used.

Shapes are:

J : (n_z,) -> scalar (0-D scalar expression), h : (n_z,) -> (n_h,), g : (n_z,) -> (n_g,).

param n_z:

Dimension of the decision vector z.

type n_z:

int

param J:

Objective function J(z) -> scalar. The input and output should stay native to the active array backend: with NumPy input, return a NumPy scalar expression; with JAX input, return a JAX scalar expression. Prefer code like return z @ z over return float(z @ z).

type J:

callable

param h:

Equality residual h(z) -> array with shape (n_h,). The returned array should be native to the active backend. Missing means no equalities.

type h:

callable, optional

param g:

Inequality margin g(z) -> array with shape (n_g,) and convention g(z) >= 0. The returned array should be native to the active backend. Missing means no inequalities.

type g:

callable, optional

param lower:

Lower and upper box bounds on z. None means unbounded on that side.

type lower:

array_like, optional

param upper:

Lower and upper box bounds on z. None means unbounded on that side.

type upper:

array_like, optional

param grad_J:

Objective gradient grad_J(z) -> array with shape (n_z,).

type grad_J:

callable, optional

param hess_J:

Objective Hessian hess_J(z) -> array with shape (n_z, n_z).

type hess_J:

callable, optional

param jac_h:

Constraint Jacobians dh/dz and dg/dz with shapes (n_h, n_z) and (n_g, n_z).

type jac_h:

callable, optional

param jac_g:

Constraint Jacobians dh/dz and dg/dz with shapes (n_h, n_z) and (n_g, n_z).

type jac_g:

callable, optional

param backend:

Native array backend of the callables ("numpy" or "jax") — the program-evaluator backend they should be compiled with.

type backend:

str

param metadata:

Optional transcription or diagnostic metadata.

type metadata:

dict

Parameters:
  • n_z (int)

  • J (Callable[[Any], Any])

  • h (Callable[[Any], Any] | None)

  • g (Callable[[Any], Any] | None)

  • lower (ndarray | None)

  • upper (ndarray | None)

  • grad_J (Callable[[Any], Any] | None)

  • hess_J (Callable[[Any], Any] | None)

  • jac_h (Callable[[Any], Any] | None)

  • jac_g (Callable[[Any], Any] | None)

  • backend (str)

  • metadata (dict[str, object])

class minilink.optimization.mathematical_program.OptimizationResult(z, success, cost=None, message='', stats=<factory>, raw_result=None, solve_time_s=None)[source]

Result returned by an Optimizer.

Parameters:
  • solve_time_s (float, optional) – Wall-clock time in seconds for the backend solver only, when the caller requested timing on solve() (record_solve_time=True) or a summary report (verbose=True). None means not measured.

  • z (ndarray)

  • success (bool)

  • cost (float | None)

  • message (str)

  • stats (dict[str, object])

  • raw_result (object | None)

The optimizer: one mathematical program, compiled once, solved by a method preset.

class minilink.optimization.optimizer.Optimizer(program, z0, *, method='scipy_slsqp', compile_backend=None, use_hessian=False, options=None, **method_kwargs)[source]

Bound optimizer for one mathematical program.

It owns the program, its compiled evaluator, a default initial guess z0 and a solver method preset; solve() runs the compiled program from z0 or a one-off override:

program = MathematicalProgram(n_z=2, J=J, grad_J=grad_J)
opt = Optimizer(program, z0=[0.0, 0.0], method="scipy_slsqp")
result = opt.solve(verbose=True)

An optional progress hook callback(z, J, t) on solve() receives t, the elapsed wall seconds; see OptimizationProgressCallback.

Parameters:
  • program (MathematicalProgram) – Pure NLP description to compile and solve.

  • z0 (array_like) – Default initial decision vector for solve().

  • method (str, optional) – Optimizer method preset. One of "scipy_slsqp", "scipy_trust_constr", or "ipopt".

  • compile_backend (str, optional) – Mathematical-program evaluator backend, "numpy" or "jax". Defaults to program.backend (the native backend of the program’s callables).

  • use_hessian (bool, optional) – For JAX program evaluators, auto-generate a dense objective Hessian when no hess_J is supplied.

  • options (dict, optional) – Solver options merged into the preset’s options dict (user keys win).

  • **method_kwargs – Extra keyword arguments override the preset’s top-level kwargs and are forwarded to the backend constructor.

solve(*, z0=None, callback=None, record_solve_time=False, verbose=False)[source]

Solve the bound finite-dimensional mathematical program.

Parameters:
  • z0 (array_like, optional) – One-off initial decision vector. If omitted, use the default z0 supplied to Optimizer.

  • record_solve_time (bool, optional) – If True, set solve_time_s to the wall-clock duration (seconds) of the backend solve only, measured with time.perf_counter().

  • callback (callable, optional) – If not None, called during the solve as callback(z, J, t): current decision z (1-D ndarray), objective \(J(z)\), and t elapsed wall time (seconds) since the backend solve started. Each invocation evaluates J(z) again (one extra objective call per iterate). Not supported by the Ipopt backend (native path); use SciPy or omit.

  • verbose (bool, optional) – If True, print the framed solve panel (preamble and report).

Return type:

OptimizationResult

Program evaluators: the solver-facing side of a mathematical program.

class minilink.optimization.evaluators.program_evaluator.MathematicalProgramEvaluator(program, sample_z=None)[source]

Base class for compiled mathematical-program evaluators.

The solver-facing counterpart of a pure MathematicalProgram: it owns backend-specific validation, scalar conversion, residual flattening, and derivative availability. Subclasses provide backend-native J / h / g methods. The base class defines SciPy/Ipopt bridge helpers that convert native scalar and array expressions to Python float / flat NumPy arrays.

Parameters:

program (MathematicalProgram)

abstract J(z)[source]

Return backend-native objective scalar expression J(z).

abstract h(z)[source]

Return backend-native equality residual array h(z).

abstract g(z)[source]

Return backend-native inequality margin array g(z).

property has_gradient: bool

True when gradient() can be called.

property has_hessian: bool

True when hessian() can be called.

property has_jacobian_h: bool

True when jacobian_h() can be evaluated.

Note this means “callable”, not “analytic derivatives exist”: with no equality constraints the empty (0, n_z) Jacobian is always available. Backends with analytic/AD derivatives override this.

property has_jacobian_g: bool

True when jacobian_g() can be evaluated (see has_jacobian_h).

objective(z)[source]

Return J(z) as a Python float for optimizer backends.

Return type:

float

equality_residual(z)[source]

Return h(z) as a flat NumPy residual vector.

Return type:

ndarray

inequality_margin(z)[source]

Return g(z) as a flat NumPy nonnegative margin vector.

Return type:

ndarray

constraint_violations(z)[source]

Constraint-violation summary of a solution z.

Returns:

  • eq_inf (float) – Max absolute equality residual (0.0 when there are no equalities).

  • min_ineq (float or None) – Smallest inequality margin (negative = violated); None when there are no inequality constraints.

  • bound_inf (float) – Max box-bound violation (0.0 when within bounds or unbounded).

Return type:

tuple[float, float | None, float]

gradient(z)[source]

Return objective gradient dJ/dz or raise if unavailable.

Return type:

ndarray

hessian(z)[source]

Return objective Hessian d2J/dz2 or raise if unavailable.

Return type:

ndarray

jacobian_h(z)[source]

Return equality Jacobian dh/dz.

Return type:

ndarray

jacobian_g(z)[source]

Return inequality Jacobian dg/dz.

Return type:

ndarray

scipy_bounds()[source]

Return SciPy minimize bounds or None.

The NumPy program evaluator: a mathematical program evaluated as given, with the derivatives it supplies.

class minilink.optimization.evaluators.numpy_evaluator.NumpyMathematicalProgramEvaluator(program, sample_z=None)[source]

Solver-facing NumPy program evaluator for MathematicalProgram.

This program evaluator does not create finite-difference derivatives. It exposes only derivative callables supplied on the program.

Parameters:

program (MathematicalProgram)

property has_gradient: bool

True when gradient() can be called.

property has_hessian: bool

True when hessian() can be called.

property has_jacobian_h: bool

True when jacobian_h() can be evaluated.

Note this means “callable”, not “analytic derivatives exist”: with no equality constraints the empty (0, n_z) Jacobian is always available. Backends with analytic/AD derivatives override this.

property has_jacobian_g: bool

True when jacobian_g() can be evaluated (see has_jacobian_h).

J(z)[source]

Return backend-native objective scalar expression J(z).

h(z)[source]

Return backend-native equality residual array h(z).

g(z)[source]

Return backend-native inequality margin array g(z).

gradient(z)[source]

Return objective gradient dJ/dz or raise if unavailable.

Return type:

ndarray

hessian(z)[source]

Return objective Hessian d2J/dz2 or raise if unavailable.

Return type:

ndarray

jacobian_h(z)[source]

Return equality Jacobian dh/dz.

Return type:

ndarray

jacobian_g(z)[source]

Return inequality Jacobian dg/dz.

Return type:

ndarray

The JAX program evaluator: a mathematical program JIT-compiled, its missing derivatives by autodiff.

class minilink.optimization.evaluators.jax_evaluator.JaxMathematicalProgramEvaluator(program, sample_z=None, *, use_hessian=False, verbose=False)[source]

JIT-compiled program evaluator for MathematicalProgram.

JAX is imported lazily. The program evaluator JIT-compiles J / h / g, auto-generates grad_J and constraint Jacobians when not supplied, and only auto-generates a dense objective Hessian when use_hessian=True.

Parameters:
property has_gradient: bool

True when gradient() can be called.

property has_hessian: bool

True when hessian() can be called.

property has_jacobian_h: bool

True when jacobian_h() can be evaluated.

Note this means “callable”, not “analytic derivatives exist”: with no equality constraints the empty (0, n_z) Jacobian is always available. Backends with analytic/AD derivatives override this.

property has_jacobian_g: bool

True when jacobian_g() can be evaluated (see has_jacobian_h).

J(z)[source]

Return backend-native objective scalar expression J(z).

h(z)[source]

Return backend-native equality residual array h(z).

g(z)[source]

Return backend-native inequality margin array g(z).

gradient(z)[source]

Return objective gradient dJ/dz or raise if unavailable.

Return type:

ndarray

hessian(z)[source]

Return objective Hessian d2J/dz2 or raise if unavailable.

Return type:

ndarray

jacobian_h(z)[source]

Return equality Jacobian dh/dz.

Return type:

ndarray

jacobian_g(z)[source]

Return inequality Jacobian dg/dz.

Return type:

ndarray

Optimizer backends: the contract of an adapter to a third-party solver.

class minilink.optimization.optimizers.optimizer_backend.OptimizerBackend[source]

Pure adapter contract for a finite-dimensional optimizer backend.

Concrete subclasses adapt a compiled MathematicalProgramEvaluator to a third-party solver such as SciPy or Ipopt. The user-facing minilink.optimization.optimizer.Optimizer owns program compilation, timing, diagnostics, and default initial guesses.

abstract solve(program_evaluator, z0, *, callback=None)[source]

Run the backend solver from z0.

Parameters:
Return type:

OptimizationResult

minilink.optimization.optimizers.optimizer_backend.scipy_constraints_of(program_evaluator)[source]

The program’s constraints in SciPy’s dict form, as SciPy and Ipopt take them.

Equalities h(z) = 0 as one "eq" entry and inequalities g(z) ≥ 0 as one "ineq" entry, each with its Jacobian when the evaluator has one; an empty kind is left out.

Parameters:

program_evaluator (MathematicalProgramEvaluator)

Return type:

list

The SciPy backend: a compiled program solved by scipy.optimize.minimize().

class minilink.optimization.optimizers.scipy_minimize.ScipyMinimizeOptimizer(scipy_method='SLSQP', options=None)[source]

Optimizer adapter for scipy.optimize.minimize().

Equality constraints are passed as type='eq' residuals and inequality constraints as type='ineq' nonnegative margins, matching Minilink’s mathematical-program convention.

solve(program_evaluator, z0, *, callback=None)[source]

Solve program_evaluator with SciPy and return a backend-neutral result.

Parameters:
Return type:

OptimizationResult