supernova-photon 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- Supernova_photon/__init__.py +5 -0
- Supernova_photon/cli.py +95 -0
- Supernova_photon/engine.py +606 -0
- Supernova_photon/v5.py +21 -0
- supernova_photon-0.1.1.dist-info/METADATA +60 -0
- supernova_photon-0.1.1.dist-info/RECORD +9 -0
- supernova_photon-0.1.1.dist-info/WHEEL +5 -0
- supernova_photon-0.1.1.dist-info/entry_points.txt +2 -0
- supernova_photon-0.1.1.dist-info/top_level.txt +1 -0
Supernova_photon/cli.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from .v5 import photon
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def main():
|
|
6
|
+
|
|
7
|
+
print("=" * 60)
|
|
8
|
+
print("SUPERNOVA PHOTON-1 V5 — TERMINAL")
|
|
9
|
+
print("=" * 60)
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
engine = photon()
|
|
13
|
+
except Exception as exc:
|
|
14
|
+
print("Initialization failed:", exc)
|
|
15
|
+
return
|
|
16
|
+
|
|
17
|
+
print("\nEnter 'exit' to quit.")
|
|
18
|
+
print("Example target: speed")
|
|
19
|
+
print("Example input: distance=100 m")
|
|
20
|
+
print("Example input: time=10 s")
|
|
21
|
+
|
|
22
|
+
while True:
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
target = input("\nTarget variable: ").strip()
|
|
26
|
+
|
|
27
|
+
if target.lower() in ("exit", "quit"):
|
|
28
|
+
break
|
|
29
|
+
|
|
30
|
+
known = {}
|
|
31
|
+
|
|
32
|
+
print("Enter known values.")
|
|
33
|
+
print("Leave variable name empty when finished.")
|
|
34
|
+
|
|
35
|
+
while True:
|
|
36
|
+
|
|
37
|
+
name = input("Variable: ").strip()
|
|
38
|
+
|
|
39
|
+
if not name:
|
|
40
|
+
break
|
|
41
|
+
|
|
42
|
+
raw = input("Value and unit (e.g. 100 m): ").strip()
|
|
43
|
+
|
|
44
|
+
parts = raw.split()
|
|
45
|
+
|
|
46
|
+
if len(parts) != 2:
|
|
47
|
+
print("Use format: value unit")
|
|
48
|
+
continue
|
|
49
|
+
|
|
50
|
+
known[name] = (
|
|
51
|
+
float(parts[0]),
|
|
52
|
+
parts[1]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
output_unit = input(
|
|
56
|
+
"Output unit (Enter for SI): "
|
|
57
|
+
).strip() or None
|
|
58
|
+
|
|
59
|
+
equation = input(
|
|
60
|
+
"Equation name (Enter for automatic): "
|
|
61
|
+
).strip() or None
|
|
62
|
+
|
|
63
|
+
result = engine.solve(
|
|
64
|
+
target,
|
|
65
|
+
known,
|
|
66
|
+
equation_name=equation,
|
|
67
|
+
target_unit=output_unit
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
print("\nRESULT")
|
|
71
|
+
print("-" * 40)
|
|
72
|
+
print("Equation:", result["equation"])
|
|
73
|
+
print("Formula:", result["formula"])
|
|
74
|
+
print(
|
|
75
|
+
"Answer:",
|
|
76
|
+
result["result"],
|
|
77
|
+
result["unit"]
|
|
78
|
+
)
|
|
79
|
+
print(
|
|
80
|
+
"Validation probability:",
|
|
81
|
+
result["validation_probability"]
|
|
82
|
+
)
|
|
83
|
+
print("-" * 40)
|
|
84
|
+
|
|
85
|
+
except KeyboardInterrupt:
|
|
86
|
+
break
|
|
87
|
+
|
|
88
|
+
except Exception as exc:
|
|
89
|
+
print("Error:", exc)
|
|
90
|
+
|
|
91
|
+
print("Photon-1 V5 terminated.")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if __name__ == "__main__":
|
|
95
|
+
main()
|
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import os
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
HF_REPO_ID = "Supernova11c/Supernova-Photon-1-V5"
|
|
7
|
+
HF_FILENAME = "photon1_v5.pt"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
ALIASES = {
|
|
11
|
+
"e": "energy",
|
|
12
|
+
"energy": "energy",
|
|
13
|
+
"m": "mass",
|
|
14
|
+
"mass": "mass",
|
|
15
|
+
"c": "speed",
|
|
16
|
+
"v": "speed",
|
|
17
|
+
"speed": "speed",
|
|
18
|
+
"d": "distance",
|
|
19
|
+
"distance": "distance",
|
|
20
|
+
"t": "time",
|
|
21
|
+
"time": "time",
|
|
22
|
+
"rho": "density",
|
|
23
|
+
"ρ": "density",
|
|
24
|
+
"density": "density",
|
|
25
|
+
"volume": "volume",
|
|
26
|
+
"f": "force",
|
|
27
|
+
"force": "force",
|
|
28
|
+
"a": "acceleration",
|
|
29
|
+
"acceleration": "acceleration",
|
|
30
|
+
"w": "work",
|
|
31
|
+
"work": "work",
|
|
32
|
+
"p": "power",
|
|
33
|
+
"power": "power",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
UNIT_TABLE = {
|
|
38
|
+
"energy": {"J": 1.0, "kJ": 1000.0},
|
|
39
|
+
"mass": {"kg": 1.0, "g": 0.001},
|
|
40
|
+
"speed": {
|
|
41
|
+
"m/s": 1.0,
|
|
42
|
+
"km/s": 1000.0,
|
|
43
|
+
"km/h": 1 / 3.6
|
|
44
|
+
},
|
|
45
|
+
"distance": {
|
|
46
|
+
"m": 1.0,
|
|
47
|
+
"cm": 0.01,
|
|
48
|
+
"km": 1000.0
|
|
49
|
+
},
|
|
50
|
+
"time": {
|
|
51
|
+
"s": 1.0,
|
|
52
|
+
"min": 60.0,
|
|
53
|
+
"h": 3600.0
|
|
54
|
+
},
|
|
55
|
+
"density": {
|
|
56
|
+
"kg/m3": 1.0,
|
|
57
|
+
"g/cm3": 1000.0
|
|
58
|
+
},
|
|
59
|
+
"volume": {
|
|
60
|
+
"m3": 1.0,
|
|
61
|
+
"L": 0.001,
|
|
62
|
+
"cm3": 1e-6
|
|
63
|
+
},
|
|
64
|
+
"force": {"N": 1.0, "kN": 1000.0},
|
|
65
|
+
"acceleration": {
|
|
66
|
+
"m/s2": 1.0,
|
|
67
|
+
"cm/s2": 0.01
|
|
68
|
+
},
|
|
69
|
+
"work": {"J": 1.0, "kJ": 1000.0},
|
|
70
|
+
"power": {"W": 1.0, "kW": 1000.0}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
DEFAULT_UNITS = {
|
|
75
|
+
"energy": "J",
|
|
76
|
+
"mass": "kg",
|
|
77
|
+
"speed": "m/s",
|
|
78
|
+
"distance": "m",
|
|
79
|
+
"time": "s",
|
|
80
|
+
"density": "kg/m3",
|
|
81
|
+
"volume": "m3",
|
|
82
|
+
"force": "N",
|
|
83
|
+
"acceleration": "m/s2",
|
|
84
|
+
"work": "J",
|
|
85
|
+
"power": "W"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
FORMULAS = {
|
|
90
|
+
"einstein": "E = mc²",
|
|
91
|
+
"speed": "v = d/t",
|
|
92
|
+
"density": "ρ = m/V",
|
|
93
|
+
"newton": "F = ma",
|
|
94
|
+
"work": "W = Fd",
|
|
95
|
+
"power": "P = W/t"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def normalize_variable(name):
|
|
100
|
+
key = str(name).strip().lower()
|
|
101
|
+
|
|
102
|
+
if key not in ALIASES:
|
|
103
|
+
raise ValueError(f"Unknown variable: {name}")
|
|
104
|
+
|
|
105
|
+
return ALIASES[key]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def to_si(variable, value, unit):
|
|
109
|
+
variable = normalize_variable(variable)
|
|
110
|
+
|
|
111
|
+
if unit not in UNIT_TABLE[variable]:
|
|
112
|
+
raise ValueError(
|
|
113
|
+
f"Invalid unit {unit!r} for {variable}"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
value = float(value)
|
|
117
|
+
|
|
118
|
+
if not math.isfinite(value):
|
|
119
|
+
raise ValueError("Input must be finite")
|
|
120
|
+
|
|
121
|
+
return value * UNIT_TABLE[variable][unit]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def from_si(variable, value, unit):
|
|
125
|
+
variable = normalize_variable(variable)
|
|
126
|
+
|
|
127
|
+
if unit not in UNIT_TABLE[variable]:
|
|
128
|
+
raise ValueError(
|
|
129
|
+
f"Invalid output unit {unit!r} for {variable}"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
return value / UNIT_TABLE[variable][unit]
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def safe_divide(a, b):
|
|
136
|
+
if b == 0:
|
|
137
|
+
raise ValueError("Division by zero")
|
|
138
|
+
|
|
139
|
+
return a / b
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# ============================================================
|
|
143
|
+
# EQUATION REGISTRY
|
|
144
|
+
# ============================================================
|
|
145
|
+
|
|
146
|
+
EQUATIONS = {
|
|
147
|
+
|
|
148
|
+
"einstein": {
|
|
149
|
+
"variables": {"energy", "mass", "speed"},
|
|
150
|
+
"solvers": {
|
|
151
|
+
"energy": lambda x: x["mass"] * x["speed"]**2,
|
|
152
|
+
"mass": lambda x: safe_divide(
|
|
153
|
+
x["energy"], x["speed"]**2
|
|
154
|
+
),
|
|
155
|
+
"speed": lambda x: math.sqrt(
|
|
156
|
+
safe_divide(x["energy"], x["mass"])
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
"speed": {
|
|
162
|
+
"variables": {"speed", "distance", "time"},
|
|
163
|
+
"solvers": {
|
|
164
|
+
"speed": lambda x: safe_divide(
|
|
165
|
+
x["distance"], x["time"]
|
|
166
|
+
),
|
|
167
|
+
"distance": lambda x: x["speed"] * x["time"],
|
|
168
|
+
"time": lambda x: safe_divide(
|
|
169
|
+
x["distance"], x["speed"]
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
"density": {
|
|
175
|
+
"variables": {"density", "mass", "volume"},
|
|
176
|
+
"solvers": {
|
|
177
|
+
"density": lambda x: safe_divide(
|
|
178
|
+
x["mass"], x["volume"]
|
|
179
|
+
),
|
|
180
|
+
"mass": lambda x: x["density"] * x["volume"],
|
|
181
|
+
"volume": lambda x: safe_divide(
|
|
182
|
+
x["mass"], x["density"]
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
"newton": {
|
|
188
|
+
"variables": {"force", "mass", "acceleration"},
|
|
189
|
+
"solvers": {
|
|
190
|
+
"force": lambda x: x["mass"] * x["acceleration"],
|
|
191
|
+
"mass": lambda x: safe_divide(
|
|
192
|
+
x["force"], x["acceleration"]
|
|
193
|
+
),
|
|
194
|
+
"acceleration": lambda x: safe_divide(
|
|
195
|
+
x["force"], x["mass"]
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
"work": {
|
|
201
|
+
"variables": {"work", "force", "distance"},
|
|
202
|
+
"solvers": {
|
|
203
|
+
"work": lambda x: x["force"] * x["distance"],
|
|
204
|
+
"force": lambda x: safe_divide(
|
|
205
|
+
x["work"], x["distance"]
|
|
206
|
+
),
|
|
207
|
+
"distance": lambda x: safe_divide(
|
|
208
|
+
x["work"], x["force"]
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
"power": {
|
|
214
|
+
"variables": {"power", "work", "time"},
|
|
215
|
+
"solvers": {
|
|
216
|
+
"power": lambda x: safe_divide(
|
|
217
|
+
x["work"], x["time"]
|
|
218
|
+
),
|
|
219
|
+
"work": lambda x: x["power"] * x["time"],
|
|
220
|
+
"time": lambda x: safe_divide(
|
|
221
|
+
x["work"], x["power"]
|
|
222
|
+
)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
# ============================================================
|
|
229
|
+
# ADAPTIVE TOLERANCE
|
|
230
|
+
# ============================================================
|
|
231
|
+
|
|
232
|
+
class AdaptiveTolerance:
|
|
233
|
+
|
|
234
|
+
def __init__(self, tolerance=1e-6):
|
|
235
|
+
tolerance = float(tolerance)
|
|
236
|
+
|
|
237
|
+
if not math.isfinite(tolerance) or tolerance <= 0:
|
|
238
|
+
raise ValueError("Invalid adaptive tolerance")
|
|
239
|
+
|
|
240
|
+
self.log_tolerance = math.log(tolerance)
|
|
241
|
+
self.temperature = 0.5
|
|
242
|
+
|
|
243
|
+
@property
|
|
244
|
+
def tolerance(self):
|
|
245
|
+
return math.exp(self.log_tolerance)
|
|
246
|
+
|
|
247
|
+
def probability_valid(self, residual):
|
|
248
|
+
|
|
249
|
+
residual = float(residual)
|
|
250
|
+
|
|
251
|
+
if not math.isfinite(residual) or residual < 0:
|
|
252
|
+
return 0.0
|
|
253
|
+
|
|
254
|
+
residual = max(residual, 1e-16)
|
|
255
|
+
|
|
256
|
+
z = (
|
|
257
|
+
self.log_tolerance - math.log(residual)
|
|
258
|
+
) / self.temperature
|
|
259
|
+
|
|
260
|
+
z = max(-60, min(60, z))
|
|
261
|
+
|
|
262
|
+
return 1.0 / (1.0 + math.exp(-z))
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
# ============================================================
|
|
266
|
+
# EQUATION SELECTION
|
|
267
|
+
# ============================================================
|
|
268
|
+
|
|
269
|
+
def select_equation(target, known_variables, equation_name=None):
|
|
270
|
+
|
|
271
|
+
target = normalize_variable(target)
|
|
272
|
+
|
|
273
|
+
known_variables = {
|
|
274
|
+
normalize_variable(x)
|
|
275
|
+
for x in known_variables
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if equation_name is not None:
|
|
279
|
+
|
|
280
|
+
if equation_name not in EQUATIONS:
|
|
281
|
+
raise ValueError("Unknown equation")
|
|
282
|
+
|
|
283
|
+
equation = EQUATIONS[equation_name]
|
|
284
|
+
|
|
285
|
+
if target not in equation["solvers"]:
|
|
286
|
+
raise ValueError("Unsupported target")
|
|
287
|
+
|
|
288
|
+
expected = equation["variables"] - {target}
|
|
289
|
+
|
|
290
|
+
if known_variables != expected:
|
|
291
|
+
raise ValueError("Incompatible equation inputs")
|
|
292
|
+
|
|
293
|
+
return equation_name
|
|
294
|
+
|
|
295
|
+
matches = []
|
|
296
|
+
|
|
297
|
+
for name, equation in EQUATIONS.items():
|
|
298
|
+
|
|
299
|
+
expected = equation["variables"] - {target}
|
|
300
|
+
|
|
301
|
+
if (
|
|
302
|
+
target in equation["solvers"]
|
|
303
|
+
and known_variables == expected
|
|
304
|
+
):
|
|
305
|
+
matches.append(name)
|
|
306
|
+
|
|
307
|
+
if len(matches) != 1:
|
|
308
|
+
raise ValueError(
|
|
309
|
+
"No unique compatible equation found"
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
return matches[0]
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
# ============================================================
|
|
316
|
+
# NUMERICAL RESIDUAL
|
|
317
|
+
# ============================================================
|
|
318
|
+
|
|
319
|
+
def equation_residual(name, values):
|
|
320
|
+
|
|
321
|
+
if name == "einstein":
|
|
322
|
+
lhs = values["energy"]
|
|
323
|
+
rhs = values["mass"] * values["speed"]**2
|
|
324
|
+
|
|
325
|
+
elif name == "speed":
|
|
326
|
+
lhs = values["speed"]
|
|
327
|
+
rhs = safe_divide(
|
|
328
|
+
values["distance"], values["time"]
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
elif name == "density":
|
|
332
|
+
lhs = values["density"]
|
|
333
|
+
rhs = safe_divide(
|
|
334
|
+
values["mass"], values["volume"]
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
elif name == "newton":
|
|
338
|
+
lhs = values["force"]
|
|
339
|
+
rhs = values["mass"] * values["acceleration"]
|
|
340
|
+
|
|
341
|
+
elif name == "work":
|
|
342
|
+
lhs = values["work"]
|
|
343
|
+
rhs = values["force"] * values["distance"]
|
|
344
|
+
|
|
345
|
+
elif name == "power":
|
|
346
|
+
lhs = values["power"]
|
|
347
|
+
rhs = safe_divide(
|
|
348
|
+
values["work"], values["time"]
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
else:
|
|
352
|
+
raise ValueError("Unknown equation")
|
|
353
|
+
|
|
354
|
+
scale = max(abs(lhs), abs(rhs), 1e-300)
|
|
355
|
+
|
|
356
|
+
return abs(lhs - rhs) / scale
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
# ============================================================
|
|
360
|
+
# MAIN PHOTON ENGINE
|
|
361
|
+
# ============================================================
|
|
362
|
+
|
|
363
|
+
class PhotonCoreV5:
|
|
364
|
+
|
|
365
|
+
def __init__(
|
|
366
|
+
self,
|
|
367
|
+
adaptive_model,
|
|
368
|
+
checkpoint=None
|
|
369
|
+
):
|
|
370
|
+
self.adaptive_model = adaptive_model
|
|
371
|
+
self.checkpoint = checkpoint
|
|
372
|
+
|
|
373
|
+
def validate_result(self, equation_name, values):
|
|
374
|
+
|
|
375
|
+
residual = equation_residual(
|
|
376
|
+
equation_name, values
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
probability = (
|
|
380
|
+
self.adaptive_model.probability_valid(residual)
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
return {
|
|
384
|
+
"accepted": probability >= 0.5,
|
|
385
|
+
"residual": residual,
|
|
386
|
+
"tolerance": self.adaptive_model.tolerance,
|
|
387
|
+
"probability": probability
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
def solve(
|
|
391
|
+
self,
|
|
392
|
+
target,
|
|
393
|
+
known_values,
|
|
394
|
+
equation_name=None,
|
|
395
|
+
target_unit=None
|
|
396
|
+
):
|
|
397
|
+
|
|
398
|
+
target = normalize_variable(target)
|
|
399
|
+
|
|
400
|
+
if not isinstance(known_values, dict) or not known_values:
|
|
401
|
+
raise ValueError("Provide a non-empty dictionary")
|
|
402
|
+
|
|
403
|
+
values = {}
|
|
404
|
+
|
|
405
|
+
for name, item in known_values.items():
|
|
406
|
+
|
|
407
|
+
variable = normalize_variable(name)
|
|
408
|
+
|
|
409
|
+
if variable in values:
|
|
410
|
+
raise ValueError("Duplicate variable")
|
|
411
|
+
|
|
412
|
+
if not isinstance(item, (tuple, list)) or len(item) != 2:
|
|
413
|
+
raise ValueError(
|
|
414
|
+
f"{variable} must be (value, unit)"
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
value, unit = item
|
|
418
|
+
|
|
419
|
+
values[variable] = to_si(
|
|
420
|
+
variable, value, unit
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
if target in values:
|
|
424
|
+
raise ValueError("Target already supplied")
|
|
425
|
+
|
|
426
|
+
selected = select_equation(
|
|
427
|
+
target,
|
|
428
|
+
values.keys(),
|
|
429
|
+
equation_name
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
nonnegative = {
|
|
433
|
+
"energy", "mass", "speed", "distance",
|
|
434
|
+
"time", "density", "volume", "force",
|
|
435
|
+
"work", "power"
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
for variable, value in values.items():
|
|
439
|
+
|
|
440
|
+
if variable in nonnegative and value < 0:
|
|
441
|
+
raise ValueError(
|
|
442
|
+
f"{variable} cannot be negative"
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
result_si = EQUATIONS[selected]["solvers"][target](
|
|
446
|
+
values
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
if not math.isfinite(result_si):
|
|
450
|
+
raise ValueError("Non-finite calculation result")
|
|
451
|
+
|
|
452
|
+
if target in nonnegative and result_si < 0:
|
|
453
|
+
raise ValueError("Negative result is invalid")
|
|
454
|
+
|
|
455
|
+
complete = dict(values)
|
|
456
|
+
complete[target] = result_si
|
|
457
|
+
|
|
458
|
+
validation = self.validate_result(
|
|
459
|
+
selected, complete
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
if not validation["accepted"]:
|
|
463
|
+
raise ArithmeticError(
|
|
464
|
+
"Numerical validation failed"
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
unit = target_unit or DEFAULT_UNITS[target]
|
|
468
|
+
|
|
469
|
+
result = from_si(target, result_si, unit)
|
|
470
|
+
|
|
471
|
+
return {
|
|
472
|
+
"equation": selected,
|
|
473
|
+
"formula": FORMULAS[selected],
|
|
474
|
+
"target": target,
|
|
475
|
+
"result": result,
|
|
476
|
+
"unit": unit,
|
|
477
|
+
"si_result": result_si,
|
|
478
|
+
"residual": validation["residual"],
|
|
479
|
+
"adaptive_tolerance": validation["tolerance"],
|
|
480
|
+
"validation_probability": validation["probability"]
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
def convert(self, variable, value, input_unit, output_unit):
|
|
484
|
+
|
|
485
|
+
si = to_si(variable, value, input_unit)
|
|
486
|
+
|
|
487
|
+
return from_si(variable, si, output_unit)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
# ============================================================
|
|
491
|
+
# HUGGING FACE CHECKPOINT INITIALIZATION
|
|
492
|
+
# ============================================================
|
|
493
|
+
|
|
494
|
+
def load_checkpoint(
|
|
495
|
+
repo_id=HF_REPO_ID,
|
|
496
|
+
filename=HF_FILENAME,
|
|
497
|
+
local_path=None
|
|
498
|
+
):
|
|
499
|
+
|
|
500
|
+
if local_path is None:
|
|
501
|
+
|
|
502
|
+
from huggingface_hub import hf_hub_download
|
|
503
|
+
|
|
504
|
+
print("[PHOTON] Downloading checkpoint...")
|
|
505
|
+
|
|
506
|
+
local_path = hf_hub_download(
|
|
507
|
+
repo_id=repo_id,
|
|
508
|
+
filename=filename,
|
|
509
|
+
repo_type="model"
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
if not os.path.isfile(local_path):
|
|
513
|
+
raise FileNotFoundError(local_path)
|
|
514
|
+
|
|
515
|
+
import torch
|
|
516
|
+
|
|
517
|
+
try:
|
|
518
|
+
checkpoint = torch.load(
|
|
519
|
+
local_path,
|
|
520
|
+
map_location="cpu",
|
|
521
|
+
weights_only=True
|
|
522
|
+
)
|
|
523
|
+
except Exception as exc:
|
|
524
|
+
raise RuntimeError(
|
|
525
|
+
"Checkpoint could not be safely loaded. "
|
|
526
|
+
"Check the checkpoint format."
|
|
527
|
+
) from exc
|
|
528
|
+
|
|
529
|
+
if not isinstance(checkpoint, dict):
|
|
530
|
+
raise ValueError("Invalid checkpoint structure")
|
|
531
|
+
|
|
532
|
+
required = {
|
|
533
|
+
"version",
|
|
534
|
+
"equations",
|
|
535
|
+
"solving_directions",
|
|
536
|
+
"learned_tolerance"
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
if not required.issubset(checkpoint):
|
|
540
|
+
raise ValueError("Checkpoint metadata is incomplete")
|
|
541
|
+
|
|
542
|
+
if checkpoint["version"] != "V5":
|
|
543
|
+
raise ValueError("Incorrect Photon checkpoint version")
|
|
544
|
+
|
|
545
|
+
if set(checkpoint["equations"]) != set(EQUATIONS):
|
|
546
|
+
raise ValueError("Equation registry mismatch")
|
|
547
|
+
|
|
548
|
+
if checkpoint["solving_directions"] != 18:
|
|
549
|
+
raise ValueError("Incorrect solving direction count")
|
|
550
|
+
|
|
551
|
+
tolerance = float(checkpoint["learned_tolerance"])
|
|
552
|
+
|
|
553
|
+
if not math.isfinite(tolerance) or tolerance <= 0:
|
|
554
|
+
raise ValueError("Invalid saved tolerance")
|
|
555
|
+
|
|
556
|
+
print("[PHOTON] Checkpoint verified.")
|
|
557
|
+
print("[PHOTON] Saved tolerance:", tolerance)
|
|
558
|
+
|
|
559
|
+
return checkpoint
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
# ============================================================
|
|
563
|
+
# PUBLIC INITIALIZATION
|
|
564
|
+
# ============================================================
|
|
565
|
+
|
|
566
|
+
def initialize(
|
|
567
|
+
download_checkpoint=True,
|
|
568
|
+
checkpoint_path=None,
|
|
569
|
+
repo_id=HF_REPO_ID
|
|
570
|
+
):
|
|
571
|
+
|
|
572
|
+
checkpoint = None
|
|
573
|
+
|
|
574
|
+
if download_checkpoint:
|
|
575
|
+
|
|
576
|
+
checkpoint = load_checkpoint(
|
|
577
|
+
repo_id=repo_id,
|
|
578
|
+
local_path=checkpoint_path
|
|
579
|
+
)
|
|
580
|
+
|
|
581
|
+
tolerance = float(
|
|
582
|
+
checkpoint["learned_tolerance"]
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
else:
|
|
586
|
+
tolerance = 1e-6
|
|
587
|
+
|
|
588
|
+
adaptive_model = AdaptiveTolerance(tolerance)
|
|
589
|
+
|
|
590
|
+
photon = PhotonCoreV5(
|
|
591
|
+
adaptive_model,
|
|
592
|
+
checkpoint=checkpoint
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
print("=" * 60)
|
|
596
|
+
print("SUPERNOVA TERAILLM — PHOTON-1 V5")
|
|
597
|
+
print("=" * 60)
|
|
598
|
+
print("Initialization: SUCCESS")
|
|
599
|
+
print("Equations:", len(EQUATIONS))
|
|
600
|
+
print("Solving directions:", 18)
|
|
601
|
+
print("Adaptive parameters:", 1)
|
|
602
|
+
print("Checkpoint loaded:", checkpoint is not None)
|
|
603
|
+
print("Execution: LOCAL")
|
|
604
|
+
print("=" * 60)
|
|
605
|
+
|
|
606
|
+
return photon
|
Supernova_photon/v5.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .engine import initialize, PhotonCoreV5
|
|
2
|
+
|
|
3
|
+
def photon(
|
|
4
|
+
download_checkpoint=True,
|
|
5
|
+
checkpoint_path=None,
|
|
6
|
+
repo_id="Supernova11c/Supernova-Photon-1-V5"
|
|
7
|
+
):
|
|
8
|
+
"""
|
|
9
|
+
Initialize Photon-1 V5.
|
|
10
|
+
|
|
11
|
+
Downloads and verifies the Hugging Face checkpoint
|
|
12
|
+
by default. Calculations run locally.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
return initialize(
|
|
16
|
+
download_checkpoint=download_checkpoint,
|
|
17
|
+
checkpoint_path=checkpoint_path,
|
|
18
|
+
repo_id=repo_id
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = ["photon", "PhotonCoreV5"]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: supernova-photon
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Supernova Photon-1 V5 mathematical computing engine
|
|
5
|
+
License: MIT
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: numpy>=1.24
|
|
12
|
+
Requires-Dist: huggingface-hub>=0.23
|
|
13
|
+
Requires-Dist: torch>=2.0
|
|
14
|
+
|
|
15
|
+
# Supernova Photon-1 V5
|
|
16
|
+
|
|
17
|
+
A local mathematical computation library developed by Supernova.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install supernova-photon
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Initialization
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from Supernova_photon import v5
|
|
29
|
+
|
|
30
|
+
photon = v5.photon()
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Example
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
result = photon.solve(
|
|
37
|
+
"speed",
|
|
38
|
+
{
|
|
39
|
+
"distance": (100, "m"),
|
|
40
|
+
"time": (10, "s")
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
print(result)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Supported equations
|
|
48
|
+
|
|
49
|
+
- Einstein: E = mc²
|
|
50
|
+
- Speed: v = d/t
|
|
51
|
+
- Density: rho = m/V
|
|
52
|
+
- Newton: F = ma
|
|
53
|
+
- Work: W = Fd
|
|
54
|
+
- Power: P = W/t
|
|
55
|
+
|
|
56
|
+
The checkpoint is downloaded from Hugging Face during
|
|
57
|
+
initialization. Calculations are performed locally.
|
|
58
|
+
|
|
59
|
+
The checkpoint provides saved calibration and metadata.
|
|
60
|
+
It is not an executable neural arithmetic model.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Supernova_photon/__init__.py,sha256=mVqILiW0BwbPq4vtJxhDdghxOLQw_vvXeFZFGqPPaWs,58
|
|
2
|
+
Supernova_photon/cli.py,sha256=torVaBfxrXeC6frNlY7IA-2pTGPjlVg-NOI0Xeel87w,2222
|
|
3
|
+
Supernova_photon/engine.py,sha256=2hcp8V3cC_sfeLP-3D1tiswKAH7Q45LC_toEEm485o0,14537
|
|
4
|
+
Supernova_photon/v5.py,sha256=6iLau3-XAfv2YwH6QZJFsOZ4R7E3Is5ZARBlrCJnv5g,490
|
|
5
|
+
supernova_photon-0.1.1.dist-info/METADATA,sha256=KoLxYMeU2jJMs1diFZ_DPZlPmuY_WIbHu5EeG6MNGHw,1172
|
|
6
|
+
supernova_photon-0.1.1.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
7
|
+
supernova_photon-0.1.1.dist-info/entry_points.txt,sha256=wdekc2K9yCdcrgiUSuxCNLx4ydZRbjHD1hHCMTL2W8U,53
|
|
8
|
+
supernova_photon-0.1.1.dist-info/top_level.txt,sha256=Rb0AFGSma0VsuGV8NqMrj5UKuYdu4zNXoMVQk3mmgn0,17
|
|
9
|
+
supernova_photon-0.1.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Supernova_photon
|