Source code for qmlhc.loss.consistency
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Triadic Consistency Loss
------------------------
Enforces coherence among past, present, and projected future states
(`S_{t-1}`, `S_t`, `Ŝ_{t+1}`).
This loss penalizes deviations between the current state and both its
immediate predecessor and projected successor, promoting smooth temporal
evolution in hypercausal models.
"""
from __future__ import annotations
import numpy as np
from ..core.types import Array, LossFn, TensorLike
[docs]
class ConsistencyLoss(LossFn):
"""
Compute triadic consistency loss.
Penalizes incoherence between the previous, current, and projected
future states. The overall loss is a weighted sum of the mean squared
deviations between consecutive temporal states.
Parameters
----------
alpha : float, optional
Weight for the present–past term, by default ``1.0``.
beta : float, optional
Weight for the present–future term, by default ``1.0``.
Notes
-----
This formulation stabilizes dynamic state transitions by encouraging
local temporal consistency:
``L = α‖S_t - S_{t-1}‖² + β‖S_t - Ŝ_{t+1}‖²``.
"""
def __init__(self, alpha: float = 1.0, beta: float = 1.0):
# Alpha weights present–past coherence; beta weights present–future coherence.
self._a = float(alpha)
self._b = float(beta)
def __call__(self, s_tm1: TensorLike, s_t: TensorLike, s_tp1_hat: TensorLike) -> float:
"""
Evaluate the triadic consistency loss.
Parameters
----------
s_tm1 : TensorLike
Previous state vector ``S_{t-1}``.
s_t : TensorLike
Current state vector ``S_t``.
s_tp1_hat : TensorLike
Projected future state vector ``Ŝ_{t+1}``.
Returns
-------
float
Weighted triadic consistency loss.
Raises
------
ValueError
If input vectors differ in dimensionality.
"""
s1 = np.asarray(s_tm1, dtype=float).reshape(-1)
s2 = np.asarray(s_t, dtype=float).reshape(-1)
s3 = np.asarray(s_tp1_hat, dtype=float).reshape(-1)
if not (s1.size == s2.size == s3.size):
raise ValueError("All state vectors must have the same dimension.")
# Mean squared deviations: present–past and present–future
d_prev = np.mean((s2 - s1) ** 2)
d_fut = np.mean((s2 - s3) ** 2)
loss = self._a * d_prev + self._b * d_fut
return float(loss)