The base submodule#

The new inversion framework is built on top of a set of base classes that specify the interface of the child ones that will finally implement the particular methods. These base classes live in the inversion_ideas.base submodule (see the API reference for the base submodule). The majority of the base classes are abstract classes that require child classes to implement all the abstract methods for that class to be instatiable. We can understand these abstract classes as a design layout that the child classes are forced to follow.

For example, the inversion_ideas.base.Objective is an abstract class that works as a base class for every objective function. The base.Objective implements a few methods and properties that will be shared by all objective functions, but define some abstract methods that any child should implement:

We cannot directly instantiate this class:

import inversion_ideas as ii

ii.base.Objective()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[1], line 3
      1 import inversion_ideas as ii
      2 
----> 3 ii.base.Objective()

TypeError: Can't instantiate abstract class Objective without an implementation for abstract methods '__call__', 'gradient', 'hessian', 'n_params'

But we can instantiate the inversion_ideas.SimpleSmallness a subclass of base.Objective that implements all its abstract methods and properties.

smallness = ii.SimpleSmallness(4)

Note

The use of abstract classes makes it easier to guarantee that non-abstract classes implement the same interface as all its sibling classes. This make the framework more modular: a minimizer like GaussNewtonConjugateGradient can take any base.Objective object as an objective function, regardless how it’s implemented and where it comes from, as long as it correctly implements its abstract methods.

The inversion_ideas.base submodule also contains container classes like the base.Combo and base.Combo. These classes are non-abstract Objective that implements all of its abstract methods, but they are not intended to be instantiated by end users: they are formed when adding together two Objective functions, or when multiplying one of them by a scalar.

flatness = ii.SimpleFlatness(4)
combo = smallness + flatness
type(combo)
inversion_ideas.base.objective_function.Combo
scaled = 2.4 * smallness
type(scaled)
inversion_ideas.base.objective_function.Scaled