nlsq.fallback module

Automatic Fallback Strategies for Robust Optimization

This module provides automatic fallback mechanisms that attempt to recover from optimization failures by trying alternative approaches.

Key Features: - Automatic method selection (trf → alternative approaches) - Initial guess perturbation for escaping local minima - Tolerance adjustment for difficult problems - Parameter bound inference when needed - Robust loss function application - Problem rescaling for numerical stability

Example

>>> from nlsq.stability.fallback import FallbackOrchestrator
>>>
>>> orchestrator = FallbackOrchestrator(verbose=True)
>>> result = orchestrator.fit_with_fallback(
...     model, xdata, ydata, p0=[1, 0.5],
...     max_attempts=5
... )
>>> print(f"Success with strategy: {result.fallback_strategy_used}")
class nlsq.stability.fallback.FallbackOrchestrator(strategies=None, max_attempts=10, verbose=False)[source]

Bases: object

Orchestrates automatic fallback strategies for robust optimization.

The orchestrator tries multiple recovery strategies when optimization fails, including alternative methods, perturbed initial guesses, relaxed tolerances, and robust loss functions.

Parameters:
  • strategies (list of FallbackStrategy, optional) – List of strategies to try. If None, uses default strategies.

  • max_attempts (int, optional) – Maximum total attempts across all strategies. Default: 10

  • verbose (bool, optional) – Print progress messages. Default: False

strategies

Active fallback strategies, sorted by priority

Type:

list of FallbackStrategy

total_attempts

Total number of fit attempts made

Type:

int

successful_strategies

Count of successes per strategy

Type:

dict

Examples

>>> from nlsq.stability.fallback import FallbackOrchestrator
>>> import numpy as np
>>>
>>> def model(x, a, b):
...     return a * np.exp(-b * x)
>>>
>>> x = np.linspace(0, 10, 100)
>>> y = 2.5 * np.exp(-0.5 * x) + 0.1 * np.random.randn(100)
>>>
>>> orchestrator = FallbackOrchestrator(verbose=True)
>>> result = orchestrator.fit_with_fallback(
...     model, x, y, p0=[1, 0.1]  # Deliberately poor p0
... )
>>>
>>> if result.fallback_strategy_used:
...     print(f"Recovered using: {result.fallback_strategy_used}")
DEFAULT_STRATEGIES: ClassVar[list[StrategyFactory]] = [<class 'nlsq.stability.fallback.AlternativeMethodStrategy'>, <class 'nlsq.stability.fallback.PerturbInitialGuessStrategy'>, <class 'nlsq.stability.fallback.AdjustTolerancesStrategy'>, <class 'nlsq.stability.fallback.AddParameterBoundsStrategy'>, <class 'nlsq.stability.fallback.UseRobustLossStrategy'>, <class 'nlsq.stability.fallback.RescaleProblemStrategy'>]
__init__(strategies=None, max_attempts=10, verbose=False)[source]

Initialize fallback orchestrator.

successful_strategies: dict[str, int]
fit_with_fallback(f, xdata, ydata, **kwargs)[source]

Attempt curve fit with automatic fallback on failure.

Parameters:
  • f (callable) – Model function

  • xdata (array_like) – Independent variable data

  • ydata (array_like) – Dependent variable data

  • **kwargs – Additional arguments passed to curve_fit

Returns:

result – Optimization result with fallback metadata

Return type:

FallbackResult

Raises:

RuntimeError – If all fallback strategies fail

get_statistics()[source]

Get statistics on fallback strategy performance.

Returns:

stats – Dictionary with success rates and attempt counts

Return type:

dict

print_statistics()[source]

Print human-readable statistics.

class nlsq.stability.fallback.FallbackResult(result, strategy_used=None, attempts=1)[source]

Bases: object

Enhanced optimization result with fallback information.

__init__(result, strategy_used=None, attempts=1)[source]

Initialize fallback result.

Parameters:
  • result (OptimizeResult) – Underlying optimization result

  • strategy_used (str, optional) – Name of fallback strategy that succeeded

  • attempts (int, optional) – Number of attempts before success

__getattr__(name)[source]

Delegate attribute access to underlying result.

class nlsq.stability.fallback.FallbackStrategy(name, description, priority=0)[source]

Bases: object

Base class for fallback strategies.

__init__(name, description, priority=0)[source]

Initialize fallback strategy.

Parameters:
  • name (str) – Strategy name

  • description (str) – Human-readable description

  • priority (int, optional) – Execution priority (higher = earlier). Default: 0

apply(kwargs)[source]

Apply strategy by modifying fit parameters.

Parameters:

kwargs (dict) – Original curve_fit keyword arguments

Returns:

modified_kwargs – Modified keyword arguments

Return type:

dict

Overview

The nlsq.fallback module (located at nlsq.stability.fallback) provides automatic fallback strategies for recovering from failed optimizations. When curve fitting fails, the module intelligently tries alternative approaches to achieve convergence.

Key Features

  • Automatic method selection - try alternative optimization methods

  • Initial guess perturbation - escape local minima with random perturbations

  • Tolerance adjustment - relax tolerances for difficult problems

  • Parameter bound inference - infer reasonable bounds from data

  • Robust loss functions - use soft_l1 or huber for outlier resistance

  • Problem rescaling - improve conditioning through rescaling

Classes

Main Classes

FallbackOrchestrator([strategies, ...])

Orchestrates automatic fallback strategies for robust optimization.

FallbackResult(result[, strategy_used, attempts])

Enhanced optimization result with fallback information.

FallbackStrategy(name, description[, priority])

Base class for fallback strategies.

Strategy Classes

AlternativeMethodStrategy()

Try alternative optimization methods.

PerturbInitialGuessStrategy([...])

Perturb initial guess to escape local minima.

AdjustTolerancesStrategy([relaxation_factor])

Relax optimization tolerances.

AddParameterBoundsStrategy()

Infer and add parameter bounds if not provided.

UseRobustLossStrategy()

Apply robust loss function to handle outliers.

RescaleProblemStrategy()

Rescale data for numerical stability.

Usage Examples

Basic Usage with FallbackOrchestrator

from nlsq.stability.fallback import FallbackOrchestrator
import jax.numpy as jnp


def model(x, a, b):
    return a * jnp.exp(-b * x)


# Create orchestrator with verbose output
orchestrator = FallbackOrchestrator(verbose=True)

# Fit with automatic fallback
result = orchestrator.fit_with_fallback(
    model, xdata, ydata, p0=[1.0, 0.5], max_attempts=5
)

if result.success:
    print(f"Fitted parameters: {result.popt}")
    print(f"Strategy used: {result.fallback_strategy_used}")
else:
    print(f"All strategies failed after {result.attempts} attempts")

Custom Strategy Selection

from nlsq.stability.fallback import (
    FallbackOrchestrator,
    PerturbInitialGuessStrategy,
    AdjustTolerancesStrategy,
)

# Create orchestrator with specific strategies
orchestrator = FallbackOrchestrator(
    strategies=[
        PerturbInitialGuessStrategy(),
        AdjustTolerancesStrategy(),
    ],
    verbose=True,
)

result = orchestrator.fit_with_fallback(model, x, y, p0=[1.0, 0.5])

Available Strategies

The following fallback strategies are available, ordered by default priority:

Strategy

Priority

Description

AlternativeMethodStrategy

10

Try alternative optimization methods

PerturbInitialGuessStrategy

8

Perturb initial parameters with random noise

AdjustTolerancesStrategy

6

Relax convergence tolerances

AddParameterBoundsStrategy

4

Infer and add parameter bounds

UseRobustLossStrategy

2

Switch to robust loss functions

RescaleProblemStrategy

1

Rescale problem for better conditioning

See Also