Skip to content

NDCompositeCost

NDCompositeCost(cost_terms: List[Union[CompositeCost, CostSegment]])

Bases: BaseCost


              flowchart TD
              lmlib.statespace.cost.NDCompositeCost[NDCompositeCost]
              lmlib.statespace.cost.BaseCost[BaseCost]

                              lmlib.statespace.cost.BaseCost --> lmlib.statespace.cost.NDCompositeCost
                


              click lmlib.statespace.cost.NDCompositeCost href "" "lmlib.statespace.cost.NDCompositeCost"
              click lmlib.statespace.cost.BaseCost href "" "lmlib.statespace.cost.BaseCost"
            

N-dimensional composite cost function over multiple signal dimensions.

Wraps a list of CompositeCost or CostSegment objects, one per signal dimension. The Gram matrix is formed as the Kronecker product of the per-dimension Gram matrices, enabling separable multi-dimensional filtering.

Parameters:

  • cost_terms (list of CompositeCost or CostSegment) –

    One cost term per dimension. All terms must share the same ALSSM output dimension Q.

Examples:

Build a separable 2-D cost from two 1-D CompositeCost terms (one per image axis) and filter a 2-D signal — the pattern used for 2-D ALSSM filtering in the Text Recognition example (ex801):

import numpy as np
import lmlib as lm

# A two-sided Legendre line model, reused on each image axis
g, l_side, poly_degree = 100, 35, 2
alssm_left  = lm.AlssmPolyLegendre(poly_degree, a_seg=-l_side, b_seg=-1)
alssm_right = lm.AlssmPolyLegendre(poly_degree, a_seg=0, b_seg=l_side)
segment_left  = lm.Segment(a=-l_side, b=-1, direction=lm.FW, g=g)
segment_right = lm.Segment(a=0, b=l_side, direction=lm.BW, g=g)
F = [[1, 0], [0, 1]]   # mixing matrix (per-segment model on/off)

# One CompositeCost per image dimension, wrapped into an NDCompositeCost
cost_dim1 = lm.CompositeCost([alssm_left, alssm_right], [segment_left, segment_right], F)
cost_dim2 = lm.CompositeCost([alssm_left, alssm_right], [segment_left, segment_right], F)
nd_cost = lm.NDCompositeCost([cost_dim1, cost_dim2])

# Filter a 2-D signal and recover the per-pixel state estimates
Y = np.random.randn(80, 60)
rls = lm.RLSAlssm(nd_cost, backend='lfilter')
rls.filter(Y)
xs = rls.minimize_x()   # shape (80, 60, 36)

Initialise an NDCompositeCost.

Parameters:

  • cost_terms (list of CompositeCost or CostSegment) –

    One cost term per dimension L.

Methods:

Attributes:

  • cost_terms

    list : Per-dimension cost terms (CompositeCost or CostSegment).

  • L

    int : Number of Dimensions/Costs \(L\)

  • label

    str : Label of the Cost Model

Source code in lmlib/statespace/cost.py
def __init__(self, cost_terms: List[Union[CompositeCost, CostSegment]]):
    """
    Initialise an NDCompositeCost.

    Parameters
    ----------
    cost_terms : list of CompositeCost or CostSegment
        One cost term per dimension L.
    """
    self.cost_terms = cost_terms

Methods

get_number_of_dimensions

get_number_of_dimensions()

Return the number of signal dimensions L.

Source code in lmlib/statespace/cost.py
def get_number_of_dimensions(self):
    """Return the number of signal dimensions L."""
    return self.L

get_alssm_order

get_alssm_order()

Return the Kronecker-product state order N = prod(N_l for l in dims).

Source code in lmlib/statespace/cost.py
def get_alssm_order(self):
    """Return the Kronecker-product state order N = prod(N_l for l in dims)."""
    return int(np.prod([cost.get_alssm_order() for cost in self.cost_terms]))

get_alssm_output_dimension

get_alssm_output_dimension()

Return the output dimension Q (shared across all dimensions).

Source code in lmlib/statespace/cost.py
def get_alssm_output_dimension(self):
    """Return the output dimension Q (shared across all dimensions)."""
    return self.cost_terms[0].get_alssm_output_dimension()

get_steady_state_W

get_steady_state_W(dim_order=None, method='schur')

Compute the n-dimensional steady-state Gram matrix as a Kronecker product.

Parameters:

  • dim_order (list of int or None, default: None ) –

    Order in which dimensions are Kronecker-multiplied. Default: range(self.L).

  • method (str, default: 'schur' ) –

    Forwarded to each per-dimension get_steady_state_W.

Returns:

  • W ( ndarray of shape (N, N) ) –

    Combined steady-state Gram matrix.

Source code in lmlib/statespace/cost.py
def get_steady_state_W(self, dim_order=None, method='schur'):
    """
    Compute the n-dimensional steady-state Gram matrix as a Kronecker product.

    Parameters
    ----------
    dim_order : list of int or None, optional
        Order in which dimensions are Kronecker-multiplied.
        Default: ``range(self.L)``.
    method : str, optional
        Forwarded to each per-dimension ``get_steady_state_W``.

    Returns
    -------
    W : ndarray of shape (N, N)
        Combined steady-state Gram matrix.
    """
    if dim_order is None:
        dim_order = range(self.L)

    W = [1]
    for n in dim_order:
        W = np.kron(W, self.cost_terms[n].get_steady_state_W(method))
    return W

eval_alssm_output

eval_alssm_output(xs, nd_alssm_weights=None)

Evaluate the n-dimensional ALSSM output.

Forms a separable (Kronecker-product) ALSSM from the per-dimension sub-models and evaluates it at each state vector in xs.

Parameters:

  • xs (array_like of shape (..., N)) –

    State vectors at which to evaluate the output. The last axis must equal the combined model order \(N = \prod_l N_l\).

  • nd_alssm_weights (array_like of shape (L, M), default: None ) –

    Per-ALSSM output weights for each signal dimension. Element [l, m] scales the output of ALSSM m in dimension l. If None, all ALSSMs in every dimension contribute equally.

Returns:

  • out ( ndarray of shape (..., [Q]) ) –

    ALSSM output evaluated at each state vector in xs. The [Q] dimension is present only when is_MC is True.

Source code in lmlib/statespace/cost.py
def eval_alssm_output(self, xs, nd_alssm_weights=None):
    r"""
    Evaluate the n-dimensional ALSSM output.

    Forms a separable (Kronecker-product) ALSSM from the per-dimension
    sub-models and evaluates it at each state vector in ``xs``.

    Parameters
    ----------
    xs : array_like of shape (..., N)
        State vectors at which to evaluate the output. The last axis must
        equal the combined model order $N = \prod_l N_l$.
    nd_alssm_weights : array_like of shape (L, M), optional
        Per-ALSSM output weights for each signal dimension.  Element
        ``[l, m]`` scales the output of ALSSM ``m`` in dimension ``l``.
        If ``None``, all ALSSMs in every dimension contribute equally.

    Returns
    -------
    out : ndarray of shape (..., [Q])
        ALSSM output evaluated at each state vector in ``xs``.
        The ``[Q]`` dimension is present only when [`is_MC`][lmlib.statespace.model.ModelBase.is_MC] is True.
    """
    alssms = []
    for l in range(self.L):
        sub_cost = self._get_sub_cost_term(dim=l)
        if nd_alssm_weights is not None:
            alssms.append(AlssmSum(sub_cost.alssms, nd_alssm_weights[l]))
        else:
            alssms.append(AlssmSum(sub_cost.alssms))
    alssm = AlssmProd(alssms)
    return alssm.eval_output(xs)