Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,7 +3,7 @@ import time
|
|
| 3 |
import collections
|
| 4 |
import threading
|
| 5 |
import random
|
| 6 |
-
from fastapi import FastAPI
|
| 7 |
from fastapi.responses import HTMLResponse, FileResponse
|
| 8 |
from fastapi.middleware.cors import CORSMiddleware
|
| 9 |
from pydantic import BaseModel
|
|
@@ -16,7 +16,8 @@ class SimEngine:
|
|
| 16 |
self.nodes = {}
|
| 17 |
self.running = False
|
| 18 |
self.mode = 'inference'
|
| 19 |
-
self.problem_type = '
|
|
|
|
| 20 |
self.batch_queue = collections.deque()
|
| 21 |
self.logs = []
|
| 22 |
self.iteration = 0
|
|
@@ -24,72 +25,70 @@ class SimEngine:
|
|
| 24 |
self.reset()
|
| 25 |
|
| 26 |
def reset(self):
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
self.batch_queue.clear()
|
| 34 |
self.logs = []
|
| 35 |
self.iteration = 0
|
| 36 |
-
self.
|
| 37 |
|
| 38 |
def add_log(self, msg):
|
| 39 |
self.logs.insert(0, f"[{self.iteration}]: {msg}")
|
| 40 |
-
if len(self.logs) >
|
| 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 |
self.nodes['C']['x'] = float(c_target)
|
| 48 |
self.nodes['C']['anchored'] = True
|
| 49 |
-
symbol = "+" if self.problem_type == 'add' else "*"
|
| 50 |
-
self.add_log(f"TRAIN: {a} {symbol} {b} = {c_target}")
|
| 51 |
else:
|
| 52 |
self.nodes['C']['anchored'] = False
|
| 53 |
-
self.nodes['C']['x'] = random.uniform(
|
| 54 |
-
self.add_log(f"INFER: {a} {self.problem_type} {b} = ?")
|
| 55 |
|
| 56 |
def physics_step(self):
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
else:
|
| 63 |
-
base_val = na['x'] * nb['x']
|
| 64 |
|
| 65 |
-
#
|
| 66 |
-
prediction =
|
| 67 |
-
self.current_error = prediction -
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
if abs(self.current_error) < 0.01:
|
| 71 |
if self.batch_queue:
|
| 72 |
p = self.batch_queue.popleft()
|
| 73 |
self.set_problem(p['a'], p['b'], p['c'])
|
| 74 |
return True
|
| 75 |
else:
|
| 76 |
self.running = False
|
| 77 |
-
self.add_log("Task Complete.")
|
| 78 |
return False
|
| 79 |
|
|
|
|
| 80 |
if self.mode == 'inference':
|
| 81 |
-
#
|
| 82 |
-
|
| 83 |
-
nc['x'] += move
|
| 84 |
-
nc['f'] = move
|
| 85 |
-
|
| 86 |
elif self.mode == 'training':
|
| 87 |
-
#
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
nc['f'] = k_error
|
| 93 |
|
| 94 |
self.iteration += 1
|
| 95 |
return True
|
|
@@ -108,41 +107,37 @@ async def get_ui(): return FileResponse("index.html")
|
|
| 108 |
|
| 109 |
@app.get("/state")
|
| 110 |
async def get_state():
|
| 111 |
-
return {'nodes': engine.nodes, 'error': engine.current_error, 'iter': engine.iteration, 'logs': engine.logs
|
| 112 |
|
| 113 |
@app.post("/config")
|
| 114 |
async def config(data: dict):
|
| 115 |
engine.mode = data['mode']
|
|
|
|
| 116 |
engine.problem_type = data['type']
|
| 117 |
engine.running = False
|
| 118 |
-
engine.
|
| 119 |
return {"ok": True}
|
| 120 |
|
| 121 |
-
@app.post("/
|
| 122 |
-
async def
|
| 123 |
engine.batch_queue.clear()
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
b
|
| 128 |
-
|
|
|
|
|
|
|
|
|
|
| 129 |
engine.batch_queue.append({'a': a, 'b': b, 'c': c})
|
| 130 |
p = engine.batch_queue.popleft()
|
| 131 |
engine.set_problem(p['a'], p['b'], p['c'])
|
| 132 |
engine.running = True
|
| 133 |
return {"ok": True}
|
| 134 |
|
| 135 |
-
@app.post("/test_custom")
|
| 136 |
-
async def test_custom(data: dict):
|
| 137 |
-
engine.mode = 'inference'
|
| 138 |
-
engine.set_problem(data['a'], data['b'])
|
| 139 |
-
engine.running = True
|
| 140 |
-
return {"ok": True}
|
| 141 |
-
|
| 142 |
@app.post("/halt")
|
| 143 |
async def halt():
|
| 144 |
engine.running = False
|
| 145 |
-
engine.reset()
|
| 146 |
return {"ok": True}
|
| 147 |
|
| 148 |
if __name__ == "__main__":
|
|
|
|
| 3 |
import collections
|
| 4 |
import threading
|
| 5 |
import random
|
| 6 |
+
from fastapi import FastAPI
|
| 7 |
from fastapi.responses import HTMLResponse, FileResponse
|
| 8 |
from fastapi.middleware.cors import CORSMiddleware
|
| 9 |
from pydantic import BaseModel
|
|
|
|
| 16 |
self.nodes = {}
|
| 17 |
self.running = False
|
| 18 |
self.mode = 'inference'
|
| 19 |
+
self.problem_type = 'housing' # add, mult, housing, sub, div
|
| 20 |
+
self.mesh_depth = 2
|
| 21 |
self.batch_queue = collections.deque()
|
| 22 |
self.logs = []
|
| 23 |
self.iteration = 0
|
|
|
|
| 25 |
self.reset()
|
| 26 |
|
| 27 |
def reset(self):
|
| 28 |
+
self.nodes = {}
|
| 29 |
+
# Fixed Anchors
|
| 30 |
+
self.nodes['A'] = {'x': 1.0, 'y': 2.0, 'anchored': True, 'k': 1.0}
|
| 31 |
+
self.nodes['B'] = {'x': 1.0, 'y': -2.0, 'anchored': True, 'k': 1.0}
|
| 32 |
+
self.nodes['C'] = {'x': 1.0, 'y': 0.0, 'anchored': False, 'k': 1.0}
|
| 33 |
+
|
| 34 |
+
# Generate Multicellular Mesh between A->C and B->C
|
| 35 |
+
for i in range(self.mesh_depth):
|
| 36 |
+
self.nodes[f'H_AC_{i}'] = {'x': random.uniform(0, 1), 'y': 1.0, 'anchored': False, 'k': random.uniform(0.1, 1.0)}
|
| 37 |
+
self.nodes[f'H_BC_{i}'] = {'x': random.uniform(0, 1), 'y': -1.0, 'anchored': False, 'k': random.uniform(0.1, 1.0)}
|
| 38 |
+
|
| 39 |
self.batch_queue.clear()
|
| 40 |
self.logs = []
|
| 41 |
self.iteration = 0
|
| 42 |
+
self.add_log(f"Mesh Reset: Depth {self.mesh_depth}")
|
| 43 |
|
| 44 |
def add_log(self, msg):
|
| 45 |
self.logs.insert(0, f"[{self.iteration}]: {msg}")
|
| 46 |
+
if len(self.logs) > 15: self.logs.pop()
|
| 47 |
|
| 48 |
def set_problem(self, a, b, c_target=None):
|
| 49 |
self.nodes['A']['x'] = float(a)
|
| 50 |
self.nodes['B']['x'] = float(b)
|
|
|
|
| 51 |
if self.mode == 'training':
|
| 52 |
self.nodes['C']['x'] = float(c_target)
|
| 53 |
self.nodes['C']['anchored'] = True
|
|
|
|
|
|
|
| 54 |
else:
|
| 55 |
self.nodes['C']['anchored'] = False
|
| 56 |
+
self.nodes['C']['x'] = random.uniform(0, 10)
|
|
|
|
| 57 |
|
| 58 |
def physics_step(self):
|
| 59 |
+
# 1. Forward Pass: Summing the chains
|
| 60 |
+
# We simulate the "Law" as a chain of K-stiffness through the hidden cells
|
| 61 |
+
val_ac = self.nodes['A']['x']
|
| 62 |
+
for i in range(self.mesh_depth):
|
| 63 |
+
val_ac *= self.nodes[f'H_AC_{i}']['k']
|
| 64 |
|
| 65 |
+
val_bc = self.nodes['B']['x']
|
| 66 |
+
for i in range(self.mesh_depth):
|
| 67 |
+
val_bc *= self.nodes[f'H_BC_{i}']['k']
|
|
|
|
|
|
|
| 68 |
|
| 69 |
+
# The relationship is the sum of the two mesh flows
|
| 70 |
+
prediction = val_ac + val_bc
|
| 71 |
+
self.current_error = prediction - self.nodes['C']['x']
|
| 72 |
+
|
| 73 |
+
if abs(self.current_error) < 0.05:
|
|
|
|
| 74 |
if self.batch_queue:
|
| 75 |
p = self.batch_queue.popleft()
|
| 76 |
self.set_problem(p['a'], p['b'], p['c'])
|
| 77 |
return True
|
| 78 |
else:
|
| 79 |
self.running = False
|
|
|
|
| 80 |
return False
|
| 81 |
|
| 82 |
+
# 2. Back-Propagating Tension
|
| 83 |
if self.mode == 'inference':
|
| 84 |
+
# Drift C to meet the mesh output
|
| 85 |
+
self.nodes['C']['x'] += self.current_error * 0.1
|
|
|
|
|
|
|
|
|
|
| 86 |
elif self.mode == 'training':
|
| 87 |
+
# Update K factors in the mesh to minimize error
|
| 88 |
+
adjustment = self.current_error * 0.01
|
| 89 |
+
for i in range(self.mesh_depth):
|
| 90 |
+
self.nodes[f'H_AC_{i}']['k'] -= adjustment
|
| 91 |
+
self.nodes[f'H_BC_{i}']['k'] -= adjustment
|
|
|
|
| 92 |
|
| 93 |
self.iteration += 1
|
| 94 |
return True
|
|
|
|
| 107 |
|
| 108 |
@app.get("/state")
|
| 109 |
async def get_state():
|
| 110 |
+
return {'nodes': engine.nodes, 'error': engine.current_error, 'iter': engine.iteration, 'logs': engine.logs}
|
| 111 |
|
| 112 |
@app.post("/config")
|
| 113 |
async def config(data: dict):
|
| 114 |
engine.mode = data['mode']
|
| 115 |
+
engine.mesh_depth = int(data['depth'])
|
| 116 |
engine.problem_type = data['type']
|
| 117 |
engine.running = False
|
| 118 |
+
engine.reset()
|
| 119 |
return {"ok": True}
|
| 120 |
|
| 121 |
+
@app.post("/generate")
|
| 122 |
+
async def generate(data: dict):
|
| 123 |
engine.batch_queue.clear()
|
| 124 |
+
for _ in range(20):
|
| 125 |
+
a = random.uniform(1, 10)
|
| 126 |
+
b = random.uniform(1, 10)
|
| 127 |
+
# Housing Rule: Location(a) * 2 + Size(b) * 0.5 = Price(c)
|
| 128 |
+
if engine.problem_type == 'housing': c = (a * 2.5) + (b * 1.2)
|
| 129 |
+
elif engine.problem_type == 'sub': c = a - b
|
| 130 |
+
elif engine.problem_type == 'div': c = a / (b + 0.1)
|
| 131 |
+
else: c = a + b
|
| 132 |
engine.batch_queue.append({'a': a, 'b': b, 'c': c})
|
| 133 |
p = engine.batch_queue.popleft()
|
| 134 |
engine.set_problem(p['a'], p['b'], p['c'])
|
| 135 |
engine.running = True
|
| 136 |
return {"ok": True}
|
| 137 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
@app.post("/halt")
|
| 139 |
async def halt():
|
| 140 |
engine.running = False
|
|
|
|
| 141 |
return {"ok": True}
|
| 142 |
|
| 143 |
if __name__ == "__main__":
|