import numpy as np class SpectralEdgeController: """Multiplicative edge controller for h'=tanh(g W h + input).""" def __init__(self, target=0.9, alpha=0.25, g_min=1e-3, g_max=3.0): self.target = float(target) self.alpha = float(alpha) self.g_min, self.g_max = float(g_min), float(g_max) self.g = 1.0 @staticmethod def edge_estimate(W, derivative, iterations=5, rng=None): # Singular edge of D W is robust when the nonlinear local Jacobian is nonsymmetric. rng = np.random.default_rng() if rng is None else rng v = rng.normal(size=W.shape[0]); v /= np.linalg.norm(v) for _ in range(iterations): u = derivative * (W @ v) nu = np.linalg.norm(u) if nu == 0: return 0.0 u /= nu v = W.T @ (derivative * u) nv = np.linalg.norm(v) if nv == 0: return 0.0 v /= nv return float(np.linalg.norm(derivative * (W @ v))) def update(self, edge): self.g *= np.exp(self.alpha * (self.target - self.g * edge)) self.g = float(np.clip(self.g, self.g_min, self.g_max)) return self.g