cognithread-ssm / src_wave.py
gamer729's picture
Upload src_wave.py
350f35d verified
Raw History Blame Contribute Delete
3.32 kB
import os, sys, math, struct
os.environ['JAX_PLATFORMS'] = 'cpu'
import jax
import jax.numpy as jnp
import flax.nnx as nn
import numpy as np
from typing import Tuple
print(f"=== CogniThread SSM Architecture === JAX {jax.__version__}")
###############################################################################
# 1. WAVESCALAR — Thermal Analog Wave Representation
###############################################################################
class WaveScalar(nn.Module):
"""
Encodes each scalar as a radionics scalar wave with 5 parameters:
amplitude, phase_shift, frequency, period (1/freq), fractal_dim.
v(t) = A * sin(2*pi*f*t + phi) * fractal_mod(t, D)
fractal_mod = 1 + sum_{n=1}^{N} (1/n^D) * sin(2*pi*n*f*t + n*phi)
"""
def __init__(self, shape: Tuple[int, ...], *, rngs: nn.Rngs,
init_amp_scale: float = 1.0,
freq_range: Tuple[float, float] = (0.1, 10.0),
fractal_range: Tuple[float, float] = (1.0, 2.0)):
super().__init__()
self.shape = shape
key = rngs.params()
fan_in = max(math.prod(shape), 1)
std = init_amp_scale / math.sqrt(fan_in)
self.amplitude = nn.Param(jax.random.normal(key, shape) * std)
key, sk = jax.random.split(key)
self.phase_shift = nn.Param(jax.random.uniform(sk, shape, minval=0, maxval=2*jnp.pi))
key, sk = jax.random.split(key)
lf = jax.random.uniform(sk, shape, minval=jnp.log(freq_range[0]), maxval=jnp.log(freq_range[1]))
self.frequency = nn.Param(jnp.exp(lf))
key, sk = jax.random.split(key)
self.fractal_dim = nn.Param(jax.random.uniform(sk, shape, minval=fractal_range[0], maxval=fractal_range[1]))
@property
def period(self):
return 1.0 / self.frequency.value
def fractal_mod(self, t, D, n_harm=8):
harms = jnp.arange(1, n_harm+1, dtype=jnp.float32)
w = 1.0 / jnp.power(harms, D[..., None])
f, phi = self.frequency.value, self.phase_shift.value
sigs = jnp.sin(2*jnp.pi*harms*f[..., None]*t + harms*phi[..., None])
mod = 1.0 + jnp.sum(w * sigs, axis=-1)
return mod / jnp.sqrt(1.0 + jnp.sum(w**2, axis=-1))
def evaluate(self, t=None):
if t is None:
t = jnp.array(0.0)
A = self.amplitude.value
f = self.frequency.value
phi = self.phase_shift.value
D = self.fractal_dim.value
base = A * jnp.sin(2*jnp.pi*f*t + phi)
return base * self.fractal_mod(t, D)
def decode(self):
return self.evaluate(t=jnp.array(0.0))
def rms_value(self):
A, D = self.amplitude.value, self.fractal_dim.value
harms = jnp.arange(1, 9, dtype=jnp.float32)
w = 1.0 / jnp.power(harms, D[..., None])
rf = jnp.sqrt(1.0 + jnp.sum(w**2, axis=-1)/2.0)
nm = jnp.sqrt(1.0 + jnp.sum(w**2, axis=-1))
return A / jnp.sqrt(2.0) * rf / nm
class WaveScalarLinear(nn.Module):
def __init__(self, in_f: int, out_f: int, *, rngs: nn.Rngs):
super().__init__()
self.weight = WaveScalar((out_f, in_f), rngs=rngs)
self.bias = WaveScalar((out_f,), rngs=rngs, init_amp_scale=0.01)
def __call__(self, x):
return x @ self.weight.decode().T + self.bias.decode()
print("[1/6] WaveScalar defined")