1990two commited on
Commit
4deea85
·
verified ·
1 Parent(s): b20a806

Upload 2 files

Browse files
Files changed (2) hide show
  1. mobius_markov.py +330 -0
  2. 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
+ ###########################################################################################################################################