Quantum Hypercore Case Study#
Introduction#
This case study demonstrates a complete hyper-causal DAG (Directed Acyclic Graph) experiment that integrates counterfactual projection, finite-difference training, and post-training evaluation metrics. It simulates a dynamic system with injected anomalies to assess the stability, consistency, and predictive robustness of a multi-node hyper-causal architecture.
Main objectives:
Build a synthetic dynamic environment with controlled anomalies.
Train a three-node hyper-causal DAG using counterfactual backends.
Evaluate robustness through quantitative metrics such as MAPE, Settling Time, and ROC-AUC.
—
General Flow Structure#
The experiment combines deterministic simulation with causal inference and finite-difference optimization. Each backend models a dynamic node connected through directed edges forming a DAG, where causal dependencies propagate forward in time.
SyntheticScenario: generates a temporal dataset with sinusoidal base signals and anomaly injections.
CFBackend: a parametric backend with recursive \(\tanh\) transformation and counterfactual anticipation.
HCGraph: connects nodes via directed edges to form a fully causal structure.
Loss functions: combine MSE, consistency, and coherence components.
Finite-difference optimization: updates parameters numerically per epoch.
DepthScheduler: progressively increases recursion depth through epochs.
—
How to Run#
# From the project root
python -m examples.ex_quantum_hypercore_case_study
# Or directly
python examples/ex_quantum_hypercore_case_study.py
—
Relevant Code Snippets#
1 # Base smooth signals (3 channels)
2 base = np.stack([
3 0.35 * np.sin(0.25 * t + 0.10),
4 0.20 * np.sin(0.25 * t + 0.75),
5 0.15 * np.cos(0.25 * t + 0.40),
6 ], axis=1)
7
8 # Small Gaussian noise
9 noise = 0.02 * rng.standard_normal(size=base.shape)
10
11 x_seq = base + noise
12 y_target = np.zeros_like(x_seq)
13
14 # Inject anomalies into channel 0
15 y_anom = np.zeros(self.T, dtype=float)
16 for at in self.anomaly_times:
17 if 0 <= at < self.T:
18 y_anom[at] = 1.0
19 x_seq[at:, 0] += self.anomaly_mag
20
21 return x_seq, y_target, y_anom
22
23
24# ============================================================================
25# 2) Parametric backend with counterfactual anticipator
26# ============================================================================
27def shock_up(center: Array) -> Array:
28 """What-if scenario: channel 0 increases slightly."""
29 v = center.copy()
30 v[0] += 0.10
31 return v
32
33
34def shock_down(center: Array) -> Array:
35 """What-if scenario: channel 0 decreases slightly."""
36 v = center.copy()
37 v[0] -= 0.10
38 return v
39
40
41def lateral_shift(center: Array) -> Array:
42 """What-if scenario: small lateral shift in channel 1."""
43 v = center.copy()
44 v[1] += 0.06
45 return v
46
47
48class CFBackend(BaseBackend):
49 """
50 Parametric backend with counterfactual anticipation.
51
52 - ``run()``: applies a tanh transformation depth times.
53 - ``project_future()``: linear projection around s_t with counterfactual perturbations.
54 """
55
56 def __init__(
57 self, config: BackendConfig, w: float = 0.95, b: float = 0.02,
58 proj_span: float = 0.25,
59 perts: Sequence[Callable[[Array], Array]] | None = None,
60 symmetric: bool = True,
61 ):
62 super().__init__(config)
63 self.w = float(w)
64 self.b = float(b)
65 self.depth = 1
66 self._base_span = float(proj_span)
67 self._projector = LinearProjector(weight=1.0, bias=0.0, span=self._base_span)
68 self._perts = list(perts or [])
69 self._anticipator = ContrafactualAnticipator(
70 projector=self._projector,
71 perturbations=self._perts,
72 config=None,
73 )
74 self._symmetric = bool(symmetric)
75
76 def get_params(self):
77 """Return current parameters as arrays."""
78 return {"w": np.array([self.w], dtype=float),
79 "b": np.array([self.b], dtype=float)}
80
81 def set_params(self, params: dict):
82 """Set backend parameters."""
83 if "w" in params:
84 self.w = float(np.asarray(params["w"]).reshape(()))
85 if "b" in params:
86 self.b = float(np.asarray(params["b"]).reshape(()))
87
88 def run(self, params: dict | None = None) -> Array:
89 """Apply recursive tanh transformation."""
90 if params:
91 self.set_params(params)
92 x = self._require_input()
93 s = x.astype(float)
94 for _ in range(max(1, int(self.depth))):
95 s = np.tanh(self.w * s + self.b)
96 return self._validate_state(s)
97
98 def project_future(self, s_t: Array, branches: int = 2) -> Array:
99 """Generate future states using updated projector span and perturbations."""
100 s = self._validate_state(s_t)
101 k = max(2, int(branches))
102 span = max(0.05, self._base_span / (1.0 + 0.25 * (self.depth - 1)))
103 self._projector = LinearProjector(weight=1.0, bias=0.0, span=span)
104 self._anticipator = ContrafactualAnticipator(
105 projector=self._projector,
106 perturbations=self._perts,
107 config=None,
108 )
109 fut = self._anticipator.generate(s)
110 if fut.shape[0] >= k:
111 fut = fut[:k]
112 else:
113 rep = np.repeat(fut[-1][None, :], k - fut.shape[0], axis=0)
114 fut = np.concatenate([fut, rep], axis=0)
115 return self._validate_branches(fut)
116
117
118# ============================================================================
119# 3) Building the hyper-causal DAG and training utilities
120# ============================================================================
121def build_hc_dag(D=3, seed=7):
122 """Construct a minimal 3-node hyper-causal DAG."""
123 cfg = BackendConfig(output_dim=D, seed=seed)
124 bA = CFBackend(cfg, w=0.95, b=0.03, proj_span=0.22, perts=[shock_up, lateral_shift])
125 bB = CFBackend(cfg, w=1.00, b=0.01, proj_span=0.25, perts=[shock_down])
126 bC = CFBackend(cfg, w=1.05, b=0.00, proj_span=0.28, perts=[lateral_shift])
127
128 def l2_risk(branch: Array) -> float:
129 return float(np.sqrt(np.sum(branch ** 2)))
1 coh_vals = []
2 for key in ("A", "B", "C"):
3 branches = info_map[key].get("branches", None)
4 if isinstance(branches, np.ndarray) and branches.ndim == 2:
5 coh_vals.append(loss_coh(branches))
6 if coh_vals:
7 total_coh += float(np.mean(coh_vals))
8 s_prev = s_map
9 callbacks.on_step_end(t_idx, {
10 "step": int(t_idx),
11 "norm_sC": float(np.linalg.norm(sC)),
12 "task_sC": float(loss_task(sC, y_target[t_idx])),
13 })
14 task, cons, coh = total_task / T, total_cons / max(1, T - 1), total_coh / T
15 total = task + 0.5 * cons + 0.3 * coh
16 return total, {"task": task, "cons": cons, "coh": coh, "total": total}, np.asarray(y_pred_seq), np.asarray(scores)
17
18 best = None
19 for epoch in range(EPOCHS):
20 for be in backends:
21 depth_cb.on_epoch_begin(epoch, {"backend": be})
22 callbacks.on_epoch_begin(epoch, {"epoch": int(epoch)})
23 total0, det0, _, _ = forward_sequence()
24
25 def loss_wrapper():
26 l, _, _, _ = forward_sequence()
27 return l
28
29 grads = finite_diff_grads(loss_wrapper, params, apply_params_fn)
30 params, opt_state = opt.step(params, grads, opt_state)
31 apply_params_fn(params)
32 total1, det1, _, _ = forward_sequence()
33 callbacks.on_epoch_end(epoch, {"epoch": int(epoch), "loss_before": det0, "loss_after": det1})
34
35 if best is None or det1["total"] < best["total"]:
36 best = {"epoch": int(epoch), **{k: float(v) for k, v in det1.items()}}
37
38 print(f"[Epoch {epoch}] total_before={det0['total']:.6f} total_after={det1['total']:.6f} depth={[int(be.depth) for be in backends]}")
39
40 _, _, y_pred, scores = forward_sequence()
41
42 # Evaluation
43 mape_val = mape(y_target[:, 0], y_pred[:, 0])
44 over_val = overshoot(y_target[:, 0], y_pred[:, 0])
45 setl_val = settling_time(y_target[:, 0], y_pred[:, 0], tol=0.05)
46 rob_val = robustness(y_target[:, 0], y_pred[:, 0])
47 auc_early = early_roc_auc(y_true=y_anom, scores=scores, horizon=3)
48 thr = np.percentile(scores, 80)
49 rec_lag = recall_at_lag(y_true=y_anom, y_pred=(scores > thr).astype(float), lag=3)
50
51 print("\n=== Final Metrics ===")
52 print(f"MAPE (%): {mape_val:.6f}")
53 print(f"Overshoot: {over_val:.6f}")
54 print(f"Settling Time: {int(setl_val)} samples")
55 print(f"Robustness: {rob_val:.6f}")
56 print(f"Early ROC-AUC@H=3: {auc_early:.6f}")
57 print(f"Recall@Lag=3: {rec_lag:.6f}")
58 print("\nBest epoch snapshot:", best)
59
60 if LOG_PATH.exists():
61 print("\nTelemetry JSONL →", LOG_PATH.resolve())
62
63 return {
64 "best": best,
65 "metrics": {
66 "mape": float(mape_val),
67 "overshoot": float(over_val),
68 "settling_time": int(setl_val),
69 "robustness": float(rob_val),
70 "early_auc_h3": float(auc_early),
71 "recall_lag3": float(rec_lag),
72 },
73 }
74
75
76# ============================================================================
77# 5) Entry point
78# ============================================================================
79if __name__ == "__main__":
80 summary = quantum_hypercore_case_study()
81 print("\nSummary:")
82 print(json.dumps(summary, indent=2))
—
Functional Explanation#
This experiment evaluates a hyper-causal DAG under perturbative dynamics and counterfactual projections. It integrates predictive, causal, and diagnostic components in a single computational framework.
Synthetic Dynamic Environment
The SyntheticScenario generates temporal signals with injected anomalies:
\[x_t = \sin(\omega t + \phi) + \epsilon_t, \qquad x_{t,\text{anom}} = x_t + \delta \mathbf{1}_{t \in \mathcal{A}}\]where \(\epsilon_t\) represents Gaussian noise and \(\mathcal{A}\) marks anomaly indices. This allows controlled evaluation of the model’s ability to adapt to irregular perturbations.
Counterfactual Backend
Each backend implements recursive dynamics:
\[S_t = \tanh(w S_{t-1} + b)\]and generates counterfactual future branches:
\[S_{t+1}^{(k)} = S_t + \mathcal{P}_k(S_t)\]where \(\mathcal{P}_k\) are perturbation operators encoding “what-if” transformations. This enables simultaneous evaluation of nominal and hypothetical state trajectories.
Hyper-Causal Graph Structure
The DAG is defined as:
\[\mathcal{G} = (\mathcal{V}, \mathcal{E}), \quad \mathcal{V} = \{A, B, C\}, \quad \mathcal{E} = \{A \to B, A \to C, B \to C\}\]Each node receives upstream states, applies its transformation, and emits a projected state to downstream nodes. This simulates hierarchical causal propagation within a directed structure.
Loss Composition
The total loss function integrates predictive, temporal, and coherence constraints:
\[\mathcal{L}_{total} = \mathcal{L}_{task} + 0.5\,\mathcal{L}_{consistency} + 0.3\,\mathcal{L}_{coherence}\]Task loss: prediction accuracy.
Consistency loss: stability of consecutive states.
Coherence loss: alignment across projected branches.
Each loss term contributes to maintaining causal smoothness and coherent evolution.
Training via Finite-Difference Gradients
Instead of backpropagation, gradients are computed numerically:
\[g_i = \frac{\mathcal{L}(\theta_i + \epsilon) - \mathcal{L}(\theta_i - \epsilon)}{2\epsilon}\]Parameters are updated using simple gradient descent with adaptive learning rate control.
Evaluation Metrics
After training, several metrics are computed to quantify system stability and sensitivity:
MAPE – Mean Absolute Percentage Error.
Overshoot – amplitude deviation beyond target.
Settling Time – number of samples to reach stability within tolerance.
Robustness – correlation between predicted and target signals.
Early ROC-AUC@H=3 – anomaly discrimination within a 3-step horizon.
Recall@Lag=3 – sensitivity to delayed anomaly detection.
These indicators evaluate both predictive accuracy and control stability under dynamic perturbations.
—
Exact Output#
[Epoch 0] total_before=0.098290 total_after=0.092576 depth=[1, 1, 1]
[Epoch 1] total_before=0.069731 total_after=0.062847 depth=[2, 2, 2]
[Epoch 2] total_before=0.062847 total_after=0.056539 depth=[2, 2, 2]
[Epoch 3] total_before=0.042616 total_after=0.041622 depth=[3, 3, 3]
[Epoch 4] total_before=0.041622 total_after=0.039550 depth=[3, 3, 3]
[Epoch 5] total_before=0.030317 total_after=0.029850 depth=[4, 4, 4]
=== Final Metrics ===
MAPE (%): 19094053004148.468750
Overshoot: 0.000000
Settling Time: 60 samples
Robustness: 0.957343
Early ROC-AUC@H=3: 0.224138
Recall@Lag=3: 0.000000
Best epoch snapshot: {'epoch': 5, 'task': 0.019989936715902698, 'cons': 0.015169491076939604, 'coh': 0.007584946879521136, 'total': 0.02985016631822884}
Telemetry JSONL → runs/quantum_hypercore_case_telemetry.jsonl
Summary:
{
"best": {
"epoch": 5,
"task": 0.019989936715902698,
"cons": 0.015169491076939604,
"coh": 0.007584946879521136,
"total": 0.02985016631822884
},
"metrics": {
"mape": 19094053004148.47,
"overshoot": 0.0,
"settling_time": 60,
"robustness": 0.9573428590759466,
"early_auc_h3": 0.22413793103448276,
"recall_lag3": 0.0
}
}