gko::Composition#

Function composition of LinOps. Given \(n\) operators \(\mathit{op}_1, \ldots, \mathit{op}_n\), Composition represents

\[ \mathit{Composition}(x) = \mathit{op}_1\, \bigl( \mathit{op}_2\, ( \cdots ( \mathit{op}_n\, x ) ) \bigr), \]

and is itself a LinOp. apply runs the operators right-to-left, feeding each one’s output as the input to the next. The constructor moves all operators onto the executor of the first one if their executors differ.

The classic use case is assembling triangular-solve chains for factorisation-based preconditioners: an Ilu preconditioner is a Composition{U_solver, L_solver} that, applied to \(b\), computes \(L^{-1} b\) first and then \(U^{-1}(L^{-1} b)\). The same pattern shows up in Ic (lower-then-conjugate-transpose), in multigrid V-cycles, and anywhere else where the inverse of a product needs to be expressed as the product of inverses in reverse order.

When an inner operator requires an initial guess, Composition supplies one automatically: the previous operator’s output if the current operator is square, or zero if it is rectangular.

template<typename ValueType = default_precision>
class Composition #

Inherits from

The Composition class can be used to compose linear operators op1, op2, ..., opn and obtain the operator op1 * op2 * ... * opn.

All LinOps of the Composition must operate on Dense inputs. For an operator op_k that require an initial guess for their apply, Composition provides either

  • the output of the previous op_{k+1}->apply if op_k has square dimension

  • zero if op_k is rectangular as an initial guess.

Composition ensures that all LinOps passed to its constructor use the same executor, and if not, copies the operators to the executor of the first operator.

Template Parameters:

ValueType – precision of input and result vectors

Public Functions

inline const std::vector<std::shared_ptr<const LinOp>> &get_operators(
) const noexcept#

Returns a list of operators of the composition.

Returns:

a list of operators

virtual std::unique_ptr<LinOp> transpose() const override#

Returns a LinOp representing the transpose of the Transposable object.

Returns:

a pointer to the new transposed object

virtual std::unique_ptr<LinOp> conj_transpose() const override#

Returns a LinOp representing the conjugate transpose of the Transposable object.

Returns:

a pointer to the new conjugate transposed object

Composition &operator=(const Composition&)#

Copy-assigns a Composition. The executor is not modified, and the wrapped LinOps are only being cloned if they are on a different executor.

Composition &operator=(Composition&&)#

Move-assigns a Composition. The executor is not modified, and the wrapped LinOps are only being cloned if they are on a different executor, otherwise they share ownership. The moved-from object is empty (0x0 LinOp without operators) afterwards.

Composition(const Composition&)#

Copy-constructs a Composition. This inherits the executor of the input Composition and all of its operators with shared ownership.

Composition(Composition&&)#

Move-constructs a Composition. This inherits the executor of the input Composition and all of its operators. The moved-from object is empty (0x0 LinOp without operators) afterwards.