x2XcarleX2x commited on
Commit
faf5ff0
·
verified ·
1 Parent(s): 7f620bf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +110 -54
app.py CHANGED
@@ -1,86 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
  import numpy as np
3
  import matplotlib.pyplot as plt
4
  from mpl_toolkits.mplot3d import Axes3D
5
  import math
6
  from scipy.special import comb
 
7
  import time
8
 
9
- # --- Funções Matemáticas ---
10
- def bernstein_poly(i, n, t): return comb(n, i) * (t**(i)) * ((1 - t)**(n - i))
 
 
 
 
11
  def bezier_curve_3d(points, n_times=20):
12
- n_points = len(points); points_q = [np.array([quantizar(p[0]), quantizar(p[1]), quantizar(p[2])]) for p in points]
 
 
13
  x_points, y_points, z_points = np.array([p[0] for p in points_q]), np.array([p[1] for p in points_q]), np.array([p[2] for p in points_q])
14
  t = np.linspace(0.0, 1.0, n_times)
15
  polynomial_array = np.array([bernstein_poly(i, n_points - 1, t) for i in range(n_points)])
16
  x_vals, y_vals, z_vals = np.dot(x_points, polynomial_array), np.dot(y_points, polynomial_array), np.dot(z_points, polynomial_array)
17
  return x_vals, y_vals, z_vals
18
- def aprender_com_o_eco_3d(pontos_do_eco: list):
19
- if len(pontos_do_eco) < 2: return {"velocity_vector": np.array([0, 0, 0])}
20
- p1, p2 = np.array(pontos_do_eco[0]), np.array(pontos_do_eco[-1])
 
 
21
  return {"velocity_vector": p2 - p1}
22
- def quantizar(valor, multiplo=4): return multiplo * round(valor / multiplo)
23
 
24
- # --- Motor da Simulação ---
25
- def motor_da_simulacao_infinita(angulo_camera: int):
26
- ponto_a = np.array([quantizar(v) for v in [0., 0., 0.]])
27
- vetor_inercia = np.array([quantizar(v) for v in [10., 10., 10.]])
28
- historico_rastro = [ponto_a.tolist()]
 
 
 
 
 
 
 
 
 
 
 
29
  fig = plt.figure(figsize=(8, 8)); ax = fig.add_subplot(111, projection='3d')
30
- cor_fundo = '#0a0a0a'; fig.patch.set_facecolor(cor_fundo); ax.set_facecolor(cor_fundo)
31
- ciclo_num = 0
32
- while True:
33
- ciclo_num += 1; ponto_b_raw = np.random.rand(3) * 50 - 25
34
- ponto_b = np.array([quantizar(v) for v in ponto_b_raw])
35
- ponto_controle = ponto_a + vetor_inercia
36
- pontos_curva = [ponto_a, ponto_controle, ponto_b]
37
- x_ciclo, y_ciclo, z_ciclo = bezier_curve_3d(pontos_curva)
38
- novos_pontos_rastro = list(zip(x_ciclo, y_ciclo, z_ciclo))
39
- historico_rastro.extend(novos_pontos_rastro)
40
- historico_rastro = historico_rastro[-150:]
41
- pontos_eco = historico_rastro[-10:]
42
- vetor_inercia = aprender_com_o_eco_3d(pontos_eco)["velocity_vector"]
43
- rastro_np = np.array(historico_rastro)
44
- for frame in range(len(x_ciclo)):
45
- ax.cla(); ax.xaxis.pane.fill = False; ax.yaxis.pane.fill = False; ax.zaxis.pane.fill = False
46
- ax.grid(color='#222222', linestyle='--'); ax.view_init(elev=30., azim=angulo_camera)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  ax.set_xlim(-30, 30); ax.set_ylim(-30, 30); ax.set_zlim(-30, 30)
48
  ax.set_xticklabels([]); ax.set_yticklabels([]); ax.set_zticklabels([])
49
- ax.scatter(*ponto_a, s=150, c='lime', alpha=0.7); ax.scatter(*ponto_b, s=150, c='red', marker='X', alpha=0.9)
50
-
51
- # --- CORREÇÃO DO RASTRO EM DEGRADÊ ---
52
- tamanho_rastro_fixo = 12
53
- indice_global_frame = len(historico_rastro) - len(x_ciclo) + frame
54
- start_index = max(0, indice_global_frame - tamanho_rastro_fixo)
55
- rastro_atual = historico_rastro[start_index:indice_global_frame+1]
56
- if len(rastro_atual) > 1:
57
- # Desenha cada segmento do rastro com uma transparência diferente
58
- for i in range(len(rastro_atual) - 1):
59
- p1 = rastro_atual[i]; p2 = rastro_atual[i+1]
60
- alpha = 0.8 * (i / tamanho_rastro_fixo) # Calcula o alfa para o degradê
 
61
  ax.plot([p1[0], p2[0]], [p1[1], p2[1]], [p1[2], p2[2]], color='#ff4500', linewidth=4, alpha=alpha)
62
- # ------------------------------------
63
 
64
- ax.plot([x_ciclo[frame]], [y_ciclo[frame]], [z_ciclo[frame]], 'o', color='#ff4500', markersize=8, markeredgecolor='white')
65
- info_texto = f"Ciclo: {ciclo_num}\nAlvo: {np.round(ponto_b)}"; ax.text2D(0.05, 0.95, info_texto, transform=ax.transAxes, color='white')
 
 
 
 
66
  yield fig
67
- time.sleep(0.01)
68
- ponto_a = ponto_b
69
  plt.close(fig)
70
 
71
- # --- Interface Gradio ---
72
  with gr.Blocks(theme=gr.themes.Base(primary_hue="purple", secondary_hue="orange")) as demo:
73
- gr.Markdown("# ✨ Simulador de Convergência Causal ✨"); gr.Markdown("### A Matemática do Próximo Passo")
74
  with gr.Tabs():
75
- with gr.TabItem("🔬 A Simulação"):
76
  with gr.Row():
77
  with gr.Column(scale=1):
78
- gr.Markdown("Controle a perspectiva da câmera e inicie a simulação. O agente (bola) irá navegar autonomamente, gerando novos alvos e deixando um rastro de inércia em degradê."); angulo_camera_slider = gr.Slider(-180, 180, value=25, label="Ângulo da Câmera (Fixo)"); start_btn = gr.Button("🚀 Iniciar Simulação", variant="primary")
79
  with gr.Column(scale=2):
80
- plot_output = gr.Plot(label="Visualização em Tempo Real")
81
- with gr.TabItem("📜 A Teoria"):
82
- with open("explanation.md", "r", encoding="utf-8") as f: gr.Markdown(f.read())
83
- start_btn.click(fn=motor_da_simulacao_infinita, inputs=[angulo_camera_slider], outputs=[plot_output])
 
 
 
84
 
85
  if __name__ == "__main__":
86
  demo.launch()
 
1
+ # ==============================================================================
2
+ # Causal Convergence Simulator (Final Documented Version)
3
+ # ==============================================================================
4
+ # Author: Carlos R. Santos (in collaboration with a development partner)
5
+ #
6
+ # This Gradio application provides a real-time, interactive 3D simulation
7
+ # of the Causal Convergence principle. An agent (sphere) autonomously
8
+ # navigates a 3D space by learning from its immediate past ("causal echo")
9
+ # to determine the most logical next step towards a new random target.
10
+ # ==============================================================================
11
+
12
  import gradio as gr
13
  import numpy as np
14
  import matplotlib.pyplot as plt
15
  from mpl_toolkits.mplot3d import Axes3D
16
  import math
17
  from scipy.special import comb
18
+ import json
19
  import time
20
 
21
+ # --- Core Mathematical Functions ---
22
+
23
+ def bernstein_poly(i, n, t):
24
+ """ The Bernstein polynomial, which is the basis for Bézier curves. """
25
+ return comb(n, i) * (t**(i)) * ((1 - t)**(n - i))
26
+
27
  def bezier_curve_3d(points, n_times=20):
28
+ """ Generates a 3D Bézier curve from a list of control points. """
29
+ n_points = len(points)
30
+ points_q = [np.array([quantize(p[0]), quantize(p[1]), quantize(p[2])]) for p in points]
31
  x_points, y_points, z_points = np.array([p[0] for p in points_q]), np.array([p[1] for p in points_q]), np.array([p[2] for p in points_q])
32
  t = np.linspace(0.0, 1.0, n_times)
33
  polynomial_array = np.array([bernstein_poly(i, n_points - 1, t) for i in range(n_points)])
34
  x_vals, y_vals, z_vals = np.dot(x_points, polynomial_array), np.dot(y_points, polynomial_array), np.dot(z_points, polynomial_array)
35
  return x_vals, y_vals, z_vals
36
+
37
+ def learn_from_echo_3d(echo_points: list):
38
+ """ Calculates the essence of motion (the inertia vector) from the echo. """
39
+ if len(echo_points) < 2: return {"velocity_vector": np.array([0, 0, 0])}
40
+ p1, p2 = np.array(echo_points[0]), np.array(echo_points[-1])
41
  return {"velocity_vector": p2 - p1}
 
42
 
43
+ def quantize(value, multiple=4):
44
+ """ Rounds a value to the nearest specified multiple. """
45
+ return multiple * round(value / multiple)
46
+
47
+ # --- Main Gradio Simulation Engine ---
48
+
49
+ def infinite_simulation_engine(camera_angle: int):
50
+ """
51
+ A generator function that runs an infinite simulation loop, yielding
52
+ a new plot for the Gradio UI on each frame.
53
+ """
54
+ # 1. Initialize the simulation state
55
+ start_point = np.array([quantize(v) for v in [0., 0., 0.]])
56
+ inertia_vector = np.array([quantize(v) for v in [10., 10., 10.]])
57
+ trail_history = [start_point.tolist()]
58
+
59
  fig = plt.figure(figsize=(8, 8)); ax = fig.add_subplot(111, projection='3d')
60
+ background_color = '#0a0a0a'; fig.patch.set_facecolor(background_color); ax.set_facecolor(background_color)
61
+
62
+ cycle_num = 0
63
+ while True: # The infinite loop
64
+ cycle_num += 1
65
+
66
+ # 2. The previous target becomes the new starting point
67
+ current_point = np.array(trail_history[-1])
68
+
69
+ # 3. Generate a new random target, quantized to the grid
70
+ random_target_raw = np.random.rand(3) * 50 - 25
71
+ next_target = np.array([quantize(v) for v in random_target_raw])
72
+
73
+ # 4. Calculate the trajectory for the current cycle
74
+ control_point = current_point + inertia_vector
75
+ curve_points = [current_point, control_point, next_target]
76
+ x_cycle, y_cycle, z_cycle = bezier_curve_3d(curve_points)
77
+
78
+ # 5. Update the continuous trail history
79
+ new_trail_points = list(zip(x_cycle, y_cycle, z_cycle))
80
+ trail_history.extend(new_trail_points)
81
+ max_trail_length = 150
82
+ trail_history = trail_history[-max_trail_length:]
83
+
84
+ # 6. Learn the inertia from the end of this cycle for the *next* one
85
+ echo_size = 10
86
+ echo_points = trail_history[-echo_size:]
87
+ inertia_vector = learn_from_echo_3d(echo_points)["velocity_vector"]
88
+
89
+ trail_np = np.array(trail_history)
90
+
91
+ # 7. Render and yield each frame of the current cycle
92
+ for frame_idx in range(len(x_cycle)):
93
+ ax.cla() # Clear the plot for the new frame
94
+ ax.xaxis.pane.fill = False; ax.yaxis.pane.fill = False; ax.zaxis.pane.fill = False
95
+ ax.grid(color='#222222', linestyle='--'); ax.view_init(elev=30., azim=camera_angle)
96
  ax.set_xlim(-30, 30); ax.set_ylim(-30, 30); ax.set_zlim(-30, 30)
97
  ax.set_xticklabels([]); ax.set_yticklabels([]); ax.set_zticklabels([])
98
+
99
+ # Draw static elements
100
+ ax.scatter(*current_point, s=150, c='lime', alpha=0.7)
101
+ ax.scatter(*next_target, s=150, c='red', marker='X', alpha=0.9)
102
+
103
+ # Draw the gradient trail
104
+ trail_end_index = len(trail_history) - len(x_cycle) + frame_idx
105
+ trail_start_index = max(0, trail_end_index - 12)
106
+ current_trail_segment = trail_history[trail_start_index:trail_end_index+1]
107
+ if len(current_trail_segment) > 1:
108
+ for i in range(len(current_trail_segment) - 1):
109
+ p1, p2 = current_trail_segment[i], current_trail_segment[i+1]
110
+ alpha = 0.8 * (i / 12)
111
  ax.plot([p1[0], p2[0]], [p1[1], p2[1]], [p1[2], p2[2]], color='#ff4500', linewidth=4, alpha=alpha)
 
112
 
113
+ # Draw the agent sphere
114
+ ax.plot([x_cycle[frame_idx]], [y_cycle[frame_idx]], [z_cycle[frame_idx]], 'o', color='#ff4500', markersize=8, markeredgecolor='white')
115
+
116
+ # Draw info text
117
+ info_text = f"Cycle: {cycle_num}\nTarget: {np.round(next_target)}"; ax.text2D(0.05, 0.95, info_text, transform=ax.transAxes, color='white')
118
+
119
  yield fig
120
+ time.sleep(0.01) # Controls animation speed for UI responsiveness
121
+
122
  plt.close(fig)
123
 
124
+ # --- Gradio User Interface ---
125
  with gr.Blocks(theme=gr.themes.Base(primary_hue="purple", secondary_hue="orange")) as demo:
126
+ gr.Markdown("# ✨ Causal Convergence Simulator ✨"); gr.Markdown("### The Mathematics of the Next Step")
127
  with gr.Tabs():
128
+ with gr.TabItem("🔬 The Simulation"):
129
  with gr.Row():
130
  with gr.Column(scale=1):
131
+ gr.Markdown("Control the camera perspective and start the simulation. The agent (sphere) will navigate autonomously, generating new random targets and leaving a fading trail of its inertia."); camera_angle_slider = gr.Slider(-180, 180, value=25, label="Camera Angle (Azimuth)"); start_btn = gr.Button("🚀 Start Simulation", variant="primary")
132
  with gr.Column(scale=2):
133
+ plot_output = gr.Plot(label="Real-Time Visualization")
134
+ with gr.TabItem("📜 The Theory"):
135
+ # Load the explanation from an external markdown file
136
+ with open("explanation_en.md", "r", encoding="utf-8") as f:
137
+ gr.Markdown(f.read())
138
+
139
+ start_btn.click(fn=infinite_simulation_engine, inputs=[camera_angle_slider], outputs=[plot_output])
140
 
141
  if __name__ == "__main__":
142
  demo.launch()