RFTSystems commited on
Commit
32cbb56
·
verified ·
1 Parent(s): 8d79e2a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +34 -65
app.py CHANGED
@@ -106,7 +106,6 @@ def simulate_neo(
106
  dist = float(np.linalg.norm(meas))
107
 
108
  speed = float(np.linalg.norm(vel))
109
- # uncertainty proxy: noise relative to alert radius + a mild speed term
110
  uncertainty = clamp((noise_km / max(alert_km, 1.0)) * 2.0 + (speed / 200.0) * 0.2, 0.0, 1.0)
111
 
112
  baseline_alert = dist <= alert_km
@@ -251,7 +250,6 @@ def simulate_jitter(
251
  "jitter_rft_next": jitter_rft_next,
252
  })
253
 
254
- # Run the plant under RFT to reflect "using the RFT agent"
255
  jitter = jitter_rft_next
256
  jitter_rate *= 0.92
257
 
@@ -321,13 +319,11 @@ def simulate_landing(
321
  ):
322
  set_seed(seed)
323
 
324
- # State
325
  alt = 1000.0
326
  vv = -45.0
327
  x = 60.0
328
  xv = 0.0
329
 
330
- # Integral term helps remove persistent bias
331
  ix = 0.0
332
 
333
  anomalies = 0
@@ -341,9 +337,6 @@ def simulate_landing(
341
  WIND_PUSH = 0.28
342
  VERT_CTRL = 0.22
343
 
344
- OVERRIDE_X = 18.0
345
- OVERRIDE_ALT = 260.0
346
-
347
  for t in range(int(steps)):
348
  gust = math.sin(0.08 * t) + 0.55 * math.sin(0.21 * t + 0.7)
349
  wind = (wind_max * 0.75) * gust + np.random.normal(0.0, 0.65)
@@ -382,9 +375,7 @@ def simulate_landing(
382
  if meas_alt < 600:
383
  ix = clamp(ix + (meas_x * dt) * 0.0025, -40.0, 40.0)
384
 
385
- do_action = rft_gate(conf, tau, gate_threshold)
386
- must_act = (abs(meas_x) > OVERRIDE_X) or (meas_alt < OVERRIDE_ALT)
387
- do_action = bool(do_action or must_act)
388
 
389
  u_rft_x = 0.0
390
  u_rft_v = 0.0
@@ -485,7 +476,6 @@ def simulate_landing(
485
  # ===============================================================
486
  # Predator Avoidance (Reflex vs QuantumConscious "RFT-style")
487
  # ===============================================================
488
-
489
  def numpy_convolve2d_toroidal(array: np.ndarray, kernel: np.ndarray) -> np.ndarray:
490
  out = np.zeros_like(array, dtype=float)
491
  kcx = kernel.shape[0] // 2
@@ -544,13 +534,11 @@ class QuantumConsciousAgent:
544
  self.grid_size = grid_size
545
  self.move_kernel = move_kernel.astype(float)
546
 
547
- # "probability field" + initial collapse
548
  self.pos_prob = np.zeros((grid_size, grid_size), dtype=float)
549
  x, y = np.random.randint(grid_size), np.random.randint(grid_size)
550
  self.pos_prob[x, y] = 1.0
551
  self.x, self.y = int(x), int(y)
552
 
553
- # energy + override state
554
  self.energy_max = float(energy_max)
555
  self.energy = float(energy_max)
556
  self.energy_regen = float(energy_regen)
@@ -564,7 +552,8 @@ class QuantumConsciousAgent:
564
  self.dt_internal = float(dt_internal)
565
  self.override_threshold = float(override_threshold)
566
 
567
- self.psi_override = (0.1 + 0j)
 
568
  self.overrides = 0
569
  self.collisions = 0
570
 
@@ -573,17 +562,19 @@ class QuantumConsciousAgent:
573
  self.x = (self.x + dx) % self.grid_size
574
  self.y = (self.y + dy) % self.grid_size
575
 
 
 
 
 
576
  def sense_predators(self, predators):
577
  perceived = []
578
  for p in predators:
579
  if random.random() < self.sense_noise_prob:
580
- # drop this predator (sensor miss)
581
  continue
582
  perceived.append((p.x, p.y))
583
  return perceived
584
 
585
  def compute_threat(self, perceived):
586
- # threat = probability mass near predators (radius window)
587
  threat = 0.0
588
  radius = 2
589
  for (px, py) in perceived:
@@ -594,21 +585,36 @@ class QuantumConsciousAgent:
594
  return threat
595
 
596
  def update_override_state(self, perceived):
 
 
 
 
597
  T = self.compute_threat(perceived)
598
  E = self.energy / max(self.energy_max, 1e-9)
599
- # same structural shape as your PDF: H = alpha*T - beta*E + small recursion term
600
- H = self.alpha * T - self.beta * E + 0.01 * (abs(self.psi_override) ** 2)
601
- self.psi_override *= np.exp(-1j * H * self.dt_internal)
 
 
 
 
 
 
 
 
 
 
 
 
 
602
 
603
  def get_override_probability(self):
604
- return float(abs(self.psi_override) ** 2)
605
 
606
  def apply_override(self, perceived):
607
- # diffuse probability a little (kernel), then suppress regions near predators
608
  field = numpy_convolve2d_toroidal(self.pos_prob, self.move_kernel)
609
  field = np.maximum(field, 0.0)
610
 
611
- # suppress predator neighborhoods
612
  for (px, py) in perceived:
613
  for dx in range(-2, 3):
614
  for dy in range(-2, 3):
@@ -619,21 +625,18 @@ class QuantumConsciousAgent:
619
 
620
  s = float(field.sum())
621
  if s <= 0:
622
- # fallback to uniform
623
  field[:] = 1.0 / (self.grid_size * self.grid_size)
624
  else:
625
  field /= s
626
 
627
  self.pos_prob = field
628
 
629
- # collapse away from predator cells explicitly
630
  flat = self.pos_prob.flatten().copy()
631
  for (px, py) in perceived:
632
  flat[px * self.grid_size + py] = 0.0
633
 
634
  tot = float(flat.sum())
635
  if tot <= 0:
636
- # if all got zeroed (rare), just random move
637
  self.move()
638
  return
639
 
@@ -649,28 +652,28 @@ class QuantumConsciousAgent:
649
  def regen_energy(self):
650
  boost = self.quantum_energy_boost()
651
  self.energy = clamp(self.energy + self.energy_regen + boost, 0.0, self.energy_max)
652
- # occasional full regen (as in your runs)
653
  if self.energy < self.energy_max and random.random() < 0.05:
654
  self.energy = self.energy_max
655
 
656
  def move_consciously(self, predators, group_coherence: float):
657
  if self.energy <= 0:
658
  self.move()
659
- return 0, 0.0, 0.0 # acted?, P_ov, threat
660
 
661
  perceived = self.sense_predators(predators)
662
  self.update_override_state(perceived)
 
663
  P_ov = self.get_override_probability()
664
  threat = self.compute_threat(perceived)
665
 
666
  acted = 0
667
- if (P_ov > self.override_threshold) and (self.energy > 0):
668
  effective_cost = self.base_override_cost * (1.0 - float(group_coherence))
669
  if self.energy >= effective_cost:
670
  self.overrides += 1
671
  self.energy -= effective_cost
672
  self.apply_override(perceived)
673
- self.psi_override = (0.1 + 0j)
674
  acted = 1
675
  else:
676
  self.move()
@@ -725,30 +728,19 @@ def simulate_predator(
725
  ]
726
  predators = [Predator(grid_size) for _ in range(int(num_predators))]
727
 
728
- reflex_collisions_cum = []
729
- conscious_collisions_cum = []
730
- conscious_overrides_avg = []
731
- conscious_energy_avg = []
732
- conscious_threat_avg = []
733
- conscious_pov_avg = []
734
- conscious_actions_avg = []
735
-
736
  rows = []
737
  ops_proxy = 0
738
 
739
  for t in range(int(steps)):
740
- # predators move first
741
  for p in predators:
742
  p.move()
743
 
744
- # reflex move + collision check
745
  for a in reflex_agents:
746
  a.move()
747
  for p in predators:
748
  if a.x == p.x and a.y == p.y:
749
  a.collisions += 1
750
 
751
- # conscious move + collision check
752
  actions = []
753
  povs = []
754
  threats = []
@@ -772,15 +764,6 @@ def simulate_predator(
772
  avg_pov = float(np.mean(povs)) if povs else 0.0
773
  avg_act = float(np.mean(actions)) if actions else 0.0
774
 
775
- reflex_collisions_cum.append(reflex_collisions)
776
- conscious_collisions_cum.append(conscious_collisions)
777
- conscious_overrides_avg.append(avg_overrides)
778
- conscious_energy_avg.append(avg_energy)
779
- conscious_threat_avg.append(avg_threat)
780
- conscious_pov_avg.append(avg_pov)
781
- conscious_actions_avg.append(avg_act)
782
-
783
- # log row (one line per step)
784
  rows.append({
785
  "t": t,
786
  "reflex_collisions_cum": reflex_collisions,
@@ -796,7 +779,6 @@ def simulate_predator(
796
  df = pd.DataFrame(rows)
797
  csv_path = df_to_csv_file(df, f"predator_log_seed{seed}.csv")
798
 
799
- # Plot 1: collisions (cumulative)
800
  fig1 = plt.figure(figsize=(10, 4))
801
  ax = fig1.add_subplot(111)
802
  ax.plot(df["t"], df["reflex_collisions_cum"], label="Reflex collisions (cum)")
@@ -807,7 +789,6 @@ def simulate_predator(
807
  ax.legend()
808
  p_col = save_plot(fig1, f"predator_collisions_seed{seed}.png")
809
 
810
- # Plot 2: overrides + energy
811
  fig2 = plt.figure(figsize=(10, 4))
812
  ax = fig2.add_subplot(111)
813
  ax.plot(df["t"], df["avg_conscious_overrides"], label="Avg overrides (conscious)")
@@ -818,7 +799,6 @@ def simulate_predator(
818
  ax.legend()
819
  p_ov = save_plot(fig2, f"predator_overrides_energy_seed{seed}.png")
820
 
821
- # Plot 3: threat + P_override + actions
822
  fig3 = plt.figure(figsize=(10, 4))
823
  ax = fig3.add_subplot(111)
824
  ax.plot(df["t"], df["avg_conscious_threat"], label="Avg threat")
@@ -832,7 +812,6 @@ def simulate_predator(
832
 
833
  heatmap_path = None
834
  if show_heatmap and len(conscious_agents) > 0:
835
- # show the final probability field of agent 0
836
  field = conscious_agents[0].pos_prob
837
  fig4 = plt.figure(figsize=(6, 5))
838
  ax = fig4.add_subplot(111)
@@ -875,7 +854,6 @@ def run_benchmarks(
875
  ):
876
  seed = int(seed)
877
 
878
- # NEO
879
  s_rft, _, neo_imgs, neo_csv = simulate_neo(
880
  seed=seed,
881
  steps=neo_steps,
@@ -891,7 +869,6 @@ def run_benchmarks(
891
  neo_rft = int(neo_df["rft_alert"].sum())
892
  neo_candidates = int(neo_df["rft_candidate"].sum())
893
 
894
- # Jitter
895
  j_sum, jit_imgs, jit_csv = simulate_jitter(
896
  seed=seed,
897
  steps=jit_steps,
@@ -903,7 +880,6 @@ def run_benchmarks(
903
  tau_gain=tau_gain
904
  )
905
 
906
- # Landing
907
  l_sum, land_imgs, land_csv = simulate_landing(
908
  seed=seed,
909
  steps=land_steps,
@@ -953,7 +929,7 @@ def run_benchmarks(
953
  f"- Landing: final offset={l_sum['final_landing_offset_m']:.2f} m (goal 10 m), anomalies={l_sum['total_anomalies_detected']}, actions={l_sum['total_control_actions']}\n"
954
  )
955
 
956
- all_imgs = neo_imgs + jit_imgs + land_imgs # 3 + 3 + 4 = 10
957
  return txt, score, score_path, all_imgs, [neo_csv, jit_csv, land_csv]
958
 
959
  # -----------------------------
@@ -1142,7 +1118,6 @@ def ui_run_predator(seed, grid_size, steps, num_reflex, num_conscious, num_preda
1142
  show_heatmap=bool(show_heatmap)
1143
  )
1144
  summary_txt = json.dumps(summary, indent=2)
1145
- # imgs: 3 or 4
1146
  img1 = imgs[0] if len(imgs) > 0 else None
1147
  img2 = imgs[1] if len(imgs) > 1 else None
1148
  img3 = imgs[2] if len(imgs) > 2 else None
@@ -1170,7 +1145,6 @@ with gr.Blocks(title="RFT — Agent Console (NEO / Jitter / Landing / Predator)"
1170
  gr.Markdown(HOME_MD)
1171
 
1172
  with gr.Tabs():
1173
- # ----------------------------------------------------------
1174
  with gr.Tab("Live Console"):
1175
  gr.Markdown(LIVE_MD)
1176
 
@@ -1230,7 +1204,6 @@ with gr.Blocks(title="RFT — Agent Console (NEO / Jitter / Landing / Predator)"
1230
  ]
1231
  )
1232
 
1233
- # ----------------------------------------------------------
1234
  with gr.Tab("NEO Agent"):
1235
  gr.Markdown(
1236
  "# Near-Earth Object (NEO) Alerting Agent\n"
@@ -1263,7 +1236,6 @@ with gr.Blocks(title="RFT — Agent Console (NEO / Jitter / Landing / Predator)"
1263
  outputs=[out_neo_summary, out_neo_debug, out_neo_img1, out_neo_img2, out_neo_img3, out_neo_csv]
1264
  )
1265
 
1266
- # ----------------------------------------------------------
1267
  with gr.Tab("Satellite Jitter Agent"):
1268
  gr.Markdown(
1269
  "# Satellite Jitter Reduction\n"
@@ -1295,7 +1267,6 @@ with gr.Blocks(title="RFT — Agent Console (NEO / Jitter / Landing / Predator)"
1295
  outputs=[out_j_summary, out_j_img1, out_j_img2, out_j_img3, out_j_csv]
1296
  )
1297
 
1298
- # ----------------------------------------------------------
1299
  with gr.Tab("Starship Landing Harness"):
1300
  gr.Markdown(
1301
  "# Starship-style Landing Harness (Simplified)\n"
@@ -1330,7 +1301,6 @@ with gr.Blocks(title="RFT — Agent Console (NEO / Jitter / Landing / Predator)"
1330
  outputs=[out_l_summary, out_l_img1, out_l_img2, out_l_img3, out_l_img4, out_l_csv]
1331
  )
1332
 
1333
- # ----------------------------------------------------------
1334
  with gr.Tab("Predator Avoidance"):
1335
  gr.Markdown(
1336
  "# Predator Avoidance (Reflex vs RFT)\n"
@@ -1353,7 +1323,7 @@ with gr.Blocks(title="RFT — Agent Console (NEO / Jitter / Landing / Predator)"
1353
  with gr.Row():
1354
  group_coherence = gr.Slider(0.0, 0.95, value=0.30, step=0.01, label="Group coherence")
1355
  sense_noise_prob = gr.Slider(0.0, 0.9, value=0.10, step=0.01, label="Sense noise probability")
1356
- override_threshold = gr.Slider(0.0, 1.0, value=0.01, step=0.005, label="Override threshold (P_ov)")
1357
 
1358
  with gr.Row():
1359
  alpha = gr.Slider(0.0, 50.0, value=15.0, step=0.5, label="alpha (threat gain)")
@@ -1392,7 +1362,6 @@ with gr.Blocks(title="RFT — Agent Console (NEO / Jitter / Landing / Predator)"
1392
  outputs=[out_p_summary, out_p_img1, out_p_img2, out_p_img3, out_p_img4, out_p_csv]
1393
  )
1394
 
1395
- # ----------------------------------------------------------
1396
  with gr.Tab("Theory → Practice"):
1397
  gr.Markdown(THEORY_PRACTICE_MD)
1398
 
 
106
  dist = float(np.linalg.norm(meas))
107
 
108
  speed = float(np.linalg.norm(vel))
 
109
  uncertainty = clamp((noise_km / max(alert_km, 1.0)) * 2.0 + (speed / 200.0) * 0.2, 0.0, 1.0)
110
 
111
  baseline_alert = dist <= alert_km
 
250
  "jitter_rft_next": jitter_rft_next,
251
  })
252
 
 
253
  jitter = jitter_rft_next
254
  jitter_rate *= 0.92
255
 
 
319
  ):
320
  set_seed(seed)
321
 
 
322
  alt = 1000.0
323
  vv = -45.0
324
  x = 60.0
325
  xv = 0.0
326
 
 
327
  ix = 0.0
328
 
329
  anomalies = 0
 
337
  WIND_PUSH = 0.28
338
  VERT_CTRL = 0.22
339
 
 
 
 
340
  for t in range(int(steps)):
341
  gust = math.sin(0.08 * t) + 0.55 * math.sin(0.21 * t + 0.7)
342
  wind = (wind_max * 0.75) * gust + np.random.normal(0.0, 0.65)
 
375
  if meas_alt < 600:
376
  ix = clamp(ix + (meas_x * dt) * 0.0025, -40.0, 40.0)
377
 
378
+ do_action = bool(rft_gate(conf, tau, gate_threshold))
 
 
379
 
380
  u_rft_x = 0.0
381
  u_rft_v = 0.0
 
476
  # ===============================================================
477
  # Predator Avoidance (Reflex vs QuantumConscious "RFT-style")
478
  # ===============================================================
 
479
  def numpy_convolve2d_toroidal(array: np.ndarray, kernel: np.ndarray) -> np.ndarray:
480
  out = np.zeros_like(array, dtype=float)
481
  kcx = kernel.shape[0] // 2
 
534
  self.grid_size = grid_size
535
  self.move_kernel = move_kernel.astype(float)
536
 
 
537
  self.pos_prob = np.zeros((grid_size, grid_size), dtype=float)
538
  x, y = np.random.randint(grid_size), np.random.randint(grid_size)
539
  self.pos_prob[x, y] = 1.0
540
  self.x, self.y = int(x), int(y)
541
 
 
542
  self.energy_max = float(energy_max)
543
  self.energy = float(energy_max)
544
  self.energy_regen = float(energy_regen)
 
552
  self.dt_internal = float(dt_internal)
553
  self.override_threshold = float(override_threshold)
554
 
555
+ # Start low so P_override is not pinned at the threshold.
556
+ self.psi_override = (0.08 + 0j) # |psi|^2 = 0.0064
557
  self.overrides = 0
558
  self.collisions = 0
559
 
 
562
  self.x = (self.x + dx) % self.grid_size
563
  self.y = (self.y + dy) % self.grid_size
564
 
565
+ # Keep pos_prob consistent with actual state (otherwise threat stays meaningless)
566
+ self.pos_prob.fill(0.0)
567
+ self.pos_prob[self.x, self.y] = 1.0
568
+
569
  def sense_predators(self, predators):
570
  perceived = []
571
  for p in predators:
572
  if random.random() < self.sense_noise_prob:
 
573
  continue
574
  perceived.append((p.x, p.y))
575
  return perceived
576
 
577
  def compute_threat(self, perceived):
 
578
  threat = 0.0
579
  radius = 2
580
  for (px, py) in perceived:
 
585
  return threat
586
 
587
  def update_override_state(self, perceived):
588
+ """
589
+ Make P_override responsive (amplitude changes), not phase-only.
590
+ Threat pushes amplitude up; energy pushes it down.
591
+ """
592
  T = self.compute_threat(perceived)
593
  E = self.energy / max(self.energy_max, 1e-9)
594
+
595
+ drive = (self.alpha * T) - (self.beta * E)
596
+
597
+ # amplitude pump/decay (bounded)
598
+ exp_term = clamp(drive, -6.0, 6.0) * 0.22 * self.dt_internal
599
+ amp = math.exp(exp_term)
600
+ amp = clamp(amp, 0.75, 1.35)
601
+
602
+ # keep a "quantum-style" phase evolution too
603
+ H = drive + 0.01 * (abs(self.psi_override) ** 2)
604
+ self.psi_override *= amp * np.exp(-1j * H * self.dt_internal)
605
+
606
+ # cap magnitude so probability stays within [0,1]
607
+ mag = abs(self.psi_override)
608
+ if mag > 1.0:
609
+ self.psi_override /= mag
610
 
611
  def get_override_probability(self):
612
+ return float(min(abs(self.psi_override) ** 2, 1.0))
613
 
614
  def apply_override(self, perceived):
 
615
  field = numpy_convolve2d_toroidal(self.pos_prob, self.move_kernel)
616
  field = np.maximum(field, 0.0)
617
 
 
618
  for (px, py) in perceived:
619
  for dx in range(-2, 3):
620
  for dy in range(-2, 3):
 
625
 
626
  s = float(field.sum())
627
  if s <= 0:
 
628
  field[:] = 1.0 / (self.grid_size * self.grid_size)
629
  else:
630
  field /= s
631
 
632
  self.pos_prob = field
633
 
 
634
  flat = self.pos_prob.flatten().copy()
635
  for (px, py) in perceived:
636
  flat[px * self.grid_size + py] = 0.0
637
 
638
  tot = float(flat.sum())
639
  if tot <= 0:
 
640
  self.move()
641
  return
642
 
 
652
  def regen_energy(self):
653
  boost = self.quantum_energy_boost()
654
  self.energy = clamp(self.energy + self.energy_regen + boost, 0.0, self.energy_max)
 
655
  if self.energy < self.energy_max and random.random() < 0.05:
656
  self.energy = self.energy_max
657
 
658
  def move_consciously(self, predators, group_coherence: float):
659
  if self.energy <= 0:
660
  self.move()
661
+ return 0, 0.0, 0.0
662
 
663
  perceived = self.sense_predators(predators)
664
  self.update_override_state(perceived)
665
+
666
  P_ov = self.get_override_probability()
667
  threat = self.compute_threat(perceived)
668
 
669
  acted = 0
670
+ if (P_ov >= self.override_threshold) and (self.energy > 0):
671
  effective_cost = self.base_override_cost * (1.0 - float(group_coherence))
672
  if self.energy >= effective_cost:
673
  self.overrides += 1
674
  self.energy -= effective_cost
675
  self.apply_override(perceived)
676
+ self.psi_override = (0.08 + 0j) # reset after a collapse action
677
  acted = 1
678
  else:
679
  self.move()
 
728
  ]
729
  predators = [Predator(grid_size) for _ in range(int(num_predators))]
730
 
 
 
 
 
 
 
 
 
731
  rows = []
732
  ops_proxy = 0
733
 
734
  for t in range(int(steps)):
 
735
  for p in predators:
736
  p.move()
737
 
 
738
  for a in reflex_agents:
739
  a.move()
740
  for p in predators:
741
  if a.x == p.x and a.y == p.y:
742
  a.collisions += 1
743
 
 
744
  actions = []
745
  povs = []
746
  threats = []
 
764
  avg_pov = float(np.mean(povs)) if povs else 0.0
765
  avg_act = float(np.mean(actions)) if actions else 0.0
766
 
 
 
 
 
 
 
 
 
 
767
  rows.append({
768
  "t": t,
769
  "reflex_collisions_cum": reflex_collisions,
 
779
  df = pd.DataFrame(rows)
780
  csv_path = df_to_csv_file(df, f"predator_log_seed{seed}.csv")
781
 
 
782
  fig1 = plt.figure(figsize=(10, 4))
783
  ax = fig1.add_subplot(111)
784
  ax.plot(df["t"], df["reflex_collisions_cum"], label="Reflex collisions (cum)")
 
789
  ax.legend()
790
  p_col = save_plot(fig1, f"predator_collisions_seed{seed}.png")
791
 
 
792
  fig2 = plt.figure(figsize=(10, 4))
793
  ax = fig2.add_subplot(111)
794
  ax.plot(df["t"], df["avg_conscious_overrides"], label="Avg overrides (conscious)")
 
799
  ax.legend()
800
  p_ov = save_plot(fig2, f"predator_overrides_energy_seed{seed}.png")
801
 
 
802
  fig3 = plt.figure(figsize=(10, 4))
803
  ax = fig3.add_subplot(111)
804
  ax.plot(df["t"], df["avg_conscious_threat"], label="Avg threat")
 
812
 
813
  heatmap_path = None
814
  if show_heatmap and len(conscious_agents) > 0:
 
815
  field = conscious_agents[0].pos_prob
816
  fig4 = plt.figure(figsize=(6, 5))
817
  ax = fig4.add_subplot(111)
 
854
  ):
855
  seed = int(seed)
856
 
 
857
  s_rft, _, neo_imgs, neo_csv = simulate_neo(
858
  seed=seed,
859
  steps=neo_steps,
 
869
  neo_rft = int(neo_df["rft_alert"].sum())
870
  neo_candidates = int(neo_df["rft_candidate"].sum())
871
 
 
872
  j_sum, jit_imgs, jit_csv = simulate_jitter(
873
  seed=seed,
874
  steps=jit_steps,
 
880
  tau_gain=tau_gain
881
  )
882
 
 
883
  l_sum, land_imgs, land_csv = simulate_landing(
884
  seed=seed,
885
  steps=land_steps,
 
929
  f"- Landing: final offset={l_sum['final_landing_offset_m']:.2f} m (goal 10 m), anomalies={l_sum['total_anomalies_detected']}, actions={l_sum['total_control_actions']}\n"
930
  )
931
 
932
+ all_imgs = neo_imgs + jit_imgs + land_imgs
933
  return txt, score, score_path, all_imgs, [neo_csv, jit_csv, land_csv]
934
 
935
  # -----------------------------
 
1118
  show_heatmap=bool(show_heatmap)
1119
  )
1120
  summary_txt = json.dumps(summary, indent=2)
 
1121
  img1 = imgs[0] if len(imgs) > 0 else None
1122
  img2 = imgs[1] if len(imgs) > 1 else None
1123
  img3 = imgs[2] if len(imgs) > 2 else None
 
1145
  gr.Markdown(HOME_MD)
1146
 
1147
  with gr.Tabs():
 
1148
  with gr.Tab("Live Console"):
1149
  gr.Markdown(LIVE_MD)
1150
 
 
1204
  ]
1205
  )
1206
 
 
1207
  with gr.Tab("NEO Agent"):
1208
  gr.Markdown(
1209
  "# Near-Earth Object (NEO) Alerting Agent\n"
 
1236
  outputs=[out_neo_summary, out_neo_debug, out_neo_img1, out_neo_img2, out_neo_img3, out_neo_csv]
1237
  )
1238
 
 
1239
  with gr.Tab("Satellite Jitter Agent"):
1240
  gr.Markdown(
1241
  "# Satellite Jitter Reduction\n"
 
1267
  outputs=[out_j_summary, out_j_img1, out_j_img2, out_j_img3, out_j_csv]
1268
  )
1269
 
 
1270
  with gr.Tab("Starship Landing Harness"):
1271
  gr.Markdown(
1272
  "# Starship-style Landing Harness (Simplified)\n"
 
1301
  outputs=[out_l_summary, out_l_img1, out_l_img2, out_l_img3, out_l_img4, out_l_csv]
1302
  )
1303
 
 
1304
  with gr.Tab("Predator Avoidance"):
1305
  gr.Markdown(
1306
  "# Predator Avoidance (Reflex vs RFT)\n"
 
1323
  with gr.Row():
1324
  group_coherence = gr.Slider(0.0, 0.95, value=0.30, step=0.01, label="Group coherence")
1325
  sense_noise_prob = gr.Slider(0.0, 0.9, value=0.10, step=0.01, label="Sense noise probability")
1326
+ override_threshold = gr.Slider(0.0, 1.0, value=0.02, step=0.005, label="Override threshold (P_ov)")
1327
 
1328
  with gr.Row():
1329
  alpha = gr.Slider(0.0, 50.0, value=15.0, step=0.5, label="alpha (threat gain)")
 
1362
  outputs=[out_p_summary, out_p_img1, out_p_img2, out_p_img3, out_p_img4, out_p_csv]
1363
  )
1364
 
 
1365
  with gr.Tab("Theory → Practice"):
1366
  gr.Markdown(THEORY_PRACTICE_MD)
1367