# symforce.opt.optimizer module¶

class Optimizer(factors, optimized_keys=None, params=None, debug_stats=False, include_jacobians=False)[source]

Bases: object

A nonlinear least-squares optimizer

Typical usage is to construct an Optimizer from a set of factors and keys to optimize, and then call optimize repeatedly with a Values.

Example creation with an OptimizationProblem using make_numeric_factors(). The linearization functions are generated in make_numeric_factors() and are linearized with respect to problem.optimized_keys().

problem = OptimizationProblem(subproblems=[…], residual_blocks=…) factors = problem.make_numeric_factors(“my_problem”) optimizer = Optimizer(factors)

Example creation with an OptimizationProblem using make_symbolic_factors(). The symbolic factors are converted into numeric factors when the optimizer is created, and are linearized with respect to the “optimized keys” passed to the optimizer. The linearization functions are generated when converting to numeric factors when the optimizer is created.

problem = OptimizationProblem(subproblems=[…], residual_blocks=…) factors = problem.make_symbolic_factors(“my_problem”) optimizer = Optimizer(factors, problem.optimized_keys())

Example creation with a single Factor:

factor = Factor(

[my_key_0, my_key_1, my_key_2], my_residual_function

) optimizer = Optimizer(

factors=[factor], optimized_keys=[my_key_0, my_key_1],

)

And usage:

initial_guess = Values(…) result = optimizer.optimize(initial_guess) print(result.optimized_values)

Wraps the C++ sym::Optimizer class in opt/optimizer.h, so the API is mostly the same and optimization results will be identical.

Parameters:
• factors (Iterable[Union[Factor, NumericFactor]]) – A sequence of either Factor or NumericFactor objects representing the residuals in the problem. If (symbolic) Factors are passed, they are convered to NumericFactors by generating linearization functions of the residual with respect to the keys in optimized_keys.

• optimized_keys (Optional[Sequence[str]]) – A set of the keys to be optimized. Only required if symbolic factors are passed to the optimizer.

• params (Optional[Params]) – Params for the optimizer

• debug_stats (bool) – Whether the optimizer should record debugging stats such as the optimized values, residual, jacobian, etc. computed at each iteration of the optimization.

• include_jacobians (bool) – Whether the optimizer should compute jacobians (required for linear error)

class Params(verbose=True, initial_lambda=1.0, lambda_up_factor=4.0, lambda_down_factor=0.25, lambda_lower_bound=0.0, lambda_upper_bound=1000000.0, use_diagonal_damping=False, use_unit_damping=True, keep_max_diagonal_damping=False, diagonal_damping_min=1e-06, iterations=50, early_exit_min_reduction=1e-06, enable_bold_updates=False)[source]

Bases: object

Parameters for the Python Optimizer

Mirrors the optimizer_params_t LCM type, see documentation there for information on each parameter

Note: For the Python optimizer, verbose defaults to True

Parameters:
• verbose (bool) –

• initial_lambda (float) –

• lambda_up_factor (float) –

• lambda_down_factor (float) –

• lambda_lower_bound (float) –

• lambda_upper_bound (float) –

• use_diagonal_damping (bool) –

• use_unit_damping (bool) –

• keep_max_diagonal_damping (bool) –

• diagonal_damping_min (float) –

• iterations (int) –

• early_exit_min_reduction (float) –

• enable_bold_updates (bool) –

verbose: bool = True
initial_lambda: float = 1.0
lambda_up_factor: float = 4.0
lambda_down_factor: float = 0.25
lambda_lower_bound: float = 0.0
lambda_upper_bound: float = 1000000.0
use_diagonal_damping: bool = False
use_unit_damping: bool = True
keep_max_diagonal_damping: bool = False
diagonal_damping_min: float = 1e-06
iterations: int = 50
early_exit_min_reduction: float = 1e-06
enable_bold_updates: bool = False
__init__(verbose=True, initial_lambda=1.0, lambda_up_factor=4.0, lambda_down_factor=0.25, lambda_lower_bound=0.0, lambda_upper_bound=1000000.0, use_diagonal_damping=False, use_unit_damping=True, keep_max_diagonal_damping=False, diagonal_damping_min=1e-06, iterations=50, early_exit_min_reduction=1e-06, enable_bold_updates=False)
Parameters:
• verbose (bool) –

• initial_lambda (float) –

• lambda_up_factor (float) –

• lambda_down_factor (float) –

• lambda_lower_bound (float) –

• lambda_upper_bound (float) –

• use_diagonal_damping (bool) –

• use_unit_damping (bool) –

• keep_max_diagonal_damping (bool) –

• diagonal_damping_min (float) –

• iterations (int) –

• early_exit_min_reduction (float) –

• enable_bold_updates (bool) –

class Result(initial_values, optimized_values, iteration_stats, early_exited, best_index)[source]

Bases: object

The result of an optimization, with additional stats and debug information

initial_values:

The initial guess used for this optimization

optimized_values:

The best Values achieved during the optimization (Values with the smallest error)

iteration_stats:

Per-iteration stats, if requested, like the error per iteration. If debug stats are turned on, also the Values and linearization per iteration.

early_exited:

Did the optimization early exit? This can happen because it converged successfully, of because it was unable to make progress

best_index:

The index into iteration_stats for the iteration that produced the smallest error. I.e. result.iteration_stats[best_index].values == optimized_values. This is not guaranteed to be the last iteration, if the optimizer tried additional steps which did not reduce the error

Parameters:
• initial_values (Values) –

• optimized_values (Values) –

• iteration_stats (Sequence[optimization_iteration_t]) –

• early_exited (bool) –

• best_index (int) –

initial_values: Values
optimized_values: Values
iteration_stats: Sequence[optimization_iteration_t]
early_exited: bool
best_index: int
error()[source]
Return type:

float

__init__(initial_values, optimized_values, iteration_stats, early_exited, best_index)
Parameters:
• initial_values (Values) –

• optimized_values (Values) –

• iteration_stats (Sequence[optimization_iteration_t]) –

• early_exited (bool) –

• best_index (int) –

__init__(factors, optimized_keys=None, params=None, debug_stats=False, include_jacobians=False)[source]
Parameters:
• factors (Iterable[Union[Factor, NumericFactor]]) –

• optimized_keys (Optional[Sequence[str]]) –

• params (Optional[Params]) –

• debug_stats (bool) –

• include_jacobians (bool) –

optimize(initial_guess)[source]

Optimize from the given initial guess, and return the optimized Values and stats

Parameters:

initial_guess (Values) – A Values containing the initial guess, should contain at least all the keys required by the factors passed to the constructor

Return type:

Result

Returns:

The optimization results, with additional stats and debug information. See the Optimizer.Result documentation for more information

linearize(values)[source]

Compute and return the linearization at the given Values

Parameters:

values (Values) –

Return type:

Linearization

load_iteration_values(values_msg)[source]

Load a values_t message into a Python Values by first creating a C++ Values, then converting back to the python key names.

Parameters:

values_msg (values_t) –

Return type:

Values

linearization_index()[source]

Get the index mapping keys to their positions in the linearized state vector. Useful for extracting blocks from the problem jacobian, hessian, or RHS

Returns: The index for the Optimizer’s problem linearization

Return type:

Dict[str, index_entry_t]

linearization_index_entry(key)[source]

Get the index entry for a given key in the linearized state vector. Useful for extracting blocks from the problem jacobian, hessian, or RHS

Parameters:

key (str) – The string key for a variable in the Python Values

Returns: The index entry for the variable in the Optimizer’s problem linearization

Return type:

index_entry_t