RFTSystems commited on
Commit
d97d368
·
verified ·
1 Parent(s): b684a6d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +100 -43
app.py CHANGED
@@ -26,24 +26,35 @@ def coherent_step(Psi, E, L):
26
  # Metrics
27
  # -----------------------------
28
  def compute_coherence(a, b):
29
- num = np.dot(a, b)
30
- den = np.linalg.norm(a) * np.linalg.norm(b) + 1e-9
31
  return float(abs(num / den))
32
 
33
 
34
  # -----------------------------
35
- # Optional baseline (context only)
36
  # -----------------------------
37
  def python_loop_baseline(n, steps, cap=50_000):
38
- n_cap = min(n, cap)
39
  x = [0.5] * n_cap
40
  t0 = time.time()
41
- for _ in range(steps):
42
  for i in range(n_cap):
43
  x[i] = 0.999 * x[i] + 0.001
44
  elapsed = time.time() - t0
45
- items = n_cap * steps
46
- return items / elapsed / 1e9
 
 
 
 
 
 
 
 
 
 
 
47
 
48
 
49
  # -----------------------------
@@ -57,14 +68,16 @@ def run_engine(n_osc, steps, include_baselines):
57
  E = np.random.rand(n).astype(np.float32)
58
  L = np.random.rand(n).astype(np.float32)
59
 
60
- Psi_start = Psi[:200_000].copy()
 
 
61
 
62
  t0 = time.time()
63
  for _ in range(steps):
64
  Psi, E, L = coherent_step(Psi, E, L)
65
  elapsed = time.time() - t0
66
 
67
- Psi_end = Psi[:200_000].copy()
68
 
69
  coherence = compute_coherence(Psi_start, Psi_end)
70
  mean_energy = float(np.mean(E))
@@ -82,44 +95,72 @@ def run_engine(n_osc, steps, include_baselines):
82
  "Oscillators": f"{n:,}",
83
  "Steps": f"{steps}",
84
  "Engine": "numpy",
85
- "CPU": platform.processor(),
86
- "Cores Available": os.cpu_count(),
87
  }
88
 
89
- # Context-only baselines
90
  if include_baselines:
91
- py_b = python_loop_baseline(n, steps)
92
- np_b = throughput_b # same engine, context label
93
-
94
  result.update({
95
- "Baseline: numpy (B items/s)": f"{np_b:.3f}",
96
  "Baseline: python_loop (B items/s)": f"{py_b:.3f}",
97
- "Speedup vs python_loop (x)": f"{(throughput_b / max(py_b,1e-9)):.1f}",
98
- "Note": "Baselines are context-only; measured live and safety-capped."
 
 
99
  })
100
 
101
- # Receipt
102
  receipt = {
103
  "timestamp_utc": datetime.utcnow().isoformat() + "Z",
 
104
  "results": result,
105
  "platform": platform.platform(),
106
  "python": platform.python_version(),
107
  }
108
 
109
- receipt_json = json.dumps(receipt, indent=2).encode()
110
- sha = hashlib.sha256(receipt_json).hexdigest()
111
- receipt["sha256"] = sha
112
 
113
  os.makedirs("receipts", exist_ok=True)
114
  fname = f"receipts/receipt_{datetime.utcnow().strftime('%Y-%m-%dT%H-%M-%S')}.json"
115
- with open(fname, "wb") as f:
116
- f.write(json.dumps(receipt, indent=2).encode())
117
 
118
- result["Receipt SHA-256 (in file)"] = sha
119
 
 
120
  return json.dumps(result, indent=2), fname
121
 
122
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  # -----------------------------
124
  # UI
125
  # -----------------------------
@@ -138,31 +179,47 @@ Everything you see below is computed **right now**, on this machine.
138
  • Stability proxy (|C|)
139
  • Energy behaviour
140
  • A downloadable **receipt with SHA-256** (verification-first)
141
- Optional baselines (**context only**, measured live)
142
 
143
- No precomputed results. No estimates. No GPUs required.
144
  """
145
  )
146
 
147
- n_slider = gr.Slider(250_000, 8_000_000, value=6_400_000, step=250_000,
148
- label="Number of Oscillators")
149
- steps_slider = gr.Slider(50, 1_000, value=650, step=25,
150
- label="Simulation Steps")
 
 
151
 
152
- baseline_toggle = gr.Checkbox(
153
- label="Include baselines (context only)",
154
- value=True
155
- )
156
 
157
- run_btn = gr.Button("Run Engine")
158
 
159
- output = gr.Code(label="Results", language="json")
160
- receipt_file = gr.File(label="Receipt (download)")
161
 
162
- run_btn.click(
163
- fn=run_engine,
164
- inputs=[n_slider, steps_slider, baseline_toggle],
165
- outputs=[output, receipt_file]
166
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
  demo.launch()
 
26
  # Metrics
27
  # -----------------------------
28
  def compute_coherence(a, b):
29
+ num = float(np.dot(a, b))
30
+ den = float(np.linalg.norm(a) * np.linalg.norm(b) + 1e-9)
31
  return float(abs(num / den))
32
 
33
 
34
  # -----------------------------
35
+ # Optional baseline (context only, safety-capped)
36
  # -----------------------------
37
  def python_loop_baseline(n, steps, cap=50_000):
38
+ n_cap = min(int(n), int(cap))
39
  x = [0.5] * n_cap
40
  t0 = time.time()
41
+ for _ in range(int(steps)):
42
  for i in range(n_cap):
43
  x[i] = 0.999 * x[i] + 0.001
44
  elapsed = time.time() - t0
45
+ items = n_cap * int(steps)
46
+ return items / elapsed / 1e9, n_cap
47
+
48
+
49
+ # -----------------------------
50
+ # Receipt hashing
51
+ # IMPORTANT: sha256 is computed over receipt JSON WITHOUT the sha256 field
52
+ # -----------------------------
53
+ def compute_receipt_sha256(receipt_obj: dict) -> str:
54
+ obj = dict(receipt_obj)
55
+ obj.pop("sha256", None)
56
+ payload = json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
57
+ return hashlib.sha256(payload).hexdigest()
58
 
59
 
60
  # -----------------------------
 
68
  E = np.random.rand(n).astype(np.float32)
69
  L = np.random.rand(n).astype(np.float32)
70
 
71
+ # sample slice for coherence proxy (keeps runtime sane)
72
+ sample = min(n, 200_000)
73
+ Psi_start = Psi[:sample].copy()
74
 
75
  t0 = time.time()
76
  for _ in range(steps):
77
  Psi, E, L = coherent_step(Psi, E, L)
78
  elapsed = time.time() - t0
79
 
80
+ Psi_end = Psi[:sample].copy()
81
 
82
  coherence = compute_coherence(Psi_start, Psi_end)
83
  mean_energy = float(np.mean(E))
 
95
  "Oscillators": f"{n:,}",
96
  "Steps": f"{steps}",
97
  "Engine": "numpy",
98
+ "CPU": platform.processor() or "",
99
+ "Cores Available": os.cpu_count() or 0,
100
  }
101
 
 
102
  if include_baselines:
103
+ py_b, py_ncap = python_loop_baseline(n, steps)
 
 
104
  result.update({
105
+ "Baseline: numpy (B items/s)": f"{throughput_b:.3f}",
106
  "Baseline: python_loop (B items/s)": f"{py_b:.3f}",
107
+ "Baseline: python_loop items measured": f"{py_ncap:,}",
108
+ "Speedup vs python_loop (x)": f"{(throughput_b / max(py_b, 1e-12)):.1f}",
109
+ "Speedup vs numpy (x)": f"{(throughput_b / max(throughput_b, 1e-12)):.2f}",
110
+ "Note": "Baselines are context-only; python loop is safety-capped and measured live."
111
  })
112
 
 
113
  receipt = {
114
  "timestamp_utc": datetime.utcnow().isoformat() + "Z",
115
+ "app": APP_TITLE,
116
  "results": result,
117
  "platform": platform.platform(),
118
  "python": platform.python_version(),
119
  }
120
 
121
+ receipt["sha256"] = compute_receipt_sha256(receipt)
 
 
122
 
123
  os.makedirs("receipts", exist_ok=True)
124
  fname = f"receipts/receipt_{datetime.utcnow().strftime('%Y-%m-%dT%H-%M-%S')}.json"
125
+ with open(fname, "w", encoding="utf-8") as f:
126
+ json.dump(receipt, f, indent=2, ensure_ascii=False)
127
 
128
+ result["Receipt SHA-256 (in file)"] = receipt["sha256"]
129
 
130
+ # Return pretty results + receipt file
131
  return json.dumps(result, indent=2), fname
132
 
133
 
134
+ # -----------------------------
135
+ # Receipt verifier
136
+ # -----------------------------
137
+ def verify_receipt(uploaded_file):
138
+ if uploaded_file is None:
139
+ return "No file uploaded.", ""
140
+
141
+ path = uploaded_file.name if hasattr(uploaded_file, "name") else str(uploaded_file)
142
+ try:
143
+ with open(path, "r", encoding="utf-8") as f:
144
+ receipt = json.load(f)
145
+ except Exception as e:
146
+ return f"Invalid JSON file: {e}", ""
147
+
148
+ claimed = str(receipt.get("sha256", "")).strip()
149
+ computed = compute_receipt_sha256(receipt)
150
+
151
+ ok = (claimed != "" and claimed.lower() == computed.lower())
152
+
153
+ verdict = {
154
+ "verified": bool(ok),
155
+ "claimed_sha256": claimed,
156
+ "computed_sha256": computed,
157
+ "note": "Verified means: sha256(receipt_without_sha256_field) matches the sha256 stored in the receipt."
158
+ }
159
+
160
+ banner = "✅ Receipt verified (SHA-256 match)" if ok else "❌ Receipt FAILED verification (SHA-256 mismatch)"
161
+ return banner, json.dumps(verdict, indent=2)
162
+
163
+
164
  # -----------------------------
165
  # UI
166
  # -----------------------------
 
179
  • Stability proxy (|C|)
180
  • Energy behaviour
181
  • A downloadable **receipt with SHA-256** (verification-first)
182
+ A built-in **receipt verifier** (upload → verify → done)
183
 
184
+ No precomputed results. No estimates.
185
  """
186
  )
187
 
188
+ with gr.Tabs():
189
+ with gr.Tab("Run"):
190
+ n_slider = gr.Slider(250_000, 8_000_000, value=6_400_000, step=250_000,
191
+ label="Number of Oscillators")
192
+ steps_slider = gr.Slider(50, 1_000, value=650, step=25,
193
+ label="Simulation Steps")
194
 
195
+ baseline_toggle = gr.Checkbox(
196
+ label="Include baselines (context only)",
197
+ value=True
198
+ )
199
 
200
+ run_btn = gr.Button("Run Engine")
201
 
202
+ output = gr.Code(label="Results", language="json")
203
+ receipt_file = gr.File(label="Receipt (download)")
204
 
205
+ run_btn.click(
206
+ fn=run_engine,
207
+ inputs=[n_slider, steps_slider, baseline_toggle],
208
+ outputs=[output, receipt_file]
209
+ )
210
+
211
+ with gr.Tab("Verify receipt"):
212
+ gr.Markdown(
213
+ """
214
+ Upload a receipt JSON generated by this Space.
215
+
216
+ This verifier recomputes the SHA-256 (over the receipt JSON **without** the `sha256` field) and checks it matches the stored value.
217
+ """
218
+ )
219
+ up = gr.File(label="Upload receipt (.json)")
220
+ verify_btn = gr.Button("Verify")
221
+ banner = gr.Textbox(label="Verification result", interactive=False)
222
+ detail = gr.Code(label="Details", language="json")
223
+ verify_btn.click(fn=verify_receipt, inputs=[up], outputs=[banner, detail])
224
 
225
  demo.launch()