""" Coherent collapse -- complex amplitudes and real interference. Why this module exists ---------------------- Every "quantum" operation in v44 reduced to a classical one with a physics name attached. The Born rule was the clearest case: amplitude = exp(-E / 2T); L2-normalize; probability = amplitude^2 is *algebraically identical* to softmax(-E / T) when the amplitudes are real and non-negative -- verified numerically to fp32 epsilon (5.96e-08). And with no phases, |sum_k c_k|^2 = sum_k |c_k|^2 exactly: there are no cross-terms, so nothing can interfere. The module named "interference" could not interfere; the "collapse" was a temperature- scaled softmax; the "superposition" was a tensor axis. v45 gives each hypothesis a complex amplitude c_k = r_k * exp(i * phi_k) and each (hypothesis, option) compatibility a complex amplitude v_kn = t_kn * exp(i * theta_kn), t_kn = exp(-E_kn / 2T) and scores option n by the expectation of a rank-1 Hermitian projector P_n = |v_n> = sum_k c_k |k>: = | sum_k c_k v_kn |^2 = sum_k |c_k|^2 |v_kn|^2 <- classical + sum_{i != j} 2 Re(c_i conj(c_j) v_in conj(v_jn)) The second line is the whole point. It is a genuine cross-term, it can be NEGATIVE, and therefore two hypotheses can cancel each other's support for an option. That is destructive interference, it is not expressible as a mixture over a latent variable, and it is the one place this project earns the word "quantum". P_n is Hermitian and positive semi-definite, so is real and non-negative -- a legitimate measurement, not a metaphor. The classical line is exactly the decohered (diagonal) limit, which is what `phase_mode="classical"` computes. Falsifiability -------------- This is a claim, so it ships with the test. `interference_ratio` is mean|coherent - classical| / mean(classical), reported every epoch. If it sits at ~0, the phases learned nothing and the coherent formulation is inert -- exactly the failure mode of every previous "quantum" component here, and it will show up as a number instead of hiding behind an accuracy that looks plausible. The ablation grid contains parameter-matched `phase_mode="zero"` and `phase_mode="classical"` arms so the effect can be attributed rather than assumed. v46 adds the comparison those diagnostics cannot make. `interference_ratio`, `phase_effect` and `destructive_fraction` all say the mechanism is LIVE; none of them says it helps. `destructive_fraction` is the clearest case: with K = 2N matched support/attack pairs and near-equal amplitudes it is a step function of the single relative phase between the two channels (models/full_model.py::polarity_phase). Sweeping that scalar through this module with everything else held fixed gives 0.000 from 0 to 1.6 rad, 0.494 at 2.4, 0.994 at 2.8, and 1.000 at 3.0 and above -- and it is initialized at pi, past the step, so it reads 1.0 for an untrained model. The number that decides the claim is therefore `coherent_acc` vs `classical_acc` in training/evaluate.py: the accuracy of ranking options by `coherent` against ranking them by `classical`, the decohered limit of the SAME amplitudes over the SAME energies in the same forward pass. If the coherent sum does not rank options better than the mixture it replaced, the complex amplitudes are not earning their place however live they measure. Modes ----- "learned" full complex amplitudes; phases supplied by the caller "zero" coherent sum, all phases pinned to 0 -- constructive only. Isolates "having phases" from "summing amplitudes before squaring", which are two different claims. "classical" diagonal/decohered: P(n) = sum_k |c_k|^2 |v_kn|^2, i.e. a plain probability-weighted mixture over hypotheses, the v44 behaviour. """ import torch import torch.nn as nn import torch.nn.functional as F MODES = ("learned", "zero", "classical") class CoherentCollapse(nn.Module): def __init__(self, phase_mode="learned"): super().__init__() if phase_mode not in MODES: raise ValueError(f"phase_mode must be one of {MODES}, got {phase_mode!r}") self.phase_mode = phase_mode # Two temperatures, one per axis. Stored as logits into # 0.3 + softplus(.) so they stay strictly positive without a # clamp, and start near 1.0. self.hypothesis_temp = nn.Parameter(torch.tensor(0.5413)) self.option_temp = nn.Parameter(torch.tensor(0.5413)) def forward( self, collapse_energy, answer_energy, phase_h=None, phase_kn=None, H_mask=None, O_mask=None, hyp_temperature=None, ): """ collapse_energy : (B, K) fused per-hypothesis energy answer_energy : (B, K, N) per (hypothesis, option) energy phase_h : (B, K) hypothesis phases, radians phase_kn : (B, K, N) compatibility phases, radians H_mask : (B, K) bool O_mask : (B, N) bool hyp_temperature : (B, 1) optional per-sample temperature from models/collapse.py, overriding the global one Returns log-probabilities over options. They are already normalized, so F.cross_entropy(log_probs, y) is exact: log_softmax(log p) = log p - log(sum p) = log p. """ B, K, N = answer_energy.shape # ------------------------------------------------------------ # Hypothesis amplitudes r_k, normalized so sum_k r_k^2 = 1 # ------------------------------------------------------------ if hyp_temperature is not None: t_hyp = hyp_temperature else: t_hyp = 0.3 + F.softplus(self.hypothesis_temp) log_r = -collapse_energy / (2.0 * t_hyp) if H_mask is not None: log_r = log_r.masked_fill(~H_mask, float("-inf")) log_r = log_r - log_r.max(dim=1, keepdim=True).values r = torch.exp(log_r) r = r / torch.sqrt((r ** 2).sum(dim=1, keepdim=True) + 1e-8) # |c_k|^2 -- the marginal weight of each hypothesis. Same object # v44 called `collapse_probs`, kept under that name so the # existing collapse diagnostics and input-ablation checks read # the same quantity. collapse_probs = r.pow(2) collapse_probs = collapse_probs / ( collapse_probs.sum(dim=1, keepdim=True) + 1e-8 ) # ------------------------------------------------------------ # Compatibility amplitudes t_kn # ------------------------------------------------------------ t_opt = 0.3 + F.softplus(self.option_temp) log_t = -answer_energy / (2.0 * t_opt) invalid = torch.zeros(B, K, N, dtype=torch.bool, device=log_t.device) if H_mask is not None: invalid = invalid | ~H_mask.view(B, K, 1) if O_mask is not None: invalid = invalid | ~O_mask.view(B, 1, N) log_t = log_t.masked_fill(invalid, float("-inf")) # Per-sample max subtraction over BOTH axes jointly: answer_energy # is clamped to +/-12 upstream and the temperature can fall to # 0.3, so exp(-E/2T) reaches e^20 without this. log_t = log_t - log_t.reshape(B, -1).max(dim=1).values.view(B, 1, 1) t = torch.exp(log_t) # ------------------------------------------------------------ # Classical (decohered) and coherent option weights # ------------------------------------------------------------ w = r.unsqueeze(-1) * t # |c_k| * |v_kn| classical = (w ** 2).sum(dim=1) # (B, N) # The in-phase (all phases 0) coherent sum. Reference point for # `phase_effect` below, and the value used directly in "zero" # mode. in_phase = w.sum(dim=1) ** 2 if self.phase_mode == "classical": coherent = classical elif self.phase_mode == "zero" or phase_h is None: coherent = in_phase else: phase = phase_h.unsqueeze(-1).expand_as(w) if phase_kn is not None: phase = phase + phase_kn real = (w * torch.cos(phase)).sum(dim=1) imag = (w * torch.sin(phase)).sum(dim=1) coherent = real ** 2 + imag ** 2 interference = coherent - classical # ------------------------------------------------------------ # Normalize to a distribution over options # ------------------------------------------------------------ weights = coherent if O_mask is not None: weights = weights.masked_fill(~O_mask, 0.0) weights = weights.clamp(min=1e-12) log_probs = torch.log(weights) - torch.log( weights.sum(dim=1, keepdim=True) ) if O_mask is not None: neg_inf = torch.finfo(log_probs.dtype).min / 2 log_probs = log_probs.masked_fill(~O_mask, neg_inf) # ------------------------------------------------------------ # Diagnostics # ------------------------------------------------------------ if O_mask is not None: om = O_mask.to(classical.dtype) else: om = torch.ones_like(classical) denom = om.sum().clamp(min=1.0) def masked_mean(t): return (t * om).sum() / denom mean_classical = masked_mean(classical) # How far the coherent sum is from the decohered mixture. Note # that this is LARGE even with all phases at zero -- a purely # constructive coherent sum is already a long way from a # mixture -- so it says "amplitudes are being summed before # squaring", not "the phases are doing something". interference_ratio = masked_mean(interference.abs()) / ( mean_classical + 1e-12 ) # The two numbers that actually test the phase channel: # # phase_effect how much the learned phases move the # result away from the in-phase sum. Zero # means the phases are inert and this is # just constructive summation. # destructive_fraction the share of (sample, option) entries # where the cross-term is NEGATIVE, i.e. # hypotheses cancelling. It is identically # 0 for phase_mode "zero" and "classical", # because a sum of non-negative terms # cannot cancel. Anything above 0 here is # destructive interference, which no # mixture over a latent variable can # express. phase_effect = masked_mean((coherent - in_phase).abs()) / ( masked_mean(in_phase) + 1e-12 ) destructive_fraction = masked_mean((interference < 0).to(classical.dtype)) # Relative spread of the option weights, (max - min) / mean, for # the coherent sum and for the decohered mixture it replaced. # # Read the obvious way round this is actively misleading, so state # it explicitly: contrast RISES under cancellation. When the # coherent sum nearly cancels, what survives is a small residual, # and the relative spread of a small residual is amplified. A high # `coherent_contrast` therefore says the phases pulled the option # weights apart -- NOT that they pulled the correct option away # from the rest. Separating those two takes `ece` and the # coherent_acc vs classical_acc comparison in evaluate.py. valid_opt = om > 0 n_opt = om.sum(dim=1).clamp(min=1.0) def option_contrast(x): x_mean = (x * om).sum(dim=1) / n_opt x_max = x.masked_fill(~valid_opt, float("-inf")).max(dim=1).values x_min = x.masked_fill(~valid_opt, float("inf")).min(dim=1).values return ((x_max - x_min) / (x_mean + 1e-12)).mean() coherent_contrast = option_contrast(coherent).detach() classical_contrast = option_contrast(classical).detach() entropy = -( log_probs.exp() * log_probs.clamp(min=-30) ).sum(dim=1) return { "log_probs": log_probs, "probabilities": log_probs.exp(), "collapse_probs": collapse_probs, "amplitude": r, "classical": classical, "coherent": coherent, "interference": interference, "interference_ratio": interference_ratio, "phase_effect": phase_effect, "destructive_fraction": destructive_fraction, "coherent_contrast": coherent_contrast, "classical_contrast": classical_contrast, "answer_entropy": entropy.mean(), "hypothesis_temperature": ( t_hyp.detach().mean() if torch.is_tensor(t_hyp) else t_hyp ), "option_temperature": t_opt.detach(), }