Optimization API Reference¶
Overview¶
The Opifex optimization module provides full optimization algorithms and meta-learning approaches for scientific computing, including production optimization, learn-to-optimize algorithms, control systems, and quantum-aware optimization.
Core Optimization Components¶
Meta-Optimization Framework¶
Advanced meta-optimization algorithms that learn to optimize across families of related problems.
Meta-optimization algorithms for scientific machine learning.
This package implements meta-learning approaches to optimization including learn-to-optimize (L2O) algorithms, adaptive learning rate scheduling, warm-starting strategies, and performance monitoring. All implementations follow FLAX NNX patterns and are designed for scientific computing applications.
Key Features
- Learn-to-optimize (L2O) meta-learning algorithms
- Adaptive learning rate scheduling with multiple strategies
- Warm-starting based on problem similarity
- Performance monitoring and analytics
- Quantum-aware optimization adaptations
- Integration with existing training infrastructure
Author: Opifex Framework Team Date: December 2024 License: MIT
MetaOptimizerConfig
dataclass
¶
MetaOptimizerConfig(*, meta_algorithm: str = 'l2o', base_optimizer: str = 'adam', meta_learning_rate: float = 0.0001, adaptation_steps: int = 10, warm_start_strategy: str = 'previous_params', performance_tracking: bool = True, memory_efficient: bool = True, quantum_aware: bool = False, scf_adaptation: bool = False, energy_convergence_tracking: bool = False, chemical_accuracy_target: float = 0.001)
Configuration for meta-optimization algorithms.
This configuration class defines all parameters for meta-optimization including algorithm selection, adaptation strategies, and performance monitoring settings.
Attributes:
| Name | Type | Description |
|---|---|---|
meta_algorithm |
str
|
Meta-optimization algorithm ('l2o', 'adaptive_lr', 'warm_start') |
base_optimizer |
str
|
Base optimizer to enhance ('adam', 'sgd', 'rmsprop', 'adamw') |
meta_learning_rate |
float
|
Learning rate for meta-parameters |
adaptation_steps |
int
|
Number of steps for adaptation |
warm_start_strategy |
str
|
Strategy for warm-starting ('previous_params', 'similar_problems') |
performance_tracking |
bool
|
Enable performance monitoring |
memory_efficient |
bool
|
Use memory-efficient implementations |
quantum_aware |
bool
|
Enable quantum-specific adaptations |
scf_adaptation |
bool
|
Enable SCF convergence acceleration |
energy_convergence_tracking |
bool
|
Track energy convergence for quantum systems |
chemical_accuracy_target |
float
|
Target chemical accuracy (kcal/mol) |
MetaOptimizer
¶
MetaOptimizer(config: MetaOptimizerConfig, *, rngs: Rngs)
Integrated meta-optimization system.
This class provides a complete meta-optimization system that integrates learn-to-optimize algorithms, adaptive learning rate scheduling, warm-starting strategies, and performance monitoring.
Attributes:
| Name | Type | Description |
|---|---|---|
config |
Meta-optimizer configuration |
|
l2o_engine |
Learn-to-optimize engine |
|
learning_rate_scheduler |
Adaptive learning rate scheduler |
|
warm_start_strategy |
Warm-starting strategy |
|
performance_monitor |
Performance monitoring system |
|
current_step |
Current optimization step |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
MetaOptimizerConfig
|
Meta-optimizer configuration |
required |
rngs
|
Rngs
|
Random number generators |
required |
init_optimizer_state
¶
step
¶
step(loss_fn: Callable[[Array], Array], params: Array, opt_state: Any, step: int) -> tuple[Array, Any, dict[str, Any]]
Perform single meta-optimization step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
loss_fn
|
Callable[[Array], Array]
|
Loss function to optimize |
required |
params
|
Array
|
Current parameters |
required |
opt_state
|
Any
|
Current optimizer state |
required |
step
|
int
|
Current step number |
required |
Returns:
| Type | Description |
|---|---|
tuple[Array, Any, dict[str, Any]]
|
Tuple of (new_params, new_opt_state, meta_info) |
store_optimization_result
¶
get_warm_start_params
¶
quantum_step
¶
quantum_step(energy_fn: Callable[[Array], Array], orbital_coeffs: Array, opt_state: Any, scf_context: dict[str, Any], step: int) -> tuple[Array, Any, dict[str, Any]]
Perform quantum-aware meta-optimization step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
energy_fn
|
Callable[[Array], Array]
|
Energy function to minimize |
required |
orbital_coeffs
|
Array
|
Current orbital coefficients |
required |
opt_state
|
Any
|
Current optimizer state |
required |
scf_context
|
dict[str, Any]
|
SCF iteration context |
required |
step
|
int
|
Current step number |
required |
Returns:
| Type | Description |
|---|---|
tuple[Array, Any, dict[str, Any]]
|
Tuple of (new_coeffs, new_opt_state, quantum_info) |
PerformanceMonitor
¶
PerformanceMonitor(metrics: list[str] | None = None, window_size: int = 100, tracking_frequency: int = 1, convergence_tolerance: float = 1e-06, convergence_patience: int = 10, analytics_enabled: bool = False, quantum_aware: bool = False)
Performance monitoring and analytics for meta-optimization.
This class provides full performance monitoring capabilities including metric tracking, convergence detection, and performance analytics for optimization algorithms.
Attributes:
| Name | Type | Description |
|---|---|---|
metrics |
List of metrics to track |
|
window_size |
Size of rolling window for metrics |
|
tracking_frequency |
Frequency of metric updates |
|
convergence_tolerance |
Tolerance for convergence detection |
|
convergence_patience |
Patience for convergence detection |
|
analytics_enabled |
Enable detailed analytics |
|
quantum_aware |
Enable quantum-specific metrics |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metrics
|
list[str] | None
|
List of metrics to track |
None
|
window_size
|
int
|
Rolling window size |
100
|
tracking_frequency
|
int
|
How often to update metrics |
1
|
convergence_tolerance
|
float
|
Tolerance for convergence |
1e-06
|
convergence_patience
|
int
|
Patience for convergence detection |
10
|
analytics_enabled
|
bool
|
Enable detailed analytics |
False
|
quantum_aware
|
bool
|
Enable quantum metrics |
False
|
LearnToOptimize
¶
LearnToOptimize(meta_network_layers: list[int] | None = None, base_optimizer: str = 'adam', meta_learning_rate: float = 0.0001, unroll_steps: int = 20, adaptive_step_size: bool = False, quantum_aware: bool = False, scf_integration: bool = False, *, rngs: Rngs)
Bases: Module
Learn-to-optimize (L2O) meta-learning system.
This class implements learn-to-optimize algorithms that use neural networks to learn optimization strategies from data. The meta-network learns to predict good parameter updates based on gradient information and optimization history.
Attributes:
| Name | Type | Description |
|---|---|---|
meta_network |
Neural network for learning optimization rules |
|
base_optimizer |
Base optimization algorithm |
|
meta_learning_rate |
Learning rate for meta-network training |
|
unroll_steps |
Number of unrolling steps for meta-gradient computation |
|
adaptive_step_size |
Enable adaptive step size learning |
|
quantum_aware |
Enable quantum-specific adaptations |
|
scf_integration |
Enable SCF convergence acceleration |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
meta_network_layers
|
list[int] | None
|
Architecture of meta-network |
None
|
base_optimizer
|
str
|
Base optimizer to enhance |
'adam'
|
meta_learning_rate
|
float
|
Learning rate for meta-network training |
0.0001
|
unroll_steps
|
int
|
Number of unroll steps for meta-gradients |
20
|
adaptive_step_size
|
bool
|
Enable adaptive step size learning |
False
|
quantum_aware
|
bool
|
Enable quantum-specific optimizations |
False
|
scf_integration
|
bool
|
Enable SCF convergence acceleration |
False
|
rngs
|
Rngs
|
Random number generators for initialization |
required |
compute_update
¶
compute_update(gradient: Array, previous_updates: Array, loss_history: Array | None = None) -> Array
Compute parameter update using meta-network.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gradient
|
Array
|
Current gradient |
required |
previous_updates
|
Array
|
History of previous updates |
required |
loss_history
|
Array | None
|
History of loss values |
None
|
Returns:
| Type | Description |
|---|---|
Array
|
Predicted parameter update |
compute_meta_gradients
¶
compute_meta_gradients(loss_fn: Callable[[Array], Array], initial_params: Array) -> dict[str, Array]
Compute meta-gradients for meta-network training.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
loss_fn
|
Callable[[Array], Array]
|
Loss function for optimization problem |
required |
initial_params
|
Array
|
Initial parameters for optimization |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Array]
|
Meta-gradients for meta-network parameters |
compute_adaptive_update
¶
Compute adaptive parameter update.
compute_quantum_update
¶
AdaptiveLearningRateScheduler
¶
AdaptiveLearningRateScheduler(schedule_type: str = 'cosine_annealing', initial_lr: float = 0.001, final_lr: float = 1e-06, adaptation_period: int = 100, warmup_steps: int = 0, patience: int = 5, factor: float = 0.5, min_lr: float = 1e-08, **kwargs: Any)
Adaptive learning rate scheduling for meta-optimization.
This class implements various adaptive learning rate scheduling strategies including cosine annealing, performance-based adaptation, and quantum-aware scheduling for scientific applications.
Attributes:
| Name | Type | Description |
|---|---|---|
schedule_type |
Type of scheduling algorithm |
|
initial_lr |
Initial learning rate |
|
final_lr |
Final learning rate (for annealing schedules) |
|
adaptation_period |
Period for adaptation cycles |
|
warmup_steps |
Number of warmup steps |
|
patience |
Patience for performance-based adaptation |
|
factor |
Factor for learning rate reduction |
|
min_lr |
Minimum learning rate |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
schedule_type
|
str
|
Type of scheduling ('cosine_annealing', 'performance_based', 'quantum_aware') |
'cosine_annealing'
|
initial_lr
|
float
|
Initial learning rate |
0.001
|
final_lr
|
float
|
Final learning rate |
1e-06
|
adaptation_period
|
int
|
Period for complete adaptation cycle |
100
|
warmup_steps
|
int
|
Number of warmup steps |
0
|
patience
|
int
|
Patience for performance-based adaptation |
5
|
factor
|
float
|
Reduction factor for learning rate |
0.5
|
min_lr
|
float
|
Minimum allowed learning rate |
1e-08
|
**kwargs
|
Any
|
Additional scheduler-specific parameters |
{}
|
WarmStartingStrategy
¶
WarmStartingStrategy(strategy_type: str = 'parameter_transfer', similarity_threshold: float = 0.8, adaptation_steps: int = 5, memory_size: int = 10, adaptation_ratio: float = 0.9, similarity_metric: str = 'cosine', min_similarity: float = 0.7)
Warm-starting strategies for optimization acceleration.
This class implements various warm-starting strategies to accelerate optimization by leveraging information from previous optimizations or similar problems.
Attributes:
| Name | Type | Description |
|---|---|---|
strategy_type |
Type of warm-starting strategy |
|
similarity_threshold |
Threshold for problem similarity |
|
adaptation_steps |
Steps for parameter adaptation |
|
memory_size |
Size of optimization memory |
|
adaptation_ratio |
Ratio for optimizer state adaptation |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
strategy_type
|
str
|
Strategy type ('parameter_transfer', 'optimizer_state_transfer', 'molecular_similarity') |
'parameter_transfer'
|
similarity_threshold
|
float
|
Threshold for considering problems similar |
0.8
|
adaptation_steps
|
int
|
Number of adaptation steps |
5
|
memory_size
|
int
|
Maximum number of previous optimizations to remember |
10
|
adaptation_ratio
|
float
|
Ratio for adapting previous states |
0.9
|
similarity_metric
|
str
|
Metric for similarity computation |
'cosine'
|
min_similarity
|
float
|
Minimum similarity for warm-starting |
0.7
|
get_warm_start_params
¶
Get warm-start parameters based on parameter transfer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
previous_params
|
Array
|
Parameters from previous optimization |
required |
current_problem_features
|
Array
|
Features of current problem |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Warm-start parameters for current problem |
adapt_optimizer_state
¶
get_molecular_warm_start
¶
get_molecular_warm_start(previous_fingerprints: Array, previous_params: Array, current_fingerprint: Array) -> Array
Get warm-start parameters based on molecular similarity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
previous_fingerprints
|
Array
|
Fingerprints of previous molecules |
required |
previous_params
|
Array
|
Parameters for previous molecules |
required |
current_fingerprint
|
Array
|
Fingerprint of current molecule |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Warm-start parameters based on most similar molecule |
Production Optimization¶
Optimization systems for deployment and scaling in production environments.
Production optimisation for the Opifex framework.
The :class:HybridPerformancePlatform combines adaptive JIT compilation
(:class:AdaptiveJAXOptimizer), GPU memory-pool planning
(:class:IntelligentGPUMemoryManager), and physics/numerical validation
(:class:~opifex.optimization.scientific_integration.ScientificComputingIntegrator) into a
single production-optimisation pass. Serving telemetry, autoscaling, and edge/deployment
orchestration are out of scope (owned by external infrastructure such as KServe / Ray Serve /
k8s HPA / Prometheus).
WorkloadProfile
dataclass
¶
WorkloadProfile(batch_size: int, sequence_length: int, memory_footprint: float, compute_intensity: float, latency_requirement: float, throughput_requirement: float, model_complexity: str)
Profiling data for production workloads.
PerformanceMetrics
dataclass
¶
PerformanceMetrics(*, latency_ms: float, throughput_rps: float, memory_usage_gb: float, improvement_factor: float)
Measured performance metrics for an optimized model.
All fields are directly measured. GPU utilization and energy efficiency are intentionally omitted: measuring them requires device/power telemetry (e.g. NVML) that is not a dependency of this framework, so they cannot be reported here as measurements.
OptimizedModel
dataclass
¶
OptimizedModel(*, model: Module, optimization_type: OptimizationStrategy, performance_metrics: PerformanceMetrics, optimization_metadata: dict[str, Any])
Container for optimized model with performance metadata.
AdaptiveJAXOptimizer
¶
AdaptiveJAXOptimizer(performance_threshold: float = 1.1, memory_efficiency_target: float = 0.85, cache_size: int = 100)
Bases: Module
Adaptive JIT optimization for JAX-based neural operators.
This class implements intelligent JIT compilation strategies based on workload patterns, providing optimal performance for production deployments.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
performance_threshold
|
float
|
Minimum performance improvement factor to accept optimization |
1.1
|
memory_efficiency_target
|
float
|
Target memory efficiency (0-1 scale) |
0.85
|
cache_size
|
int
|
Number of optimization strategies to cache |
100
|
analyze_workload_patterns
¶
analyze_workload_patterns(workload: WorkloadProfile) -> OptimizationStrategy
Analyze workload to select optimal optimization strategy.
apply_aggressive_kernel_fusion
¶
Apply aggressive kernel fusion for compute-intensive workloads.
apply_memory_optimization
¶
Apply memory optimization for large models.
apply_latency_optimization
¶
Apply latency optimization for real-time inference.
apply_balanced_optimization
¶
Apply balanced optimization for general workloads.
benchmark_model_performance
¶
benchmark_model_performance(model: Module, workload: WorkloadProfile, improvement_factor: float = 1.0) -> PerformanceMetrics
Benchmark a single model on the given workload.
Latency is measured by timing repeated forward passes; throughput is
derived from that latency. Memory usage is estimated from the workload
footprint. improvement_factor defaults to 1.0 (no baseline to
compare against in a single-model benchmark) and should be supplied by
the caller when a measured baseline latency is available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Module
|
Model to benchmark. |
required |
workload
|
WorkloadProfile
|
Workload profile defining batch size and footprint. |
required |
improvement_factor
|
float
|
Measured speedup relative to a baseline model
(baseline_latency / this_latency); |
1.0
|
Returns:
| Type | Description |
|---|---|
PerformanceMetrics
|
Measured performance metrics for the model. |
optimize_neural_operator
¶
optimize_neural_operator(model: Module, workload: WorkloadProfile) -> OptimizedModel
Optimize neural operator for production workload.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Module
|
Neural operator model to optimize |
required |
workload
|
WorkloadProfile
|
Workload profile for optimization |
required |
Returns:
| Type | Description |
|---|---|
OptimizedModel
|
OptimizedModel with performance improvements |
IntelligentGPUMemoryManager
¶
IntelligentGPUMemoryManager(fragmentation_threshold: float = 0.15, gc_trigger_threshold: float = 0.85, pool_sizes: dict[str, tuple[int, int]] | None = None)
Bases: Module
Advanced GPU memory management for production workloads.
Implements intelligent allocation, fragmentation prevention, and multi-model inference optimization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fragmentation_threshold
|
float
|
Maximum acceptable fragmentation (0-1) |
0.15
|
gc_trigger_threshold
|
float
|
Memory usage threshold to trigger GC (0-1) |
0.85
|
pool_sizes
|
dict[str, tuple[int, int]] | None
|
Memory pool sizes as {pool_name: (min_size_mb, max_size_mb)} |
None
|
HybridPerformancePlatform
¶
HybridPerformancePlatform(jit_optimizer: AdaptiveJAXOptimizer | None = None, memory_manager: IntelligentGPUMemoryManager | None = None, scientific_integrator: ScientificComputingIntegrator | None = None, physics_domain: PhysicsDomain = GENERAL, target_latency_ms: float = 0.5)
Bases: Module
Production optimisation orchestrator: JIT, GPU memory, and scientific validation.
Combines the three genuine optimisation components — :class:AdaptiveJAXOptimizer
(jax.jit kernel fusion), :class:IntelligentGPUMemoryManager (memory-pool planning), and
:class:~opifex.optimization.scientific_integration.ScientificComputingIntegrator (physics /
numerical validation) — into a single production-optimisation pass. It does not perform
serving telemetry or autoscaling; those concerns belong to external infrastructure
(KServe / Ray Serve / k8s HPA / Prometheus).
optimize_for_production
¶
optimize_for_production(model: Module, workload: WorkloadProfile) -> OptimizedModel
Full production optimisation for a model: JIT, memory, and scientific validation.
get_model_input_features
¶
get_model_input_features(model: Module) -> int
Extract the correct input feature dimension from a model.
This utility function provides a robust way to determine the expected input dimension for any model, preventing dimension mismatch errors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Module
|
The model to inspect |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The input feature dimension |
Raises:
| Type | Description |
|---|---|
ValueError
|
If input features cannot be determined |
Scientific Computing Integration¶
Physics-aware optimization with scientific validation and benchmarking.
Scientific computing integration for Opifex production optimization.
This module implements physics-informed optimization, numerical validation, and conservation checking for the Version 7.4 Production Optimization system.
Part of: Hybrid Performance Platform + Intelligent Edge + Adaptive Optimization
PhysicsMetrics
dataclass
¶
PhysicsMetrics(*, domain: PhysicsDomain, conservation_violations: dict[ConservationLaw, float] = dict(), symmetry_preservation: float = 0.0, numerical_stability: float = 0.0, energy_conservation_error: float = 0.0, momentum_conservation_error: float = 0.0, mass_conservation_error: float = 0.0, unitarity_preservation: float = 0.0, thermodynamic_consistency: float = 0.0, boundary_condition_accuracy: float = 0.0)
Physics-specific performance metrics.
NumericalValidationResult
dataclass
¶
NumericalValidationResult(*, is_valid: bool, precision_score: float, stability_score: float, convergence_rate: float, condition_number: float, validation_errors: list[str] = list(), recommendations: list[str] = list())
Result of numerical validation.
ConservationCheckResult
dataclass
¶
ConservationCheckResult(*, law: ConservationLaw, is_conserved: bool, violation_magnitude: float, tolerance: float, relative_error: float, time_evolution_consistency: bool = True)
Result of conservation law checking.
ScientificBenchmarkResult
dataclass
¶
ScientificBenchmarkResult(*, benchmark_name: str, domain: PhysicsDomain, accuracy_score: float, reference_value: float, computed_value: float, relative_error: float, meets_accuracy_threshold: bool, chemical_accuracy: bool = False)
Result of scientific benchmark validation.
PhysicsProfilerProtocol
¶
Bases: Protocol
Protocol for physics profiling implementations.
profile_physics_metrics
¶
profile_physics_metrics(model_output: ndarray, reference_data: dict[str, Any]) -> PhysicsMetrics
Profile physics-specific metrics.
validate_domain_constraints
¶
validate_domain_constraints(model_output: ndarray, domain: PhysicsDomain) -> bool
Validate domain-specific constraints.
PhysicsProfiler
¶
PhysicsProfiler(domain: PhysicsDomain, validation_tolerances: dict[str, float] | None = None)
NumericalValidator
¶
Numerical precision and stability validator.
validate_numerical_precision
¶
validate_numerical_precision(computed_values: ndarray, reference_values: ndarray) -> NumericalValidationResult
Validate numerical precision against reference values.
check_conservation_law
¶
check_conservation_law(computed_quantity: ndarray, reference_quantity: ndarray, law: ConservationLaw, tolerance: float | None = None) -> ConservationCheckResult
Check specific conservation law.
ScientificBenchmarkValidator
¶
ScientificBenchmarkValidator(domain: PhysicsDomain)
ScientificComputingIntegrator
¶
ScientificComputingIntegrator(domain: PhysicsDomain, physics_profiler: PhysicsProfiler | None = None, numerical_validator: NumericalValidator | None = None, benchmark_validator: ScientificBenchmarkValidator | None = None)
Main integrator for scientific computing optimization.
translation_invariance_error
¶
Relative L2 discrepancy between a field and its periodic translation.
A translation-invariant field is unchanged by a periodic spatial shift, so shifting it and measuring the relative L2 difference yields ~0 for a constant or periodic field and a positive value for a field with spatial structure.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
field
|
Array
|
Spatial field to test for translation invariance. |
required |
shifts
|
tuple[int, ...]
|
Integer roll amount applied along each axis in |
required |
axes
|
tuple[int, ...]
|
Axes along which the periodic shift is applied. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Relative L2 discrepancy between the field and its shifted copy. |
Learn-to-Optimize (L2O) Algorithms¶
Advanced neural optimization methods that achieve significant speedups on learned problem families.
Tasks and the optimiser interface¶
Objective-carrying Task/TaskFamily abstractions and the shared stateful Optimizer
interface (with the optax-wrapped baseline family).
Core learn-to-optimize abstractions: tasks and the optimizer interface.
A learned optimizer is meta-trained to minimise a distribution of objectives. The
objective is carried by a :class:Task (an init for the optimisee parameters plus a
loss), and a :class:TaskFamily samples tasks for meta-generalisation. This mirrors the
canonical design in Google's learned_optimization library
(learned_optimization/tasks/base.py); see Andrychowicz et al. 2016
(arXiv:1606.04474) for the original learning-to-learn formulation.
The key contrast with the previous opifex L2O code is that the objective lives on the
task: optimisers and meta-trainers close over task.loss rather than guessing a
placeholder. Task.normalizer maps a raw loss onto a comparable scale so a meta-loss
aggregated across differently-conditioned tasks is not dominated by the worst-scaled task
(learned_optimization/tasks/base.py normalizer).
Task
¶
Bases: ABC
A single optimisation objective: init the params, evaluate loss.
Subclasses implement :meth:init (sample the initial optimisee parameters) and
:meth:loss (a scalar objective). :meth:normalizer defaults to the identity and
should be overridden when meta-training mixes tasks of very different loss scales.
TaskFamily
¶
single_task_to_family
¶
single_task_to_family(task: Task) -> TaskFamily
Lift a fixed :class:Task into a :class:TaskFamily (mirrors the reference).
Meta-training always consumes a family; this adapts a single task for the case where no task distribution is needed (e.g. overfitting a learned optimiser to one problem).
The optimiser interface shared by hand-designed and learned optimisers.
Mirrors learned_optimization/optimizers/base.py: an :class:Optimizer threads an opaque
state through init / update / get_params. Both an optax-wrapped hand-designed
optimiser (:class:OptaxOptimizer) and a meta-learned optimiser fit this interface, so they
are interchangeable at every call site. init accepts num_steps so horizon-aware
optimisers (e.g. learned optimisers conditioning on training fraction) know the unroll length;
update accepts the current loss because learned optimisers may consume it.
OptaxOptState
¶
Bases: PyTreeNode
Pytree state for :class:OptaxOptimizer (params + optax state + step count).
Optimizer
¶
Stateful optimiser interface (object-aware, not an optax.GradientTransformation).
The state is opaque to callers; use :meth:get_params to read the current optimisee
parameters. num_steps (at :meth:init) is the planned unroll length, surfaced for
horizon-aware optimisers; loss (at :meth:update) is the current objective value,
consumed by learned optimisers and ignored by hand-designed ones.
init
abstractmethod
¶
Initialise optimiser state for the given starting params.
update
abstractmethod
¶
update(state: StateT, grad: PyTree, *, loss: Array | None = None) -> StateT
Apply one optimiser step, returning the new state.
get_params
abstractmethod
¶
Read the current optimisee parameters from state.
OptaxOptimizer
¶
Bases: Optimizer[OptaxOptState]
Wraps any optax.GradientTransformation as an :class:Optimizer.
This is the hand-designed baseline family (SGD/Adam/...). num_steps/key are
accepted for interface uniformity and ignored; loss is ignored (optax updates depend
only on the gradient and optimiser state).
init
¶
init(params: PyTree, *, num_steps: int | None = None, key: Array | None = None) -> OptaxOptState
Initialise optax state around params.
update
¶
update(state: OptaxOptState, grad: PyTree, *, loss: Array | None = None) -> OptaxOptState
Apply the optax update and advance the iteration counter.
Concrete tasks¶
QuadraticTaskFamily (convex smoke task) and MLPTaskFamily (the non-convex small-MLP
training showcase task).
Concrete optimisation tasks and task families for L2O meta-training/meta-test.
QuadraticTask is the canonical L2O smoke task (a strictly convex quadratic with a known
optimum; cf. learned_optimization/tasks/quadratics.py). QuadraticTaskFamily samples
quadratics with varied conditioning so a meta-trained optimiser must generalise across
loss landscapes of different curvature/scale — the diversity that makes a meta-test on
held-out tasks meaningful (Wichrowska et al. 2017, arXiv:1703.04813).
MLPTask is the canonical L2O showcase task: a small multilayer perceptron trained by the
inner optimiser. It mirrors the MLPTask used throughout Google's learned_optimization
tutorials (docs/notebooks/no_dependency_learned_optimizer) — a genuinely non-convex
neural-network training objective, which is the regime where learned optimisers demonstrably
beat fixed-hyperparameter baselines (Metz et al. 2020, arXiv:2009.11243). To stay
self-contained (no dataset dependency) the data is a synthetic teacher-student regression: a
random teacher MLP generates targets from Gaussian inputs and the student fits them with MSE, so
the global optimum is realisable yet the landscape is non-convex.
QuadraticTask
dataclass
¶
QuadraticTask(matrix: Array, optimum: Array, init_scale: float = 1.0, loss_scale: Array | float = 1.0)
Bases: Task
Strictly convex quadratic f(x) = 0.5 (x - x*)^T A (x - x*) with SPD A.
Shapes: matrix is (dim, dim) SPD, optimum (x*) is (dim,). The unique
minimiser is optimum with f(x*) = 0. The objective is deterministic, so the
per-call key is unused.
QuadraticTaskFamily
dataclass
¶
Bases: TaskFamily
Quadratics with random optima and random SPD curvature of varied conditioning.
Each draw builds A = Q diag(eigs) Q^T with a random orthogonal Q and eigenvalues
log-uniformly spread over a sampled condition number in
[1, 10**max_log_condition] — so tasks differ in both scale and conditioning.
sample
¶
sample(key: Array) -> QuadraticTask
Draw a quadratic task: random SPD A, random optimum, matched loss scale.
MLPTask
dataclass
¶
MLPTask(inputs: Array, targets: Array, teacher_params: MLPParams, layer_sizes: tuple[int, ...], init_scale: float, loss_scale: Array, batch_size: int)
Bases: Task
Minibatch MLP regression onto a per-task teacher-generated dataset.
The student MLP (architecture layer_sizes) is fit by MSE to targets produced by a
random teacher MLP on inputs. Each :meth:loss call draws a fresh batch_size
minibatch using the supplied key (mirroring the reference MLPTask, which consumes a
new minibatch per step), so the gradients are stochastic — the regime where a learned
optimiser's implicit learning-rate schedule beats a fixed-step baseline. The objective is
non-convex in the student weights; the optimum (loss 0) is realised at teacher_params.
MLPTaskFamily
dataclass
¶
MLPTaskFamily(input_dim: int, hidden_dim: int, output_dim: int, num_data: int = 512, batch_size: int = 32, init_scale: float = 0.02, teacher_scale: float = 1.0)
Bases: TaskFamily
Teacher-student MLP regression tasks: random teacher + synthetic Gaussian data per draw.
Each draw samples a fresh teacher MLP and a fresh dataset, so a meta-trained optimiser must generalise across many non-convex training problems rather than memorise one (the diversity that makes the held-out meta-test meaningful). Gradients are stochastic minibatch gradients.
Learned optimisers¶
Coordinatewise learned optimisers (the per-parameter MLP of Metz et al. 2020) and their input features.
Per-parameter input features for learned optimisers.
Faithful re-implementation of the feature primitives in Google's
learned_optimization (learned_optimizers/common.py and
learned_optimizers/mlp_lopt.py). A coordinatewise learned optimiser consumes, per scalar
parameter: multi-timescale momentum and RMS EMAs of the gradient, the gradient and parameter
themselves (second-moment-normalised across the tensor), and a tanh embedding of the iteration
(training-fraction awareness). Feature design follows Metz et al. 2020 (arXiv:2009.11243).
These are pure functions on arrays; learned.py composes them into the per-parameter feature
vector fed to the optimiser MLP. Multi-decay EMAs carry the decay along a trailing axis.
init_ema
¶
Zero EMA buffer of shape grad.shape + (num_decays,).
update_momentum
¶
Multi-decay momentum EMA: m = decay*m + (1-decay)*grad (decay on the last axis).
update_rms
¶
Multi-decay second-moment EMA: rms = decay*rms + (1-decay)*grad**2.
second_moment_normalize
¶
Scale features to unit second moment along axis.
Matches mlp_lopt._second_moment_normalizer.
tanh_time_embedding
¶
Tanh embedding of the iteration over 11 timescales (mlp_lopt._tanh_embedding).
Returns a length-11 vector tanh(iteration / timescale - 1) — a smooth, bounded
encoding of training progress shared across all parameters of a tensor.
factored_dims
¶
Adafactor factoring dims: the two largest axes, or None if rank < 2.
Matches learned_optimizers/common.factored_dims: factored second-moment estimation only
applies to tensors of rank >= 2; for those it factors the two largest dimensions. Returns
(d1, d0) with d0 the largest axis (reduced for the row estimate) and d1 the
second-largest (reduced for the column estimate).
init_adafactor_accum
¶
Zeroed factored accumulators (v_row, v_col, v_diag) for one parameter tensor.
Decay is the leading axis. Rank->=2 tensors use (v_row, v_col) (the unused v_diag
is an empty placeholder); rank-<2 tensors use a diagonal v_diag (RMSProp-style),
mirroring common.factored_rolling.
update_adafactor_accum
¶
update_adafactor_accum(v_row: Array, v_col: Array, v_diag: Array, grad: Array, decays: Array) -> tuple[Array, Array, Array, Array, Array, Array, Array]
Update the factored accumulators and return Adafactor features for one tensor.
Faithful to common.factored_rolling / adafac_mlp_lopt._mod. Returns
(new_v_row, new_v_col, new_v_diag, fac_g, row_feat, col_feat, factor) where the four
feature arrays carry a trailing decay axis (grad.shape + (num_decays,)):
fac_g is the Adafactor-preconditioned gradient, row_feat/col_feat the raw row/column
second-moment estimates broadcast back to the tensor shape, and factor the
row_factor * col_factor preconditioner (the diagonal rsqrt in the non-factored case).
Coordinatewise learned optimisers (meta-learned update rules).
A :class:LearnedOptimizer carries meta-parameters theta and an opt_fn(theta) that
bakes theta into an :class:~opifex.optimization.l2o.optimizers.Optimizer. theta is a
plain pytree (the optimiser MLP's :class:flax.nnx state, obtained via nnx.split), so it
is directly perturbable/vmappable for evolution-strategies meta-training (PES).
:class:MLPLearnedOptimizer is the per-parameter MLP design of Metz et al. 2020
(arXiv:2009.11243; "LOLv2", learned_optimization/learned_optimizers/mlp_lopt.py): a tiny
MLP, shared across all scalar parameters, maps a 19-feature per-parameter vector to a
(direction, magnitude) pair, and the update is
step = direction * exp(magnitude * exp_mult) * step_mult. The richer Adafactor-feature
variant (adafac_mlp_lopt.py) extends the same scaffolding and is added on top of this base.
LearnedOptimizer
¶
Bases: ABC
A meta-learned optimiser: init samples theta; opt_fn(theta) applies it.
MLPLOptState
¶
Bases: PyTreeNode
Inner state for learned optimisers: optimisee params, momentum EMAs, iteration.
LearnableSGD
¶
LearnableSGD(initial_learning_rate: float = 0.1)
Bases: LearnedOptimizer
SGD with a single learnable log learning rate (learned_optimizers/base.LearnableSGD).
The simplest learned optimiser: theta is one scalar (log_lr). Useful as a
meta-training smoke optimiser and for validating the meta-gradient estimator, since the
full-unroll meta-gradient w.r.t. log_lr is analytically differentiable.
MLPLearnedOptimizer
¶
MLPLearnedOptimizer(hidden_size: int = 32, hidden_layers: int = 2, exp_mult: float = 0.001, step_mult: float = 0.001)
Bases: LearnedOptimizer
Per-parameter MLP learned optimiser (LOLv2; Metz et al. 2020).
theta is the MLP's nnx parameter state; opt_fn(theta) applies it coordinatewise
with the direction * exp(magnitude * exp_mult) * step_mult update.
AdafacMLPLOptState
¶
Bases: PyTreeNode
Inner state for the Adafactor-MLP lopt: params, momentum/RMS EMAs, factored accums, step.
mom/rms are multi-decay EMA trees; v_row/v_col/v_diag are the Adafactor
factored second-moment accumulators (one tree each, matching the params structure).
AdafacMLPLearnedOptimizer
¶
AdafacMLPLearnedOptimizer(hidden_size: int = 32, hidden_layers: int = 2, exp_mult: float = 0.001, step_mult: float = 0.001)
Bases: LearnedOptimizer
Adafactor-feature per-parameter MLP learned optimiser (adafac_mlp_lopt.py).
Extends :class:MLPLearnedOptimizer with Adafactor-style inputs — multi-decay RMS,
m * rsqrt(rms), rsqrt(rms), and factored row/column second-moment features (Metz et al.
2020). theta is the optimiser MLP's nnx state; the update head is the same
direction * exp(magnitude * exp_mult) * step_mult rule.
PES meta-training¶
Persistent Evolution Strategies meta-training (Vicol et al. 2021).
Meta-training of learned optimisers via Persistent Evolution Strategies (PES).
Meta-training searches for optimiser meta-parameters theta that minimise the inner task
loss accumulated over an unroll, across a distribution of tasks. Back-propagating through a long
inner unroll is biased (short truncations) or has exploding/chaotic gradients (long
truncations) — Metz et al. 2019 (arXiv:1810.10180). PES (Vicol, Metz & Sohl-Dickstein 2021,
arXiv:2112.13835) instead estimates the meta-gradient with antithetic Gaussian perturbations
of theta over short truncations, while keeping a persistent accumulator of the
perturbations across truncation boundaries so the estimate is unbiased w.r.t. the full-horizon
objective. Faithful to learned_optimization/outer_trainers/truncated_pes.py
(compute_pes_grad): es_grad = (1 / (2 std**2)) * delta_loss * accumulator.
This implementation runs num_tasks inner problems in parallel (jax.vmap). Each trajectory
is started at a random clock offset in [0, total_horizon)
(random_initial_iteration_offset in learned_optimization's lopt_truncated_step) and is
reset per inner step when its clock reaches total_horizon; the truncation's meta-gradient
is split at that reset (has_finished = cumsum(is_done) > 0) so the pre-reset losses attribute
to the full accumulator and the post-reset losses only to the new perturbation. Staggering the
truncations so the parallel tasks are not phase-aligned is load-bearing
(learned_optimization/outer_trainers/truncation_schedule.py): it removes the sawtooth that a
synchronous reset would imprint on the meta-loss and lowers the PES gradient variance.
PESState
¶
Bases: PyTreeNode
Persistent PES state, batched over num_tasks inner problems.
task_keys fixes which task each parallel trajectory optimises (so the persistent inner
state corresponds to a consistent task); inner_state is the batched inner optimiser
state; accumulator is the batched, theta-shaped sum of perturbations since the last
horizon reset; inner_step is the per-task inner-step count in the current trajectory
(shape (num_tasks,)) — per-task so resets stagger across the parallel trajectories.
pes_gradient_step
¶
pes_gradient_step(learned_optimizer: LearnedOptimizer, task_family: TaskFamily, theta: PyTree, pes_state: PESState, key: Array, *, std: float, trunc_length: int, total_horizon: int) -> tuple[Array, PyTree, PESState]
One PES truncation: return (mean_loss, meta_gradient, new_pes_state).
Faithful to truncated_pes.compute_pes_grad. Antithetic perturbations theta +/- pos are
unrolled trunc_length steps from the persistent inner state; the per-step delta-losses are
split at the (per-step) horizon reset by has_finished = cumsum(is_done) > 0: losses before
the reset attribute to the running accumulator (all perturbations since the last reset),
losses after attribute only to the current perturbation pos. The accumulator carries
pos forward, or restarts at pos if the trajectory reset during this truncation.
init_pes_state
¶
init_pes_state(learned_optimizer: LearnedOptimizer, task_family: TaskFamily, theta: PyTree, key: Array, *, num_tasks: int, total_horizon: int, trunc_length: int = 1) -> PESState
Build the initial :class:PESState with per-task staggered truncation phases.
Each trajectory starts from a fresh inner state but with a random clock offset in
[0, total_horizon) (random_initial_iteration_offset in the reference
lopt_truncated_step): because the per-step reset in :func:pes_gradient_step then fires at
the staggered clock crossings, the parallel trajectories are never phase-aligned, which removes
the sawtooth a synchronous reset would imprint on the meta-loss and lowers the PES variance.
meta_train
¶
meta_train(learned_optimizer: LearnedOptimizer, task_family: TaskFamily, key: Array, *, num_outer_steps: int = 1000, num_tasks: int = 16, trunc_length: int = 20, total_horizon: int = 100, perturbation_std: float = 0.01, meta_learning_rate: float = 0.003) -> tuple[PyTree, Array]
Meta-train learned_optimizer on task_family with PES + outer Adam.
Returns the trained theta and the per-outer-step mean loss curve. PES does not
back-propagate through the unroll: theta is updated by the ES estimate fed to Adam.
Baselines and benchmarking¶
optimistix classical baselines and honest learning-curve / speedup-at-target benchmarking.
Real classical optimisation baselines for honest L2O comparison.
A learned optimiser is only interesting if it beats a properly tuned classical optimiser, so
the baselines here are genuine: optimistix second-order/line-search minimisers
(BFGS/GradientDescent/NonlinearCG) run to convergence, and a tuned first-order
optax optimiser (learning-rate swept on the task) for a step-by-step learning-curve comparison.
No fabricated baselines or speedups (cf. the deleted _traditional_fallback).
Honest benchmarking follows the L2O literature (Andrychowicz et al. 2016; the VeLO-scaling critique arXiv:2310.18191): compare learning curves and report speedup against a tuned baseline, never an arbitrary one.
optimistix_minimise
¶
optimistix_minimise(task: Task, solver: AbstractMinimiser, start: PyTree, *, max_steps: int = 256, key: Array | None = None) -> tuple[PyTree, Array]
Run a real optimistix minimiser on task from start.
Adapts Task.loss(params, key) to optimistix's fn(y, args) -> scalar (a fixed key,
since classical solvers need a deterministic objective). Returns (minimiser, final_loss).
loss_curve
¶
Return the per-step loss curve of an :class:Optimizer on task.
Index 0 is the loss at start; index t is the loss after t update steps.
tuned_optax_baseline
¶
tuned_optax_baseline(task: Task, start: PyTree, learning_rates: Array, *, num_steps: int, key: Array, transformation: Callable[[Array], GradientTransformation] = adam) -> tuple[Array, Array]
Sweep learning_rates and return the best optimiser's (loss_curve, learning_rate).
"Tuned" means the learning rate is chosen by a real sweep (best final loss) — the honest classical first-order baseline for a learning-curve comparison against a learned optimiser.
Honest learned-optimiser benchmarking: learning curves and speedup-at-target.
The primary metric is the loss-vs-step learning curve; the secondary metric is speedup-at-target-loss = (baseline steps to reach the target) / (learned-optimiser steps), censored when a method never reaches the target.
The baseline is tuned with the standard L2O protocol (Andrychowicz et al. 2016): a single learning rate is selected on a tuning batch from the task family (best mean final loss) and then applied unchanged to every held-out task. This is the honest comparison — a learned optimiser's value is precisely that it adapts per-task and per-coordinate without re-tuning, whereas a per-task learning-rate sweep would be an undeployable oracle. Generalisation claims are scoped to in-distribution held-out tasks (cf. the VeLO-scaling critique, arXiv:2310.18191).
steps_to_target
¶
First step index at which curve reaches target (inf if never).
speedup_at_target
¶
Speedup = baseline-steps / candidate-steps to reach target (censored).
Returns 0 when the candidate never reaches the target, inf when only the baseline
fails to — so the value is never fabricated when a method does not converge.
distribution_tuned_lr
¶
distribution_tuned_lr(task_family: TaskFamily, learning_rates: Array, key: Array, *, num_steps: int, num_tune_tasks: int = 16, transformation: Callable[[Array], GradientTransformation] = adam) -> Array
Select one learning rate minimising the mean final loss over a tuning batch.
The standard L2O baseline protocol: tune a single hyperparameter on the task distribution, then apply it unchanged to held-out tasks. Returns the chosen scalar rate.
benchmark_on_held_out_tasks
¶
benchmark_on_held_out_tasks(learned_optimizer: LearnedOptimizer, theta: PyTree, task_family: TaskFamily, key: Array, *, num_tasks: int = 16, num_steps: int = 100, learning_rates: Array = DEFAULT_LR_SWEEP, target_fraction: float = 0.1, transformation: Callable[[Array], GradientTransformation] = adam) -> dict[str, Array]
Meta-test the learned optimiser against a distribution-tuned baseline on held-out tasks.
A single baseline learning rate is tuned on a separate batch from task_family and applied
to every held-out task. For each held-out task: run the learned optimiser and the fixed-rate
baseline for num_steps, then compute speedup at a per-task target loss (target_fraction
of the baseline's initial loss). Returns mean learning curves, the per-task speedups, the
median speedup (robust to censored inf/0 entries), and the tuned baseline rate.
L2O Engine¶
High-level orchestrator: meta-train a learned optimiser on a task family, apply it,
benchmark it honestly, and persist theta.
High-level learn-to-optimize engine: meta-train, apply, benchmark, persist.
A thin orchestration over the L2O building blocks — it meta-trains a :class:LearnedOptimizer
on a :class:TaskFamily with PES, applies the trained optimiser to new tasks, benchmarks it
honestly against a tuned classical baseline on held-out tasks, and serialises the meta-learned
parameters theta. There is no hidden objective or fabricated speedup: every task carries its
own loss and every reported number is measured.
L2OEngine
¶
L2OEngine(learned_optimizer: LearnedOptimizer, task_family: TaskFamily)
Meta-train a learned optimiser on a task family, then apply/benchmark/persist it.
meta_train
¶
Meta-train the optimiser (PES); store theta and return the loss curve.
optimize
¶
Apply the trained optimiser to task from start; return its loss curve.
benchmark
¶
Benchmark the trained optimiser against a tuned baseline on held-out tasks.
Control Systems¶
Differentiable predictive control components for scientific machine learning.
System Identification¶
Neural networks that learn system dynamics from data.
System Identification Networks for Learn-to-Optimize (L2O).
This module implements neural network-based system identification that learns to model dynamical systems with physics constraints, online adaptation, and control integration.
Key Features: - Neural networks for learning system dynamics - Physics-constrained system identification - Online learning and adaptation capabilities - Integration with control policy optimization - Validation on benchmark control systems
PhysicsConstraint
dataclass
¶
PhysicsConstraint(*, name: str, constraint_type: str, tolerance: float = 0.001, weight: float = 1.0)
Represents a physics constraint for system identification.
This class encapsulates physical laws and constraints that must be enforced during the learning process.
BenchmarkValidationResult
dataclass
¶
BenchmarkValidationResult(*, benchmark_name: str, metrics: dict[str, float], validation_passed: bool, details: dict[str, Any] | None = None)
Results from benchmark validation.
SystemIdentifier
¶
SystemIdentifier(state_dim: int, input_dim: int, hidden_dim: int = 64, num_layers: int = 3, activation: Callable = gelu, *, rngs: Rngs, dtype: dtype = float32)
Bases: Module
Neural network-based system identification.
This module learns to predict the next state of a dynamical system given the current state and input.
validate_on_benchmark
¶
validate_on_benchmark(benchmark_name: str, test_data: dict[str, Array]) -> BenchmarkValidationResult
Validate system identification on benchmark problem.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
benchmark_name
|
str
|
Name of the benchmark |
required |
test_data
|
dict[str, Array]
|
Test data containing states, inputs, targets |
required |
Returns:
| Type | Description |
|---|---|
BenchmarkValidationResult
|
Validation results |
PhysicsConstrainedSystemID
¶
PhysicsConstrainedSystemID(state_dim: int, input_dim: int, constraints: Sequence[PhysicsConstraint], hidden_dim: int = 64, *, rngs: Rngs, dtype: dtype = float32)
Bases: SystemIdentifier
Physics-constrained system identification.
Extends basic system identification with physics constraints and conservation laws.
OnlineSystemLearner
¶
OnlineSystemLearner(state_dim: int, input_dim: int, learning_rate: float = 0.001, adaptation_rate: float = 0.95, buffer_size: int = 100, adaptive_lr: bool = False, *, rngs: Rngs, dtype: dtype = float32)
Bases: SystemIdentifier
Online learning system identification.
Adapts the system model in real-time based on new observations.
update_online
¶
ControlIntegratedSystemID
¶
ControlIntegratedSystemID(state_dim: int, input_dim: int, control_dim: int, hidden_dim: int = 64, *, rngs: Rngs, dtype: dtype = float32)
Bases: SystemIdentifier
System identification integrated with control policy learning.
Jointly optimizes system identification and control policy for improved performance.
compute_control_action
¶
joint_optimization
¶
simulate_closed_loop
¶
validate_control_benchmark
¶
validate_control_benchmark(benchmark_name: str, initial_state: Array, reference_trajectory: Array, steps: int) -> BenchmarkValidationResult
Validate control performance on benchmark.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
benchmark_name
|
str
|
Name of control benchmark |
required |
initial_state
|
Array
|
Starting state |
required |
reference_trajectory
|
Array
|
Desired trajectory |
required |
steps
|
int
|
Number of steps |
required |
Returns:
| Type | Description |
|---|---|
BenchmarkValidationResult
|
Validation results |
Model Predictive Control¶
Differentiable MPC frameworks with safety guarantees.
Model Predictive Control (MPC) Framework for Opifex.
Provides differentiable MPC implementation with neural network-based predictive models, constraint handling and projection, real-time control policy optimization, and safety-critical system support.
MPCConfig
dataclass
¶
MPCConfig(*, horizon: int = 10, control_dim: int = 2, state_dim: int = 4, prediction_steps: int | None = None, objective_weights: dict[str, float] | None = None, max_iterations: int = 50, tolerance: float = 0.0001, time_limit: float = 0.01, learning_rate: float = 0.01)
Configuration for MPC controller.
MPCResult
¶
OptimizationResult
¶
BatchMPCResult
¶
PredictiveModel
¶
PredictiveModel(state_dim: int, control_dim: int, hidden_dims: list[int] | None = None, prediction_horizon: int = 10, model_type: str = 'neural', physics_informed: bool = False, conservation_laws: list[str] | None = None, *, rngs: Rngs)
Bases: Module
Neural network-based predictive model for system dynamics.
ConstraintProjector
¶
ConstraintProjector(state_dim: int, control_dim: int, state_bounds: dict[str, list[float]] | None = None, control_bounds: dict[str, list[float]] | None = None, safety_constraints: bool = False, *, rngs: Rngs)
ControlBarrier
¶
RealTimeOptimizer
¶
RealTimeOptimizer(max_iterations: int = 50, tolerance: float = 0.0001, learning_rate: float = 0.01, warm_start: bool = True, time_limit: float = 0.01)
Bases: Module
Real-time optimizer for MPC problems.
optimize
¶
optimize(objective: Callable, constraints: Callable | None, initial_guess: ndarray, warm_start_solution: ndarray | None = None) -> OptimizationResult
Optimize objective subject to constraints.
Note: This is not JIT-compatible due to time limits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
objective
|
Callable
|
Objective function to optimize. |
required |
constraints
|
Callable | None
|
Constraints to enforce. |
required |
initial_guess
|
ndarray
|
Initial guess for the solution. |
required |
warm_start_solution
|
ndarray | None
|
Solution from previous iteration for warm start. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
OptimizationResult |
OptimizationResult
|
Result of the optimization. |
optimize_with_time_limit
¶
optimize_with_time_limit(objective: Callable, constraints: Callable | None, initial_guess: ndarray, warm_start_solution: ndarray | None = None) -> OptimizationResult
Optimize with real-time constraints (not JIT-compatible due to time limits).
This method includes time limit enforcement and therefore cannot be JIT-compiled. Use optimize() for JIT-compatible optimization without time limits.
DifferentiableMPC
¶
DifferentiableMPC(config: MPCConfig, dynamics_model: PredictiveModel | None = None, constraint_projector: ConstraintProjector | None = None)
Bases: Module
Differentiable Model Predictive Control implementation.
SafetyCriticalMPC
¶
SafetyCriticalMPC(horizon: int = 10, control_dim: int = 2, state_dim: int = 4, safety_barriers: bool = True, emergency_control: bool = True, backup_policy: bool = True, **kwargs)
Bases: DifferentiableMPC
Safety-critical MPC with emergency control and backup policies.
RecedingHorizonController
¶
RecedingHorizonController(mpc_horizon: int = 10, control_horizon: int = 5, state_dim: int = 4, control_dim: int = 2, sampling_time: float = 0.1, safety_critical: bool = False)
Bases: Module
Receding horizon controller implementation.
compute_control
¶
Compute control using receding horizon.
Module Overview¶
The optimization module is organized into several key components:
Core Components¶
meta_optimization/: Meta-optimization framework with L2O algorithms (modular package)production.py: Production optimization (adaptive JIT, GPU memory planning)scientific_integration.py: Physics-aware optimization integration
L2O Submodule (l2o/)¶
core.py:Task/TaskFamily(objective-carrying) and theOptimizerinterfaceoptimizers.py:OptimizerABC +OptaxOptimizer(hand-designed baseline family)tasks.py:QuadraticTaskFamilyand theMLPTaskFamilyshowcase taskfeatures.py: per-parameter input features (momentum/RMS, time embedding)learned.py:LearnedOptimizerABC,MLPLearnedOptimizer,LearnableSGDmeta_train.py: Persistent Evolution Strategies (PES) meta-trainingbaselines.py: optimistix classical baselines and tuned-optax baselinesbenchmark.py: honest learning-curve and speedup-at-target benchmarkingengine.py: high-levelL2OEngineorchestrator
Control Submodule (control/)¶
system_id.py: System identification networksmpc.py: Model predictive control frameworks
Key Features¶
Meta-Optimization Features¶
- Learn-to-Optimize (L2O) algorithms with meta-learned update rules
- Adaptive learning rate scheduling
- Warm-starting strategies for related problems
Production Optimization Features¶
- Hybrid performance platform with adaptive JIT
- Intelligent GPU memory management
- Physics-aware scientific validation of optimized models
Control Systems Features¶
- Differentiable model predictive control
- Physics-constrained system identification
- Safety-critical control with barrier functions
- Real-time optimization capabilities
Scientific Integration Features¶
- Physics-informed optimization
- Conservation law enforcement
- Numerical validation and stability checks
- Domain-specific profiling and benchmarking
Usage Examples¶
Basic Meta-Optimization¶
from opifex.optimization.meta_optimization import LearnToOptimize, MetaOptimizerConfig
config = MetaOptimizerConfig(
meta_learning_rate=1e-4,
adaptation_steps=5,
warm_start_strategy="previous_params"
)
l2o = LearnToOptimize(config=config, rngs=nnx.Rngs(42))
optimized_params = l2o.optimize(params, objective_fn, num_steps=1000)
Production Optimization¶
from opifex.optimization.production import HybridPerformancePlatform, WorkloadProfile
platform = HybridPerformancePlatform()
workload = WorkloadProfile(
batch_size=32,
sequence_length=128,
memory_footprint=2.0,
compute_intensity=8.0,
latency_requirement=10.0,
throughput_requirement=100.0,
model_complexity="medium",
)
optimized = platform.optimize_for_production(model, workload)
Control System¶
from opifex.optimization.control import DifferentiableMPC, SystemIdentifier
# Learn system dynamics
system_id = SystemIdentifier(model=dynamics_model)
trained_model = system_id.fit(state_data, input_data)
# Create MPC controller
mpc = DifferentiableMPC(system_model=trained_model, config=mpc_config)
control_action = mpc.solve(current_state, reference_trajectory)
Performance Characteristics¶
- L2O Speedup: meta-learned optimizers accelerate convergence on learned problem families
- Meta-Optimization: faster convergence on related problems via warm-starting
- Production Optimization: adaptive JIT kernel fusion with measured speedups
- Memory Efficiency: pool-based GPU memory planning for co-located models
Integration¶
The optimization module integrates seamlessly with:
- Training: Meta-optimization for training workflows
- Neural Networks: Compatible with all neural architectures
- Physics: Physics-informed optimization constraints
- Deployment: Production-ready optimization systems
Second-Order Optimization¶
Curvature-based optimization methods including L-BFGS and hybrid optimizers.
Configuration Classes¶
opifex.optimization.second_order.config
¶
Configuration classes for second-order optimization methods.
This module provides unified configuration dataclasses for all second-order optimization methods supported by the Opifex framework.
Design Principles
- All configs are frozen dataclasses (immutable)
- Validation happens at construction time via post_init
- Sensible defaults based on literature recommendations
- Clear separation between method-specific and shared configs
References
- Survey: arXiv:2601.10222v1 Section 7
- L-BFGS memory size: typically 3-20 (Liu & Nocedal, 1989)
- Hybrid switching: Section 7.4 of the survey
LBFGSConfig
dataclass
¶
LBFGSConfig(memory_size: int = 10, scale_init_precond: bool = True, linesearch: LinesearchType = ZOOM, max_linesearch_steps: int = 20, max_iterations: int = 100, tolerance: float = 1e-06)
Configuration for L-BFGS optimizer.
L-BFGS (Limited-memory BFGS) approximates the inverse Hessian using a limited history of gradient differences. This makes it suitable for large-scale optimization where storing the full Hessian is infeasible.
Attributes:
| Name | Type | Description |
|---|---|---|
memory_size |
int
|
Number of gradient pairs to store (typically 3-20) |
scale_init_precond |
bool
|
Whether to scale initial preconditioner |
linesearch |
LinesearchType
|
Line search algorithm to use |
max_linesearch_steps |
int
|
Maximum steps for line search |
max_iterations |
int
|
Maximum L-BFGS iterations |
tolerance |
float
|
Convergence tolerance |
References
- Liu & Nocedal (1989): On the limited memory BFGS method
- optax.lbfgs documentation
GaussNewtonConfig
dataclass
¶
GaussNewtonConfig(damping_factor: float = 0.001, damping_increase_factor: float = 10.0, damping_decrease_factor: float = 0.1, min_damping: float = 1e-10, max_damping: float = 10000000000.0, max_iterations: int = 100, rtol: float = 1e-06, atol: float = 1e-06)
Configuration for Gauss-Newton and Levenberg-Marquardt solvers.
Gauss-Newton is effective for nonlinear least-squares problems where the residual Jacobian can be computed efficiently. Levenberg-Marquardt adds damping for improved robustness.
Attributes:
| Name | Type | Description |
|---|---|---|
damping_factor |
float
|
Initial damping factor (λ) for LM |
damping_increase_factor |
float
|
Factor to increase damping on failure (> 1) |
damping_decrease_factor |
float
|
Factor to decrease damping on success (< 1) |
min_damping |
float
|
Minimum allowed damping value |
max_damping |
float
|
Maximum allowed damping value |
max_iterations |
int
|
Maximum solver iterations |
rtol |
float
|
Relative tolerance for convergence |
atol |
float
|
Absolute tolerance for convergence |
References
- optimistix.LevenbergMarquardt documentation
- Survey Section 7.3
HybridOptimizerConfig
dataclass
¶
HybridOptimizerConfig(first_order_steps: int = 1000, switch_criterion: SwitchCriterion = LOSS_VARIANCE, loss_variance_threshold: float = 0.0001, loss_history_window: int = 50, gradient_norm_threshold: float = 0.001, relative_improvement_threshold: float = 0.0001, adam_learning_rate: float = 0.001, adam_b1: float = 0.9, adam_b2: float = 0.999, lbfgs_config: LBFGSConfig = LBFGSConfig())
Configuration for hybrid Adam→L-BFGS optimizer.
This optimizer starts with Adam for initial exploration and switches to L-BFGS for efficient convergence once the loss landscape becomes smooth. This follows recommendations from Survey Section 7.4.
The switch can be triggered by various criteria
- EPOCH: Switch after fixed number of steps
- LOSS_VARIANCE: Switch when loss variance drops below threshold
- GRADIENT_NORM: Switch when gradient norm drops below threshold
- RELATIVE_IMPROVEMENT: Switch when relative improvement slows
Attributes:
| Name | Type | Description |
|---|---|---|
first_order_steps |
int
|
Steps to run Adam before considering switch |
switch_criterion |
SwitchCriterion
|
Criterion for switching to L-BFGS |
loss_variance_threshold |
float
|
Threshold for loss variance criterion |
loss_history_window |
int
|
Window size for computing loss statistics |
gradient_norm_threshold |
float
|
Threshold for gradient norm criterion |
relative_improvement_threshold |
float
|
Threshold for relative improvement |
adam_learning_rate |
float
|
Learning rate for Adam phase |
adam_b1 |
float
|
Adam beta1 parameter |
adam_b2 |
float
|
Adam beta2 parameter |
lbfgs_config |
LBFGSConfig
|
Configuration for L-BFGS phase |
References
- Survey Section 7.4: "L-BFGS is more effective in later stages when loss varies smoothly"
L-BFGS and Gauss-Newton Wrappers¶
opifex.optimization.second_order.wrappers
¶
Wrappers for external second-order optimization libraries.
This module provides thin wrappers around optax and optimistix to create second-order optimizers with our unified configuration interface.
Design Philosophy
- Wrap existing robust implementations (optax, optimistix)
- Don't reinvent the wheel
- Provide consistent interface through our config classes
References
- optax.lbfgs: Pure JAX L-BFGS with line search
- optimistix: Gauss-Newton, Levenberg-Marquardt, BFGS
create_lbfgs_optimizer
¶
create_lbfgs_optimizer(config: LBFGSConfig | None = None) -> GradientTransformation
Create L-BFGS optimizer using optax.
L-BFGS is a quasi-Newton method that approximates the inverse Hessian using a limited history of gradient differences. This is the recommended second-order optimizer for large-scale optimization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
LBFGSConfig | None
|
L-BFGS configuration. Uses defaults if None. |
None
|
Returns:
| Type | Description |
|---|---|
GradientTransformation
|
Optax L-BFGS gradient transformation. |
Example
config = LBFGSConfig(memory_size=20) optimizer = create_lbfgs_optimizer(config)
Use with optax training loop¶
create_gauss_newton_solver
¶
create_gauss_newton_solver(config: GaussNewtonConfig | None = None) -> AbstractLeastSquaresSolver
Create Gauss-Newton solver using optimistix.
Gauss-Newton is effective for nonlinear least-squares problems. Note that this creates a solver for root-finding/minimization, not a gradient transformation like L-BFGS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
GaussNewtonConfig | None
|
Gauss-Newton configuration. Uses defaults if None. |
None
|
Returns:
| Type | Description |
|---|---|
AbstractLeastSquaresSolver
|
Optimistix Gauss-Newton solver. |
Example
solver = create_gauss_newton_solver()
Use with optimistix.least_squares¶
Hybrid Adam → L-BFGS Optimizer¶
opifex.optimization.second_order.hybrid_optimizer
¶
Hybrid Adam→L-BFGS optimizer for physics-informed training.
This module implements a hybrid optimization strategy that starts with Adam for initial exploration and switches to L-BFGS for efficient convergence once the loss landscape becomes smooth.
Design Rationale (from Survey Section 7.4): "L-BFGS is more effective in later stages when loss varies smoothly."
The hybrid approach combines
- Adam's robustness in noisy, high-curvature early optimization
- L-BFGS's superior convergence in smooth regions near optima
Key Features
- Multiple switching criteria (epoch, loss variance, gradient norm)
- Loss history tracking for variance-based switching
- Full JAX/JIT compatibility
- Works with FLAX NNX models
References
- Survey: arXiv:2601.10222v1 Section 7.4
HybridOptimizer
dataclass
¶
HybridOptimizer(config: HybridOptimizerConfig)
Hybrid Adam→L-BFGS optimizer.
This optimizer starts with Adam and switches to L-BFGS based on configurable criteria. The transition is designed to leverage Adam's robustness in early training and L-BFGS's efficiency for final convergence.
Attributes:
| Name | Type | Description |
|---|---|---|
config |
HybridOptimizerConfig
|
Hybrid optimizer configuration |
adam |
GradientTransformation
|
Adam optimizer instance |
lbfgs |
GradientTransformationExtraArgs
|
L-BFGS optimizer instance |
Example
config = HybridOptimizerConfig(first_order_steps=1000) optimizer = HybridOptimizer(config) state = optimizer.init(params)
Training loop¶
for step in range(num_steps): ... loss, grads = loss_and_grad_fn(params) ... updates, state = optimizer.update(grads, state, params, loss=loss) ... params = optax.apply_updates(params, updates)
is_using_lbfgs
property
¶
is_using_lbfgs: bool
Check if optimizer is currently using L-BFGS.
Note: This is a convenience property. For actual state, check the HybridOptimizerState.using_lbfgs field.
init
¶
Initialize optimizer state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
PyTree
|
Model parameters (PyTree) |
required |
Returns:
| Type | Description |
|---|---|
HybridOptimizerState
|
Initial optimizer state |
update
¶
update(grads: PyTree, state: HybridOptimizerState, params: PyTree, *, loss: Float[Array, ''] | None = None, value: Float[Array, ''] | None = None, grad: PyTree | None = None, value_fn: Callable[[PyTree], Float[Array, '']] | None = None) -> tuple[PyTree, HybridOptimizerState]
Compute parameter updates.
This method handles the switching logic and delegates to either Adam or L-BFGS depending on the current state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grads
|
PyTree
|
Parameter gradients |
required |
state
|
HybridOptimizerState
|
Current optimizer state |
required |
params
|
PyTree
|
Current parameters (needed for L-BFGS) |
required |
loss
|
Float[Array, ''] | None
|
Current loss value (for variance-based switching) |
None
|
value
|
Float[Array, ''] | None
|
Alias for loss (for optax L-BFGS compatibility) |
None
|
grad
|
PyTree | None
|
Alias for grads (for optax L-BFGS compatibility) |
None
|
value_fn
|
Callable[[PyTree], Float[Array, '']] | None
|
Loss function (needed for L-BFGS line search) |
None
|
Returns:
| Type | Description |
|---|---|
tuple[PyTree, HybridOptimizerState]
|
Tuple of (updates, new_state) |
NNX Integration¶
opifex.optimization.second_order.nnx_integration
¶
FLAX NNX integration for second-order optimizers.
This module provides wrapper classes that make it easy to use second-order optimizers (L-BFGS, hybrid Adam→L-BFGS) with FLAX NNX models.
Design Philosophy
- Hide the complexity of nnx.split/merge from users
- Provide familiar step() interface similar to nnx.Optimizer
- Support both pure L-BFGS and hybrid optimization strategies
Key Classes
- NNXSecondOrderOptimizer: L-BFGS optimizer for NNX models
- NNXHybridOptimizer: Hybrid Adam→L-BFGS for NNX models
- create_nnx_lbfgs_optimizer: Factory function for L-BFGS
References
- FLAX NNX documentation: https://flax.readthedocs.io/en/latest/nnx/
- optax L-BFGS requires functional API with value_and_grad_from_state
create_nnx_lbfgs_optimizer
¶
create_nnx_lbfgs_optimizer(model: Module, config: LBFGSConfig | None = None) -> NNXSecondOrderOptimizer
Create L-BFGS optimizer for NNX model.
Factory function that creates an NNXSecondOrderOptimizer configured with L-BFGS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Module
|
FLAX NNX model to optimize |
required |
config
|
LBFGSConfig | None
|
L-BFGS configuration. Uses defaults if None. |
None
|
Returns:
| Type | Description |
|---|---|
NNXSecondOrderOptimizer
|
Configured NNXSecondOrderOptimizer instance. |
Example
model = MyModel(rngs=nnx.Rngs(0)) optimizer = create_nnx_lbfgs_optimizer(model) for _ in range(100): ... loss = optimizer.step(loss_fn)
For detailed algorithms and best practices, see the Second-Order Optimization Guide.
See Also¶
- Optimization User Guide - Practical usage guide
- Second-Order Optimization - L-BFGS, hybrid optimizers
- Meta-Optimization Methods - Detailed algorithms
- Production Optimization - Enterprise features
- Control Systems - Control theory integration