Upload 2 files
Browse files- mobius_markov.py +330 -0
- mobius_markov_docs.py +936 -0
mobius_markov.py
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
###########################################################################################################################################
|
| 2 |
+
#||||- - - |6.25.2025| - - - || MÖBIUS MARKOV || - - - |1990two| - - -|||| #
|
| 3 |
+
###########################################################################################################################################
|
| 4 |
+
import torch
|
| 5 |
+
import torch.nn as nn
|
| 6 |
+
import torch.nn.functional as F
|
| 7 |
+
import numpy as np
|
| 8 |
+
import math
|
| 9 |
+
import matplotlib.pyplot as plt
|
| 10 |
+
from typing import List, Dict, Tuple, Optional
|
| 11 |
+
|
| 12 |
+
SAFE_MIN = -1e6
|
| 13 |
+
SAFE_MAX = 1e6
|
| 14 |
+
EPS = 1e-8
|
| 15 |
+
|
| 16 |
+
#||||- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 𓅸 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -||||#
|
| 17 |
+
|
| 18 |
+
def make_safe(tensor, min_val=SAFE_MIN, max_val=SAFE_MAX):
|
| 19 |
+
zero = torch.tensor(0.0, device=tensor.device, dtype=tensor.dtype)
|
| 20 |
+
maxv = torch.tensor(max_val, device=tensor.device, dtype=tensor.dtype)
|
| 21 |
+
tensor = torch.where(torch.isnan(tensor), zero, tensor)
|
| 22 |
+
tensor = torch.where(torch.isinf(tensor), maxv, tensor)
|
| 23 |
+
return torch.clamp(tensor, min_val, max_val)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def safe_complex_division(numerator, denominator, eps=EPS):
|
| 27 |
+
denominator_conj = torch.conj(denominator)
|
| 28 |
+
norm_sq = torch.real(denominator * denominator_conj)
|
| 29 |
+
norm_sq = torch.clamp(norm_sq, min=eps)
|
| 30 |
+
return (numerator * denominator_conj) / norm_sq
|
| 31 |
+
|
| 32 |
+
###########################################################################################################################################
|
| 33 |
+
####################################################- - - MÖBIUS TRANSFORM - - -#######################################################
|
| 34 |
+
|
| 35 |
+
class MobiusTransform(nn.Module):
|
| 36 |
+
def __init__(self, learnable=True, init_identity=True):
|
| 37 |
+
super().__init__()
|
| 38 |
+
self.learnable = learnable
|
| 39 |
+
|
| 40 |
+
if init_identity:
|
| 41 |
+
a_init, b_init, c_init, d_init = 1.0, 0.0, 0.0, 1.0
|
| 42 |
+
else:
|
| 43 |
+
a_init, d_init = 1.0, 1.0
|
| 44 |
+
b_init, c_init = 0.1, 0.1
|
| 45 |
+
|
| 46 |
+
if learnable:
|
| 47 |
+
self.a = nn.Parameter(torch.tensor([a_init, 0.0]))
|
| 48 |
+
self.b = nn.Parameter(torch.tensor([b_init, 0.0]))
|
| 49 |
+
self.c = nn.Parameter(torch.tensor([c_init, 0.0]))
|
| 50 |
+
self.d = nn.Parameter(torch.tensor([d_init, 0.0]))
|
| 51 |
+
else:
|
| 52 |
+
self.register_buffer('a', torch.tensor([a_init, 0.0]))
|
| 53 |
+
self.register_buffer('b', torch.tensor([b_init, 0.0]))
|
| 54 |
+
self.register_buffer('c', torch.tensor([c_init, 0.0]))
|
| 55 |
+
self.register_buffer('d', torch.tensor([d_init, 0.0]))
|
| 56 |
+
|
| 57 |
+
def to_complex(self, param):
|
| 58 |
+
return torch.complex(param[0], param[1])
|
| 59 |
+
|
| 60 |
+
def get_determinant(self):
|
| 61 |
+
a_complex = self.to_complex(self.a)
|
| 62 |
+
b_complex = self.to_complex(self.b)
|
| 63 |
+
c_complex = self.to_complex(self.c)
|
| 64 |
+
d_complex = self.to_complex(self.d)
|
| 65 |
+
|
| 66 |
+
det = a_complex * d_complex - b_complex * c_complex
|
| 67 |
+
return det
|
| 68 |
+
|
| 69 |
+
def normalize_parameters(self):
|
| 70 |
+
if self.learnable:
|
| 71 |
+
with torch.no_grad():
|
| 72 |
+
det = torch.abs(self.get_determinant())
|
| 73 |
+
if det < EPS:
|
| 74 |
+
one = torch.tensor([1.0, 0.0], device=self.a.device, dtype=self.a.dtype)
|
| 75 |
+
self.a.copy_(one)
|
| 76 |
+
self.d.copy_(one)
|
| 77 |
+
self.b.mul_(0.1)
|
| 78 |
+
self.c.mul_(0.1)
|
| 79 |
+
for p in (self.a, self.b, self.c, self.d):
|
| 80 |
+
p.clamp_(-10.0, 10.0)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def transform(self, z):
|
| 84 |
+
self.normalize_parameters()
|
| 85 |
+
|
| 86 |
+
a_complex = self.to_complex(self.a)
|
| 87 |
+
b_complex = self.to_complex(self.b)
|
| 88 |
+
c_complex = self.to_complex(self.c)
|
| 89 |
+
d_complex = self.to_complex(self.d)
|
| 90 |
+
|
| 91 |
+
numerator = a_complex * z + b_complex
|
| 92 |
+
denominator = c_complex * z + d_complex
|
| 93 |
+
transformed = safe_complex_division(numerator, denominator)
|
| 94 |
+
|
| 95 |
+
return transformed
|
| 96 |
+
|
| 97 |
+
def inverse_transform(self, w):
|
| 98 |
+
self.normalize_parameters()
|
| 99 |
+
|
| 100 |
+
a_complex = self.to_complex(self.a)
|
| 101 |
+
b_complex = self.to_complex(self.b)
|
| 102 |
+
c_complex = self.to_complex(self.c)
|
| 103 |
+
d_complex = self.to_complex(self.d)
|
| 104 |
+
|
| 105 |
+
numerator = d_complex * w - b_complex
|
| 106 |
+
denominator = -c_complex * w + a_complex
|
| 107 |
+
|
| 108 |
+
return safe_complex_division(numerator, denominator)
|
| 109 |
+
|
| 110 |
+
def get_transform_info(self):
|
| 111 |
+
det = self.get_determinant()
|
| 112 |
+
one = torch.tensor(1.0, device=det.device, dtype=det.real.dtype)
|
| 113 |
+
return {
|
| 114 |
+
'determinant': det,
|
| 115 |
+
'is_identity': torch.allclose(torch.abs(det), one, atol=1e-6),
|
| 116 |
+
'parameters': {'a': self.to_complex(self.a), 'b': self.to_complex(self.b),
|
| 117 |
+
'c': self.to_complex(self.c), 'd': self.to_complex(self.d)}
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
###########################################################################################################################################
|
| 121 |
+
#############################################- - - COMPLEX STATE MARKOV CHAIN - - -####################################################
|
| 122 |
+
|
| 123 |
+
class ComplexStateMarkovChain(nn.Module):
|
| 124 |
+
def __init__(self, num_states, state_embedding_dim=64, distance_kernel='gaussian'):
|
| 125 |
+
super().__init__()
|
| 126 |
+
self.num_states = num_states
|
| 127 |
+
self.state_embedding_dim = state_embedding_dim
|
| 128 |
+
self.distance_kernel = distance_kernel
|
| 129 |
+
|
| 130 |
+
self.state_positions = nn.Parameter(
|
| 131 |
+
torch.complex(
|
| 132 |
+
torch.randn(num_states) * 2.0,
|
| 133 |
+
torch.randn(num_states) * 2.0
|
| 134 |
+
)
|
| 135 |
+
)
|
| 136 |
+
|
| 137 |
+
self.state_embeddings = nn.Parameter(torch.randn(num_states, state_embedding_dim) * 0.1)
|
| 138 |
+
|
| 139 |
+
self.base_transition_logits = nn.Parameter(torch.randn(num_states, num_states) * 0.1)
|
| 140 |
+
self.distance_scale = nn.Parameter(torch.tensor(1.0))
|
| 141 |
+
self.distance_bias = nn.Parameter(torch.tensor(0.0))
|
| 142 |
+
|
| 143 |
+
if distance_kernel == 'gaussian':
|
| 144 |
+
self.kernel_width = nn.Parameter(torch.tensor(1.0))
|
| 145 |
+
elif distance_kernel == 'inverse':
|
| 146 |
+
self.kernel_power = nn.Parameter(torch.tensor(1.0))
|
| 147 |
+
|
| 148 |
+
def compute_transformed_distances(self, mobius_transform):
|
| 149 |
+
transformed_positions = mobius_transform.transform(self.state_positions)
|
| 150 |
+
|
| 151 |
+
pos_i = transformed_positions.unsqueeze(0) # [1, num_states]
|
| 152 |
+
pos_j = transformed_positions.unsqueeze(1) # [num_states, 1]
|
| 153 |
+
|
| 154 |
+
complex_diff = pos_i - pos_j
|
| 155 |
+
distances = torch.abs(complex_diff)
|
| 156 |
+
|
| 157 |
+
return distances, transformed_positions
|
| 158 |
+
|
| 159 |
+
def distance_to_probability(self, distances):
|
| 160 |
+
distances = torch.clamp(distances, min=EPS)
|
| 161 |
+
|
| 162 |
+
if self.distance_kernel == 'gaussian':
|
| 163 |
+
width = torch.clamp(self.kernel_width, min=0.1, max=10.0)
|
| 164 |
+
prob_contrib = torch.exp(-distances**2 / (2 * width**2))
|
| 165 |
+
elif self.distance_kernel == 'inverse':
|
| 166 |
+
power = torch.clamp(self.kernel_power, min=0.5, max=3.0)
|
| 167 |
+
prob_contrib = 1.0 / (distances**power + EPS)
|
| 168 |
+
else:
|
| 169 |
+
prob_contrib = torch.clamp(1.0 - distances, min=0.0)
|
| 170 |
+
|
| 171 |
+
return prob_contrib
|
| 172 |
+
|
| 173 |
+
def compute_transition_matrix(self, mobius_transform):
|
| 174 |
+
distances, transformed_positions = self.compute_transformed_distances(mobius_transform)
|
| 175 |
+
|
| 176 |
+
distance_contrib = self.distance_to_probability(distances)
|
| 177 |
+
|
| 178 |
+
scale = torch.clamp(self.distance_scale, min=0.1, max=10.0)
|
| 179 |
+
bias = torch.clamp(self.distance_bias, min=-5.0, max=5.0)
|
| 180 |
+
scaled_distance = scale * distance_contrib + bias
|
| 181 |
+
|
| 182 |
+
transition_logits = self.base_transition_logits + scaled_distance
|
| 183 |
+
transition_logits = transition_logits + torch.eye(self.num_states, device=transition_logits.device)*0.05
|
| 184 |
+
|
| 185 |
+
transition_matrix = F.softmax(transition_logits, dim=1)
|
| 186 |
+
|
| 187 |
+
return transition_matrix, transformed_positions
|
| 188 |
+
|
| 189 |
+
def forward(self, initial_state, num_steps, mobius_transform):
|
| 190 |
+
batch_size = initial_state.shape[0] if initial_state.dim() > 1 else 1
|
| 191 |
+
|
| 192 |
+
if initial_state.dim() == 1:
|
| 193 |
+
current_state = initial_state.unsqueeze(0)
|
| 194 |
+
else:
|
| 195 |
+
current_state = initial_state
|
| 196 |
+
|
| 197 |
+
transition_matrix, transformed_positions = self.compute_transition_matrix(mobius_transform)
|
| 198 |
+
|
| 199 |
+
trajectory = [current_state.clone()]
|
| 200 |
+
state_positions = [transformed_positions[current_state.argmax(dim=-1)]]
|
| 201 |
+
|
| 202 |
+
for step in range(num_steps):
|
| 203 |
+
current_state = torch.matmul(current_state, transition_matrix)
|
| 204 |
+
trajectory.append(current_state.clone())
|
| 205 |
+
|
| 206 |
+
most_likely_states = current_state.argmax(dim=-1)
|
| 207 |
+
state_positions.append(transformed_positions[most_likely_states])
|
| 208 |
+
|
| 209 |
+
return {
|
| 210 |
+
'trajectory': torch.stack(trajectory),
|
| 211 |
+
'final_state': current_state,
|
| 212 |
+
'state_positions': torch.stack(state_positions),
|
| 213 |
+
'transition_matrix': transition_matrix,
|
| 214 |
+
'transformed_positions': transformed_positions
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
###########################################################################################################################################
|
| 218 |
+
#############################################- - - MÖBIUS MARKOV SYSTEM - - -##########################################################
|
| 219 |
+
|
| 220 |
+
class MobiusMarkovSystem(nn.Module):
|
| 221 |
+
def __init__(self, num_states, state_embedding_dim=64, evolution_steps=10):
|
| 222 |
+
super().__init__()
|
| 223 |
+
self.num_states = num_states
|
| 224 |
+
self.evolution_steps = evolution_steps
|
| 225 |
+
|
| 226 |
+
self.mobius_transform = MobiusTransform(learnable=True, init_identity=True)
|
| 227 |
+
self.markov_chain = ComplexStateMarkovChain(num_states, state_embedding_dim)
|
| 228 |
+
|
| 229 |
+
self.mobius_evolution = nn.Sequential(
|
| 230 |
+
nn.Linear(state_embedding_dim, state_embedding_dim),
|
| 231 |
+
nn.Tanh(),
|
| 232 |
+
nn.Linear(state_embedding_dim, 8), # 4 complex parameters = 8 real values
|
| 233 |
+
)
|
| 234 |
+
|
| 235 |
+
self.state_encoder = nn.Sequential(
|
| 236 |
+
nn.Linear(num_states, state_embedding_dim),
|
| 237 |
+
nn.LayerNorm(state_embedding_dim),
|
| 238 |
+
nn.ReLU(),
|
| 239 |
+
nn.Linear(state_embedding_dim, state_embedding_dim)
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
self.state_decoder = nn.Sequential(
|
| 243 |
+
nn.Linear(state_embedding_dim, state_embedding_dim),
|
| 244 |
+
nn.ReLU(),
|
| 245 |
+
nn.Linear(state_embedding_dim, num_states),
|
| 246 |
+
nn.Softmax(dim=-1)
|
| 247 |
+
)
|
| 248 |
+
|
| 249 |
+
self.geometry_controller = nn.Parameter(torch.tensor(0.1))
|
| 250 |
+
|
| 251 |
+
def evolve_mobius_parameters(self, state_embedding):
|
| 252 |
+
evolution_signal = self.mobius_evolution(state_embedding)
|
| 253 |
+
evolution_rate = torch.clamp(self.geometry_controller, 0.01, 1.0)
|
| 254 |
+
if self.mobius_transform.learnable:
|
| 255 |
+
with torch.no_grad():
|
| 256 |
+
updates = (evolution_signal.view(4, 2) * evolution_rate * 0.01)\
|
| 257 |
+
.to(device=self.mobius_transform.a.device, dtype=self.mobius_transform.a.dtype)
|
| 258 |
+
self.mobius_transform.a.add_(updates[0])
|
| 259 |
+
self.mobius_transform.b.add_(updates[1])
|
| 260 |
+
self.mobius_transform.c.add_(updates[2])
|
| 261 |
+
self.mobius_transform.d.add_(updates[3])
|
| 262 |
+
self.mobius_transform.normalize_parameters()
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
def forward(self, initial_state, return_full_trajectory=False):
|
| 266 |
+
state_embedding = self.state_encoder(initial_state)
|
| 267 |
+
|
| 268 |
+
evolution_history = {
|
| 269 |
+
'states': [],
|
| 270 |
+
'geometries': [],
|
| 271 |
+
'transition_matrices': [],
|
| 272 |
+
'transformed_positions': []
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
current_state = initial_state
|
| 276 |
+
|
| 277 |
+
for step in range(self.evolution_steps):
|
| 278 |
+
state_embedding = self.state_encoder(current_state)
|
| 279 |
+
|
| 280 |
+
self.evolve_mobius_parameters(state_embedding.mean(dim=0))
|
| 281 |
+
|
| 282 |
+
markov_output = self.markov_chain.forward(
|
| 283 |
+
current_state,
|
| 284 |
+
num_steps=1,
|
| 285 |
+
mobius_transform=self.mobius_transform
|
| 286 |
+
)
|
| 287 |
+
|
| 288 |
+
current_state = markov_output['final_state']
|
| 289 |
+
|
| 290 |
+
if return_full_trajectory:
|
| 291 |
+
evolution_history['states'].append(current_state.clone())
|
| 292 |
+
evolution_history['geometries'].append(self.mobius_transform.get_transform_info())
|
| 293 |
+
evolution_history['transition_matrices'].append(markov_output['transition_matrix'])
|
| 294 |
+
evolution_history['transformed_positions'].append(markov_output['transformed_positions'])
|
| 295 |
+
|
| 296 |
+
final_embedding = self.state_encoder(current_state)
|
| 297 |
+
final_prediction = self.state_decoder(final_embedding)
|
| 298 |
+
|
| 299 |
+
output = {
|
| 300 |
+
'final_state': current_state,
|
| 301 |
+
'final_prediction': final_prediction,
|
| 302 |
+
'final_embedding': final_embedding,
|
| 303 |
+
'final_geometry': self.mobius_transform.get_transform_info()
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
if return_full_trajectory:
|
| 307 |
+
output['evolution_history'] = evolution_history
|
| 308 |
+
|
| 309 |
+
return output
|
| 310 |
+
|
| 311 |
+
def predict_sequence(self, initial_state, sequence_length):
|
| 312 |
+
predictions = []
|
| 313 |
+
current_state = initial_state
|
| 314 |
+
|
| 315 |
+
for _ in range(sequence_length):
|
| 316 |
+
output = self.forward(current_state)
|
| 317 |
+
predictions.append(output['final_prediction'])
|
| 318 |
+
current_state = output['final_state']
|
| 319 |
+
|
| 320 |
+
return torch.stack(predictions)
|
| 321 |
+
|
| 322 |
+
def get_system_info(self):
|
| 323 |
+
return {
|
| 324 |
+
'num_states': self.num_states,
|
| 325 |
+
'evolution_steps': self.evolution_steps,
|
| 326 |
+
'current_geometry': self.mobius_transform.get_transform_info(),
|
| 327 |
+
'state_positions': self.markov_chain.state_positions,
|
| 328 |
+
'geometry_evolution_rate': self.geometry_controller.item()
|
| 329 |
+
}
|
| 330 |
+
|
mobius_markov_docs.py
ADDED
|
@@ -0,0 +1,936 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
###########################################################################################################################################
|
| 2 |
+
#||||- - - |6.25.2025| - - - || MÖBIUS MARKOV || - - - |1990two| - - -|||| #
|
| 3 |
+
###########################################################################################################################################
|
| 4 |
+
"""
|
| 5 |
+
Mathematical Foundation & Conceptual Documentation
|
| 6 |
+
-------------------------------------------------
|
| 7 |
+
|
| 8 |
+
CORE PRINCIPLE:
|
| 9 |
+
Combines Möbius transformations (complex analysis) with Markov chains to create
|
| 10 |
+
probabilistic systems evolving in dynamically warped non-Euclidean state spaces.
|
| 11 |
+
The geometry of the state space continuously adapts based on the system's evolution,
|
| 12 |
+
enabling rich, non-linear dynamics impossible in traditional Euclidean spaces.
|
| 13 |
+
|
| 14 |
+
MATHEMATICAL FOUNDATION:
|
| 15 |
+
=======================
|
| 16 |
+
|
| 17 |
+
1. MÖBIUS TRANSFORMATIONS:
|
| 18 |
+
f(z) = (az + b)/(cz + d)
|
| 19 |
+
|
| 20 |
+
Where:
|
| 21 |
+
- z ∈ ℂ: complex state variable
|
| 22 |
+
- a,b,c,d ∈ ℂ: complex parameters with ad - bc ≠ 0
|
| 23 |
+
- f: ℂ ∪ {∞} → ℂ ∪ {∞} (extended complex plane)
|
| 24 |
+
|
| 25 |
+
Properties:
|
| 26 |
+
- Conformal mapping (preserves angles)
|
| 27 |
+
- Maps circles/lines to circles/lines
|
| 28 |
+
- Group structure under composition
|
| 29 |
+
- Inverse: f⁻¹(w) = (dw - b)/(-cw + a)
|
| 30 |
+
|
| 31 |
+
2. COMPLEX STATE SPACE:
|
| 32 |
+
State positions: z₁, z₂, ..., zₙ ∈ ℂ
|
| 33 |
+
|
| 34 |
+
Transformed positions: w_i = f(z_i) = (az_i + b)/(cz_i + d)
|
| 35 |
+
|
| 36 |
+
Distance in transformed space: d(w_i, w_j) = |w_i - w_j|
|
| 37 |
+
|
| 38 |
+
3. MARKOV TRANSITION PROBABILITIES:
|
| 39 |
+
P(i → j) = softmax(β · K(d(w_i, w_j)) + θ_ij)
|
| 40 |
+
|
| 41 |
+
Where:
|
| 42 |
+
- K(d): distance kernel (Gaussian, inverse, linear)
|
| 43 |
+
- β: distance scaling parameter
|
| 44 |
+
- θ_ij: base transition logits
|
| 45 |
+
- Transformed distances create non-Euclidean transition structure
|
| 46 |
+
|
| 47 |
+
4. ADAPTIVE GEOMETRY EVOLUTION:
|
| 48 |
+
∂(a,b,c,d)/∂t = η · G(x_t, E_t)
|
| 49 |
+
|
| 50 |
+
Where:
|
| 51 |
+
- G: geometry evolution function
|
| 52 |
+
- x_t: current state distribution
|
| 53 |
+
- E_t: embedded state features
|
| 54 |
+
- η: geometry learning rate
|
| 55 |
+
|
| 56 |
+
The Möbius parameters evolve based on system state.
|
| 57 |
+
|
| 58 |
+
5. KERNEL FUNCTIONS:
|
| 59 |
+
Gaussian: K(d) = exp(-d²/(2σ²))
|
| 60 |
+
Inverse: K(d) = 1/(d^α + ε)
|
| 61 |
+
Linear: K(d) = max(0, 1 - d)
|
| 62 |
+
|
| 63 |
+
Different kernels create different transition locality structures.
|
| 64 |
+
|
| 65 |
+
CONCEPTUAL REASONING:
|
| 66 |
+
====================
|
| 67 |
+
|
| 68 |
+
WHY MÖBIUS + MARKOV?
|
| 69 |
+
- Standard Markov chains assume fixed, Euclidean state spaces
|
| 70 |
+
- Real systems often have curved, adaptive state geometries
|
| 71 |
+
- Möbius transformations provide rich geometric transformations
|
| 72 |
+
- Complex analysis offers elegant mathematical framework
|
| 73 |
+
- Dynamic geometry enables meta-learning of state representations
|
| 74 |
+
|
| 75 |
+
KEY INNOVATIONS:
|
| 76 |
+
1. **Dynamic Non-Euclidean Geometry**: State space warps over time
|
| 77 |
+
2. **Complex State Representations**: Rich 2D embedding in complex plane
|
| 78 |
+
3. **Conformal Invariance**: Angle-preserving transformations maintain local structure
|
| 79 |
+
4. **Learnable Geometry**: Möbius parameters adapt to data
|
| 80 |
+
5. **Multi-Scale Dynamics**: Both local transitions and global geometry evolve
|
| 81 |
+
|
| 82 |
+
APPLICATIONS:
|
| 83 |
+
- Dynamical systems with changing phase spaces
|
| 84 |
+
- Neural representations learning geometric structure
|
| 85 |
+
- Sequential data with non-stationary transition patterns
|
| 86 |
+
- Robotics in environments with changing topology
|
| 87 |
+
- Financial modeling with regime changes
|
| 88 |
+
|
| 89 |
+
COMPLEXITY ANALYSIS:
|
| 90 |
+
- Möbius Transform: O(n) for n states
|
| 91 |
+
- Distance Computation: O(n²) for all pairs
|
| 92 |
+
- Markov Step: O(n²) for transition matrix
|
| 93 |
+
- Geometry Evolution: O(1) for parameter updates
|
| 94 |
+
- Memory: O(n²) for transition probabilities
|
| 95 |
+
|
| 96 |
+
BIOLOGICAL INSPIRATION:
|
| 97 |
+
- Neural manifold learning in cortical representations
|
| 98 |
+
- Synaptic plasticity reshaping connectivity patterns
|
| 99 |
+
- Developmental changes in brain network topology
|
| 100 |
+
- Spatial navigation with changing environmental maps
|
| 101 |
+
- Memory consolidation through representational geometry changes
|
| 102 |
+
"""
|
| 103 |
+
|
| 104 |
+
from __future__ import annotations
|
| 105 |
+
import torch
|
| 106 |
+
import torch.nn as nn
|
| 107 |
+
import torch.nn.functional as F
|
| 108 |
+
import numpy as np
|
| 109 |
+
import math
|
| 110 |
+
import matplotlib.pyplot as plt
|
| 111 |
+
from typing import List, Dict, Tuple, Optional
|
| 112 |
+
|
| 113 |
+
SAFE_MIN = -1e6
|
| 114 |
+
SAFE_MAX = 1e6
|
| 115 |
+
EPS = 1e-8
|
| 116 |
+
|
| 117 |
+
#||||- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 𝔦 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -||||#
|
| 118 |
+
|
| 119 |
+
def make_safe(tensor, min_val=SAFE_MIN, max_val=SAFE_MAX):
|
| 120 |
+
zero = torch.tensor(0.0, device=tensor.device, dtype=tensor.dtype)
|
| 121 |
+
maxv = torch.tensor(max_val, device=tensor.device, dtype=tensor.dtype)
|
| 122 |
+
tensor = torch.where(torch.isnan(tensor), zero, tensor)
|
| 123 |
+
tensor = torch.where(torch.isinf(tensor), maxv, tensor)
|
| 124 |
+
return torch.clamp(tensor, min_val, max_val)
|
| 125 |
+
|
| 126 |
+
def safe_complex_division(numerator, denominator, eps=EPS):
|
| 127 |
+
"""Safe complex division with numerical stability.
|
| 128 |
+
|
| 129 |
+
Performs complex division z₁/z₂ = (z₁ * conj(z₂))/(|z₂|²) with
|
| 130 |
+
proper handling of near-zero denominators to prevent numerical instability.
|
| 131 |
+
|
| 132 |
+
Mathematical Details:
|
| 133 |
+
- z₁/z₂ = (z₁ * z̄₂)/(z₂ * z̄₂) = (z₁ * z̄₂)/|z₂|²
|
| 134 |
+
- |z₂|² = Re(z₂ * z̄₂) clamped to minimum value
|
| 135 |
+
|
| 136 |
+
Args:
|
| 137 |
+
numerator: Complex numerator tensor
|
| 138 |
+
denominator: Complex denominator tensor
|
| 139 |
+
eps: Minimum denominator magnitude
|
| 140 |
+
|
| 141 |
+
Returns:
|
| 142 |
+
Result of safe complex division
|
| 143 |
+
"""
|
| 144 |
+
denominator_conj = torch.conj(denominator)
|
| 145 |
+
norm_sq = torch.real(denominator * denominator_conj)
|
| 146 |
+
norm_sq = torch.clamp(norm_sq, min=eps)
|
| 147 |
+
return (numerator * denominator_conj) / norm_sq
|
| 148 |
+
|
| 149 |
+
###########################################################################################################################################
|
| 150 |
+
####################################################- - - MÖBIUS TRANSFORM - - -#######################################################
|
| 151 |
+
|
| 152 |
+
class MobiusTransform(nn.Module):
|
| 153 |
+
"""Learnable Möbius transformation for complex plane warping.
|
| 154 |
+
|
| 155 |
+
Implements a Möbius transformation f(z) = (az + b)/(cz + d) with
|
| 156 |
+
learnable complex parameters. Provides both forward and inverse
|
| 157 |
+
transformations with automatic parameter normalization for stability.
|
| 158 |
+
|
| 159 |
+
Mathematical Properties:
|
| 160 |
+
- Conformal mapping (preserves angles locally)
|
| 161 |
+
- Maps circles and lines to circles and lines
|
| 162 |
+
- Determinant constraint: ad - bc ≠ 0 for invertibility
|
| 163 |
+
- Group structure: composition of Möbius transforms is Möbius
|
| 164 |
+
|
| 165 |
+
The transformation can be initialized as identity or with random parameters.
|
| 166 |
+
Parameters are stored as [real, imaginary] pairs and converted to complex
|
| 167 |
+
tensors during computation.
|
| 168 |
+
"""
|
| 169 |
+
def __init__(self, learnable=True, init_identity=True):
|
| 170 |
+
super().__init__()
|
| 171 |
+
self.learnable = learnable
|
| 172 |
+
|
| 173 |
+
if init_identity:
|
| 174 |
+
# Initialize as identity transform: f(z) = z (a=1, b=0, c=0, d=1)
|
| 175 |
+
a_init, b_init, c_init, d_init = 1.0, 0.0, 0.0, 1.0
|
| 176 |
+
else:
|
| 177 |
+
# Random initialization (ensuring ad - bc ≠ 0)
|
| 178 |
+
a_init, d_init = 1.0, 1.0
|
| 179 |
+
b_init, c_init = 0.1, 0.1
|
| 180 |
+
|
| 181 |
+
if learnable:
|
| 182 |
+
# Möbius parameters: f(z) = (az + b)/(cz + d)
|
| 183 |
+
# Stored as [real, imaginary] pairs for each complex parameter
|
| 184 |
+
self.a = nn.Parameter(torch.tensor([a_init, 0.0]))
|
| 185 |
+
self.b = nn.Parameter(torch.tensor([b_init, 0.0]))
|
| 186 |
+
self.c = nn.Parameter(torch.tensor([c_init, 0.0]))
|
| 187 |
+
self.d = nn.Parameter(torch.tensor([d_init, 0.0]))
|
| 188 |
+
else:
|
| 189 |
+
# Fixed parameters (non-learnable)
|
| 190 |
+
self.register_buffer('a', torch.tensor([a_init, 0.0]))
|
| 191 |
+
self.register_buffer('b', torch.tensor([b_init, 0.0]))
|
| 192 |
+
self.register_buffer('c', torch.tensor([c_init, 0.0]))
|
| 193 |
+
self.register_buffer('d', torch.tensor([d_init, 0.0]))
|
| 194 |
+
|
| 195 |
+
def to_complex(self, param):
|
| 196 |
+
"""Convert [real, imag] tensor to complex tensor.
|
| 197 |
+
|
| 198 |
+
Args:
|
| 199 |
+
param: Tensor [real_part, imaginary_part]
|
| 200 |
+
|
| 201 |
+
Returns:
|
| 202 |
+
Complex tensor with real and imaginary components
|
| 203 |
+
"""
|
| 204 |
+
return torch.complex(param[0], param[1])
|
| 205 |
+
|
| 206 |
+
def get_determinant(self):
|
| 207 |
+
"""Compute transformation determinant ad - bc.
|
| 208 |
+
|
| 209 |
+
The determinant must be non-zero for the transformation to be invertible.
|
| 210 |
+
This is automatically enforced by parameter normalization.
|
| 211 |
+
|
| 212 |
+
Mathematical Details:
|
| 213 |
+
- det(M) = ad - bc where M = [[a,b],[c,d]]
|
| 214 |
+
- det ≠ 0 ensures bijective mapping
|
| 215 |
+
- |det| measures area scaling factor
|
| 216 |
+
|
| 217 |
+
Returns:
|
| 218 |
+
Complex determinant value
|
| 219 |
+
"""
|
| 220 |
+
a_complex = self.to_complex(self.a)
|
| 221 |
+
b_complex = self.to_complex(self.b)
|
| 222 |
+
c_complex = self.to_complex(self.c)
|
| 223 |
+
d_complex = self.to_complex(self.d)
|
| 224 |
+
|
| 225 |
+
det = a_complex * d_complex - b_complex * c_complex
|
| 226 |
+
return det
|
| 227 |
+
|
| 228 |
+
def normalize_parameters(self):
|
| 229 |
+
"""Ensure parameter validity and numerical stability.
|
| 230 |
+
|
| 231 |
+
Enforces constraints:
|
| 232 |
+
1. Determinant magnitude > ε (invertibility)
|
| 233 |
+
2. Parameter magnitudes bounded (numerical stability)
|
| 234 |
+
3. Reset to identity if determinant too small
|
| 235 |
+
|
| 236 |
+
Called automatically before each transformation to maintain stability.
|
| 237 |
+
"""
|
| 238 |
+
if self.learnable:
|
| 239 |
+
with torch.no_grad():
|
| 240 |
+
det = torch.abs(self.get_determinant())
|
| 241 |
+
if det < EPS:
|
| 242 |
+
# Reset to identity if determinant too small
|
| 243 |
+
one = torch.tensor([1.0, 0.0], device=self.a.device, dtype=self.a.dtype)
|
| 244 |
+
self.a.copy_(one)
|
| 245 |
+
self.d.copy_(one)
|
| 246 |
+
self.b.mul_(0.1)
|
| 247 |
+
self.c.mul_(0.1)
|
| 248 |
+
|
| 249 |
+
# Clamp parameter magnitudes for numerical stability
|
| 250 |
+
for p in (self.a, self.b, self.c, self.d):
|
| 251 |
+
p.clamp_(-10.0, 10.0)
|
| 252 |
+
|
| 253 |
+
def transform(self, z):
|
| 254 |
+
"""Apply Möbius transform: f(z) = (az + b)/(cz + d).
|
| 255 |
+
|
| 256 |
+
Performs the forward Möbius transformation on complex input.
|
| 257 |
+
Automatically normalizes parameters before computation for stability.
|
| 258 |
+
|
| 259 |
+
Mathematical Details:
|
| 260 |
+
- Numerator: az + b (complex multiplication and addition)
|
| 261 |
+
- Denominator: cz + d (complex multiplication and addition)
|
| 262 |
+
- Division: safe complex division with stability checks
|
| 263 |
+
|
| 264 |
+
Args:
|
| 265 |
+
z: Complex input tensor [..., any_shape]
|
| 266 |
+
|
| 267 |
+
Returns:
|
| 268 |
+
Transformed complex tensor of same shape
|
| 269 |
+
"""
|
| 270 |
+
self.normalize_parameters()
|
| 271 |
+
|
| 272 |
+
a_complex = self.to_complex(self.a)
|
| 273 |
+
b_complex = self.to_complex(self.b)
|
| 274 |
+
c_complex = self.to_complex(self.c)
|
| 275 |
+
d_complex = self.to_complex(self.d)
|
| 276 |
+
|
| 277 |
+
# Numerator: az + b
|
| 278 |
+
numerator = a_complex * z + b_complex
|
| 279 |
+
|
| 280 |
+
# Denominator: cz + d
|
| 281 |
+
denominator = c_complex * z + d_complex
|
| 282 |
+
|
| 283 |
+
# Safe complex division
|
| 284 |
+
transformed = safe_complex_division(numerator, denominator)
|
| 285 |
+
|
| 286 |
+
return transformed
|
| 287 |
+
|
| 288 |
+
def inverse_transform(self, w):
|
| 289 |
+
"""Apply inverse Möbius transform: f⁻¹(w) = (dw - b)/(-cw + a).
|
| 290 |
+
|
| 291 |
+
Computes the inverse transformation to map from transformed space
|
| 292 |
+
back to original space. Uses the standard Möbius inverse formula.
|
| 293 |
+
|
| 294 |
+
Mathematical Details:
|
| 295 |
+
- For f(z) = (az + b)/(cz + d)
|
| 296 |
+
- f⁻¹(w) = (dw - b)/(-cw + a)
|
| 297 |
+
- Inverse determinant: det(f⁻¹) = 1/det(f)
|
| 298 |
+
|
| 299 |
+
Args:
|
| 300 |
+
w: Complex input in transformed space
|
| 301 |
+
|
| 302 |
+
Returns:
|
| 303 |
+
Original complex values before transformation
|
| 304 |
+
"""
|
| 305 |
+
self.normalize_parameters()
|
| 306 |
+
|
| 307 |
+
a_complex = self.to_complex(self.a)
|
| 308 |
+
b_complex = self.to_complex(self.b)
|
| 309 |
+
c_complex = self.to_complex(self.c)
|
| 310 |
+
d_complex = self.to_complex(self.d)
|
| 311 |
+
|
| 312 |
+
# Inverse: f⁻¹(w) = (dw - b)/(-cw + a)
|
| 313 |
+
numerator = d_complex * w - b_complex
|
| 314 |
+
denominator = -c_complex * w + a_complex
|
| 315 |
+
|
| 316 |
+
return safe_complex_division(numerator, denominator)
|
| 317 |
+
|
| 318 |
+
def get_transform_info(self):
|
| 319 |
+
"""Get comprehensive information about current transformation.
|
| 320 |
+
|
| 321 |
+
Returns diagnostic information including determinant, identity check,
|
| 322 |
+
and current parameter values for analysis and debugging.
|
| 323 |
+
|
| 324 |
+
Returns:
|
| 325 |
+
Dictionary with transformation properties
|
| 326 |
+
"""
|
| 327 |
+
det = self.get_determinant()
|
| 328 |
+
one = torch.tensor(1.0, device=det.device, dtype=det.real.dtype)
|
| 329 |
+
return {
|
| 330 |
+
'determinant': det,
|
| 331 |
+
'is_identity': torch.allclose(torch.abs(det), one, atol=1e-6),
|
| 332 |
+
'parameters': {
|
| 333 |
+
'a': self.to_complex(self.a),
|
| 334 |
+
'b': self.to_complex(self.b),
|
| 335 |
+
'c': self.to_complex(self.c),
|
| 336 |
+
'd': self.to_complex(self.d)
|
| 337 |
+
}
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
###########################################################################################################################################
|
| 341 |
+
#############################################- - - COMPLEX STATE MARKOV CHAIN - - -####################################################
|
| 342 |
+
|
| 343 |
+
class ComplexStateMarkovChain(nn.Module):
|
| 344 |
+
"""Markov chain with complex state positions and distance-based transitions.
|
| 345 |
+
|
| 346 |
+
Implements a Markov chain where states are positioned in the complex plane
|
| 347 |
+
and transition probabilities depend on distances in the (potentially transformed)
|
| 348 |
+
complex space. Supports multiple distance kernels and learnable parameters.
|
| 349 |
+
|
| 350 |
+
Mathematical Framework:
|
| 351 |
+
- State positions: z₁, z₂, ..., zₙ ∈ ℂ (learnable)
|
| 352 |
+
- Transformed positions: w_i = f(z_i) via Möbius transform
|
| 353 |
+
- Distance-based transitions: P(i→j) ∝ K(|w_i - w_j|)
|
| 354 |
+
- Multiple kernel options: Gaussian, inverse power, linear
|
| 355 |
+
|
| 356 |
+
The chain combines base transition logits with distance-based terms,
|
| 357 |
+
allowing both learned and geometric transition structure.
|
| 358 |
+
"""
|
| 359 |
+
def __init__(self, num_states, state_embedding_dim=64, distance_kernel='gaussian'):
|
| 360 |
+
super().__init__()
|
| 361 |
+
self.num_states = num_states
|
| 362 |
+
self.state_embedding_dim = state_embedding_dim
|
| 363 |
+
self.distance_kernel = distance_kernel
|
| 364 |
+
|
| 365 |
+
# Complex state positions (learnable parameters)
|
| 366 |
+
# Each state has a position in the complex plane
|
| 367 |
+
self.state_positions = nn.Parameter(
|
| 368 |
+
torch.complex(
|
| 369 |
+
torch.randn(num_states) * 2.0, # Real parts
|
| 370 |
+
torch.randn(num_states) * 2.0 # Imaginary parts
|
| 371 |
+
)
|
| 372 |
+
)
|
| 373 |
+
|
| 374 |
+
# State feature embeddings for additional representation
|
| 375 |
+
self.state_embeddings = nn.Parameter(torch.randn(num_states, state_embedding_dim) * 0.1)
|
| 376 |
+
|
| 377 |
+
# Learnable transition parameters
|
| 378 |
+
self.base_transition_logits = nn.Parameter(torch.randn(num_states, num_states) * 0.1)
|
| 379 |
+
self.distance_scale = nn.Parameter(torch.tensor(1.0))
|
| 380 |
+
self.distance_bias = nn.Parameter(torch.tensor(0.0))
|
| 381 |
+
|
| 382 |
+
# Kernel-specific parameters
|
| 383 |
+
if distance_kernel == 'gaussian':
|
| 384 |
+
self.kernel_width = nn.Parameter(torch.tensor(1.0))
|
| 385 |
+
elif distance_kernel == 'inverse':
|
| 386 |
+
self.kernel_power = nn.Parameter(torch.tensor(1.0))
|
| 387 |
+
|
| 388 |
+
def compute_transformed_distances(self, mobius_transform):
|
| 389 |
+
"""Compute pairwise distances between states in transformed space.
|
| 390 |
+
|
| 391 |
+
Applies the Möbius transformation to all state positions and computes
|
| 392 |
+
the Euclidean distances in the transformed complex plane.
|
| 393 |
+
|
| 394 |
+
Mathematical Details:
|
| 395 |
+
- Transform: w_i = f(z_i) for each state position z_i
|
| 396 |
+
- Distance: d(i,j) = |w_i - w_j| = |f(z_i) - f(z_j)|
|
| 397 |
+
- Results in [num_states, num_states] distance matrix
|
| 398 |
+
|
| 399 |
+
Args:
|
| 400 |
+
mobius_transform: MobiusTransform instance
|
| 401 |
+
|
| 402 |
+
Returns:
|
| 403 |
+
Tuple of (distance_matrix, transformed_positions)
|
| 404 |
+
"""
|
| 405 |
+
# Transform all state positions through Möbius map
|
| 406 |
+
transformed_positions = mobius_transform.transform(self.state_positions)
|
| 407 |
+
|
| 408 |
+
# Compute pairwise distances in transformed space
|
| 409 |
+
pos_i = transformed_positions.unsqueeze(0) # [1, num_states]
|
| 410 |
+
pos_j = transformed_positions.unsqueeze(1) # [num_states, 1]
|
| 411 |
+
|
| 412 |
+
# Complex distance: |w_i - w_j|
|
| 413 |
+
complex_diff = pos_i - pos_j
|
| 414 |
+
distances = torch.abs(complex_diff)
|
| 415 |
+
|
| 416 |
+
return distances, transformed_positions
|
| 417 |
+
|
| 418 |
+
def distance_to_probability(self, distances):
|
| 419 |
+
"""Convert distances to probability contributions via kernel function.
|
| 420 |
+
|
| 421 |
+
Applies the selected kernel function to transform geometric distances
|
| 422 |
+
into probability weights. Different kernels create different locality
|
| 423 |
+
structures in the transition probabilities.
|
| 424 |
+
|
| 425 |
+
Kernel Options:
|
| 426 |
+
- Gaussian: K(d) = exp(-d²/(2σ²)) - smooth, localized
|
| 427 |
+
- Inverse: K(d) = 1/(d^α + ε) - power-law decay
|
| 428 |
+
- Linear: K(d) = max(0, 1-d) - linear decay with cutoff
|
| 429 |
+
|
| 430 |
+
Args:
|
| 431 |
+
distances: Distance matrix [num_states, num_states]
|
| 432 |
+
|
| 433 |
+
Returns:
|
| 434 |
+
Probability contribution matrix [num_states, num_states]
|
| 435 |
+
"""
|
| 436 |
+
distances = torch.clamp(distances, min=EPS)
|
| 437 |
+
|
| 438 |
+
if self.distance_kernel == 'gaussian':
|
| 439 |
+
width = torch.clamp(self.kernel_width, min=0.1, max=10.0)
|
| 440 |
+
prob_contrib = torch.exp(-distances**2 / (2 * width**2))
|
| 441 |
+
elif self.distance_kernel == 'inverse':
|
| 442 |
+
power = torch.clamp(self.kernel_power, min=0.5, max=3.0)
|
| 443 |
+
prob_contrib = 1.0 / (distances**power + EPS)
|
| 444 |
+
else:
|
| 445 |
+
# Linear kernel with cutoff
|
| 446 |
+
prob_contrib = torch.clamp(1.0 - distances, min=0.0)
|
| 447 |
+
|
| 448 |
+
return prob_contrib
|
| 449 |
+
|
| 450 |
+
def compute_transition_matrix(self, mobius_transform):
|
| 451 |
+
"""Compute full transition matrix combining geometry and learned weights.
|
| 452 |
+
|
| 453 |
+
Creates the Markov transition matrix by combining:
|
| 454 |
+
1. Base transition logits (learned affinities)
|
| 455 |
+
2. Distance-based contributions (geometric structure)
|
| 456 |
+
3. Scaling and bias parameters
|
| 457 |
+
4. Softmax normalization for valid probabilities
|
| 458 |
+
|
| 459 |
+
Mathematical Details:
|
| 460 |
+
- Base logits: θᵢⱼ (learned transition preferences)
|
| 461 |
+
- Distance terms: β·K(d(wᵢ,wⱼ)) + γ (scaled kernel)
|
| 462 |
+
- Combined: logits = θᵢⱼ + β·K(d(wᵢ,wⱼ)) + γ
|
| 463 |
+
- Probabilities: P(i→j) = softmax_j(logits_i)
|
| 464 |
+
|
| 465 |
+
Args:
|
| 466 |
+
mobius_transform: MobiusTransform for state space warping
|
| 467 |
+
|
| 468 |
+
Returns:
|
| 469 |
+
Tuple of (transition_matrix, transformed_positions)
|
| 470 |
+
"""
|
| 471 |
+
# Get transformed distances
|
| 472 |
+
distances, transformed_positions = self.compute_transformed_distances(mobius_transform)
|
| 473 |
+
|
| 474 |
+
# Convert distances to probability contributions
|
| 475 |
+
distance_contrib = self.distance_to_probability(distances)
|
| 476 |
+
|
| 477 |
+
# Scale and bias distance contributions
|
| 478 |
+
scale = torch.clamp(self.distance_scale, min=0.1, max=10.0)
|
| 479 |
+
bias = torch.clamp(self.distance_bias, min=-5.0, max=5.0)
|
| 480 |
+
scaled_distance = scale * distance_contrib + bias
|
| 481 |
+
|
| 482 |
+
# Combine with base transition logits
|
| 483 |
+
transition_logits = self.base_transition_logits + scaled_distance
|
| 484 |
+
|
| 485 |
+
# Add small diagonal bias for numerical stability
|
| 486 |
+
transition_logits = transition_logits + torch.eye(self.num_states, device=transition_logits.device) * 0.05
|
| 487 |
+
|
| 488 |
+
# Convert to valid probability matrix (row-stochastic)
|
| 489 |
+
transition_matrix = F.softmax(transition_logits, dim=1)
|
| 490 |
+
|
| 491 |
+
return transition_matrix, transformed_positions
|
| 492 |
+
|
| 493 |
+
def forward(self, initial_state, num_steps, mobius_transform):
|
| 494 |
+
"""Execute Markov chain evolution in transformed space.
|
| 495 |
+
|
| 496 |
+
Runs the Markov chain for the specified number of steps using
|
| 497 |
+
transition probabilities computed in the Möbius-transformed space.
|
| 498 |
+
Records complete trajectory for analysis.
|
| 499 |
+
|
| 500 |
+
Mathematical Process:
|
| 501 |
+
1. Compute transition matrix P in transformed space
|
| 502 |
+
2. Evolve state: s_{t+1} = s_t · P
|
| 503 |
+
3. Track most likely state positions over time
|
| 504 |
+
4. Return complete trajectory and final state
|
| 505 |
+
|
| 506 |
+
Args:
|
| 507 |
+
initial_state: Initial state distribution [batch_size, num_states]
|
| 508 |
+
num_steps: Number of Markov steps to execute
|
| 509 |
+
mobius_transform: MobiusTransform for space warping
|
| 510 |
+
|
| 511 |
+
Returns:
|
| 512 |
+
Dictionary containing trajectory, final state, and diagnostics
|
| 513 |
+
"""
|
| 514 |
+
batch_size = initial_state.shape[0] if initial_state.dim() > 1 else 1
|
| 515 |
+
|
| 516 |
+
if initial_state.dim() == 1:
|
| 517 |
+
current_state = initial_state.unsqueeze(0)
|
| 518 |
+
else:
|
| 519 |
+
current_state = initial_state
|
| 520 |
+
|
| 521 |
+
# Get transition matrix in transformed space
|
| 522 |
+
transition_matrix, transformed_positions = self.compute_transition_matrix(mobius_transform)
|
| 523 |
+
|
| 524 |
+
# Store complete trajectory
|
| 525 |
+
trajectory = [current_state.clone()]
|
| 526 |
+
state_positions = [transformed_positions[current_state.argmax(dim=-1)]]
|
| 527 |
+
|
| 528 |
+
# Execute Markov chain evolution
|
| 529 |
+
for step in range(num_steps):
|
| 530 |
+
# Matrix multiplication for batch processing
|
| 531 |
+
current_state = torch.matmul(current_state, transition_matrix)
|
| 532 |
+
trajectory.append(current_state.clone())
|
| 533 |
+
|
| 534 |
+
# Track most likely state positions in transformed space
|
| 535 |
+
most_likely_states = current_state.argmax(dim=-1)
|
| 536 |
+
state_positions.append(transformed_positions[most_likely_states])
|
| 537 |
+
|
| 538 |
+
return {
|
| 539 |
+
'trajectory': torch.stack(trajectory),
|
| 540 |
+
'final_state': current_state,
|
| 541 |
+
'state_positions': torch.stack(state_positions),
|
| 542 |
+
'transition_matrix': transition_matrix,
|
| 543 |
+
'transformed_positions': transformed_positions
|
| 544 |
+
}
|
| 545 |
+
|
| 546 |
+
###########################################################################################################################################
|
| 547 |
+
############################################- - - MÖBIUS MARKOV SYSTEM - - -###########################################################
|
| 548 |
+
|
| 549 |
+
class MobiusMarkovSystem(nn.Module):
|
| 550 |
+
"""Complete system integrating Möbius transformations with Markov dynamics.
|
| 551 |
+
|
| 552 |
+
Implements the full Möbius-Markov architecture where:
|
| 553 |
+
1. Complex state positions define Markov chain geometry
|
| 554 |
+
2. Möbius transformations dynamically warp the state space
|
| 555 |
+
3. Transformation parameters evolve based on system state
|
| 556 |
+
4. State transitions depend on transformed distances
|
| 557 |
+
|
| 558 |
+
This creates a meta-learning system where the geometry of state space
|
| 559 |
+
adapts based on the system's evolutionary trajectory, enabling
|
| 560 |
+
discovery of optimal representational geometries for different tasks.
|
| 561 |
+
|
| 562 |
+
Architecture Components:
|
| 563 |
+
- MobiusTransform: Learnable complex plane warping
|
| 564 |
+
- ComplexStateMarkovChain: Distance-based probabilistic transitions
|
| 565 |
+
- Evolution dynamics: State-dependent geometry adaptation
|
| 566 |
+
- Encoder/decoder: Interface with external representations
|
| 567 |
+
"""
|
| 568 |
+
def __init__(self, num_states, state_embedding_dim=64, evolution_steps=10):
|
| 569 |
+
super().__init__()
|
| 570 |
+
self.num_states = num_states
|
| 571 |
+
self.evolution_steps = evolution_steps
|
| 572 |
+
|
| 573 |
+
# Core components
|
| 574 |
+
self.mobius_transform = MobiusTransform(learnable=True, init_identity=True)
|
| 575 |
+
self.markov_chain = ComplexStateMarkovChain(num_states, state_embedding_dim)
|
| 576 |
+
|
| 577 |
+
# Evolution dynamics for Möbius parameters
|
| 578 |
+
# Maps state embeddings to parameter updates
|
| 579 |
+
self.mobius_evolution = nn.Sequential(
|
| 580 |
+
nn.Linear(state_embedding_dim, state_embedding_dim),
|
| 581 |
+
nn.Tanh(),
|
| 582 |
+
nn.Linear(state_embedding_dim, 8), # 4 complex parameters = 8 real values
|
| 583 |
+
)
|
| 584 |
+
|
| 585 |
+
# State encoder/decoder for external interface
|
| 586 |
+
self.state_encoder = nn.Sequential(
|
| 587 |
+
nn.Linear(num_states, state_embedding_dim),
|
| 588 |
+
nn.LayerNorm(state_embedding_dim),
|
| 589 |
+
nn.ReLU(),
|
| 590 |
+
nn.Linear(state_embedding_dim, state_embedding_dim)
|
| 591 |
+
)
|
| 592 |
+
|
| 593 |
+
self.state_decoder = nn.Sequential(
|
| 594 |
+
nn.Linear(state_embedding_dim, state_embedding_dim),
|
| 595 |
+
nn.ReLU(),
|
| 596 |
+
nn.Linear(state_embedding_dim, num_states),
|
| 597 |
+
nn.Softmax(dim=-1)
|
| 598 |
+
)
|
| 599 |
+
|
| 600 |
+
# Geometric evolution controller
|
| 601 |
+
self.geometry_controller = nn.Parameter(torch.tensor(0.1))
|
| 602 |
+
|
| 603 |
+
def evolve_mobius_parameters(self, state_embedding):
|
| 604 |
+
"""Evolve Möbius transformation parameters based on current state.
|
| 605 |
+
|
| 606 |
+
Updates the complex parameters (a,b,c,d) of the Möbius transformation
|
| 607 |
+
based on the current state embedding. This enables the geometry to
|
| 608 |
+
adapt dynamically as the system evolves.
|
| 609 |
+
|
| 610 |
+
Mathematical Details:
|
| 611 |
+
- Parameter updates: Δp = η·G(embedding)
|
| 612 |
+
- G: neural network mapping embeddings to parameter changes
|
| 613 |
+
- η: learnable evolution rate
|
| 614 |
+
- Updates applied directly to parameter tensors
|
| 615 |
+
|
| 616 |
+
The evolution is designed to be conservative (small steps) to
|
| 617 |
+
maintain stability while allowing adaptive geometry.
|
| 618 |
+
|
| 619 |
+
Args:
|
| 620 |
+
state_embedding: Current state representation [embedding_dim]
|
| 621 |
+
"""
|
| 622 |
+
# Generate parameter evolution signal
|
| 623 |
+
evolution_signal = self.mobius_evolution(state_embedding)
|
| 624 |
+
evolution_rate = torch.clamp(self.geometry_controller, 0.01, 1.0)
|
| 625 |
+
|
| 626 |
+
if self.mobius_transform.learnable:
|
| 627 |
+
with torch.no_grad():
|
| 628 |
+
# Reshape evolution signal to 4 complex parameters (8 real values)
|
| 629 |
+
updates = (evolution_signal.view(4, 2) * evolution_rate * 0.01)\
|
| 630 |
+
.to(device=self.mobius_transform.a.device, dtype=self.mobius_transform.a.dtype)
|
| 631 |
+
|
| 632 |
+
# Apply updates to Möbius parameters
|
| 633 |
+
self.mobius_transform.a.add_(updates[0])
|
| 634 |
+
self.mobius_transform.b.add_(updates[1])
|
| 635 |
+
self.mobius_transform.c.add_(updates[2])
|
| 636 |
+
self.mobius_transform.d.add_(updates[3])
|
| 637 |
+
|
| 638 |
+
# Ensure parameters remain valid
|
| 639 |
+
self.mobius_transform.normalize_parameters()
|
| 640 |
+
|
| 641 |
+
def forward(self, initial_state, return_full_trajectory=False):
|
| 642 |
+
"""Execute complete Möbius-Markov evolution cycle.
|
| 643 |
+
|
| 644 |
+
Implements the full system dynamics:
|
| 645 |
+
1. Encode initial state to embedding space
|
| 646 |
+
2. Iteratively evolve: geometry → Markov step → state update
|
| 647 |
+
3. Adapt Möbius parameters based on current state
|
| 648 |
+
4. Generate final prediction with learned decoder
|
| 649 |
+
|
| 650 |
+
This creates a feedback loop where the geometry of state space
|
| 651 |
+
continuously adapts based on the system's trajectory, enabling
|
| 652 |
+
meta-learning of optimal spatial representations.
|
| 653 |
+
|
| 654 |
+
Args:
|
| 655 |
+
initial_state: Initial state distribution [batch_size, num_states]
|
| 656 |
+
return_full_trajectory: Whether to return complete evolution history
|
| 657 |
+
|
| 658 |
+
Returns:
|
| 659 |
+
Dictionary containing final state, prediction, and optional trajectory
|
| 660 |
+
"""
|
| 661 |
+
# Encode initial state to embedding space
|
| 662 |
+
state_embedding = self.state_encoder(initial_state)
|
| 663 |
+
|
| 664 |
+
# Store complete evolution history if requested
|
| 665 |
+
evolution_history = {
|
| 666 |
+
'states': [],
|
| 667 |
+
'geometries': [],
|
| 668 |
+
'transition_matrices': [],
|
| 669 |
+
'transformed_positions': []
|
| 670 |
+
}
|
| 671 |
+
|
| 672 |
+
current_state = initial_state
|
| 673 |
+
|
| 674 |
+
# Multi-step evolution loop
|
| 675 |
+
for step in range(self.evolution_steps):
|
| 676 |
+
# Encode current state
|
| 677 |
+
state_embedding = self.state_encoder(current_state)
|
| 678 |
+
|
| 679 |
+
# Evolve Möbius parameters based on current state
|
| 680 |
+
self.evolve_mobius_parameters(state_embedding.mean(dim=0))
|
| 681 |
+
|
| 682 |
+
# Execute one Markov step in current transformed space
|
| 683 |
+
markov_output = self.markov_chain.forward(
|
| 684 |
+
current_state,
|
| 685 |
+
num_steps=1,
|
| 686 |
+
mobius_transform=self.mobius_transform
|
| 687 |
+
)
|
| 688 |
+
|
| 689 |
+
# Update current state distribution
|
| 690 |
+
current_state = markov_output['final_state']
|
| 691 |
+
|
| 692 |
+
# Store evolution history
|
| 693 |
+
if return_full_trajectory:
|
| 694 |
+
evolution_history['states'].append(current_state.clone())
|
| 695 |
+
evolution_history['geometries'].append(self.mobius_transform.get_transform_info())
|
| 696 |
+
evolution_history['transition_matrices'].append(markov_output['transition_matrix'])
|
| 697 |
+
evolution_history['transformed_positions'].append(markov_output['transformed_positions'])
|
| 698 |
+
|
| 699 |
+
# Generate final prediction using learned decoder
|
| 700 |
+
final_embedding = self.state_encoder(current_state)
|
| 701 |
+
final_prediction = self.state_decoder(final_embedding)
|
| 702 |
+
|
| 703 |
+
output = {
|
| 704 |
+
'final_state': current_state,
|
| 705 |
+
'final_prediction': final_prediction,
|
| 706 |
+
'final_embedding': final_embedding,
|
| 707 |
+
'final_geometry': self.mobius_transform.get_transform_info()
|
| 708 |
+
}
|
| 709 |
+
|
| 710 |
+
if return_full_trajectory:
|
| 711 |
+
output['evolution_history'] = evolution_history
|
| 712 |
+
|
| 713 |
+
return output
|
| 714 |
+
|
| 715 |
+
def predict_sequence(self, initial_state, sequence_length):
|
| 716 |
+
"""Generate sequence of predictions through iterative evolution.
|
| 717 |
+
|
| 718 |
+
Uses the system as a generative model by iteratively applying
|
| 719 |
+
the evolution process and collecting predictions at each step.
|
| 720 |
+
|
| 721 |
+
Args:
|
| 722 |
+
initial_state: Starting state distribution
|
| 723 |
+
sequence_length: Number of prediction steps
|
| 724 |
+
|
| 725 |
+
Returns:
|
| 726 |
+
Tensor of predictions [sequence_length, batch_size, num_states]
|
| 727 |
+
"""
|
| 728 |
+
predictions = []
|
| 729 |
+
current_state = initial_state
|
| 730 |
+
|
| 731 |
+
for _ in range(sequence_length):
|
| 732 |
+
output = self.forward(current_state)
|
| 733 |
+
predictions.append(output['final_prediction'])
|
| 734 |
+
current_state = output['final_state']
|
| 735 |
+
|
| 736 |
+
return torch.stack(predictions)
|
| 737 |
+
|
| 738 |
+
def get_system_info(self):
|
| 739 |
+
"""Get comprehensive system state information.
|
| 740 |
+
|
| 741 |
+
Returns diagnostic information about the current system state
|
| 742 |
+
including geometry parameters, state positions, and evolution settings.
|
| 743 |
+
|
| 744 |
+
Returns:
|
| 745 |
+
Dictionary with complete system diagnostics
|
| 746 |
+
"""
|
| 747 |
+
return {
|
| 748 |
+
'num_states': self.num_states,
|
| 749 |
+
'evolution_steps': self.evolution_steps,
|
| 750 |
+
'current_geometry': self.mobius_transform.get_transform_info(),
|
| 751 |
+
'state_positions': self.markov_chain.state_positions,
|
| 752 |
+
'geometry_evolution_rate': self.geometry_controller.item()
|
| 753 |
+
}
|
| 754 |
+
|
| 755 |
+
###########################################################################################################################################
|
| 756 |
+
###################################################- - - DEMO AND TESTING - - -########################################################
|
| 757 |
+
|
| 758 |
+
def test_mobius_markov():
|
| 759 |
+
"""Comprehensive test of Möbius-Markov system functionality."""
|
| 760 |
+
print("Testing Möbius Markov - Non-Euclidean Probabilistic Systems")
|
| 761 |
+
print("=" * 75)
|
| 762 |
+
|
| 763 |
+
# Create Möbius-Markov system
|
| 764 |
+
num_states = 8
|
| 765 |
+
system = MobiusMarkovSystem(
|
| 766 |
+
num_states=num_states,
|
| 767 |
+
state_embedding_dim=32,
|
| 768 |
+
evolution_steps=5
|
| 769 |
+
)
|
| 770 |
+
|
| 771 |
+
print(f"Created Möbius-Markov System:")
|
| 772 |
+
print(f" - Number of states: {num_states}")
|
| 773 |
+
print(f" - Evolution steps: {system.evolution_steps}")
|
| 774 |
+
print(f" - State embedding dimension: 32")
|
| 775 |
+
print(f" - Complex state space with adaptive geometry")
|
| 776 |
+
|
| 777 |
+
# Create initial state distribution
|
| 778 |
+
batch_size = 4
|
| 779 |
+
initial_state = torch.zeros(batch_size, num_states)
|
| 780 |
+
initial_state[:, 0] = 1.0 # Start in state 0
|
| 781 |
+
|
| 782 |
+
print(f"\nTesting with batch size: {batch_size}")
|
| 783 |
+
print("Initial state: All samples start in state 0")
|
| 784 |
+
|
| 785 |
+
# Test Möbius transformation components
|
| 786 |
+
print("\nTesting Möbius transformation...")
|
| 787 |
+
mobius = system.mobius_transform
|
| 788 |
+
test_complex = torch.complex(torch.randn(5), torch.randn(5))
|
| 789 |
+
transformed = mobius.transform(test_complex)
|
| 790 |
+
inverse_transformed = mobius.inverse_transform(transformed)
|
| 791 |
+
|
| 792 |
+
# Check invertibility
|
| 793 |
+
reconstruction_error = torch.mean(torch.abs(test_complex - inverse_transformed))
|
| 794 |
+
print(f" - Transformation invertibility error: {reconstruction_error:.6f}")
|
| 795 |
+
|
| 796 |
+
# Test geometry info
|
| 797 |
+
geometry_info = mobius.get_transform_info()
|
| 798 |
+
det_magnitude = torch.abs(geometry_info['determinant'])
|
| 799 |
+
print(f" - Determinant magnitude: {det_magnitude:.4f}")
|
| 800 |
+
print(f" - Is identity: {geometry_info['is_identity']}")
|
| 801 |
+
|
| 802 |
+
# Test forward evolution
|
| 803 |
+
print("\nExecuting Möbius-Markov evolution...")
|
| 804 |
+
output = system(initial_state, return_full_trajectory=True)
|
| 805 |
+
|
| 806 |
+
print("Evolution results:")
|
| 807 |
+
print(f" - Final state shape: {output['final_state'].shape}")
|
| 808 |
+
print(f" - Final prediction shape: {output['final_prediction'].shape}")
|
| 809 |
+
|
| 810 |
+
# Analyze geometric evolution
|
| 811 |
+
print("\nGeometric evolution analysis:")
|
| 812 |
+
history = output['evolution_history']
|
| 813 |
+
|
| 814 |
+
for step in range(min(3, len(history['geometries']))):
|
| 815 |
+
geometry = history['geometries'][step]
|
| 816 |
+
det = torch.abs(geometry['determinant'])
|
| 817 |
+
print(f" Step {step+1}: Determinant magnitude = {det:.3f}")
|
| 818 |
+
|
| 819 |
+
# Test state transitions and trajectory
|
| 820 |
+
print("\nState transition analysis:")
|
| 821 |
+
final_states = output['final_state']
|
| 822 |
+
for i in range(min(batch_size, 3)):
|
| 823 |
+
most_likely = final_states[i].argmax().item()
|
| 824 |
+
confidence = final_states[i].max().item()
|
| 825 |
+
print(f" Sample {i+1}: Most likely state = {most_likely}, Confidence = {confidence:.3f}")
|
| 826 |
+
|
| 827 |
+
# Test complex state positions
|
| 828 |
+
print("\nComplex state space analysis:")
|
| 829 |
+
state_positions = system.markov_chain.state_positions
|
| 830 |
+
print(f" - State positions in complex plane:")
|
| 831 |
+
for i in range(min(4, num_states)):
|
| 832 |
+
pos = state_positions[i]
|
| 833 |
+
real, imag = pos.real.item(), pos.imag.item()
|
| 834 |
+
magnitude = torch.abs(pos).item()
|
| 835 |
+
print(f" State {i}: {real:.3f} + {imag:.3f}i (|z| = {magnitude:.3f})")
|
| 836 |
+
|
| 837 |
+
# Test sequence prediction
|
| 838 |
+
print("\n Testing sequence prediction...")
|
| 839 |
+
sequence_length = 3
|
| 840 |
+
sequence = system.predict_sequence(initial_state[:1], sequence_length)
|
| 841 |
+
|
| 842 |
+
print(f"Generated sequence of length {sequence_length}:")
|
| 843 |
+
for t in range(sequence_length):
|
| 844 |
+
most_likely = sequence[t, 0].argmax().item()
|
| 845 |
+
confidence = sequence[t, 0].max().item()
|
| 846 |
+
print(f" Time {t+1}: State {most_likely} (confidence: {confidence:.3f})")
|
| 847 |
+
|
| 848 |
+
# System information and diagnostics
|
| 849 |
+
info = system.get_system_info()
|
| 850 |
+
print(f"\nSystem diagnostics:")
|
| 851 |
+
print(f" - Geometry evolution rate: {info['geometry_evolution_rate']:.4f}")
|
| 852 |
+
print(f" - Current determinant: {torch.abs(info['current_geometry']['determinant']):.3f}")
|
| 853 |
+
|
| 854 |
+
# Test adaptive behavior with different inputs
|
| 855 |
+
print("\nTesting adaptive geometry...")
|
| 856 |
+
|
| 857 |
+
# Concentrated initial state
|
| 858 |
+
concentrated_state = torch.zeros(1, num_states)
|
| 859 |
+
concentrated_state[0, 0] = 1.0
|
| 860 |
+
conc_output = system(concentrated_state)
|
| 861 |
+
|
| 862 |
+
# Uniform initial state
|
| 863 |
+
uniform_state = torch.ones(1, num_states) / num_states
|
| 864 |
+
uniform_output = system(uniform_state)
|
| 865 |
+
|
| 866 |
+
conc_det = torch.abs(conc_output['final_geometry']['determinant'])
|
| 867 |
+
uniform_det = torch.abs(uniform_output['final_geometry']['determinant'])
|
| 868 |
+
|
| 869 |
+
print(f" - Concentrated input → final determinant: {conc_det:.4f}")
|
| 870 |
+
print(f" - Uniform input → final determinant: {uniform_det:.4f}")
|
| 871 |
+
print(f" - Geometry adaptation difference: {abs(conc_det - uniform_det):.4f}")
|
| 872 |
+
|
| 873 |
+
print("\n Möbius-Markov test completed!")
|
| 874 |
+
print("✓ Non-Euclidean state space with dynamic geometry")
|
| 875 |
+
print("✓ Markov transitions in continuously warped space")
|
| 876 |
+
print("✓ Learnable Möbius transformations with invertibility")
|
| 877 |
+
print("✓ State-dependent geometric evolution")
|
| 878 |
+
print("✓ Complex plane representations and distance-based transitions")
|
| 879 |
+
print("✓ Adaptive spatial structure for different input patterns")
|
| 880 |
+
|
| 881 |
+
return True
|
| 882 |
+
|
| 883 |
+
def visualization_demo():
|
| 884 |
+
"""Demonstrate geometric transformations and state evolution."""
|
| 885 |
+
print("\n" + "="*60)
|
| 886 |
+
print(" GEOMETRIC TRANSFORMATION DEMO")
|
| 887 |
+
print("="*60)
|
| 888 |
+
|
| 889 |
+
# Create simple system for clear visualization
|
| 890 |
+
system = MobiusMarkovSystem(num_states=6, evolution_steps=3)
|
| 891 |
+
|
| 892 |
+
# Get initial state positions in complex plane
|
| 893 |
+
initial_positions = system.markov_chain.state_positions.detach()
|
| 894 |
+
print("Initial state positions (complex plane):")
|
| 895 |
+
for i, pos in enumerate(initial_positions):
|
| 896 |
+
real, imag = pos.real.item(), pos.imag.item()
|
| 897 |
+
magnitude = torch.abs(pos).item()
|
| 898 |
+
angle = torch.angle(pos).item() * 180 / math.pi
|
| 899 |
+
print(f" State {i}: {real:.3f} + {imag:.3f}i (r={magnitude:.3f}, θ={angle:.1f}°)")
|
| 900 |
+
|
| 901 |
+
# Apply several geometric transformations
|
| 902 |
+
print("\nApplying geometric transformations...")
|
| 903 |
+
|
| 904 |
+
test_state = torch.zeros(1, 6)
|
| 905 |
+
test_state[0, 0] = 1.0
|
| 906 |
+
|
| 907 |
+
for step in range(3):
|
| 908 |
+
# Get current geometry
|
| 909 |
+
geometry = system.mobius_transform.get_transform_info()
|
| 910 |
+
|
| 911 |
+
# Transform state positions to show warping
|
| 912 |
+
transformed_pos = system.mobius_transform.transform(initial_positions)
|
| 913 |
+
|
| 914 |
+
print(f"\nStep {step+1}:")
|
| 915 |
+
print(f" Transform determinant: {torch.abs(geometry['determinant']):.3f}")
|
| 916 |
+
|
| 917 |
+
# Show how first few states are transformed
|
| 918 |
+
for i in range(min(3, len(transformed_pos))):
|
| 919 |
+
orig = initial_positions[i]
|
| 920 |
+
trans = transformed_pos[i]
|
| 921 |
+
print(f" State {i}: {orig.real:.2f}+{orig.imag:.2f}i → {trans.real:.2f}+{trans.imag:.2f}i")
|
| 922 |
+
|
| 923 |
+
# Evolve the system one step
|
| 924 |
+
output = system(test_state)
|
| 925 |
+
test_state = output['final_state']
|
| 926 |
+
|
| 927 |
+
print("\n Geometric evolution creates rich, non-Euclidean probabilistic dynamics!")
|
| 928 |
+
print(" State space continuously warps based on system trajectory")
|
| 929 |
+
print(" Distance-based transitions adapt to transformed geometry")
|
| 930 |
+
|
| 931 |
+
if __name__ == "__main__":
|
| 932 |
+
test_mobius_markov()
|
| 933 |
+
visualization_demo()
|
| 934 |
+
|
| 935 |
+
###########################################################################################################################################
|
| 936 |
+
###########################################################################################################################################
|