everydaytok commited on
Commit
b39794e
·
verified ·
1 Parent(s): 7c2f631

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -117
app.py CHANGED
@@ -9,40 +9,27 @@ from fastapi.middleware.cors import CORSMiddleware
9
  from pydantic import BaseModel
10
 
11
  app = FastAPI()
12
-
13
- app.add_middleware(
14
- CORSMiddleware,
15
- allow_origins=["*"],
16
- allow_methods=["*"],
17
- allow_headers=["*"],
18
- )
19
 
20
  class SimEngine:
21
  def __init__(self):
22
  self.nodes = {}
23
- self.cells = []
24
- self.buffer = collections.deque()
25
  self.running = False
26
  self.mode = 'inference'
27
- self.distribution = 'uniform'
28
- self.problem_type = 'add'
29
- self.asymmetric = False
30
  self.batch_queue = collections.deque()
31
  self.logs = []
32
  self.iteration = 0
33
- self.current_target = None
34
  self.current_error = 0.0
35
  self.reset()
36
 
37
  def reset(self):
38
- # Initializing within a visible range (0-10)
39
  self.nodes = {
40
- 'A': {'x': random.uniform(0, 5), 'y': 1.0, 'z': 0.0, 'anchored': False, 'k': 1.0, 'force': 0.0},
41
- 'B': {'x': random.uniform(0, 5), 'y': -1.0, 'z': 0.0, 'anchored': False, 'k': 0.8, 'force': 0.0},
42
- 'C': {'x': 10.0, 'y': 0.0, 'z': 0.0, 'anchored': True, 'k': 1.0, 'force': 0.0}
43
  }
44
- self.cells = [{'id': 'Cell_1', 'a': 'A', 'b': 'B', 'c': 'C'}]
45
- self.buffer.clear()
46
  self.batch_queue.clear()
47
  self.logs = []
48
  self.iteration = 0
@@ -50,73 +37,58 @@ class SimEngine:
50
 
51
  def add_log(self, msg):
52
  self.logs.insert(0, f"[{self.iteration}]: {msg}")
53
- if len(self.logs) > 30: self.logs.pop()
54
-
55
- def set_problem(self, target_value):
56
- self.current_target = target_value
57
- self.nodes['C']['x'] = float(target_value)
58
- # Randomize A and B slightly to prevent getting stuck in a local zero
59
- self.nodes['A']['x'] = random.uniform(0, target_value/2)
60
- self.nodes['B']['x'] = random.uniform(0, target_value/2)
61
- self.add_log(f"New Target Load: {target_value}")
62
- self.trigger_cells()
63
-
64
- def trigger_cells(self):
65
- for cell in self.cells:
66
- na, nb, nc = self.nodes[cell['a']], self.nodes[cell['b']], self.nodes[cell['c']]
67
- valA, valB, valC = na['x'], nb['x'], nc['x']
68
-
69
- # Logic calculation
70
- pred = (valA + valB) if self.problem_type == 'add' else (valA * valB)
71
- self.current_error = pred - valC
72
-
73
- # If error is high, generate tension (Forces)
74
- if abs(self.current_error) > 0.01:
75
- # Calculating the specific force for this step
76
- force_mag = -self.current_error * 0.05
77
- self.nodes['A']['force'] = force_mag
78
- self.nodes['B']['force'] = force_mag
79
- self.buffer.append({'target': cell['a'], 'f': force_mag})
80
- self.buffer.append({'target': cell['b'], 'f': force_mag})
81
- else:
82
- self.nodes['A']['force'] = 0
83
- self.nodes['B']['force'] = 0
84
 
85
- def physics_step(self):
86
- if not self.buffer:
87
- if self.current_target is not None and self.running and abs(self.current_error) < 0.05:
88
- self.add_log(f"SUCCESS: C={self.current_target} Solved.")
89
- self.current_target = None
90
- if self.batch_queue:
91
- time.sleep(0.5)
92
- self.set_problem(self.batch_queue.popleft())
93
- else:
94
- self.running = False
95
- return False
96
 
97
- event = self.buffer.popleft()
98
- t_node = self.nodes[event['target']]
 
 
 
 
 
 
 
 
 
99
 
100
- if t_node['anchored'] and self.mode != 'training': return True
 
101
 
102
- # Dampening to prevent the explosion you saw
103
- damper = 0.2 if self.asymmetric else 0.5
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
  if self.mode == 'inference':
106
- move = event['f'] * damper
107
- if self.distribution == 'individual':
108
- move *= t_node['k']
109
-
110
- t_node['x'] += move
111
- # CLAMPING: Prevent numbers from flying to 40,000
112
- t_node['x'] = max(-1000, min(t_node['x'], 1000))
113
 
114
  elif self.mode == 'training':
115
- # In training, we adjust the K coefficient based on the force
116
- if self.distribution == 'individual':
117
- t_node['k'] = max(0.01, min(t_node['k'] - (abs(self.current_error) * 0.001), 2.0))
118
-
119
- self.trigger_cells()
 
 
120
  self.iteration += 1
121
  return True
122
 
@@ -125,60 +97,47 @@ engine = SimEngine()
125
  def run_loop():
126
  while True:
127
  if engine.running: engine.physics_step()
128
- time.sleep(0.03)
129
 
130
  threading.Thread(target=run_loop, daemon=True).start()
131
 
132
- # --- ROUTES (FastAPI) ---
133
  @app.get("/", response_class=HTMLResponse)
134
- async def get_ui():
135
- return FileResponse("index.html")
136
 
137
  @app.get("/state")
138
  async def get_state():
139
- return {
140
- 'nodes': engine.nodes,
141
- 'error': engine.current_error,
142
- 'iteration': engine.iteration,
143
- 'logs': engine.logs,
144
- 'batch_count': len(engine.batch_queue)
145
- }
146
-
147
- class ConfigModel(BaseModel):
148
- mode: str
149
- distribution: str
150
- problem_type: str
151
- asymmetric: bool
152
-
153
- @app.post("/apply_config")
154
- async def apply_config(cfg: ConfigModel):
155
- engine.mode = cfg.mode
156
- engine.distribution = cfg.distribution
157
- engine.problem_type = cfg.problem_type
158
- engine.asymmetric = cfg.asymmetric
159
- engine.add_log("Config Updated.")
160
- return {"success": True}
161
-
162
- @app.post("/single_run")
163
- async def single_run(data: dict):
164
- engine.set_problem(float(data['target']))
165
- engine.running = True
166
- return {"success": True}
167
 
168
- @app.post("/batch_run")
169
- async def batch_run(data: dict):
 
 
 
 
 
 
170
  engine.batch_queue.clear()
171
- for _ in range(int(data['batch_size'])):
172
- engine.batch_queue.append(round(random.uniform(float(data['val_min']), float(data['val_max'])), 2))
173
- engine.set_problem(engine.batch_queue.popleft())
 
 
 
 
 
 
 
 
 
 
174
  engine.running = True
175
- return {"success": True}
176
 
177
  @app.post("/halt")
178
  async def halt():
179
  engine.running = False
180
  engine.reset()
181
- return {"success": True}
182
 
183
  if __name__ == "__main__":
184
  import uvicorn
 
9
  from pydantic import BaseModel
10
 
11
  app = FastAPI()
12
+ app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
 
 
 
 
 
 
13
 
14
  class SimEngine:
15
  def __init__(self):
16
  self.nodes = {}
 
 
17
  self.running = False
18
  self.mode = 'inference'
19
+ self.problem_type = 'mult'
 
 
20
  self.batch_queue = collections.deque()
21
  self.logs = []
22
  self.iteration = 0
 
23
  self.current_error = 0.0
24
  self.reset()
25
 
26
  def reset(self):
27
+ # A & B are the "Inputs", C is the "Model Output"
28
  self.nodes = {
29
+ 'A': {'x': 2.0, 'anchored': True, 'k': 1.0, 'f': 0.0},
30
+ 'B': {'x': 3.0, 'anchored': True, 'k': 1.0, 'f': 0.0},
31
+ 'C': {'x': 6.0, 'anchored': False, 'k': 1.0, 'f': 0.0}
32
  }
 
 
33
  self.batch_queue.clear()
34
  self.logs = []
35
  self.iteration = 0
 
37
 
38
  def add_log(self, msg):
39
  self.logs.insert(0, f"[{self.iteration}]: {msg}")
40
+ if len(self.logs) > 20: self.logs.pop()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
+ def set_problem(self, a, b, c_target=None):
43
+ self.nodes['A']['x'] = float(a)
44
+ self.nodes['B']['x'] = float(b)
 
 
 
 
 
 
 
 
45
 
46
+ if self.mode == 'training':
47
+ # In Training, everything is locked to learn the K-factor
48
+ self.nodes['C']['x'] = float(c_target)
49
+ self.nodes['C']['anchored'] = True
50
+ self.add_log(f"TRAIN: {a} * {b} = {c_target}")
51
+ else:
52
+ # In Inference, C is free to drift to the predicted answer
53
+ self.nodes['C']['anchored'] = False
54
+ # Start C at a random point to see it "find" the answer
55
+ self.nodes['C']['x'] = random.uniform(-10, 10)
56
+ self.add_log(f"INFER: {a} * {b} = ?")
57
 
58
+ def physics_step(self):
59
+ na, nb, nc = self.nodes['A'], self.nodes['B'], self.nodes['C']
60
 
61
+ # Calculate the "Stress" of the current logic
62
+ # Pred = (A * B) * (The learned stiffness of the connection)
63
+ learned_k = nc['k']
64
+ prediction = (na['x'] * nb['x']) * learned_k
65
+ self.current_error = prediction - nc['x']
66
+
67
+ if abs(self.current_error) < 0.01:
68
+ if self.batch_queue:
69
+ p = self.batch_queue.popleft()
70
+ self.set_problem(p['a'], p['b'], p['c'])
71
+ return True
72
+ else:
73
+ self.running = False
74
+ self.add_log("Task Complete.")
75
+ return False
76
 
77
  if self.mode == 'inference':
78
+ # Move C (The Output) to satisfy the learned K
79
+ # If error is positive (pred > C), we must increase C
80
+ move = self.current_error * 0.1
81
+ nc['x'] += move
82
+ nc['f'] = move
 
 
83
 
84
  elif self.mode == 'training':
85
+ # C is locked. We must adjust K to make (A*B)*K = C
86
+ # Gradient Descent on the Stiffness
87
+ target_k = nc['x'] / (na['x'] * nb['x'] + 1e-9)
88
+ k_error = target_k - nc['k']
89
+ nc['k'] += k_error * 0.05 # Learning Rate
90
+ nc['f'] = k_error
91
+
92
  self.iteration += 1
93
  return True
94
 
 
97
  def run_loop():
98
  while True:
99
  if engine.running: engine.physics_step()
100
+ time.sleep(0.05)
101
 
102
  threading.Thread(target=run_loop, daemon=True).start()
103
 
 
104
  @app.get("/", response_class=HTMLResponse)
105
+ async def get_ui(): return FileResponse("index.html")
 
106
 
107
  @app.get("/state")
108
  async def get_state():
109
+ return {'nodes': engine.nodes, 'error': engine.current_error, 'iter': engine.iteration, 'logs': engine.logs}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
+ @app.post("/config")
112
+ async def config(data: dict):
113
+ engine.mode = data['mode']
114
+ engine.running = False
115
+ return {"ok": True}
116
+
117
+ @app.post("/generate_factors")
118
+ async def gen_factors(data: dict):
119
  engine.batch_queue.clear()
120
+ for _ in range(int(data['count'])):
121
+ a = random.randint(1, 10)
122
+ b = random.randint(1, 10)
123
+ engine.batch_queue.append({'a': a, 'b': b, 'c': a * b})
124
+ p = engine.batch_queue.popleft()
125
+ engine.set_problem(p['a'], p['b'], p['c'])
126
+ engine.running = True
127
+ return {"ok": True}
128
+
129
+ @app.post("/test_custom")
130
+ async def test_custom(data: dict):
131
+ engine.mode = 'inference'
132
+ engine.set_problem(data['a'], data['b'])
133
  engine.running = True
134
+ return {"ok": True}
135
 
136
  @app.post("/halt")
137
  async def halt():
138
  engine.running = False
139
  engine.reset()
140
+ return {"ok": True}
141
 
142
  if __name__ == "__main__":
143
  import uvicorn