Skip to content

ConstrainMatrix

ConstrainMatrix(cost)

Builder for the linear constraint matrix H used in state-vector minimization.

Constructs and accumulates pairwise equality constraints between state components, then returns a full-column-rank H matrix suitable for passing to minimize_x or minimize_v.

The constrained minimization is:

\[ \hat{x} = \operatorname{arg\,min}_x J(x) \quad \text{s.t.}\quad x = H v \]

Parameters:

Methods:

  • constrain

    Add a constraint between two state indices.

  • constrain_by_labels

    Add a constraint between two state variables identified by label.

  • digest

    Return a snapshot of the constraint matrix with redundant columns removed.

  • print_table

    Prints the actual table of constraints to the console

Attributes:

  • TSLM_TYPES

    tuple of str : Supported Two-Sided Line Model constraint type names.

Source code in lmlib/statespace/cost.py
def __init__(self, cost):
    assert isinstance(cost, (CompositeCost, CostSegment)), 'cost not of type CompositeCost,'
    self._cost = cost
    self._N = self._cost.get_alssm_order()
    self._data = np.eye(self._N)

Methods

constrain

constrain(indices, value)

Add a constraint between two state indices.

Sets H[indices[0], indices[1]] = value and H[indices[1], indices[0]] = value, creating a symmetric dependency between the two state components.

Parameters:

  • indices (array_like of shape (2,)) –

    Pair of state indices to constrain.

  • value (float) –

    Constraint value placed at both off-diagonal positions.

Returns:

Source code in lmlib/statespace/cost.py
def constrain(self, indices, value):
    """
    Add a constraint between two state indices.

    Sets ``H[indices[0], indices[1]] = value`` and
    ``H[indices[1], indices[0]] = value``, creating a symmetric dependency
    between the two state components.

    Parameters
    ----------
    indices : array_like of shape (2,)
        Pair of state indices to constrain.
    value : float
        Constraint value placed at both off-diagonal positions.

    Returns
    -------
    self : ConstrainMatrix
        Returns self to allow method chaining.
    """
    assert 0 <= indices[0] < self._N, f'first index not in range [0, {self._N - 1}]'
    assert 0 <= indices[1] < self._N, f'second index not in range [0, {self._N - 1}]'
    self._data[indices[0], indices[1]] = value
    self._data[indices[1], indices[0]] = value
    return self

constrain_by_labels

constrain_by_labels(label_1, label_2, value)

Add a constraint between two state variables identified by label.

Looks up the state indices for label_1 and label_2 and delegates to constrain.

Parameters:

  • label_1 (str) –

    Label of the first state variable.

  • label_2 (str) –

    Label of the second state variable.

  • value (float) –

    Constraint value.

Returns:

Source code in lmlib/statespace/cost.py
def constrain_by_labels(self, label_1, label_2, value):
    r"""
    Add a constraint between two state variables identified by label.

    Looks up the state indices for ``label_1`` and ``label_2`` and delegates
    to [`constrain`][lmlib.statespace.cost.ConstrainMatrix.constrain].

    Parameters
    ----------
    label_1 : str
        Label of the first state variable.
    label_2 : str
        Label of the second state variable.
    value : float
        Constraint value.

    Returns
    -------
    self : ConstrainMatrix
        Returns self to allow method chaining.
    """

    index_1 = self._cost.get_state_var_indices(label_1)
    index_2 = self._cost.get_state_var_indices(label_2)
    assert len(index_1) == 1, 'index of label_1 contains more the one element'
    assert len(index_2) == 1, 'index of label_2 contains more the one element'
    return self.constrain(index_1 + index_2, value)

digest

digest()

Return a snapshot of the constraint matrix with redundant columns removed.

Removes columns that are zero, duplicate, or linearly dependent on other columns before returning, yielding a full-column-rank H matrix.

Returns:

  • H ( ndarray of shape (N, K) ) –

    Constraint matrix, where K <= N is the number of independent constraints remaining after redundancy removal.

Source code in lmlib/statespace/cost.py
def digest(self):
    r"""
    Return a snapshot of the constraint matrix with redundant columns removed.

    Removes columns that are zero, duplicate, or linearly dependent on other
    columns before returning, yielding a full-column-rank H matrix.

    Returns
    -------
    H : ndarray of shape (N, K)
        Constraint matrix, where K <= N is the number of independent constraints
        remaining after redundancy removal.
    """
    H = self._data.copy()

    del_cols = []

    # append identical columns to del_cols
    for n in range(self._N):
        indices = np.flatnonzero(np.all(H[n, :] == H, axis=1))
        if indices.size > 1:
            del_cols.extend(np.sort(indices)[1:])

    # append zero columns to del_cols
    del_cols.extend(np.where(~H.any(axis=0))[0])

    # check if all combinations of columns in H are a mulitple of each-other when yes add last one to del_cols
    for j, c1 in enumerate(H.T):
        c1_norm = np.linalg.norm(c1)
        if c1_norm != 0.0:
            for i, c2 in enumerate(H.T):
                c2_norm = np.linalg.norm(c2)
                if c2_norm != 0.0:
                    is_multiple = np.all(np.divide(c1, c1_norm) - np.divide(c2, c2_norm) == 0.0)
                    is_multiple = is_multiple or np.all(
                        np.divide(-1 * c1, np.linalg.norm(-1 * c1)) - np.divide(c2, c2_norm) == 0.0)
                    if is_multiple and i > j:
                        del_cols.append(i)

    # delete columns
    if len(del_cols) > 0:
        return np.delete(H, np.unique(del_cols), 1)
    return H

print_table

print_table()

Prints the actual table of constraints to the console

Source code in lmlib/statespace/cost.py
def print_table(self):
    """Prints the actual table of constraints to the console"""
    print(*[f' {c}' for c in range(self._N)])
    print(' ——' * self._N)
    for r, row in enumerate(self._data):
        print(row, ' | ', r)