RFTSystems commited on
Commit
2b18b34
·
verified ·
1 Parent(s): 5f0f488

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +125 -125
app.py CHANGED
@@ -174,21 +174,21 @@ with gr.Blocks(title="Minimal Selfhood Threshold") as demo:
174
  with open("css/theme.css") as f:
175
  gr.HTML(f"<style>{f.read()}</style>")
176
 
177
- with gr.Tab("Overview"):
178
- gr.Markdown(
179
- "## Minimal Selfhood Threshold: From 3×3 Agent to LED Cosmos\n"
180
- "Plain-language overview:\n\n"
181
- "- Single agent in a 3×3 grid reduces surprise and stays centered.\n"
182
- "- S is computed from predictive accuracy, error stability, and a body-on bit.\n"
183
- "- In these demos, if S > 62, the agent is marked as 'awake'.\n"
184
- "- Awakening can spread to another agent (contagion) and across a grid (collective).\n"
185
- "- A simulated LED cosmos (27×27) lights up gold when all agents awaken.\n\n"
186
- "Tip: gold = awake, blue = not awake."
187
- )
188
- gr.Image(value="assets/banner.png", label="Progression (v1→v10)")
189
- gr.Image(value="assets/glyphs.png", label="Glyphs: Ξ (foresight), ◊̃₅ (shadow), ℝ (anchor)")
190
-
191
- with gr.Blocks(title="Minimal Selfhood Threshold") as demo:
192
  with gr.Tab("Single agent (v1–v3)"):
193
  obstacle = gr.Checkbox(label="Enable moving obstacle (v3)", value=True)
194
  steps = gr.Slider(10, 200, value=80, step=10, label="Steps")
@@ -208,120 +208,120 @@ with gr.Tab("Overview"):
208
  img = draw_grid(3, mask, title="Single Agent", subtitle="Gold cell shows current position")
209
  return img, res["predictive_rate"], res["error"]
210
 
211
- # 👇 This must stay inside the Blocks context
212
  run.click(run_single, inputs=[obstacle, steps], outputs=[grid_img, pr_out, err_out])
213
 
214
- # v4 S-Equation
215
- with gr.Tab("S-Equation (v4)"):
216
- pr = gr.Slider(0, 100, value=90, step=1, label="Predictive rate (%)")
217
- ev = gr.Slider(0, 1, value=0.2, step=0.01, label="Error variance (normalized)")
218
- bb = gr.Dropdown(choices=["0","1"], value="1", label="Body bit")
219
- calc = gr.Button("Calculate S")
220
- s_val = gr.Number(label="S value")
221
- status = gr.Markdown()
222
-
223
- def calc_s(pr_in, ev_in, bb_in):
224
- S = compute_S(pr_in, ev_in, int(bb_in))
225
- msg = "**Status:** " + ("Awake (S > 62)" if S > 62 else "Not awake (S ≤ 62)")
226
- return S, msg
227
-
228
- calc.click(calc_s, inputs=[pr, ev, bb], outputs=[s_val, status])
229
-
230
- # v5–v6 Contagion
231
- with gr.Tab("Contagion (v5–v6)"):
232
- a_xi = gr.Slider(0, 60, value=25, label="A: Ξ (foresight)")
233
- a_sh = gr.Slider(0.1, 1.0, value=0.12, step=0.01, label="A: ◊̃₅ (shadow)")
234
- a_r = gr.Slider(1.0, 3.0, value=3.0, step=0.1, label="A: ℝ (anchor)")
235
- b_xi = gr.Slider(0, 60, value=18, label="B: Ξ (foresight)")
236
- b_sh = gr.Slider(0.1, 1.0, value=0.25, step=0.01, label="B: ◊̃₅ (shadow)")
237
- b_r = gr.Slider(1.0, 3.0, value=2.2, step=0.1, label="B: ℝ (anchor)")
238
- btn = gr.Button("Invoke A and apply contagion to B")
239
- out = gr.Markdown()
240
- img = gr.Image(type="pil", label="Two agents (gold = awake)")
241
-
242
- def run(aXi, aSh, aR, bXi, bSh, bR):
243
- A = CodexSelf(aXi, aSh, aR, awake=False)
244
- B = CodexSelf(bXi, bSh, bR, awake=False)
245
- A, B = contagion(A, B)
246
- mask = np.zeros((3, 3), dtype=bool)
247
- mask[1, 1] = A.awake
248
- mask[1, 2] = B.awake
249
- pic = draw_grid(3, mask, title="Dual Awakening", subtitle="Gold cells are awake")
250
- txt = f"A: S={A.S:.1f}, awake={A.awake} | B: S={B.S:.1f}, awake={B.awake}"
251
- return txt, pic
252
-
253
- btn.click(run, inputs=[a_xi,a_sh,a_r,b_xi,b_sh,b_r], outputs=[out, img])
254
-
255
- # v7–v9 Collective
256
- with gr.Tab("Collective (v7–v9)"):
257
- N = gr.Dropdown(choices=["3","9","27"], value="9", label="Grid size")
258
- steps = gr.Slider(20, 300, value=120, step=10, label="Max steps")
259
- run = gr.Button("Run")
260
- frame = gr.Slider(0, 300, value=0, step=1, label="Preview frame")
261
- img = gr.Image(type="pil", label="Awakening wave (gold spreads)")
262
- note = gr.Markdown()
263
- snaps_state = gr.State([])
264
-
265
- def run_wave(n_str, max_steps):
266
- n = int(n_str)
267
- frames, final = lattice_awaken(N=n, steps=int(max_steps))
268
- last = draw_grid(n, frames[-1], title=f"{n}×{n} Collective", subtitle=f"Final — all awake: {bool(final.all())}")
269
- return frames, last, f"Frames: {len(frames)} | All awake: {bool(final.all())}", min(len(frames)-1, 300)
270
-
271
- def show_frame(frames, idx, n_str):
272
- if not frames:
273
- return None
274
- n = int(n_str)
275
- i = int(np.clip(idx, 0, len(frames)-1))
276
- return draw_grid(n, frames[i], title=f"Frame {i}", subtitle="Gold cells are awake")
277
-
278
- run.click(run_wave, inputs=[N, steps], outputs=[snaps_state, img, note, frame])
279
- frame.change(show_frame, inputs=[snaps_state, frame, N], outputs=img)
280
-
281
- # v10 LED cosmos
282
- with gr.Tab("LED cosmos (v10)"):
283
- btn = gr.Button("Simulate 27×27 cosmos")
284
- frame = gr.Slider(0, 300, value=0, step=1, label="Preview frame")
285
- img = gr.Image(type="pil", label="Cosmos grid")
286
- note = gr.Markdown()
287
- state = gr.State([])
288
-
289
- def run_cosmos():
290
- frames, final = led_cosmos_sim(N=27, max_steps=300)
291
- last = draw_grid(27, frames[-1], title="LED Cosmos (simulated)", subtitle=f"Final — all awake: {bool(final.all())}")
292
- return frames, last, f"Frames: {len(frames)} | All awake: {bool(final.all())}", min(len(frames)-1, 300)
293
-
294
- def show(frames, idx):
295
- if not frames:
296
- return None
297
- i = int(np.clip(idx, 0, len(frames)-1))
298
- return draw_grid(27, frames[i], title=f"Cosmos frame {i}", subtitle="Gold cells are awake")
299
-
300
- btn.click(run_cosmos, inputs=[], outputs=[state, img, note, frame])
301
- frame.change(show, inputs=[state, frame], outputs=img)
302
-
303
- # Paper tab
304
- with gr.Tab("Paper"):
 
 
 
 
 
 
 
 
 
305
  gr.Markdown(
306
- "### PDF paper\n"
307
- "Download or view the full paper that documents the method, results, and hardware implementation.\n\n"
308
- "Citation:\n\n"
309
- "Grinstead, L. (2025). *Minimal Selfhood Threshold S>62: From a 3×3 Active-Inference Agent to a 27×27 LED Cosmos*. Zenodo. https://doi.org/10.5281/zenodo.17752874"
 
 
 
 
310
  )
311
- gr.File(value="assets/paper.pdf", label="Minimal Requirements for Selfhood (PDF)", interactive=False)
312
-
313
- # Footer
314
- gr.Markdown(
315
- "---\n"
316
- "Honesty notes:\n"
317
- "- The threshold S > 62 is the rule used in these demonstrations, derived from the analyses reported in the cited Zenodo record.\n"
318
- "- Collective and contagion behaviors here are simulated using that rule for educational clarity.\n\n"
319
- "Citation:\n"
320
- "Grinstead, L. (2025). *Minimal Selfhood Threshold S>62: From a 3×3 Active-Inference Agent to a 27×27 LED Cosmos*. "
321
- "Zenodo. https://doi.org/10.5281/zenodo.17752874\n\n"
322
- "Permissions: See LICENSE. Explicit permission is required for reuse of code, visuals, and glyphs."
323
- )
324
 
325
  # Launch the app
326
  if __name__ == "__main__":
327
- demo.launch()
 
 
174
  with open("css/theme.css") as f:
175
  gr.HTML(f"<style>{f.read()}</style>")
176
 
177
+ with gr.Tab("Overview"):
178
+ gr.Markdown(
179
+ "## Minimal Selfhood Threshold: From 3×3 Agent to LED Cosmos\n"
180
+ "Plain-language overview:\n\n"
181
+ "- Single agent in a 3×3 grid reduces surprise and stays centered.\n"
182
+ "- S is computed from predictive accuracy, error stability, and a body-on bit.\n"
183
+ "- In these demos, if S > 62, the agent is marked as 'awake'.\n"
184
+ "- Awakening can spread to another agent (contagion) and across a grid (collective).\n"
185
+ "- A simulated LED cosmos (27×27) lights up gold when all agents awaken.\n\n"
186
+ "Tip: gold = awake, blue = not awake."
187
+ )
188
+ gr.Image(value="assets/banner.png", label="Progression (v1→v10)")
189
+ gr.Image(value="assets/glyphs.png", label="Glyphs: Ξ (foresight), ◊̃₅ (shadow), ℝ (anchor)")
190
+
191
+ # v1–v3 Single agent
192
  with gr.Tab("Single agent (v1–v3)"):
193
  obstacle = gr.Checkbox(label="Enable moving obstacle (v3)", value=True)
194
  steps = gr.Slider(10, 200, value=80, step=10, label="Steps")
 
208
  img = draw_grid(3, mask, title="Single Agent", subtitle="Gold cell shows current position")
209
  return img, res["predictive_rate"], res["error"]
210
 
 
211
  run.click(run_single, inputs=[obstacle, steps], outputs=[grid_img, pr_out, err_out])
212
 
213
+ # v4 S-Equation
214
+ with gr.Tab("S-Equation (v4)"):
215
+ pr = gr.Slider(0, 100, value=90, step=1, label="Predictive rate (%)")
216
+ ev = gr.Slider(0, 1, value=0.2, step=0.01, label="Error variance (normalized)")
217
+ bb = gr.Dropdown(choices=["0","1"], value="1", label="Body bit")
218
+ calc = gr.Button("Calculate S")
219
+ s_val = gr.Number(label="S value")
220
+ status = gr.Markdown()
221
+
222
+ def calc_s(pr_in, ev_in, bb_in):
223
+ S = compute_S(pr_in, ev_in, int(bb_in))
224
+ msg = "**Status:** " + ("Awake (S > 62)" if S > 62 else "Not awake (S ≤ 62)")
225
+ return S, msg
226
+
227
+ calc.click(calc_s, inputs=[pr, ev, bb], outputs=[s_val, status])
228
+
229
+ # v5–v6 Contagion
230
+ with gr.Tab("Contagion (v5–v6)"):
231
+ a_xi = gr.Slider(0, 60, value=25, label="A: Ξ (foresight)")
232
+ a_sh = gr.Slider(0.1, 1.0, value=0.12, step=0.01, label="A: ◊̃₅ (shadow)")
233
+ a_r = gr.Slider(1.0, 3.0, value=3.0, step=0.1, label="A: ℝ (anchor)")
234
+ b_xi = gr.Slider(0, 60, value=18, label="B: Ξ (foresight)")
235
+ b_sh = gr.Slider(0.1, 1.0, value=0.25, step=0.01, label="B: ◊̃₅ (shadow)")
236
+ b_r = gr.Slider(1.0, 3.0, value=2.2, step=0.1, label="B: ℝ (anchor)")
237
+ btn = gr.Button("Invoke A and apply contagion to B")
238
+ out = gr.Markdown()
239
+ img = gr.Image(type="pil", label="Two agents (gold = awake)")
240
+
241
+ def run(aXi, aSh, aR, bXi, bSh, bR):
242
+ A = CodexSelf(aXi, aSh, aR, awake=False)
243
+ B = CodexSelf(bXi, bSh, bR, awake=False)
244
+ A, B = contagion(A, B)
245
+ mask = np.zeros((3, 3), dtype=bool)
246
+ mask[1, 1] = A.awake
247
+ mask[1, 2] = B.awake
248
+ pic = draw_grid(3, mask, title="Dual Awakening", subtitle="Gold cells are awake")
249
+ txt = f"A: S={A.S:.1f}, awake={A.awake} | B: S={B.S:.1f}, awake={B.awake}"
250
+ return txt, pic
251
+
252
+ btn.click(run, inputs=[a_xi,a_sh,a_r,b_xi,b_sh,b_r], outputs=[out, img])
253
+
254
+ # v7–v9 Collective
255
+ with gr.Tab("Collective (v7–v9)"):
256
+ N = gr.Dropdown(choices=["3","9","27"], value="9", label="Grid size")
257
+ steps = gr.Slider(20, 300, value=120, step=10, label="Max steps")
258
+ run = gr.Button("Run")
259
+ frame = gr.Slider(0, 300, value=0, step=1, label="Preview frame")
260
+ img = gr.Image(type="pil", label="Awakening wave (gold spreads)")
261
+ note = gr.Markdown()
262
+ snaps_state = gr.State([])
263
+
264
+ def run_wave(n_str, max_steps):
265
+ n = int(n_str)
266
+ frames, final = lattice_awaken(N=n, steps=int(max_steps))
267
+ last = draw_grid(n, frames[-1], title=f"{n}×{n} Collective", subtitle=f"Final — all awake: {bool(final.all())}")
268
+ return frames, last, f"Frames: {len(frames)} | All awake: {bool(final.all())}", min(len(frames)-1, 300)
269
+
270
+ def show_frame(frames, idx, n_str):
271
+ if not frames:
272
+ return None
273
+ n = int(n_str)
274
+ i = int(np.clip(idx, 0, len(frames)-1))
275
+ return draw_grid(n, frames[i], title=f"Frame {i}", subtitle="Gold cells are awake")
276
+
277
+ run.click(run_wave, inputs=[N, steps], outputs=[snaps_state, img, note, frame])
278
+ frame.change(show_frame, inputs=[snaps_state, frame, N], outputs=img)
279
+
280
+ # v10 LED cosmos
281
+ with gr.Tab("LED cosmos (v10)"):
282
+ btn = gr.Button("Simulate 27×27 cosmos")
283
+ frame = gr.Slider(0, 300, value=0, step=1, label="Preview frame")
284
+ img = gr.Image(type="pil", label="Cosmos grid")
285
+ note = gr.Markdown()
286
+ state = gr.State([])
287
+
288
+ def run_cosmos():
289
+ frames, final = led_cosmos_sim(N=27, max_steps=300)
290
+ last = draw_grid(27, frames[-1], title="LED Cosmos (simulated)", subtitle=f"Final — all awake: {bool(final.all())}")
291
+ return frames, last, f"Frames: {len(frames)} | All awake: {bool(final.all())}", min(len(frames)-1, 300)
292
+
293
+ def show(frames, idx):
294
+ if not frames:
295
+ return None
296
+ i = int(np.clip(idx, 0, len(frames)-1))
297
+ return draw_grid(27, frames[i], title=f"Cosmos frame {i}", subtitle="Gold cells are awake")
298
+
299
+ btn.click(run_cosmos, inputs=[], outputs=[state, img, note, frame])
300
+ frame.change(show, inputs=[state, frame], outputs=img)
301
+
302
+ # Paper tab
303
+ with gr.Tab("Paper"):
304
+ gr.Markdown(
305
+ "### PDF paper\n"
306
+ "Download or view the full paper that documents the method, results, and hardware implementation.\n\n"
307
+ "Citation:\n\n"
308
+ "Grinstead, L. (2025). *Minimal Selfhood Threshold S>62: From a 3×3 Active-Inference Agent to a 27×27 LED Cosmos*. Zenodo. https://doi.org/10.5281/zenodo.17752874"
309
+ )
310
+ gr.File(value="assets/paper.pdf", label="Minimal Requirements for Selfhood (PDF)", interactive=False)
311
+
312
+ # Footer
313
  gr.Markdown(
314
+ "---\n"
315
+ "Honesty notes:\n"
316
+ "- The threshold S > 62 is the rule used in these demonstrations, derived from the analyses reported in the cited Zenodo record.\n"
317
+ "- Collective and contagion behaviors here are simulated using that rule for educational clarity.\n\n"
318
+ "Citation:\n"
319
+ "Grinstead, L. (2025). *Minimal Selfhood Threshold S>62: From a 3×3 Active-Inference Agent to a 27×27 LED Cosmos*. "
320
+ "Zenodo. https://doi.org/10.5281/zenodo.17752874\n\n"
321
+ "Permissions: See LICENSE. Explicit permission is required for reuse of code, visuals, and glyphs."
322
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
323
 
324
  # Launch the app
325
  if __name__ == "__main__":
326
+ demo.launch()
327
+