Source code for qbiocode.apps.quvine.fusion.fuse_fixes

# Copyright 2026, IBM Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging

import numpy as np
from numpy.linalg import svd
import scipy.sparse as sp
import scipy.sparse.linalg as spla
from typing import List, Optional


logger = logging.getLogger(__name__)

[docs] def fuse_embeddings_attention_fixed(Zs, k, temperature=1.0, mode="effective_rank"): """ FIXED: Attention-weighted SVD fusion with information-content-aware similarity. The original implementation always produced uniform weights because similarity = ||Z_norm||_F^2 / n = 1 for any row-normalized Z. """ weights_raw = [] for Z in Zs: Z = np.asarray(Z, dtype=np.float64) if mode == "effective_rank": try: _, s, _ = svd(Z, full_matrices=False) s2 = s ** 2 if s2.sum() <= 0: weights_raw.append(0.0) continue p = s2 / s2.sum() entropy = -np.sum(p * np.log(p + 1e-20)) weights_raw.append(float(np.exp(entropy))) except np.linalg.LinAlgError as exc: # LAPACK did not converge, or Z holds non-finite values. Weight 1.0 # is a neutral pre-softmax score, so this view neither dominates nor # is dropped -- but it is not a measured effective rank, so it is # logged rather than silently mixed in with the measured ones. logger.warning( "view weighting (%s): SVD failed (%s); using a neutral " "weight of 1.0 for this view", "effective_rank", exc, ) weights_raw.append(1.0) elif mode == "spectral_norm": try: _, s, _ = svd(Z, full_matrices=False) if s.mean() < 1e-12: weights_raw.append(0.0) else: weights_raw.append(float(s.max() / s.mean())) except np.linalg.LinAlgError as exc: # LAPACK did not converge, or Z holds non-finite values. Weight 1.0 # is a neutral pre-softmax score, so this view neither dominates nor # is dropped -- but it is not a measured spectral-norm ratio, so it is # logged rather than silently mixed in with the measured ones. logger.warning( "view weighting (%s): SVD failed (%s); using a neutral " "weight of 1.0 for this view", "spectral_norm", exc, ) weights_raw.append(1.0) elif mode == "variance": weights_raw.append(float(np.log1p(Z.var()))) else: raise ValueError(f"Unknown mode={mode!r}") weights_raw = np.asarray(weights_raw, dtype=np.float64) centered = (weights_raw - weights_raw.mean()) / temperature aw = np.exp(centered) / np.sum(np.exp(centered)) Z_weighted = np.concatenate([w * Z for w, Z in zip(aw, Zs)], axis=1) U, S, _ = svd(Z_weighted, full_matrices=False) k_eff = min(k, U.shape[1]) Z_fused = U[:, :k_eff] * S[:k_eff] if k_eff < k: Z_fused = np.pad(Z_fused, ((0, 0), (0, k - k_eff)), mode="constant") return Z_fused, aw
[docs] def fuse_embeddings_uniform_mean(Zs, k): """Honest baseline: simple mean of views, then SVD compression.""" if any(Z.shape[1] != Zs[0].shape[1] for Z in Zs): max_d = max(Z.shape[1] for Z in Zs) Zs = [np.pad(Z, ((0, 0), (0, max_d - Z.shape[1]))) for Z in Zs] Z_mean = np.mean(np.stack(Zs, axis=0), axis=0) U, S, _ = svd(Z_mean, full_matrices=False) k_eff = min(k, U.shape[1]) Z_fused = U[:, :k_eff] * S[:k_eff] if k_eff < k: Z_fused = np.pad(Z_fused, ((0, 0), (0, k - k_eff)), mode="constant") return Z_fused
[docs] def per_node_consensus_gate(Zs): """Compute per-node reliability score based on agreement with consensus.""" if not Zs: raise ValueError("Zs is empty") Zs_arr = np.stack([np.asarray(Z) for Z in Zs], axis=0) Zbar = Zs_arr.mean(axis=0) residuals = np.linalg.norm(Zs_arr - Zbar[None, :, :], axis=2) logits = -residuals.T logits = logits - logits.max(axis=1, keepdims=True) weights = np.exp(logits) weights = weights / weights.sum(axis=1, keepdims=True) return weights
[docs] def fuse_embeddings_consensus_gated(Zs, k): """SVD fusion with per-node consensus gating.""" n, d = Zs[0].shape W = per_node_consensus_gate(Zs) Z_weighted = np.zeros((n, d), dtype=np.float64) for v, Z in enumerate(Zs): Z_weighted += W[:, v:v+1] * Z U, S, _ = svd(Z_weighted, full_matrices=False) k_eff = min(k, U.shape[1]) Z_fused = U[:, :k_eff] * S[:k_eff] if k_eff < k: Z_fused = np.pad(Z_fused, ((0, 0), (0, k - k_eff)), mode="constant") return Z_fused, W
[docs] def calibrate_heat_kernel_fast( L, targets, node_to_idx, t_grid: Optional[np.ndarray] = None, loss: str = "l2", ): """ Vectorized heat kernel calibration. 3-4x faster than naive loop. Stacks delta vectors and calls expm_multiply once per t. """ if t_grid is None: t_grid = np.logspace(-2, 2, 40) if len(targets) == 0: raise ValueError("targets is empty") n = L.shape[0] n_targets = len(targets) # Stack delta vectors X = np.zeros((n, n_targets), dtype=np.float64) target_node_idx: List[List[int]] = [] target_p: List[np.ndarray] = [] for j, item in enumerate(targets): center = item["center"] nodes = list(item["nodes"]) idx = [node_to_idx[u] for u in nodes] p = np.asarray(item.get("pQ", item.get("p")), dtype=np.float64) p = np.maximum(p, 0.0) s = p.sum() if s <= 0: raise ValueError(f"target {j}: pQ has zero mass") p = p / s target_node_idx.append(idx) target_p.append(p) X[node_to_idx[center], j] = 1.0 best_loss = np.inf best_t: Optional[float] = None for t in t_grid: Y = spla.expm_multiply(-float(t) * L, X) if sp.issparse(L) \ else _dense_expm_multiply(-float(t) * L, X) total = 0.0 for j in range(n_targets): q = np.maximum(Y[target_node_idx[j], j], 0.0) qsum = q.sum() if qsum <= 0: continue q = q / qsum p = target_p[j] if loss == "l2": total += float(np.sum((q - p) ** 2)) elif loss == "kl": eps = 1e-12 total += float(np.sum(p * (np.log(p + eps) - np.log(q + eps)))) else: raise ValueError(f"Unknown loss {loss!r}") if total < best_loss: best_loss = total best_t = float(t) if best_t is None: raise RuntimeError("Heat kernel calibration produced no valid t") return best_loss, best_t
def _dense_expm_multiply(M, X): """Fallback for dense Laplacian.""" from scipy.linalg import expm return expm(np.asarray(M)) @ X
[docs] def calibrate_polynomial_filter_fast( L, targets, node_to_idx, K: int = 4, ridge: float = 1e-5, ) -> np.ndarray: """ Vectorized polynomial filter calibration. 2-3x faster. Builds polynomial basis as block matrix multiplications. """ if K < 0: raise ValueError("K must be non-negative") if len(targets) == 0: raise ValueError("targets is empty") n = L.shape[0] n_targets = len(targets) # Stack delta vectors X = np.zeros((n, n_targets), dtype=np.float64) target_node_idx: List[List[int]] = [] target_p: List[np.ndarray] = [] for j, item in enumerate(targets): center = item["center"] nodes = list(item["nodes"]) idx = [node_to_idx[u] for u in nodes] p = np.asarray(item.get("pQ", item.get("p")), dtype=np.float64) p = np.maximum(p, 0.0) s = p.sum() if s <= 0: raise ValueError(f"target {j}: pQ has zero mass") p = p / s target_node_idx.append(idx) target_p.append(p) X[node_to_idx[center], j] = 1.0 # Build basis tensor AtA = np.zeros((K + 1, K + 1), dtype=np.float64) Atb = np.zeros(K + 1, dtype=np.float64) V = X.copy() powers = [V.copy()] for _ in range(K): V = L @ V powers.append(np.asarray(V).copy()) # Accumulate normal equations for j in range(n_targets): idx = target_node_idx[j] Phi = np.stack([powers[k][idx, j] for k in range(K + 1)], axis=1) AtA += Phi.T @ Phi Atb += Phi.T @ target_p[j] AtA += float(ridge) * np.eye(K + 1) try: coeffs = np.linalg.solve(AtA, Atb) except np.linalg.LinAlgError: coeffs = np.linalg.lstsq(AtA, Atb, rcond=None)[0] if not np.all(np.isfinite(coeffs)): raise RuntimeError("Polynomial calibration produced non-finite coefficients") return coeffs