Spaces:
Sleeping
Sleeping
Update app.py
Browse files
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 |
-
|
|
|
|
| 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 |
-
|
| 600 |
-
|
| 601 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 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
|
| 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.
|
| 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
|
| 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.
|
| 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 |
|