symforce.opt.sub_problem module#

class SubProblem(name=None)[source]#

Bases: ABC

A logical grouping of a set of variables and objective terms that use those variables

Typical usage is to subclass SubProblem, and define an Inputs dataclass on your subclass for any variables provided by the subproblem. Then define build_residuals(), which should return a symforce.values.values.Values where each leaf is a residual_block.ResidualBlock, representing the residuals for your subproblem. For example:

class MySubProblem(SubProblem):
    @dataclass
    class Inputs:
        x: sf.Scalar
        pose: sf.Pose3
        objective_params: MyObjective.Params

    # Optional, but helpful for type checking
    inputs: MySubProblem.Inputs

    def build_residuals(self) -> Values:
        residual_blocks = Values()
        residual_blocks["my_objective"] = MyObjective.residual(
            self.inputs.x, self.inputs.pose, self.inputs.objective_params
        )
        return residual_blocks

SubProblems can also depend on variables or expressions from other subproblems; the recommended way to do this is to add arguments to build_residuals() for any expressions your subproblem needs from other subproblems.

Both Inputs and build_residuals() must be defined, but can be empty - a SubProblem can be just a set of variables with no objectives (for example, variables that are used in other subproblems). It can also be a set of objectives with no variables, i.e. with all of its inputs coming from other subproblems.

Parameters:

name (str) – (optional) The name of the subproblem, derived from the class name by default

Inputs: Type[Dataclass]#
inputs: Dataclass#
name: str#
build_inputs()[source]#

Build the inputs block of the subproblem, and store in self.inputs.

The default implementation works for fixed-size Dataclasses; for dynamic-size dataclasses, or to customize this, override this function.

Return type:

None

abstract build_residuals(*args)[source]#

Build the residual blocks for the subproblem, and return as a Values.

Each SubProblem subclass should define this. Typically, the SubProblem implementation of this function will take additional arguments, for expressions coming from other SubProblem dependencies or other hyperparameters.

Returns:

residual_blocks – A Values of any structure, but where each leaf is a ResidualBlock

Parameters:

args (Any) –

Return type:

Values

abstract optimized_values()[source]#

Return the list of optimized values for this subproblem. Each entry should be a leaf-level object in the subproblem Inputs

Return type:

List[Any]