@aleph-ai/tinyaleph 1.2.0 → 1.3.0

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.
Files changed (35) hide show
  1. package/README.md +187 -2
  2. package/backends/bioinformatics/binding.js +503 -0
  3. package/backends/bioinformatics/dna-computing.js +664 -0
  4. package/backends/bioinformatics/encoding.js +339 -0
  5. package/backends/bioinformatics/folding.js +454 -0
  6. package/backends/bioinformatics/genetic-code.js +269 -0
  7. package/backends/bioinformatics/index.js +522 -0
  8. package/backends/bioinformatics/transcription.js +221 -0
  9. package/backends/bioinformatics/translation.js +264 -0
  10. package/backends/index.js +25 -1
  11. package/core/compound.js +532 -0
  12. package/core/hilbert.js +454 -1
  13. package/core/index.js +106 -12
  14. package/core/inference.js +605 -0
  15. package/core/resonance.js +245 -616
  16. package/core/symbols/archetypes.js +478 -0
  17. package/core/symbols/base.js +302 -0
  18. package/core/symbols/elements.js +487 -0
  19. package/core/symbols/hieroglyphs.js +303 -0
  20. package/core/symbols/iching.js +471 -0
  21. package/core/symbols/index.js +77 -0
  22. package/core/symbols/tarot.js +211 -0
  23. package/core/symbols.js +22 -0
  24. package/docs/design/BIOINFORMATICS_BACKEND_DESIGN.md +493 -0
  25. package/docs/guide/06-symbolic-ai.md +370 -0
  26. package/docs/guide/README.md +2 -1
  27. package/docs/reference/05-symbolic-ai.md +570 -0
  28. package/docs/reference/06-bioinformatics.md +546 -0
  29. package/docs/reference/README.md +32 -2
  30. package/docs/theory/11-prgraph-memory.md +559 -0
  31. package/docs/theory/12-resonant-attention.md +661 -0
  32. package/modular.js +33 -1
  33. package/package.json +1 -1
  34. package/physics/index.js +16 -0
  35. package/physics/kuramoto-coupled-ladder.js +603 -0
package/core/resonance.js CHANGED
@@ -1,695 +1,324 @@
1
1
  /**
2
- * Prime Resonance Network Components
2
+ * Resonance Calculator
3
3
  *
4
- * Implementation of:
5
- * - Prime Resonance Identity (PRI) = (P_G, P_E, P_Q)
6
- * - Entanglement and Coherence
7
- * - Phase-Locked Prime Rings
8
- * - Holographic Memory Fields
4
+ * Implements Prime Resonance Theory from symprime:
5
+ * Calculates "resonance" between prime numbers using golden ratio detection.
9
6
  *
10
- * From "Prime Resonance Network Specification (PRNS)"
7
+ * Theory: Primes whose ratio approximates the golden ratio (φ ≈ 1.618)
8
+ * have "natural harmony" - a mathematically grounded measure of affinity.
9
+ *
10
+ * R(p1, p2) = 1/ratio + φ_bonus
11
+ * where φ_bonus = 0.3 if |ratio - φ| < threshold
11
12
  */
12
13
 
13
- const { GaussianInteger, EisensteinInteger, isPrime, firstNPrimes } = require('./prime');
14
- const { Complex, PrimeState } = require('./hilbert');
15
-
16
- // Golden ratio and its conjugate (for irrational phase locks)
17
- const PHI = (1 + Math.sqrt(5)) / 2; // 1.618...
18
- const PHI_CONJ = (1 - Math.sqrt(5)) / 2; // -0.618...
19
- const DELTA_S = Math.sqrt(2); // Another irrational for phase locks
14
+ // Golden ratio constant
15
+ const PHI = 1.618033988749895;
16
+ const PHI_THRESHOLD = 0.1; // How close to φ counts as "golden"
17
+ const PHI_BONUS = 0.3; // Bonus for golden ratio relationships
20
18
 
21
19
  /**
22
- * Quaternionic Prime representation
23
- * Using Hamilton quaternions: q = a + bi + cj + dk
20
+ * ResonanceCalculator - Measures harmonic relationships between primes
24
21
  */
25
- class QuaternionPrime {
26
- constructor(a, b, c, d) {
27
- this.a = a;
28
- this.b = b;
29
- this.c = c;
30
- this.d = d;
31
- }
32
-
33
- static fromPrime(p) {
34
- // Embed a prime in quaternion space using a specific encoding
35
- // p → (p, 0, 0, 0) for simplicity, or a more interesting embedding
36
- const sqrt = Math.sqrt(p);
37
- return new QuaternionPrime(p, 0, 0, 0);
38
- }
39
-
40
- static fromGaussian(g) {
41
- return new QuaternionPrime(g.real, g.imag, 0, 0);
42
- }
43
-
44
- norm() {
45
- return Math.sqrt(this.a*this.a + this.b*this.b + this.c*this.c + this.d*this.d);
22
+ class ResonanceCalculator {
23
+ constructor(cacheSize = 1000) {
24
+ this.cacheSize = cacheSize;
25
+ this.cache = new Map();
46
26
  }
47
-
48
- add(other) {
49
- return new QuaternionPrime(
50
- this.a + other.a,
51
- this.b + other.b,
52
- this.c + other.c,
53
- this.d + other.d
54
- );
55
- }
56
-
57
- mul(other) {
58
- // Hamilton product
59
- return new QuaternionPrime(
60
- this.a*other.a - this.b*other.b - this.c*other.c - this.d*other.d,
61
- this.a*other.b + this.b*other.a + this.c*other.d - this.d*other.c,
62
- this.a*other.c - this.b*other.d + this.c*other.a + this.d*other.b,
63
- this.a*other.d + this.b*other.c - this.c*other.b + this.d*other.a
64
- );
65
- }
66
-
67
- conjugate() {
68
- return new QuaternionPrime(this.a, -this.b, -this.c, -this.d);
69
- }
70
-
71
- isHurwitzPrime() {
72
- // A Hurwitz quaternion is prime if its norm is a rational prime
73
- const n = this.norm();
74
- return isPrime(Math.round(n * n));
75
- }
76
-
77
- toArray() {
78
- return [this.a, this.b, this.c, this.d];
79
- }
80
-
81
- toString() {
82
- return `${this.a} + ${this.b}i + ${this.c}j + ${this.d}k`;
83
- }
84
- }
85
27
 
86
- /**
87
- * Prime Resonance Identity (PRI)
88
- * A triadic identity composed of:
89
- * - P_G: Gaussian prime
90
- * - P_E: Eisenstein prime
91
- * - P_Q: Quaternionic prime
92
- */
93
- class PrimeResonanceIdentity {
94
- constructor(gaussianPrime, eisensteinPrime, quaternionPrime) {
95
- this.gaussian = gaussianPrime; // GaussianInteger
96
- this.eisenstein = eisensteinPrime; // EisensteinInteger
97
- this.quaternion = quaternionPrime; // QuaternionPrime
98
-
99
- // Compute combined signature
100
- this._computeSignature();
101
- }
102
-
103
- _computeSignature() {
104
- const gNorm = this.gaussian.norm();
105
- const eNorm = this.eisenstein.norm();
106
- const qNorm = this.quaternion.norm();
107
-
108
- // Signature is a triple of norms
109
- this.signature = [gNorm, eNorm, qNorm];
110
-
111
- // Hash from signature
112
- this.hash = (gNorm * 997 + eNorm * 991 + Math.round(qNorm) * 983) % 1000000007;
113
- }
114
-
115
28
  /**
116
- * Generate a PRI from a seed integer
29
+ * Calculate resonance between two primes
30
+ * R(p1, p2) = 1/ratio + φ_bonus
31
+ *
32
+ * @param {number|bigint} p1 - First prime
33
+ * @param {number|bigint} p2 - Second prime
34
+ * @returns {number} Resonance value between 0 and ~1.3
117
35
  */
118
- static fromSeed(seed) {
119
- // Use seed to generate three primes
120
- const p1 = firstNPrimes(seed + 10)[seed % 10 + 5];
121
- const p2 = firstNPrimes(seed + 15)[seed % 10 + 8];
122
- const p3 = firstNPrimes(seed + 20)[seed % 10 + 12];
123
-
124
- // Create Gaussian prime: find a + bi where a² + b² is prime
125
- const g = new GaussianInteger(p1 % 100, (seed * 7) % 50);
126
-
127
- // Create Eisenstein prime: find a + bω where a² - ab + b² ≡ 2 (mod 3)
128
- const e = new EisensteinInteger(p2 % 100, (seed * 11) % 50);
129
-
130
- // Create Quaternion prime
131
- const q = new QuaternionPrime(p3, seed % 10, (seed * 3) % 10, (seed * 7) % 10);
132
-
133
- return new PrimeResonanceIdentity(g, e, q);
134
- }
135
-
136
- /**
137
- * Generate a random PRI
138
- */
139
- static random() {
140
- const primes = firstNPrimes(50);
141
-
142
- const idx1 = Math.floor(Math.random() * primes.length);
143
- const idx2 = Math.floor(Math.random() * primes.length);
144
- const idx3 = Math.floor(Math.random() * primes.length);
145
-
146
- const p1 = primes[idx1];
147
- const p2 = primes[idx2];
148
- const p3 = primes[idx3];
149
-
150
- const g = new GaussianInteger(p1, Math.floor(Math.random() * 10));
151
- const e = new EisensteinInteger(p2, Math.floor(Math.random() * 10));
152
- const q = new QuaternionPrime(p3,
153
- Math.floor(Math.random() * 5),
154
- Math.floor(Math.random() * 5),
155
- Math.floor(Math.random() * 5)
156
- );
157
-
158
- return new PrimeResonanceIdentity(g, e, q);
159
- }
160
-
161
- /**
162
- * Compute entanglement strength with another PRI
163
- */
164
- entanglementStrength(other) {
165
- // Based on phase alignment and norm similarity
166
- const gPhase = Math.atan2(this.gaussian.imag, this.gaussian.real);
167
- const gPhaseOther = Math.atan2(other.gaussian.imag, other.gaussian.real);
168
-
169
- const ePhase = Math.atan2(this.eisenstein.b * Math.sqrt(3)/2,
170
- this.eisenstein.a - this.eisenstein.b/2);
171
- const ePhaseOther = Math.atan2(other.eisenstein.b * Math.sqrt(3)/2,
172
- other.eisenstein.a - other.eisenstein.b/2);
173
-
174
- const gAlignment = Math.cos(gPhase - gPhaseOther);
175
- const eAlignment = Math.cos(ePhase - ePhaseOther);
176
-
177
- // Quaternion alignment via normalized dot product
178
- const qNorm = this.quaternion.norm() * other.quaternion.norm();
179
- const qDot = (this.quaternion.a * other.quaternion.a +
180
- this.quaternion.b * other.quaternion.b +
181
- this.quaternion.c * other.quaternion.c +
182
- this.quaternion.d * other.quaternion.d);
183
- const qAlignment = qNorm > 0 ? qDot / qNorm : 0;
184
-
185
- // Combined entanglement strength
186
- return (gAlignment + eAlignment + qAlignment) / 3;
187
- }
188
-
189
- toJSON() {
190
- return {
191
- gaussian: { real: this.gaussian.real, imag: this.gaussian.imag },
192
- eisenstein: { a: this.eisenstein.a, b: this.eisenstein.b },
193
- quaternion: this.quaternion.toArray(),
194
- signature: this.signature,
195
- hash: this.hash
196
- };
197
- }
198
- }
199
-
200
- /**
201
- * Phase-Locked Prime Ring
202
- * Implements stable communication via irrational phase locks
203
- */
204
- class PhaseLockedRing {
205
- constructor(primes, phaseType = 'phi') {
206
- this.primes = primes;
207
- this.n = primes.length;
208
- this.phases = new Float64Array(this.n);
36
+ calculateResonance(p1, p2) {
37
+ // Convert to numbers for calculation
38
+ const n1 = Number(p1);
39
+ const n2 = Number(p2);
209
40
 
210
- // Select irrational phase lock
211
- this.phaseMultiplier = phaseType === 'phi' ? PHI :
212
- phaseType === 'deltaS' ? DELTA_S :
213
- 2 * Math.PI / PHI; // 2π/φ
214
-
215
- // Initialize phases using irrational multiples
216
- for (let i = 0; i < this.n; i++) {
217
- this.phases[i] = (i * this.phaseMultiplier) % (2 * Math.PI);
218
- }
219
- }
220
-
221
- /**
222
- * Advance all phases by one step
223
- */
224
- tick(dt = 0.01) {
225
- for (let i = 0; i < this.n; i++) {
226
- // Each prime oscillates at frequency proportional to log(p)
227
- const freq = Math.log(this.primes[i]);
228
- this.phases[i] = (this.phases[i] + freq * dt * this.phaseMultiplier) % (2 * Math.PI);
229
- }
230
- }
231
-
232
- /**
233
- * Compute order parameter (Kuramoto-style)
234
- * r = |1/N Σ e^(iθ_j)|
235
- */
236
- orderParameter() {
237
- let sumReal = 0, sumImag = 0;
238
- for (let i = 0; i < this.n; i++) {
239
- sumReal += Math.cos(this.phases[i]);
240
- sumImag += Math.sin(this.phases[i]);
41
+ // Check cache
42
+ const cacheKey = n1 < n2 ? `${n1},${n2}` : `${n2},${n1}`;
43
+ if (this.cache.has(cacheKey)) {
44
+ return this.cache.get(cacheKey);
241
45
  }
242
- return Math.sqrt(sumReal*sumReal + sumImag*sumImag) / this.n;
243
- }
244
-
245
- /**
246
- * Mean phase
247
- */
248
- meanPhase() {
249
- let sumReal = 0, sumImag = 0;
250
- for (let i = 0; i < this.n; i++) {
251
- sumReal += Math.cos(this.phases[i]);
252
- sumImag += Math.sin(this.phases[i]);
253
- }
254
- return Math.atan2(sumImag, sumReal);
255
- }
256
-
257
- /**
258
- * Synchronization measure
259
- * How well are phases aligned?
260
- */
261
- synchronization() {
262
- const order = this.orderParameter();
263
- return order; // 0 = no sync, 1 = perfect sync
264
- }
265
-
266
- /**
267
- * Apply phase correction toward target
268
- */
269
- correctPhase(targetPhase, strength = 0.1) {
270
- for (let i = 0; i < this.n; i++) {
271
- const diff = targetPhase - this.phases[i];
272
- const correction = Math.sin(diff) * strength;
273
- this.phases[i] = (this.phases[i] + correction) % (2 * Math.PI);
46
+
47
+ // Handle edge cases
48
+ if (n1 === 0 || n2 === 0) return 0;
49
+ if (n1 === n2) return 1.0; // Self-resonance is perfect
50
+
51
+ // Calculate ratio (larger / smaller)
52
+ const [smaller, larger] = n1 < n2 ? [n1, n2] : [n2, n1];
53
+ const ratio = larger / smaller;
54
+
55
+ // Base resonance: inverse of ratio (closer primes resonate more)
56
+ let resonance = 1.0 / ratio;
57
+
58
+ // Add golden ratio bonus if applicable
59
+ if (this.isGoldenRatio(ratio)) {
60
+ resonance += PHI_BONUS;
274
61
  }
62
+
63
+ // Cache result
64
+ this.addToCache(cacheKey, resonance);
65
+
66
+ return resonance;
275
67
  }
276
-
68
+
277
69
  /**
278
- * Get phase vector as complex amplitudes
70
+ * Check if a ratio is close to the golden ratio
279
71
  */
280
- toPrimeState(primesList = null) {
281
- const state = new PrimeState(primesList || this.primes);
282
- for (let i = 0; i < this.n && i < state.primes.length; i++) {
283
- const p = this.primes[i];
284
- if (state.amplitudes.has(p)) {
285
- state.set(p, Complex.fromPolar(1, this.phases[i]));
286
- }
287
- }
288
- return state.normalize();
289
- }
290
-
291
- getPhases() {
292
- return [...this.phases];
72
+ isGoldenRatio(ratio) {
73
+ return Math.abs(ratio - PHI) < PHI_THRESHOLD;
293
74
  }
294
- }
295
75
 
296
- /**
297
- * Holographic Memory Field
298
- * 2D spatial representation of prime-encoded information
299
- * I(x,y) = Σ A_p e^(-S(x,y)) e^(ipθ)
300
- */
301
- class HolographicField {
302
- constructor(width = 64, height = 64, primes = null) {
303
- this.width = width;
304
- this.height = height;
305
- this.primes = primes || firstNPrimes(25);
306
-
307
- // Complex amplitude field
308
- this.field = new Array(height);
309
- for (let y = 0; y < height; y++) {
310
- this.field[y] = new Array(width);
311
- for (let x = 0; x < width; x++) {
312
- this.field[y][x] = Complex.zero();
313
- }
314
- }
315
-
316
- // Entropy surface S(x,y)
317
- this.entropyField = new Array(height);
318
- for (let y = 0; y < height; y++) {
319
- this.entropyField[y] = new Float64Array(width);
320
- }
321
- }
322
-
323
76
  /**
324
- * Encode a PrimeState into the holographic field
77
+ * Find prime pairs near the golden ratio
78
+ * These are "naturally harmonic" pairs
79
+ *
80
+ * @param {number[]} primes - Array of primes to search
81
+ * @returns {Array<{p1: number, p2: number, ratio: number, resonance: number}>}
325
82
  */
326
- encodeState(state, centerX = null, centerY = null) {
327
- centerX = centerX ?? this.width / 2;
328
- centerY = centerY ?? this.height / 2;
329
-
330
- const sigma = Math.min(this.width, this.height) / 4; // Spread
83
+ findGoldenPairs(primes) {
84
+ const pairs = [];
331
85
 
332
- for (let y = 0; y < this.height; y++) {
333
- for (let x = 0; x < this.width; x++) {
334
- const dx = x - centerX;
335
- const dy = y - centerY;
336
- const r = Math.sqrt(dx*dx + dy*dy);
337
- const theta = Math.atan2(dy, dx);
338
-
339
- // Gaussian envelope
340
- const envelope = Math.exp(-r*r / (2*sigma*sigma));
341
-
342
- // Sum over primes
343
- let sum = Complex.zero();
344
- for (const p of state.primes) {
345
- const amp = state.get(p);
346
- const phase = p * theta; // e^(ipθ)
347
- const contribution = amp.mul(Complex.fromPolar(envelope, phase));
348
- sum = sum.add(contribution);
349
- }
350
-
351
- this.field[y][x] = this.field[y][x].add(sum);
86
+ for (let i = 0; i < primes.length; i++) {
87
+ for (let j = i + 1; j < primes.length; j++) {
88
+ const p1 = primes[i];
89
+ const p2 = primes[j];
90
+ const ratio = p2 / p1;
352
91
 
353
- // Update entropy field
354
- const intensity = sum.norm2();
355
- if (intensity > 1e-10) {
356
- this.entropyField[y][x] += -intensity * Math.log2(intensity);
92
+ if (this.isGoldenRatio(ratio)) {
93
+ pairs.push({
94
+ p1,
95
+ p2,
96
+ ratio,
97
+ resonance: this.calculateResonance(p1, p2)
98
+ });
357
99
  }
358
100
  }
359
101
  }
102
+
103
+ return pairs.sort((a, b) =>
104
+ Math.abs(a.ratio - PHI) - Math.abs(b.ratio - PHI)
105
+ );
360
106
  }
361
-
107
+
362
108
  /**
363
- * Decode field at a point back to PrimeState
109
+ * Calculate vectorized resonance matrix for multiple primes
110
+ *
111
+ * @param {number[]} primes - Array of primes
112
+ * @returns {number[][]} NxN matrix of resonance values
364
113
  */
365
- decodeAt(x, y, radius = 5) {
366
- const state = new PrimeState(this.primes);
367
-
368
- // Sample in a small neighborhood
369
- for (let dy = -radius; dy <= radius; dy++) {
370
- for (let dx = -radius; dx <= radius; dx++) {
371
- const px = Math.floor(x + dx);
372
- const py = Math.floor(y + dy);
373
-
374
- if (px >= 0 && px < this.width && py >= 0 && py < this.height) {
375
- const val = this.field[py][px];
376
- const theta = Math.atan2(dy, dx);
377
-
378
- // Recover prime contributions
379
- for (const p of this.primes) {
380
- const phase = -p * theta; // Inverse of encoding phase
381
- const contribution = val.mul(Complex.fromPolar(1, phase));
382
- state.set(p, state.get(p).add(contribution.scale(1 / (4 * radius * radius))));
383
- }
384
- }
114
+ calculateMatrix(primes) {
115
+ const n = primes.length;
116
+ const matrix = [];
117
+
118
+ for (let i = 0; i < n; i++) {
119
+ matrix[i] = [];
120
+ for (let j = 0; j < n; j++) {
121
+ matrix[i][j] = this.calculateResonance(primes[i], primes[j]);
385
122
  }
386
123
  }
387
-
388
- return state.normalize();
124
+
125
+ return matrix;
389
126
  }
390
-
127
+
391
128
  /**
392
- * Get total intensity at a point
129
+ * Calculate average resonance of a prime with a set
130
+ *
131
+ * @param {number} prime - Target prime
132
+ * @param {number[]} primes - Set of primes to compare
133
+ * @returns {number} Average resonance
393
134
  */
394
- intensity(x, y) {
395
- if (x >= 0 && x < this.width && y >= 0 && y < this.height) {
396
- return this.field[Math.floor(y)][Math.floor(x)].norm2();
135
+ calculateAverageResonance(prime, primes) {
136
+ if (primes.length === 0) return 0;
137
+
138
+ let sum = 0;
139
+ for (const p of primes) {
140
+ sum += this.calculateResonance(prime, p);
397
141
  }
398
- return 0;
142
+
143
+ return sum / primes.length;
399
144
  }
400
-
145
+
401
146
  /**
402
- * Get local entropy at a point
147
+ * Find the most resonant prime from a set
148
+ *
149
+ * @param {number} target - Target prime
150
+ * @param {number[]} candidates - Candidate primes
151
+ * @returns {{prime: number, resonance: number}|null}
403
152
  */
404
- localEntropy(x, y) {
405
- if (x >= 0 && x < this.width && y >= 0 && y < this.height) {
406
- return this.entropyField[Math.floor(y)][Math.floor(x)];
153
+ findMostResonant(target, candidates) {
154
+ if (candidates.length === 0) return null;
155
+
156
+ let maxResonance = -1;
157
+ let mostResonant = null;
158
+
159
+ for (const candidate of candidates) {
160
+ const resonance = this.calculateResonance(target, candidate);
161
+ if (resonance > maxResonance) {
162
+ maxResonance = resonance;
163
+ mostResonant = candidate;
164
+ }
407
165
  }
408
- return 0;
166
+
167
+ return { prime: mostResonant, resonance: maxResonance };
409
168
  }
410
-
169
+
411
170
  /**
412
- * Find regions of high intensity (potential memory fragments)
171
+ * Find resonance clusters - groups of primes with high mutual resonance
172
+ *
173
+ * @param {number[]} primes - Primes to cluster
174
+ * @param {number} threshold - Minimum resonance for cluster membership
175
+ * @returns {number[][]} Array of clusters
413
176
  */
414
- findPeaks(threshold = 0.1) {
415
- const peaks = [];
416
- const maxIntensity = this.maxIntensity();
417
-
418
- for (let y = 1; y < this.height - 1; y++) {
419
- for (let x = 1; x < this.width - 1; x++) {
420
- const intensity = this.field[y][x].norm2();
421
-
422
- if (intensity > threshold * maxIntensity) {
423
- // Check if local maximum
424
- let isMax = true;
425
- for (let dy = -1; dy <= 1 && isMax; dy++) {
426
- for (let dx = -1; dx <= 1 && isMax; dx++) {
427
- if (dx !== 0 || dy !== 0) {
428
- if (this.field[y+dy][x+dx].norm2() > intensity) {
429
- isMax = false;
430
- }
431
- }
432
- }
433
- }
434
-
435
- if (isMax) {
436
- peaks.push({ x, y, intensity, phase: this.field[y][x].phase() });
437
- }
177
+ findClusters(primes, threshold = 0.5) {
178
+ const clusters = [];
179
+ const visited = new Set();
180
+
181
+ for (const p of primes) {
182
+ if (visited.has(p)) continue;
183
+
184
+ const cluster = [p];
185
+ visited.add(p);
186
+
187
+ for (const q of primes) {
188
+ if (visited.has(q)) continue;
189
+ if (this.calculateResonance(p, q) >= threshold) {
190
+ cluster.push(q);
191
+ visited.add(q);
438
192
  }
439
193
  }
440
- }
441
-
442
- return peaks.sort((a, b) => b.intensity - a.intensity);
443
- }
444
-
445
- maxIntensity() {
446
- let max = 0;
447
- for (let y = 0; y < this.height; y++) {
448
- for (let x = 0; x < this.width; x++) {
449
- const i = this.field[y][x].norm2();
450
- if (i > max) max = i;
451
- }
452
- }
453
- return max;
454
- }
455
-
456
- /**
457
- * Clear the field
458
- */
459
- clear() {
460
- for (let y = 0; y < this.height; y++) {
461
- for (let x = 0; x < this.width; x++) {
462
- this.field[y][x] = Complex.zero();
463
- this.entropyField[y][x] = 0;
194
+
195
+ if (cluster.length > 1) {
196
+ clusters.push(cluster);
464
197
  }
465
198
  }
199
+
200
+ return clusters;
466
201
  }
467
-
202
+
468
203
  /**
469
- * Export as grayscale image data (intensity map)
204
+ * Add entry to cache with LRU eviction
470
205
  */
471
- toImageData() {
472
- const data = new Uint8ClampedArray(this.width * this.height * 4);
473
- const max = this.maxIntensity();
474
-
475
- for (let y = 0; y < this.height; y++) {
476
- for (let x = 0; x < this.width; x++) {
477
- const idx = (y * this.width + x) * 4;
478
- const intensity = max > 0 ? this.field[y][x].norm2() / max : 0;
479
- const phase = (this.field[y][x].phase() + Math.PI) / (2 * Math.PI);
480
-
481
- // HSV to RGB (hue = phase, value = intensity)
482
- const h = phase * 360;
483
- const s = 1;
484
- const v = Math.sqrt(intensity); // sqrt for gamma correction
485
-
486
- const [r, g, b] = hsvToRgb(h, s, v);
487
- data[idx] = r;
488
- data[idx + 1] = g;
489
- data[idx + 2] = b;
490
- data[idx + 3] = 255;
206
+ addToCache(key, value) {
207
+ if (this.cache.size >= this.cacheSize) {
208
+ // Remove oldest entry (first key)
209
+ const firstKey = this.cache.keys().next().value;
210
+ if (firstKey !== undefined) {
211
+ this.cache.delete(firstKey);
491
212
  }
492
213
  }
493
-
494
- return { width: this.width, height: this.height, data };
214
+ this.cache.set(key, value);
495
215
  }
496
- }
497
216
 
498
- // Helper: HSV to RGB conversion
499
- function hsvToRgb(h, s, v) {
500
- const c = v * s;
501
- const x = c * (1 - Math.abs((h / 60) % 2 - 1));
502
- const m = v - c;
503
-
504
- let r = 0, g = 0, b = 0;
505
- if (h < 60) { r = c; g = x; }
506
- else if (h < 120) { r = x; g = c; }
507
- else if (h < 180) { g = c; b = x; }
508
- else if (h < 240) { g = x; b = c; }
509
- else if (h < 300) { r = x; b = c; }
510
- else { r = c; b = x; }
511
-
512
- return [
513
- Math.round((r + m) * 255),
514
- Math.round((g + m) * 255),
515
- Math.round((b + m) * 255)
516
- ];
517
- }
518
-
519
- /**
520
- * Entangled Node (from ResoLang spec)
521
- * A network node with PRI, phase ring, and holographic memory
522
- */
523
- class EntangledNode {
524
- constructor(id, pri = null) {
525
- this.id = id;
526
- this.pri = pri || PrimeResonanceIdentity.random();
527
- this.phaseRing = new PhaseLockedRing(firstNPrimes(16));
528
- this.holographicMemory = new HolographicField(32, 32);
529
- this.entanglementMap = new Map(); // nodeId -> strength
530
- this.coherence = 1.0;
531
- }
532
-
533
217
  /**
534
- * Establish entanglement with another node
218
+ * Clear the resonance cache
535
219
  */
536
- entangleWith(other) {
537
- const strength = this.pri.entanglementStrength(other.pri);
538
- this.entanglementMap.set(other.id, strength);
539
- other.entanglementMap.set(this.id, strength);
540
- return strength;
220
+ clearCache() {
221
+ this.cache.clear();
541
222
  }
542
-
543
- /**
544
- * Store a memory fragment
545
- */
546
- storeMemory(state, x = null, y = null) {
547
- this.holographicMemory.encodeState(state, x, y);
548
- }
549
-
550
- /**
551
- * Retrieve memory at position
552
- */
553
- retrieveMemory(x, y) {
554
- return this.holographicMemory.decodeAt(x, y);
555
- }
556
-
557
- /**
558
- * Advance node state
559
- */
560
- tick(dt = 0.01) {
561
- this.phaseRing.tick(dt);
562
-
563
- // Coherence decays slightly over time
564
- this.coherence *= (1 - 0.001 * dt);
565
-
566
- // But increases with synchronization
567
- this.coherence = Math.min(1, this.coherence + this.phaseRing.synchronization() * 0.002 * dt);
568
- }
569
-
570
- /**
571
- * Get current state as PrimeState
572
- */
573
- getState() {
574
- return this.phaseRing.toPrimeState();
575
- }
576
-
223
+
577
224
  /**
578
- * Check if stable (coherent and synchronized)
225
+ * Get cache statistics
579
226
  */
580
- isStable() {
581
- return this.coherence > 0.85 && this.phaseRing.synchronization() > 0.7;
582
- }
583
-
584
- toJSON() {
227
+ getCacheStats() {
585
228
  return {
586
- id: this.id,
587
- pri: this.pri.toJSON(),
588
- coherence: this.coherence,
589
- synchronization: this.phaseRing.synchronization(),
590
- entanglements: Array.from(this.entanglementMap.entries())
229
+ size: this.cache.size,
230
+ maxSize: this.cacheSize
591
231
  };
592
232
  }
593
233
  }
594
234
 
595
235
  /**
596
- * Resonant Fragment (from ResoLang spec)
597
- * A portable memory fragment that can be teleported
236
+ * Compute resonance signature for a set of primes
237
+ * This is a composite measure of internal harmony
238
+ *
239
+ * @param {number[]} primes - Set of primes
240
+ * @param {ResonanceCalculator} calc - Calculator instance
241
+ * @returns {{mean: number, variance: number, goldenCount: number}}
598
242
  */
599
- class ResonantFragment {
600
- constructor(state, centerX = 0, centerY = 0) {
601
- this.state = state;
602
- this.centerX = centerX;
603
- this.centerY = centerY;
604
- this.entropy = state.entropy();
605
- this.createdAt = Date.now();
243
+ function resonanceSignature(primes, calc = new ResonanceCalculator()) {
244
+ if (primes.length < 2) {
245
+ return { mean: 1, variance: 0, goldenCount: 0 };
606
246
  }
607
-
608
- /**
609
- * Create from text
610
- */
611
- static fromText(text) {
612
- const { encodeMemory } = require('./hilbert');
613
- const state = encodeMemory(text);
614
- return new ResonantFragment(state);
615
- }
616
-
617
- /**
618
- * Create from prime list
619
- */
620
- static fromPrimes(primes, weights = null) {
621
- const state = new PrimeState();
622
- for (let i = 0; i < primes.length; i++) {
623
- const p = primes[i];
624
- const w = weights ? weights[i] : 1 / primes.length;
625
- if (state.amplitudes.has(p)) {
626
- state.set(p, new Complex(w, 0));
247
+
248
+ const resonances = [];
249
+ let goldenCount = 0;
250
+
251
+ for (let i = 0; i < primes.length; i++) {
252
+ for (let j = i + 1; j < primes.length; j++) {
253
+ const r = calc.calculateResonance(primes[i], primes[j]);
254
+ resonances.push(r);
255
+
256
+ const ratio = Math.max(primes[i], primes[j]) / Math.min(primes[i], primes[j]);
257
+ if (calc.isGoldenRatio(ratio)) {
258
+ goldenCount++;
627
259
  }
628
260
  }
629
- return new ResonantFragment(state.normalize());
630
261
  }
631
-
632
- /**
633
- * Tensor product with another fragment
634
- */
635
- tensorWith(other) {
636
- // Combine states via multiplication (non-commutative in quaternionic extension)
637
- const combined = new PrimeState(this.state.primes);
638
- for (const p of this.state.primes) {
639
- const a = this.state.get(p);
640
- const b = other.state.get(p);
641
- combined.set(p, a.mul(b));
262
+
263
+ const mean = resonances.reduce((a, b) => a + b, 0) / resonances.length;
264
+ const variance = resonances.reduce((sum, r) => sum + (r - mean) ** 2, 0) / resonances.length;
265
+
266
+ return { mean, variance, goldenCount };
267
+ }
268
+
269
+ /**
270
+ * Find Fibonacci-like sequences in primes (which approximate golden ratio)
271
+ * These sequences have naturally high resonance
272
+ *
273
+ * @param {number[]} primes - Sorted array of primes
274
+ * @param {number} minLength - Minimum sequence length
275
+ * @returns {number[][]} Fibonacci-like sequences
276
+ */
277
+ function findFibonacciSequences(primes, minLength = 3) {
278
+ const sequences = [];
279
+
280
+ for (let i = 0; i < primes.length; i++) {
281
+ for (let j = i + 1; j < primes.length; j++) {
282
+ const seq = [primes[i], primes[j]];
283
+
284
+ // Try to extend the sequence
285
+ let next = primes[i] + primes[j];
286
+ let k = j + 1;
287
+
288
+ while (k < primes.length) {
289
+ if (primes[k] === next) {
290
+ seq.push(primes[k]);
291
+ next = seq[seq.length - 2] + seq[seq.length - 1];
292
+ k++;
293
+ } else if (primes[k] > next) {
294
+ break;
295
+ } else {
296
+ k++;
297
+ }
298
+ }
299
+
300
+ if (seq.length >= minLength) {
301
+ sequences.push(seq);
302
+ }
642
303
  }
643
- return new ResonantFragment(combined.normalize());
644
- }
645
-
646
- /**
647
- * Rotate phase of fragment
648
- */
649
- rotatePhase(angle) {
650
- const rotation = Complex.fromPolar(1, angle);
651
- const rotated = this.state.scale(rotation);
652
- return new ResonantFragment(rotated);
653
- }
654
-
655
- /**
656
- * Check coherence with another fragment
657
- */
658
- coherenceWith(other) {
659
- return this.state.coherence(other.state);
660
- }
661
-
662
- /**
663
- * Get dominant primes
664
- */
665
- dominant(n = 5) {
666
- return this.state.dominant(n);
667
304
  }
668
305
 
669
- toJSON() {
670
- return {
671
- amplitudes: this.state.toArray(),
672
- center: [this.centerX, this.centerY],
673
- entropy: this.entropy,
674
- dominant: this.dominant(3)
675
- };
676
- }
306
+ return sequences;
677
307
  }
678
308
 
309
+ // Singleton instance for convenience
310
+ const defaultCalculator = new ResonanceCalculator();
311
+
679
312
  module.exports = {
680
- // Constants
313
+ ResonanceCalculator,
314
+ resonanceSignature,
315
+ findFibonacciSequences,
681
316
  PHI,
682
- PHI_CONJ,
683
- DELTA_S,
684
-
685
- // Classes
686
- QuaternionPrime,
687
- PrimeResonanceIdentity,
688
- PhaseLockedRing,
689
- HolographicField,
690
- EntangledNode,
691
- ResonantFragment,
317
+ PHI_THRESHOLD,
318
+ PHI_BONUS,
692
319
 
693
- // Helpers
694
- hsvToRgb
320
+ // Convenience functions using default calculator
321
+ calculateResonance: (p1, p2) => defaultCalculator.calculateResonance(p1, p2),
322
+ findGoldenPairs: (primes) => defaultCalculator.findGoldenPairs(primes),
323
+ findMostResonant: (target, candidates) => defaultCalculator.findMostResonant(target, candidates)
695
324
  };