RFTSystems commited on
Commit
773bea1
ยท
verified ยท
1 Parent(s): 5b375de

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -257
app.py CHANGED
@@ -5,76 +5,10 @@ import torch
5
  import matplotlib.pyplot as plt
6
  import tempfile
7
 
8
- # Conditional import of cupy (GPU optional; this app runs CPU-only by default)
9
- try:
10
- import cupy as cp
11
- _has_cupy = True
12
- except ImportError:
13
- _has_cupy = False
14
- print("CuPy not found. Running in CPU-only mode.")
15
-
16
- # --- CUDA kernel source (kept for future GPU support; not used in CPU path) ---
17
- cuda_source = r'''
18
- extern "C" {
19
- __global__ void fused_mom_update(
20
- const int Ncells,
21
- const int Nmode,
22
- const float dt,
23
- const float eps,
24
- const float sigma_const,
25
- const float theta_global,
26
- const float k_shred_global,
27
- const float * __restrict__ d_alpha,
28
- const float * __restrict__ d_gamma,
29
- const float * __restrict__ d_omega,
30
- float * __restrict__ d_mroot,
31
- float * __restrict__ d_A,
32
- float * __restrict__ d_Q,
33
- unsigned int * __restrict__ d_event_counts,
34
- unsigned long long * __restrict__ d_event_buffer
35
- ) {
36
- int cell_idx = blockIdx.x * blockDim.x + threadIdx.x;
37
- if (cell_idx >= Ncells) return;
38
- int base = cell_idx * Nmode;
39
- float m = d_mroot[cell_idx];
40
- float Xi = 0.0f;
41
- for (int n = 0; n < Nmode; ++n) {
42
- float A = d_A[base + n];
43
- float Q = d_Q[base + n];
44
- float A_dot = d_alpha[n] * m - d_gamma[n] * A + sigma_const * Q;
45
- float f_drive = sigma_const * m * d_omega[n] * A;
46
- float Q_dot = f_drive - Q;
47
- A += dt * A_dot;
48
- Q += dt * Q_dot;
49
- d_A[base + n] = A;
50
- d_Q[base + n] = Q;
51
- Xi += d_omega[n] * A;
52
- }
53
- float Xi_norm = Xi / (m + eps);
54
- if (Xi_norm >= theta_global) {
55
- float eta = 1.0f - expf(-k_shred_global * (Xi_norm - theta_global));
56
- if (eta < 0.0f) eta = 0.0f;
57
- if (eta > 1.0f) eta = 1.0f;
58
- float diss = 0.01f * m * eta;
59
- float m_post = (1.0f - eta) * m - diss;
60
- if (m_post < 0.0f) m_post = 0.0f;
61
- d_mroot[cell_idx] = m_post;
62
- unsigned int idx = atomicAdd(d_event_counts, 1u);
63
- // Event buffer not used in this example
64
- } else {
65
- d_mroot[cell_idx] = m;
66
- }
67
- }
68
- } // extern "C"
69
- '''
70
-
71
- # --- CPU kernel ---
72
- def fused_mom_update_cpu(
73
- m_root_t, A_t, Q_t, alpha_t, gamma_t, omega_t,
74
- dt, eps, sigma_const, theta_global, k_shred_global,
75
- event_counts_t=None, event_buffer_t=None
76
- ):
77
- # Ensure float32
78
  m_root_t = m_root_t.to(torch.float32)
79
  A_t = A_t.to(torch.float32)
80
  Q_t = Q_t.to(torch.float32)
@@ -82,25 +16,21 @@ def fused_mom_update_cpu(
82
  gamma_t = gamma_t.to(torch.float32)
83
  omega_t = omega_t.to(torch.float32)
84
 
85
- # Expand params
86
- alpha_exp = alpha_t.unsqueeze(0) # (1, Nmode)
87
  gamma_exp = gamma_t.unsqueeze(0)
88
  omega_exp = omega_t.unsqueeze(0)
89
- m_root_exp = m_root_t.unsqueeze(1) # (Ncells, 1)
90
 
91
- # Dynamics
92
  A_dot = alpha_exp * m_root_exp - gamma_exp * A_t + sigma_const * Q_t
93
  f_drive = sigma_const * m_root_exp * omega_exp * A_t
94
  Q_dot = f_drive - Q_t
95
 
96
- # Euler update
97
  A_t.add_(dt * A_dot)
98
  Q_t.add_(dt * Q_dot)
99
 
100
- # Shredding
101
- Xi = (omega_exp * A_t).sum(dim=1) # (Ncells)
102
- Xi_norm = Xi / (m_root_t + eps) # (Ncells)
103
- shred_mask = Xi_norm >= theta_global # bool mask
104
 
105
  if torch.any(shred_mask):
106
  eta_values = torch.zeros_like(Xi_norm)
@@ -124,63 +54,41 @@ def fused_mom_update_cpu(
124
 
125
  return m_root_t, A_t, Q_t, event_counts_t
126
 
127
- # --- Kernel wrapper (CPU-first) ---
128
  class MOMKernel:
129
- def __init__(self, cuda_source, kernel_name='fused_mom_update', block_dim=128):
130
- # CPU path by default; GPU path omitted for simplicity
131
- self.use_cuda = False
132
  self.kernel = fused_mom_update_cpu
133
  self.device = torch.device('cpu')
134
 
135
- def __call__(
136
- self, m_root_t, A_t, Q_t, alpha_t, gamma_t, omega_t,
137
- dt, eps, sigma_const, theta_global, k_shred_global,
138
- event_counts_t=None, event_buffer_t=None
139
- ):
140
- return self.kernel(
141
- m_root_t, A_t, Q_t, alpha_t, gamma_t, omega_t,
142
- dt, eps, sigma_const, theta_global, k_shred_global,
143
- event_counts_t, event_buffer_t
144
- )
145
 
146
- # --- System loop with feedback and onset tracking ---
147
  class MOMSystemLoop:
148
  def __init__(self, mom_kernel, m_root_initial, A_modes_initial, Q_drive_initial,
149
- alpha, gamma, omega,
150
- dt=0.02, eps=1e-6, sigma=0.75,
151
- theta=2.2, k_shred=1.2,
152
- event_buffer_size=1024):
153
  self.mom_kernel = mom_kernel
154
  self.device = mom_kernel.device
155
-
156
- # State
157
- self.m_root = m_root_initial.to(self.device).clone().to(torch.float32)
158
  self.A_modes = A_modes_initial.to(self.device).clone().to(torch.float32)
159
  self.Q_drive = Q_drive_initial.to(self.device).clone().to(torch.float32)
160
-
161
- # Params
162
  self.alpha = alpha.to(self.device).to(torch.float32)
163
  self.gamma = gamma.to(self.device).to(torch.float32)
164
  self.omega = omega.to(self.device).to(torch.float32)
165
-
166
  self.dt = dt; self.eps = eps; self.sigma = sigma
167
  self.theta = theta; self.k_shred = k_shred
168
-
169
- # Event tracking
170
  self.event_counts = torch.zeros((), dtype=torch.int64, device=self.device)
171
  self.event_buffer = torch.zeros(event_buffer_size, dtype=torch.int64, device=self.device)
172
-
173
- # Histories
174
  self.m_root_history = []
175
  self.A_modes_history = []
176
  self.event_counts_history = []
177
-
178
- # Shredding onset (per-cell first time reaching near-zero mass)
179
  self.shred_onset = np.full((self.m_root.shape[0],), -1, dtype=np.int32)
180
 
181
  def feedback(self, m_root, A_modes, Q_drive):
182
- decay = 0.995
183
- noise_level = 1e-4
184
  A_modes_new = A_modes * decay + noise_level * torch.randn_like(A_modes, device=self.device)
185
  A_modes_new = torch.clamp(A_modes_new, min=0.0)
186
  m_root_new = m_root * decay + noise_level * torch.randn_like(m_root, device=self.device)
@@ -190,150 +98,83 @@ class MOMSystemLoop:
190
  def run(self, iterations):
191
  for i in range(iterations):
192
  self.event_counts.zero_()
193
-
194
- self.mom_kernel(
195
- self.m_root, self.A_modes, self.Q_drive,
196
- self.alpha, self.gamma, self.omega,
197
- self.dt, self.eps, self.sigma, self.theta, self.k_shred,
198
- self.event_counts, self.event_buffer
199
- )
200
-
201
- # Record shredding onset if mass is effectively collapsed
202
  m_np = self.m_root.detach().cpu().numpy()
203
- collapsed_mask = m_np <= 1e-8 # near-zero threshold to mark onset
204
  for idx, collapsed in enumerate(collapsed_mask):
205
  if collapsed and self.shred_onset[idx] == -1:
206
  self.shred_onset[idx] = i
207
-
208
- # Feedback after kernel update
209
  self.m_root, self.A_modes, self.Q_drive = self.feedback(self.m_root, self.A_modes, self.Q_drive)
210
-
211
- # Histories
212
  self.m_root_history.append(float(self.m_root.mean().item()))
213
  self.A_modes_history.append(float(self.A_modes.mean().item()))
214
  self.event_counts_history.append(int(self.event_counts.item()))
215
 
216
- # --- Simulation wrapper ---
217
- def run_rft_simulation(
218
- Ncells: int,
219
- Nmode: int,
220
- iterations: int,
221
- dt: float = 0.02,
222
- eps: float = 1e-6,
223
- sigma: float = 0.75,
224
- theta: float = 2.2,
225
- k_shred: float = 1.2,
226
- seed: int = 42
227
- ):
228
- torch.manual_seed(seed)
229
- np.random.seed(seed)
230
-
231
- # Kernel and device
232
- mom_kernel_instance = MOMKernel(cuda_source, kernel_name='fused_mom_update', block_dim=128)
233
  device = mom_kernel_instance.device
234
-
235
- # Parameters on device
236
- alpha = torch.empty(Nmode, device=device, dtype=torch.float32).uniform_(0.02, 0.12)
237
- gamma = torch.empty(Nmode, device=device, dtype=torch.float32).uniform_(0.01, 0.06)
238
- omega = torch.linspace(1.0, 8.0, Nmode, device=device, dtype=torch.float32)
239
-
240
- # Initial states
241
- m_root_initial = torch.ones(Ncells, device=device, dtype=torch.float32)
242
- A_modes_initial = torch.rand(Ncells, Nmode, device=device, dtype=torch.float32) * 0.01
243
- Q_drive_initial = torch.zeros(Ncells, Nmode, device=device, dtype=torch.float32)
244
-
245
- mom_system = MOMSystemLoop(
246
- mom_kernel_instance, m_root_initial, A_modes_initial, Q_drive_initial,
247
- alpha, gamma, omega,
248
- dt=dt, eps=eps, sigma=sigma, theta=theta, k_shred=k_shred
249
- )
250
-
251
  start_time = time.time()
252
  mom_system.run(iterations)
253
  elapsed_time = max(time.time() - start_time, 1e-9)
254
-
255
- # GFLOPS estimate
256
  ops_per_cell_per_iter = 12 * Nmode + 13
257
  flops_per_iteration = float(Ncells) * float(ops_per_cell_per_iter)
258
  total_flops = flops_per_iteration * float(iterations)
259
  gflops = total_flops / (elapsed_time * 1e9)
260
-
261
  return {
262
- 'final_m_root': mom_system.m_root.detach().cpu().numpy().astype(np.float32),
263
- 'final_A_modes': mom_system.A_modes.detach().cpu().numpy().astype(np.float32),
264
- 'final_Q_drive': mom_system.Q_drive.detach().cpu().numpy().astype(np.float32),
265
- 'm_root_history': np.array(mom_system.m_root_history, dtype=np.float32),
266
- 'A_modes_history': np.array(mom_system.A_modes_history, dtype=np.float32),
267
- 'event_counts_history': np.array(mom_system.event_counts_history, dtype=np.int64),
268
- 'shred_onset': mom_system.shred_onset, # per-cell first-onset iteration or -1
269
  'elapsed_time_seconds': float(elapsed_time),
270
  'gflops': float(gflops),
271
  }
272
 
273
- # --- Gradio callback ---
274
- def rft_simulation_interface(
275
- Ncells: int,
276
- Nmode: int,
277
- iterations: int,
278
- dt: float,
279
- eps: float,
280
- sigma: float,
281
- theta: float,
282
- k_shred: float
283
- ):
284
  try:
285
- results = run_rft_simulation(
286
- Ncells=Ncells,
287
- Nmode=Nmode,
288
- iterations=iterations,
289
- dt=dt,
290
- eps=eps,
291
- sigma=sigma,
292
- theta=theta,
293
- k_shred=k_shred
294
- )
295
-
296
- # Create plots: 4 subplots including raster of shredding onset
297
  fig = plt.figure(figsize=(10, 14))
298
-
299
- # Plot 1: Mean m_root
300
  ax1 = fig.add_subplot(4, 1, 1)
301
  ax1.plot(results['m_root_history'], label='Mean m_root')
302
- ax1.set_title('Mean m_root Over Iterations')
303
- ax1.set_xlabel('Iteration')
304
- ax1.set_ylabel('Mean m_root')
305
- ax1.grid(True)
306
- ax1.legend()
307
-
308
- # Plot 2: Mean A_modes
309
  ax2 = fig.add_subplot(4, 1, 2)
310
  ax2.plot(results['A_modes_history'], label='Mean A_modes', color='orange')
311
  ax2.set_title('Mean A_modes Over Iterations')
312
- ax2.set_xlabel('Iteration')
313
- ax2.set_ylabel('Mean A_modes')
314
- ax2.grid(True)
315
- ax2.legend()
316
 
317
  # Plot 3: Cumulative Shredding Events
318
  ax3 = fig.add_subplot(4, 1, 3)
319
  cumulative_events = np.cumsum(results['event_counts_history'])
320
  ax3.plot(cumulative_events, label='Cumulative Shredding Events', color='red')
321
  ax3.set_title('Cumulative Shredding Events')
322
- ax3.set_xlabel('Iteration')
323
- ax3.set_ylabel('Cumulative Events')
324
- ax3.grid(True)
325
- ax3.legend()
326
 
327
  # Plot 4: Raster of shredding onset per cell
328
  ax4 = fig.add_subplot(4, 1, 4)
329
  onset = results['shred_onset']
330
- # Draw a vertical tick at the onset iteration for each cell that shredded
331
  for idx, val in enumerate(onset):
332
  if val >= 0:
333
  ax4.vlines(val, idx, idx + 1, color='black', linewidth=0.8)
334
  ax4.set_title('Shredding Onset per Cell')
335
- ax4.set_xlabel('Iteration')
336
- ax4.set_ylabel('Cell Index')
337
  ax4.grid(True)
338
 
339
  plt.tight_layout()
@@ -358,28 +199,26 @@ def rft_simulation_interface(
358
 
359
  return summary_output, plot_path
360
 
361
- # --- Explanatory markdown ---
362
- what_is_this_markdown = '''
363
- ### What is Render Frame Theory (RFT)?
364
- Render Frame Theory (RFT) is a computational framework for simulating complex adaptive systems with emergent, non-linear dynamics. It models a system as a collection of cells, each with internal modes that evolve over time through coupled updates and event-driven transitions.
365
 
366
- Key features:
367
- - **Dynamic systems:** Evolves `m_root` (root mass), `A_modes` (mode amplitudes), and `Q_drive` (drive) over iterations.
368
- - **Feedback loops:** Each iteration adjusts states based on prior values, enabling adaptation.
369
- - **Emergent behavior:** A shredding mechanism triggers non-linear collapse when stress crosses a threshold.
370
- - **Performance scaling:** Designed to scale with the number of cells and modes, enabling large explorations.
371
 
372
- Why it matters:
373
- - **Granularity:** Captures local interactions and cell-level transitions that averaged models miss.
374
- - **Critical events:** Models sudden cascades like market crashes, neural avalanches, or material failure.
375
- - **Versatility:** Applicable to finance, biology, engineering, and AI research.
 
376
 
377
- The shredding onset plot shows when each cell first collapses, making cascades visible in time.
378
- '''
 
 
379
 
380
- # --- Gradio UI ---
381
- with gr.Blocks(title="Render Frame Theory (RFT) Simulation Interface (CPU-ready)") as iface:
382
- gr.Markdown(what_is_this_markdown)
383
 
384
  with gr.Row():
385
  with gr.Column():
@@ -388,28 +227,10 @@ with gr.Blocks(title="Render Frame Theory (RFT) Simulation Interface (CPU-ready)
388
  Nmode_slider = gr.Slider(minimum=2, maximum=32, step=2, value=8, label="๐Ÿ”ฎ Number of Modes (Nmode)")
389
  iterations_slider = gr.Slider(minimum=10, maximum=200, step=10, value=50, label="โ™พ Iterations")
390
  dt_slider = gr.Slider(minimum=0.001, maximum=0.1, step=0.001, value=0.02, label="โŒ› Time Step (dt)")
391
- eps_slider = gr.Slider(
392
- minimum=1e-7, maximum=1e-4, step=1e-7, value=1e-6,
393
- label="๐Ÿงฟ Epsilon (eps)",
394
- info="Small constant to stabilize Xi_norm division."
395
- )
396
- sigma_slider = gr.Slider(
397
- minimum=0.1, maximum=1.0, step=0.05, value=0.75,
398
- label="๐ŸŒŒ Sigma (coupling strength)",
399
- info="Strength of Qโ€“A interaction; higher values intensify dynamics."
400
- )
401
- theta_slider = gr.Slider(
402
- minimum=0.1, maximum=5.0, step=0.1, value=2.2,
403
- label="๐Ÿ”ญ Theta (Shredding Threshold)",
404
- info="Stress threshold (Xi_norm) above which shredding begins."
405
- )
406
- k_shred_slider = gr.Slider(
407
- minimum=0.1, maximum=5.0, step=0.1, value=1.2,
408
- label="๐ŸŒ€ K_shred (Shredding Rate)",
409
- info="Intensity of shredding once triggered."
410
- )
411
-
412
- gr.Markdown("**Adjust parameters and click below to start the simulation.**")
413
  run_button = gr.Button("Run Simulation")
414
 
415
  with gr.Column():
@@ -419,10 +240,8 @@ with gr.Blocks(title="Render Frame Theory (RFT) Simulation Interface (CPU-ready)
419
 
420
  run_button.click(
421
  fn=rft_simulation_interface,
422
- inputs=[
423
- Ncells_slider, Nmode_slider, iterations_slider, dt_slider, eps_slider,
424
- sigma_slider, theta_slider, k_shred_slider
425
- ],
426
  outputs=[summary_output_textbox, plot_output_image]
427
  )
428
 
 
5
  import matplotlib.pyplot as plt
6
  import tempfile
7
 
8
+ # CPU kernel
9
+ def fused_mom_update_cpu(m_root_t, A_t, Q_t, alpha_t, gamma_t, omega_t,
10
+ dt, eps, sigma_const, theta_global, k_shred_global,
11
+ event_counts_t=None, event_buffer_t=None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  m_root_t = m_root_t.to(torch.float32)
13
  A_t = A_t.to(torch.float32)
14
  Q_t = Q_t.to(torch.float32)
 
16
  gamma_t = gamma_t.to(torch.float32)
17
  omega_t = omega_t.to(torch.float32)
18
 
19
+ alpha_exp = alpha_t.unsqueeze(0)
 
20
  gamma_exp = gamma_t.unsqueeze(0)
21
  omega_exp = omega_t.unsqueeze(0)
22
+ m_root_exp = m_root_t.unsqueeze(1)
23
 
 
24
  A_dot = alpha_exp * m_root_exp - gamma_exp * A_t + sigma_const * Q_t
25
  f_drive = sigma_const * m_root_exp * omega_exp * A_t
26
  Q_dot = f_drive - Q_t
27
 
 
28
  A_t.add_(dt * A_dot)
29
  Q_t.add_(dt * Q_dot)
30
 
31
+ Xi = (omega_exp * A_t).sum(dim=1)
32
+ Xi_norm = Xi / (m_root_t + eps)
33
+ shred_mask = Xi_norm >= theta_global
 
34
 
35
  if torch.any(shred_mask):
36
  eta_values = torch.zeros_like(Xi_norm)
 
54
 
55
  return m_root_t, A_t, Q_t, event_counts_t
56
 
 
57
  class MOMKernel:
58
+ def __init__(self):
 
 
59
  self.kernel = fused_mom_update_cpu
60
  self.device = torch.device('cpu')
61
 
62
+ def __call__(self, m_root_t, A_t, Q_t, alpha_t, gamma_t, omega_t,
63
+ dt, eps, sigma_const, theta_global, k_shred_global,
64
+ event_counts_t=None, event_buffer_t=None):
65
+ return self.kernel(m_root_t, A_t, Q_t, alpha_t, gamma_t, omega_t,
66
+ dt, eps, sigma_const, theta_global, k_shred_global,
67
+ event_counts_t, event_buffer_t)
 
 
 
 
68
 
 
69
  class MOMSystemLoop:
70
  def __init__(self, mom_kernel, m_root_initial, A_modes_initial, Q_drive_initial,
71
+ alpha, gamma, omega, dt=0.02, eps=1e-6, sigma=0.75,
72
+ theta=2.2, k_shred=1.2, event_buffer_size=1024):
 
 
73
  self.mom_kernel = mom_kernel
74
  self.device = mom_kernel.device
75
+ self.m_root = m_root_initial.to(self.device).clone().to(torch.float32)
 
 
76
  self.A_modes = A_modes_initial.to(self.device).clone().to(torch.float32)
77
  self.Q_drive = Q_drive_initial.to(self.device).clone().to(torch.float32)
 
 
78
  self.alpha = alpha.to(self.device).to(torch.float32)
79
  self.gamma = gamma.to(self.device).to(torch.float32)
80
  self.omega = omega.to(self.device).to(torch.float32)
 
81
  self.dt = dt; self.eps = eps; self.sigma = sigma
82
  self.theta = theta; self.k_shred = k_shred
 
 
83
  self.event_counts = torch.zeros((), dtype=torch.int64, device=self.device)
84
  self.event_buffer = torch.zeros(event_buffer_size, dtype=torch.int64, device=self.device)
 
 
85
  self.m_root_history = []
86
  self.A_modes_history = []
87
  self.event_counts_history = []
 
 
88
  self.shred_onset = np.full((self.m_root.shape[0],), -1, dtype=np.int32)
89
 
90
  def feedback(self, m_root, A_modes, Q_drive):
91
+ decay = 0.995; noise_level = 1e-4
 
92
  A_modes_new = A_modes * decay + noise_level * torch.randn_like(A_modes, device=self.device)
93
  A_modes_new = torch.clamp(A_modes_new, min=0.0)
94
  m_root_new = m_root * decay + noise_level * torch.randn_like(m_root, device=self.device)
 
98
  def run(self, iterations):
99
  for i in range(iterations):
100
  self.event_counts.zero_()
101
+ self.mom_kernel(self.m_root, self.A_modes, self.Q_drive,
102
+ self.alpha, self.gamma, self.omega,
103
+ self.dt, self.eps, self.sigma, self.theta, self.k_shred,
104
+ self.event_counts, self.event_buffer)
 
 
 
 
 
105
  m_np = self.m_root.detach().cpu().numpy()
106
+ collapsed_mask = m_np <= 1e-8
107
  for idx, collapsed in enumerate(collapsed_mask):
108
  if collapsed and self.shred_onset[idx] == -1:
109
  self.shred_onset[idx] = i
 
 
110
  self.m_root, self.A_modes, self.Q_drive = self.feedback(self.m_root, self.A_modes, self.Q_drive)
 
 
111
  self.m_root_history.append(float(self.m_root.mean().item()))
112
  self.A_modes_history.append(float(self.A_modes.mean().item()))
113
  self.event_counts_history.append(int(self.event_counts.item()))
114
 
115
+ def run_rft_simulation(Ncells, Nmode, iterations, dt=0.02, eps=1e-6, sigma=0.75,
116
+ theta=2.2, k_shred=1.2, seed=42):
117
+ torch.manual_seed(seed); np.random.seed(seed)
118
+ mom_kernel_instance = MOMKernel()
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  device = mom_kernel_instance.device
120
+ alpha = torch.empty(Nmode, device=device).uniform_(0.02, 0.12)
121
+ gamma = torch.empty(Nmode, device=device).uniform_(0.01, 0.06)
122
+ omega = torch.linspace(1.0, 8.0, Nmode, device=device)
123
+ m_root_initial = torch.ones(Ncells, device=device)
124
+ A_modes_initial = torch.rand(Ncells, Nmode, device=device) * 0.01
125
+ Q_drive_initial = torch.zeros(Ncells, Nmode, device=device)
126
+ mom_system = MOMSystemLoop(mom_kernel_instance, m_root_initial, A_modes_initial, Q_drive_initial,
127
+ alpha, gamma, omega, dt=dt, eps=eps, sigma=sigma,
128
+ theta=theta, k_shred=k_shred)
 
 
 
 
 
 
 
 
129
  start_time = time.time()
130
  mom_system.run(iterations)
131
  elapsed_time = max(time.time() - start_time, 1e-9)
 
 
132
  ops_per_cell_per_iter = 12 * Nmode + 13
133
  flops_per_iteration = float(Ncells) * float(ops_per_cell_per_iter)
134
  total_flops = flops_per_iteration * float(iterations)
135
  gflops = total_flops / (elapsed_time * 1e9)
 
136
  return {
137
+ 'final_m_root': mom_system.m_root.cpu().numpy(),
138
+ 'final_A_modes': mom_system.A_modes.cpu().numpy(),
139
+ 'final_Q_drive': mom_system.Q_drive.cpu().numpy(),
140
+ 'm_root_history': np.array(mom_system.m_root_history),
141
+ 'A_modes_history': np.array(mom_system.A_modes_history),
142
+ 'event_counts_history': np.array(mom_system.event_counts_history),
143
+ 'shred_onset': mom_system.shred_onset,
144
  'elapsed_time_seconds': float(elapsed_time),
145
  'gflops': float(gflops),
146
  }
147
 
148
+ def rft_simulation_interface(Ncells, Nmode, iterations, dt, eps, sigma, theta, k_shred):
 
 
 
 
 
 
 
 
 
 
149
  try:
150
+ results = run_rft_simulation(Ncells, Nmode, iterations, dt, eps, sigma, theta, k_shred)
 
 
 
 
 
 
 
 
 
 
 
151
  fig = plt.figure(figsize=(10, 14))
 
 
152
  ax1 = fig.add_subplot(4, 1, 1)
153
  ax1.plot(results['m_root_history'], label='Mean m_root')
154
+ ax1.set_title('Mean m_root Over Iterations'); ax1.set_xlabel('Iteration'); ax1.set_ylabel('Mean m_root')
155
+ ax1.grid(True); ax1.legend()
 
 
 
 
 
156
  ax2 = fig.add_subplot(4, 1, 2)
157
  ax2.plot(results['A_modes_history'], label='Mean A_modes', color='orange')
158
  ax2.set_title('Mean A_modes Over Iterations')
159
+ ax2.set_xlabel('Iteration'); ax2.set_ylabel('Mean A_modes')
160
+ ax2.grid(True); ax2.legend()
 
 
161
 
162
  # Plot 3: Cumulative Shredding Events
163
  ax3 = fig.add_subplot(4, 1, 3)
164
  cumulative_events = np.cumsum(results['event_counts_history'])
165
  ax3.plot(cumulative_events, label='Cumulative Shredding Events', color='red')
166
  ax3.set_title('Cumulative Shredding Events')
167
+ ax3.set_xlabel('Iteration'); ax3.set_ylabel('Cumulative Events')
168
+ ax3.grid(True); ax3.legend()
 
 
169
 
170
  # Plot 4: Raster of shredding onset per cell
171
  ax4 = fig.add_subplot(4, 1, 4)
172
  onset = results['shred_onset']
 
173
  for idx, val in enumerate(onset):
174
  if val >= 0:
175
  ax4.vlines(val, idx, idx + 1, color='black', linewidth=0.8)
176
  ax4.set_title('Shredding Onset per Cell')
177
+ ax4.set_xlabel('Iteration'); ax4.set_ylabel('Cell Index')
 
178
  ax4.grid(True)
179
 
180
  plt.tight_layout()
 
199
 
200
  return summary_output, plot_path
201
 
202
+ # --- Explanatory markdown embedded directly ---
203
+ with gr.Blocks(title="Rendered Frame Theory (RFT) Simulation Interface") as iface:
204
+ gr.Markdown("""
205
+ ### What is Rendered Frame Theory (RFT)?
206
 
207
+ Rendered Frame Theory (RFT) is a computational framework for simulating complex adaptive systems with emergent, non-linear dynamics. It models a system as a collection of cells, each with internal modes that evolve over time through coupled updates and event-driven transitions.
 
 
 
 
208
 
209
+ **Key features:**
210
+ - โšก Dynamic systems: Evolves m_root (root mass), A_modes (mode amplitudes), and Q_drive (drive) over iterations.
211
+ - ๐Ÿ”„ Feedback loops: Each iteration adjusts states based on prior values, enabling adaptation.
212
+ - ๐ŸŒ€ Emergent behavior: A shredding mechanism triggers non-linear collapse when stress crosses a threshold.
213
+ - ๐Ÿ“ˆ Performance scaling: Designed to scale with the number of cells and modes, enabling large explorations.
214
 
215
+ **Why it matters:**
216
+ - ๐Ÿ”ฌ Granularity: Captures local interactions and cell-level transitions that averaged models miss.
217
+ - โš ๏ธ Critical events: Models sudden cascades like market crashes, neural avalanches, or material failure.
218
+ - ๐ŸŒ Versatility: Applicable to finance, biology, engineering, and AI research.
219
 
220
+ The shredding onset plot shows when each cell first collapses, making cascades visible in time.
221
+ """)
 
222
 
223
  with gr.Row():
224
  with gr.Column():
 
227
  Nmode_slider = gr.Slider(minimum=2, maximum=32, step=2, value=8, label="๐Ÿ”ฎ Number of Modes (Nmode)")
228
  iterations_slider = gr.Slider(minimum=10, maximum=200, step=10, value=50, label="โ™พ Iterations")
229
  dt_slider = gr.Slider(minimum=0.001, maximum=0.1, step=0.001, value=0.02, label="โŒ› Time Step (dt)")
230
+ eps_slider = gr.Slider(minimum=1e-7, maximum=1e-4, step=1e-7, value=1e-6, label="๐Ÿงฟ Epsilon (eps)")
231
+ sigma_slider = gr.Slider(minimum=0.1, maximum=1.0, step=0.05, value=0.75, label="๐ŸŒŒ Sigma (coupling strength)")
232
+ theta_slider = gr.Slider(minimum=0.1, maximum=5.0, step=0.1, value=2.2, label="๐Ÿ”ญ Theta (Shredding Threshold)")
233
+ k_shred_slider = gr.Slider(minimum=0.1, maximum=5.0, step=0.1, value=1.2, label="๐ŸŒ€ K_shred (Shredding Rate)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  run_button = gr.Button("Run Simulation")
235
 
236
  with gr.Column():
 
240
 
241
  run_button.click(
242
  fn=rft_simulation_interface,
243
+ inputs=[Ncells_slider, Nmode_slider, iterations_slider, dt_slider, eps_slider,
244
+ sigma_slider, theta_slider, k_shred_slider],
 
 
245
  outputs=[summary_output_textbox, plot_output_image]
246
  )
247