Solver configuration#
- class jaxls.TrustRegionConfig[source]#
TrustRegionConfig(lambda_initial: ‘float | jax.Array’ = 0.0005, lambda_factor: ‘float | jax.Array’ = 2.0, lambda_min: ‘float | jax.Array’ = 1e-05, lambda_max: ‘float | jax.Array’ = 1000000.0, step_quality_min: ‘float | jax.Array’ = 0.001)
- class jaxls.TerminationConfig[source]#
TerminationConfig(max_iterations: ‘jdc.Static[int]’ = 100, early_termination: ‘jdc.Static[bool]’ = True, cost_tolerance: ‘float | jax.Array’ = 1e-05, gradient_tolerance: ‘float | jax.Array’ = 0.0001, gradient_tolerance_start_step: ‘int | jax.Array’ = 10, parameter_tolerance: ‘float | jax.Array’ = 1e-06)
- max_iterations: Annotated[int, '__jax_dataclasses_static_field__'] = 100#
Maximum number of optimization steps. For constrained problems, this is the maximum iterations per inner solve (not total iterations).
- early_termination: Annotated[bool, '__jax_dataclasses_static_field__'] = True#
If set to True, terminate when any of the tolerances are met. If False, always run max_iterations steps.
- cost_tolerance: float | Array = 1e-05#
We terminate if |cost change| / cost < cost_tolerance. For constrained problems, this acts as a floor for the adaptive inner solver tolerance.
- gradient_tolerance: float | Array = 0.0001#
We terminate if norm_inf(x - rplus(x, linear delta)) < gradient_tolerance. For constrained problems, this acts as a floor for the adaptive inner solver tolerance.
- class jaxls.ConjugateGradientConfig[source]#
Iterative solver for sparse linear systems. Can run on CPU or GPU.
For inexact steps, we use the Eisenstat-Walker criterion. For reference, see “Choosing the Forcing Terms in an Inexact Newton Method”, Eisenstat & Walker, 1996.”
- eisenstat_walker_gamma: float | Array = 0.9#
Eisenstat-Walker criterion gamma term. Controls how quickly the tolerance decreases. Typical values range from 0.5 to 0.9. Higher values lead to more aggressive tolerance reduction.
- class jaxls.AugmentedLagrangianConfig[source]#
Configuration for Augmented Lagrangian solver (ALGENCAN-style).
- penalty_initial: float | Array | None = None#
Initial penalty parameter. If None, uses ALGENCAN-style heuristic:
rho = 10 * max(1, |f|) / max(1, 0.5 * c^2). Set to a fixed value (e.g., 1.0) to override the automatic initialization.
- tolerance_absolute: float | Array = 1e-05#
max(snorm, csupn) < tol.- Type:
Absolute convergence tolerance
- tolerance_relative: float | Array = 0.0001#
snorm / snorm_initial < tol.- Type:
Relative convergence tolerance
Instrumentation#
- jaxls.record_iteration_times() Iterator[list[float]][source]#
Record a host wall-clock timestamp at each outer LM iteration of any solve() running in this block, for cost-vs-time benchmarking.
Returns a list that is filled with time.perf_counter() values (one per outer iteration, in order); times[i] - times[0] is the elapsed time to reach iteration i. Off the normal solve path entirely — the timestamps never enter the jitted computation or SolveSummary, so there is zero overhead and no dtype dependence when not recording, and the values are always host float64 (the in-array alternative would be float32 without jax_enable_x64, too coarse to resolve millisecond steps).
Timestamps include async-dispatch latency, so read differences, not absolute values, and wrap the solve in block_until_ready for precise totals. Not reentrant / not for concurrent solves from multiple threads (one active recorder at a time):
with jaxls.record_iteration_times() as times: sol = problem.solve(init) # times[1:] - times[0] -> per-iteration elapsed seconds
The recording callback is decided at trace time, so whether timestamps are captured is baked into the compiled solve. Entering and leaving this block therefore clears the solver’s JIT cache, so the first solve inside it recompiles with the callback (even if an identical solve was already compiled without one) and the first solve after it recompiles without. The compile inside the block also acts as the warmup; for steady-state timing, run the solve twice in the block and read the second:
with jaxls.record_iteration_times() as times: jax.block_until_ready(problem.solve(init)) # warmup, compiles times.clear() sol = jax.block_until_ready(problem.solve(init))