Source code for qmlhc.examples.ex_minimal_core_demo

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Example 01 – Minimal Core Demo
------------------------------
Minimal flow of a hyper-causal model:

    x_t → Backend (encode/run) → HCNode (project + policy) → Ŝ_{t+1} → ConsistencyLoss

Modules exercised
-----------------
- qmlhc.core: contracts, BackendConfig, QuantumBackend (base), HCModel
- qmlhc.hc: HCNode, MeanPolicy
- qmlhc.loss: ConsistencyLoss
"""

from __future__ import annotations
import numpy as np

# Core and contracts
from qmlhc.core import BackendConfig, QuantumBackend as BaseBackend, HCModel
# Node + policy
from qmlhc.hc import HCNode, MeanPolicy
# Triadic consistency loss
from qmlhc.loss import ConsistencyLoss


# ---------------------------------------------------------------------------
# 1) Minimal concrete backend (inherits from base and implements run/project_future)
# ---------------------------------------------------------------------------

[docs] class ToyBackend(BaseBackend): """ Demonstrative backend, deterministic and numerically stable. This backend defines the minimal deterministic behavior for demonstration purposes. It applies a smooth nonlinear transformation to the encoded input and generates future projections through uniform perturbations. Methods ------- run(params=None) Applies a tanh-based transformation to the encoded input. project_future(s_t, branches=2) Generates K possible future states. """
[docs] def run(self, params: dict | None = None) -> np.ndarray: """ Apply a smooth nonlinear transformation to the last encoded input. Parameters ---------- params : dict or None, optional Optional parameters (not used in this minimal demo). Returns ------- np.ndarray The transformed state vector ``s_t``. """ # Ensure that encode(x) was called before and fetch the last input. x = self._require_input() # Simple and stable transformation (tanh of a small affine bias). w = 0.95 b = 0.05 s_t = np.tanh(w * x + b) # Validate shape against output_dim (for real adapters that may change D at runtime). s_t = self._validate_state(s_t) return s_t
[docs] def project_future(self, s_t: np.ndarray, branches: int = 2) -> np.ndarray: """ Generate K future states around the current state. Parameters ---------- s_t : np.ndarray Current state vector. branches : int, optional Number of future branches (K). Default is 2. Returns ------- np.ndarray Future states matrix with shape ``(K, D)``. """ # Validate current state and K. s = self._validate_state(s_t) k = max(2, int(branches)) # Uniform deltas in [-span, +span]; added to s_t and passed through tanh. span = 0.25 deltas = np.linspace(-span, span, k, dtype=float) futures = np.stack([np.tanh(s + d) for d in deltas], axis=0) # (K, D) futures = self._validate_branches(futures) return futures
# --------------------------------------------------------------------------- # 2) Demo: forward pass of a single node + consistency loss # ---------------------------------------------------------------------------
[docs] def minimal_core_demo() -> None: """ Run a minimal demonstration of the hyper-causal model. This function performs a full pass through a minimal hyper-causal pipeline: it initializes a backend, defines a node with mean policy, executes the forward step, and computes the triadic consistency loss. The results are printed to the console for inspection. Returns ------- None Prints the results directly to the console. """ # State dimension and configuration. D = 3 K = 3 cfg = BackendConfig(output_dim=D, seed=42) # Instantiate backend and node with mean policy. backend = ToyBackend(cfg) policy = MeanPolicy() node = HCNode(backend=backend, policy=policy) # Example data: input x_t and previous state s_{t-1}. x_t = np.array([0.20, -0.10, 0.40], dtype=float) # (D,) s_tm1 = np.array([0.15, -0.05, 0.35], dtype=float) # (D,) # Execute hyper-causal step in the node. s_t, s_tp1_hat, info = node.forward(x_t, s_tm1=s_tm1, branches=K) # Triadic consistency loss. consistency = ConsistencyLoss(alpha=1.0, beta=1.0) loss_val = consistency(s_tm1, s_t, s_tp1_hat) # Display results. print("=== Minimal Core Demo ===") print(f"output_dim (D): {D}") print(f"branches (K): {K}\n") print("x_t: ", x_t) print("S_{t-1} (s_tm1): ", s_tm1) print("S_t (from run): ", s_t) print("Ŝ_{t+1} (selected): ", s_tp1_hat) print("\nNode information (summary):") print(" policy: ", info.get("policy")) branches_mat = info.get("branches") if isinstance(branches_mat, np.ndarray): print(" branches shape: ", branches_mat.shape) print(" branches[0]: ", branches_mat[0]) print("\nConsistencyLoss:") print(" L = α||S_t - S_{t-1}||^2 + β||S_t - Ŝ_{t+1}||^2") print(" α = 1.0, β = 1.0") print(" loss =", loss_val) # (Optional) Validate the same flow through HCModel with a single node. model = HCModel([node]) s_t_m, s_tp1_hat_m, info_m = model.forward(x_t, s_tm1=s_tm1, branches=K) assert np.allclose(s_t, s_t_m) and np.allclose(s_tp1_hat, s_tp1_hat_m) print("\nHCModel.forward() matches single-node result ✔")
# --------------------------------------------------------------------------- # 3) Entry point # --------------------------------------------------------------------------- if __name__ == "__main__": minimal_core_demo()