@aleph-ai/tinyaleph 1.5.7 → 1.6.1

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 (122) hide show
  1. package/core/alexander-module.js +1469 -0
  2. package/core/arithmetic-link-kernel.js +1338 -0
  3. package/core/emotion.js +565 -0
  4. package/core/gravity.js +714 -0
  5. package/core/hilbert.js +506 -3
  6. package/core/index.js +132 -4
  7. package/core/nonlocal.js +744 -0
  8. package/core/oracle.js +662 -0
  9. package/examples/01-hello-world.js +69 -0
  10. package/examples/02-basic-hash.js +90 -0
  11. package/examples/02-observer-stack.js +385 -0
  12. package/examples/03-quantum-coin.js +136 -0
  13. package/examples/05-symbolic-resonance.js +146 -0
  14. package/examples/06-symbol-database.js +150 -0
  15. package/examples/07-semantic-inference.js +223 -0
  16. package/examples/08-compound-symbols.js +219 -0
  17. package/examples/README.md +170 -0
  18. package/examples/ai/01-embeddings.js +155 -0
  19. package/examples/ai/02-semantic-memory.js +243 -0
  20. package/examples/ai/03-reasoning.js +243 -0
  21. package/examples/ai/04-knowledge-graph.js +279 -0
  22. package/examples/ai/05-llm-integration.js +333 -0
  23. package/examples/ai/06-agent.js +294 -0
  24. package/examples/ai/07-hybrid-ai.js +223 -0
  25. package/examples/ai/08-entropy-reasoning.js +259 -0
  26. package/examples/ai/09-concept-learning.js +271 -0
  27. package/examples/ai/10-prompt-primes.js +312 -0
  28. package/examples/ai/11-rag.js +332 -0
  29. package/examples/ai/12-neuro-symbolic.js +321 -0
  30. package/examples/ai/README.md +80 -0
  31. package/examples/arithmetic-topology/01-legendre-symbol.js +78 -0
  32. package/examples/arithmetic-topology/02-redei-symbol.js +126 -0
  33. package/examples/arithmetic-topology/03-alk-kuramoto.js +138 -0
  34. package/examples/arithmetic-topology/04-alexander-module.js +117 -0
  35. package/examples/arithmetic-topology/05-signature-memory.js +118 -0
  36. package/examples/arithmetic-topology/README.md +291 -0
  37. package/examples/bioinformatics/01-dna-encoding.js +108 -0
  38. package/examples/bioinformatics/02-central-dogma.js +162 -0
  39. package/examples/bioinformatics/03-protein-folding.js +206 -0
  40. package/examples/bioinformatics/04-dna-computing.js +192 -0
  41. package/examples/bioinformatics/05-molecular-binding.js +209 -0
  42. package/examples/book-operators-demo.js +155 -0
  43. package/examples/chat.js +105 -0
  44. package/examples/crt-homology/01-residue-encoding.js +87 -0
  45. package/examples/crt-homology/02-birkhoff-attention.js +100 -0
  46. package/examples/crt-homology/03-homology-loss.js +132 -0
  47. package/examples/crt-homology/04-crt-resoformer.js +132 -0
  48. package/examples/crt-homology/README.md +67 -0
  49. package/examples/crypto/01-password-hash.js +210 -0
  50. package/examples/crypto/02-key-derivation.js +210 -0
  51. package/examples/crypto/03-hmac.js +229 -0
  52. package/examples/crypto/04-file-integrity.js +263 -0
  53. package/examples/crypto/05-content-hash.js +263 -0
  54. package/examples/crypto/README.md +99 -0
  55. package/examples/demo-modular.js +223 -0
  56. package/examples/demo-two-layer.js +196 -0
  57. package/examples/discrete/01-integer-sine-table.js +120 -0
  58. package/examples/discrete/02-codebook-tunneling.js +118 -0
  59. package/examples/discrete/03-canonical-fusion.js +135 -0
  60. package/examples/discrete/04-tick-gate.js +139 -0
  61. package/examples/discrete/README.md +142 -0
  62. package/examples/emotion-demo.js +200 -0
  63. package/examples/formal-semantics/01-typed-terms.js +156 -0
  64. package/examples/formal-semantics/02-reduction.js +202 -0
  65. package/examples/formal-semantics/03-lambda-translation.js +206 -0
  66. package/examples/formal-semantics/04-enochian-language.js +257 -0
  67. package/examples/formal-semantics/README.md +98 -0
  68. package/examples/gravity-demo.js +190 -0
  69. package/examples/math/01-quaternions.js +237 -0
  70. package/examples/math/02-octonions.js +192 -0
  71. package/examples/math/03-prime-factorization.js +215 -0
  72. package/examples/math/04-vector-spaces.js +210 -0
  73. package/examples/math/05-gaussian-primes.js +234 -0
  74. package/examples/math/README.md +93 -0
  75. package/examples/nonlocal-demo.js +237 -0
  76. package/examples/oracle-demo.js +204 -0
  77. package/examples/physics/01-oscillator.js +177 -0
  78. package/examples/physics/02-lyapunov.js +201 -0
  79. package/examples/physics/03-collapse.js +183 -0
  80. package/examples/physics/04-kuramoto.js +212 -0
  81. package/examples/physics/05-entropy.js +226 -0
  82. package/examples/physics/05-sync-models.js +298 -0
  83. package/examples/physics/06-primeon-ladder.js +233 -0
  84. package/examples/physics/07-kuramoto-coupled-ladder.js +298 -0
  85. package/examples/physics/README.md +126 -0
  86. package/examples/quantum/01-prime-hunter.js +79 -0
  87. package/examples/quantum/02-entanglement-demo.js +79 -0
  88. package/examples/quantum/03-wave-analysis.js +63 -0
  89. package/examples/resonance/01-prime-hilbert-space.js +140 -0
  90. package/examples/resonance/02-prime-resonance-network.js +221 -0
  91. package/examples/resonance/03-resoformer.js +349 -0
  92. package/examples/resonance/04-resoformer-training.js +329 -0
  93. package/examples/resonance/05-language-model.js +484 -0
  94. package/examples/resonance/README.md +238 -0
  95. package/examples/run-examples.js +427 -0
  96. package/examples/scientific/01-single-qubit.js +185 -0
  97. package/examples/scientific/02-two-qubit.js +209 -0
  98. package/examples/scientific/03-quantum-circuits.js +270 -0
  99. package/examples/scientific/04-measurement.js +229 -0
  100. package/examples/scientific/05-algorithms.js +245 -0
  101. package/examples/scientific/06-random.js +225 -0
  102. package/examples/scientific/07-wavefunction.js +192 -0
  103. package/examples/scientific/README.md +118 -0
  104. package/examples/semantic/01-vocabulary.js +186 -0
  105. package/examples/semantic/02-similarity.js +263 -0
  106. package/examples/semantic/03-word-algebra.js +295 -0
  107. package/examples/semantic/04-clustering.js +348 -0
  108. package/examples/semantic/05-classification.js +386 -0
  109. package/examples/semantic/06-dna-encoding.js +228 -0
  110. package/examples/semantic/07-search.js +304 -0
  111. package/examples/semantic/08-qa-system.js +278 -0
  112. package/examples/semantic/README.md +116 -0
  113. package/examples/topology/01-108-invariant.js +81 -0
  114. package/examples/topology/02-trefoil-constants.js +112 -0
  115. package/examples/topology/03-gauge-symmetry.js +112 -0
  116. package/examples/topology/04-free-energy-dynamics.js +124 -0
  117. package/examples/topology/README.md +129 -0
  118. package/index.js +32 -0
  119. package/modular.js +63 -2
  120. package/package.json +8 -3
  121. package/physics/alk-kuramoto.js +817 -0
  122. package/physics/index.js +23 -2
@@ -0,0 +1,1469 @@
1
+ /**
2
+ * Complete Alexander Modules for Prime Sets
3
+ *
4
+ * Implements module-theoretic signature extraction based on:
5
+ * "Complete Alexander Modules for Prime Sets: Crowell Exact Sequences,
6
+ * Iwasawa Modules, and Resonance-Signature Extraction"
7
+ *
8
+ * Key concepts:
9
+ * - ψ-Differential modules A_ψ: Universal differentials satisfying
10
+ * d(g₁g₂) = d(g₁) + ψ(g₁)d(g₂)
11
+ * - Crowell exact sequence: 0 → N^ab → A_ψ → I_{Z[H]} → 0
12
+ * - Fitting ideals E_d(A_ψ): Characteristic invariants
13
+ * - Module signature Σ_{k,S,ℓ,ψ}: Stable memory object for prime sets
14
+ *
15
+ * @module core/alexander-module
16
+ */
17
+
18
+ 'use strict';
19
+
20
+ import { isPrime, firstNPrimes, factorize } from './prime.js';
21
+
22
+ // ============================================================================
23
+ // POLYNOMIAL AND IDEAL UTILITIES
24
+ // ============================================================================
25
+
26
+ /**
27
+ * Laurent Polynomial Class
28
+ *
29
+ * Polynomials in Z[t, t⁻¹] (the group ring Z[Z])
30
+ * Used for Alexander polynomial representation.
31
+ */
32
+ class LaurentPolynomial {
33
+ /**
34
+ * Create a Laurent polynomial
35
+ *
36
+ * @param {Object|Map|Array} coeffs - Coefficients indexed by power
37
+ * Object: { power: coeff } e.g., { 0: 1, 1: -1, 2: 1 } = 1 - t + t²
38
+ * Array: [a₀, a₁, a₂, ...] for non-negative powers
39
+ */
40
+ constructor(coeffs = {}) {
41
+ this.coeffs = new Map();
42
+
43
+ if (Array.isArray(coeffs)) {
44
+ coeffs.forEach((c, i) => {
45
+ if (c !== 0) this.coeffs.set(i, c);
46
+ });
47
+ } else if (coeffs instanceof Map) {
48
+ for (const [k, v] of coeffs) {
49
+ if (v !== 0) this.coeffs.set(k, v);
50
+ }
51
+ } else {
52
+ for (const [k, v] of Object.entries(coeffs)) {
53
+ if (v !== 0) this.coeffs.set(parseInt(k), v);
54
+ }
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Get coefficient at power n
60
+ */
61
+ get(n) {
62
+ return this.coeffs.get(n) || 0;
63
+ }
64
+
65
+ /**
66
+ * Set coefficient at power n
67
+ */
68
+ set(n, value) {
69
+ if (value === 0) {
70
+ this.coeffs.delete(n);
71
+ } else {
72
+ this.coeffs.set(n, value);
73
+ }
74
+ return this;
75
+ }
76
+
77
+ /**
78
+ * Get minimum power with non-zero coefficient
79
+ */
80
+ get minPower() {
81
+ if (this.coeffs.size === 0) return 0;
82
+ return Math.min(...this.coeffs.keys());
83
+ }
84
+
85
+ /**
86
+ * Get maximum power with non-zero coefficient
87
+ */
88
+ get maxPower() {
89
+ if (this.coeffs.size === 0) return 0;
90
+ return Math.max(...this.coeffs.keys());
91
+ }
92
+
93
+ /**
94
+ * Get degree (maxPower - minPower)
95
+ */
96
+ get degree() {
97
+ return this.maxPower - this.minPower;
98
+ }
99
+
100
+ /**
101
+ * Check if polynomial is zero
102
+ */
103
+ get isZero() {
104
+ return this.coeffs.size === 0;
105
+ }
106
+
107
+ /**
108
+ * Add two Laurent polynomials
109
+ */
110
+ add(other) {
111
+ const result = new LaurentPolynomial(this.coeffs);
112
+ for (const [k, v] of other.coeffs) {
113
+ result.set(k, result.get(k) + v);
114
+ }
115
+ return result;
116
+ }
117
+
118
+ /**
119
+ * Subtract
120
+ */
121
+ subtract(other) {
122
+ const result = new LaurentPolynomial(this.coeffs);
123
+ for (const [k, v] of other.coeffs) {
124
+ result.set(k, result.get(k) - v);
125
+ }
126
+ return result;
127
+ }
128
+
129
+ /**
130
+ * Multiply two Laurent polynomials
131
+ */
132
+ multiply(other) {
133
+ const result = new LaurentPolynomial();
134
+ for (const [k1, v1] of this.coeffs) {
135
+ for (const [k2, v2] of other.coeffs) {
136
+ result.set(k1 + k2, result.get(k1 + k2) + v1 * v2);
137
+ }
138
+ }
139
+ return result;
140
+ }
141
+
142
+ /**
143
+ * Scalar multiplication
144
+ */
145
+ scale(scalar) {
146
+ const result = new LaurentPolynomial();
147
+ for (const [k, v] of this.coeffs) {
148
+ result.set(k, scalar * v);
149
+ }
150
+ return result;
151
+ }
152
+
153
+ /**
154
+ * Evaluate at t = value
155
+ */
156
+ evaluate(value) {
157
+ let result = 0;
158
+ for (const [k, v] of this.coeffs) {
159
+ result += v * Math.pow(value, k);
160
+ }
161
+ return result;
162
+ }
163
+
164
+ /**
165
+ * Evaluate at t = e^(iθ) on unit circle
166
+ */
167
+ evaluateOnCircle(theta) {
168
+ let re = 0, im = 0;
169
+ for (const [k, v] of this.coeffs) {
170
+ re += v * Math.cos(k * theta);
171
+ im += v * Math.sin(k * theta);
172
+ }
173
+ return { re, im, abs: Math.sqrt(re * re + im * im) };
174
+ }
175
+
176
+ /**
177
+ * Normalize: divide by leading coefficient and shift to min power 0
178
+ */
179
+ normalize() {
180
+ if (this.isZero) return new LaurentPolynomial();
181
+
182
+ const shift = this.minPower;
183
+ const lead = this.get(this.maxPower);
184
+ const result = new LaurentPolynomial();
185
+
186
+ for (const [k, v] of this.coeffs) {
187
+ result.set(k - shift, v / lead);
188
+ }
189
+
190
+ return result;
191
+ }
192
+
193
+ /**
194
+ * Clone
195
+ */
196
+ clone() {
197
+ return new LaurentPolynomial(this.coeffs);
198
+ }
199
+
200
+ /**
201
+ * String representation
202
+ */
203
+ toString() {
204
+ if (this.isZero) return '0';
205
+
206
+ const powers = [...this.coeffs.keys()].sort((a, b) => a - b);
207
+ const terms = [];
208
+
209
+ for (const k of powers) {
210
+ const c = this.coeffs.get(k);
211
+ if (c === 0) continue;
212
+
213
+ let term = '';
214
+ if (k === 0) {
215
+ term = c.toString();
216
+ } else if (k === 1) {
217
+ term = c === 1 ? 't' : c === -1 ? '-t' : `${c}t`;
218
+ } else if (k < 0) {
219
+ term = c === 1 ? `t^(${k})` : c === -1 ? `-t^(${k})` : `${c}t^(${k})`;
220
+ } else {
221
+ term = c === 1 ? `t^${k}` : c === -1 ? `-t^${k}` : `${c}t^${k}`;
222
+ }
223
+
224
+ terms.push(term);
225
+ }
226
+
227
+ return terms.join(' + ').replace(/\+ -/g, '- ');
228
+ }
229
+
230
+ /**
231
+ * Create from array of roots (as Laurent poly (t - r₁)(t - r₂)...)
232
+ */
233
+ static fromRoots(roots) {
234
+ let result = new LaurentPolynomial({ 0: 1 });
235
+ for (const r of roots) {
236
+ const factor = new LaurentPolynomial({ 0: -r, 1: 1 }); // (t - r)
237
+ result = result.multiply(factor);
238
+ }
239
+ return result;
240
+ }
241
+
242
+ /**
243
+ * Create the augmentation ideal generator (t - 1)
244
+ */
245
+ static augmentationGenerator() {
246
+ return new LaurentPolynomial({ 0: -1, 1: 1 }); // t - 1
247
+ }
248
+ }
249
+
250
+ // ============================================================================
251
+ // FITTING IDEAL CLASS
252
+ // ============================================================================
253
+
254
+ /**
255
+ * Fitting Ideal Class
256
+ *
257
+ * The d-th Fitting ideal E_d(M) of a finitely presented module M
258
+ * is generated by (n-d) × (n-d) minors of a presentation matrix,
259
+ * where n is the number of generators.
260
+ *
261
+ * For Alexander modules, the 0-th Fitting ideal gives the
262
+ * Alexander polynomial (up to units).
263
+ */
264
+ class FittingIdeal {
265
+ /**
266
+ * Create a Fitting ideal
267
+ *
268
+ * @param {number} degree - The degree d of E_d
269
+ * @param {LaurentPolynomial[]} generators - Generators of the ideal
270
+ */
271
+ constructor(degree, generators = []) {
272
+ this.degree = degree;
273
+ this.generators = generators;
274
+ }
275
+
276
+ /**
277
+ * Check if ideal is trivial (equals entire ring)
278
+ */
279
+ get isTrivial() {
280
+ return this.generators.some(g => {
281
+ // Ideal is trivial if some generator is a unit
282
+ return g.coeffs.size === 1 && Math.abs([...g.coeffs.values()][0]) === 1;
283
+ });
284
+ }
285
+
286
+ /**
287
+ * Check if ideal is zero
288
+ */
289
+ get isZero() {
290
+ return this.generators.length === 0 ||
291
+ this.generators.every(g => g.isZero);
292
+ }
293
+
294
+ /**
295
+ * Get primary generator (gcd of all generators)
296
+ * For principal ideals, this is unique up to units.
297
+ */
298
+ get primaryGenerator() {
299
+ if (this.generators.length === 0) {
300
+ return new LaurentPolynomial();
301
+ }
302
+ if (this.generators.length === 1) {
303
+ return this.generators[0];
304
+ }
305
+
306
+ // For Laurent polynomials over Z, computing true gcd is complex.
307
+ // We return the first non-zero generator as approximation.
308
+ for (const g of this.generators) {
309
+ if (!g.isZero) return g;
310
+ }
311
+ return new LaurentPolynomial();
312
+ }
313
+
314
+ /**
315
+ * Compute characteristic polynomial Δ_d
316
+ * This is the generator of E_d when it's principal.
317
+ */
318
+ get characteristicPolynomial() {
319
+ return this.primaryGenerator.normalize();
320
+ }
321
+
322
+ /**
323
+ * Evaluate ideal generators on unit circle
324
+ * Returns minimum absolute value (distance to zero locus).
325
+ */
326
+ evaluateOnCircle(theta) {
327
+ const values = this.generators.map(g => g.evaluateOnCircle(theta));
328
+ const minAbs = Math.min(...values.map(v => v.abs));
329
+ return {
330
+ values,
331
+ minAbs,
332
+ theta
333
+ };
334
+ }
335
+
336
+ /**
337
+ * Find zeros on unit circle (where |generator| is minimized)
338
+ *
339
+ * @param {number} samples - Number of sample points
340
+ * @returns {number[]} Angles where ideal vanishes approximately
341
+ */
342
+ findCircleZeros(samples = 360) {
343
+ const zeros = [];
344
+ const threshold = 0.1;
345
+
346
+ for (let i = 0; i < samples; i++) {
347
+ const theta = (2 * Math.PI * i) / samples;
348
+ const { minAbs } = this.evaluateOnCircle(theta);
349
+ if (minAbs < threshold) {
350
+ zeros.push(theta);
351
+ }
352
+ }
353
+
354
+ return zeros;
355
+ }
356
+
357
+ /**
358
+ * Compute signature hash for content-addressable memory
359
+ */
360
+ get signatureHash() {
361
+ const gen = this.characteristicPolynomial;
362
+ const coeffArray = [];
363
+
364
+ for (let k = gen.minPower; k <= gen.maxPower; k++) {
365
+ coeffArray.push(gen.get(k));
366
+ }
367
+
368
+ // Simple hash: combine coefficients
369
+ let hash = 0;
370
+ for (let i = 0; i < coeffArray.length; i++) {
371
+ hash = ((hash << 5) - hash + coeffArray[i]) | 0;
372
+ }
373
+
374
+ return hash;
375
+ }
376
+ }
377
+
378
+ // ============================================================================
379
+ // CROWELL EXACT SEQUENCE
380
+ // ============================================================================
381
+
382
+ /**
383
+ * Crowell Exact Sequence Class
384
+ *
385
+ * Represents the exact sequence of Z[H]-modules:
386
+ * 0 → N^ab → A_ψ → I_{Z[H]} → 0
387
+ *
388
+ * Extended form:
389
+ * 0 → N^ab → A_ψ → Z[H] → Z → 0
390
+ *
391
+ * For prime sets, this connects:
392
+ * - N^ab: ψ-Galois module (Iwasawa module in cyclotomic case)
393
+ * - A_ψ: Complete Alexander module
394
+ * - I_{Z[H]}: Augmentation ideal
395
+ */
396
+ class CrowellSequence {
397
+ /**
398
+ * Create a Crowell exact sequence
399
+ *
400
+ * @param {Object} groupData - Group-theoretic data
401
+ * @param {Object} groupData.G - The group G (presentation)
402
+ * @param {Object} groupData.H - The abelian quotient H
403
+ * @param {Object} groupData.N - The kernel N = ker(ψ)
404
+ */
405
+ constructor(groupData) {
406
+ this.G = groupData.G;
407
+ this.H = groupData.H;
408
+ this.N = groupData.N;
409
+
410
+ this._Nab = null; // N^ab: ψ-Galois module
411
+ this._Apsi = null; // A_ψ: Alexander module
412
+ this._augIdeal = null; // I_{Z[H]}: Augmentation ideal
413
+ }
414
+
415
+ /**
416
+ * Get the ψ-Galois module N^ab
417
+ */
418
+ get NabelianModule() {
419
+ if (!this._Nab) {
420
+ this._Nab = this._computeNab();
421
+ }
422
+ return this._Nab;
423
+ }
424
+
425
+ /**
426
+ * Get the Alexander module A_ψ
427
+ */
428
+ get alexanderModule() {
429
+ if (!this._Apsi) {
430
+ this._Apsi = this._computeApsi();
431
+ }
432
+ return this._Apsi;
433
+ }
434
+
435
+ /**
436
+ * Get augmentation ideal I_{Z[H]}
437
+ */
438
+ get augmentationIdeal() {
439
+ if (!this._augIdeal) {
440
+ // For H = Z, the augmentation ideal is principal, generated by (t - 1)
441
+ this._augIdeal = new FittingIdeal(0, [
442
+ LaurentPolynomial.augmentationGenerator()
443
+ ]);
444
+ }
445
+ return this._augIdeal;
446
+ }
447
+
448
+ /**
449
+ * Compute N^ab (abelianization of kernel)
450
+ * @private
451
+ */
452
+ _computeNab() {
453
+ // For prime sets, N^ab is computed from the restricted ramification structure
454
+ // This is a simplified representation
455
+ return {
456
+ generators: this.N.generators || [],
457
+ relations: this.N.relations || [],
458
+ rank: this.N.rank || 0
459
+ };
460
+ }
461
+
462
+ /**
463
+ * Compute A_ψ (Alexander module)
464
+ * @private
465
+ */
466
+ _computeApsi() {
467
+ // The Alexander module is computed from the Fox derivatives
468
+ // of the group presentation
469
+ return {
470
+ presentationMatrix: this._computePresentationMatrix(),
471
+ rank: this.G.relations?.length || 0
472
+ };
473
+ }
474
+
475
+ /**
476
+ * Compute presentation matrix (Fox derivative matrix)
477
+ * @private
478
+ */
479
+ _computePresentationMatrix() {
480
+ // Fox derivative matrix: ∂r_i/∂x_j for relations r_i, generators x_j
481
+ // This is a matrix of Laurent polynomials
482
+ const numRelations = this.G.relations?.length || 0;
483
+ const numGenerators = this.G.generators?.length || 0;
484
+
485
+ const matrix = [];
486
+ for (let i = 0; i < numRelations; i++) {
487
+ const row = [];
488
+ for (let j = 0; j < numGenerators; j++) {
489
+ // Simplified: placeholder for actual Fox derivative
490
+ row.push(new LaurentPolynomial({ 0: 1 }));
491
+ }
492
+ matrix.push(row);
493
+ }
494
+
495
+ return matrix;
496
+ }
497
+
498
+ /**
499
+ * Check exactness at each position
500
+ */
501
+ verifyExactness() {
502
+ // In a proper implementation, this would verify:
503
+ // 1. θ₁: N^ab → A_ψ is injective
504
+ // 2. im(θ₁) = ker(θ₂)
505
+ // 3. θ₂: A_ψ → I_{Z[H]} is surjective
506
+ return {
507
+ injectiveAtNab: true,
508
+ exactAtApsi: true,
509
+ surjectiveOntoAugIdeal: true
510
+ };
511
+ }
512
+
513
+ /**
514
+ * Get splitting isomorphism (Morishita's result)
515
+ * A_ψ ≅ N^ab ⊕ Λ̂ where Λ̂ = Z_ℓ[[H]]
516
+ */
517
+ getSplitting() {
518
+ return {
519
+ directSum: true,
520
+ components: ['N^ab', 'Λ̂'],
521
+ fittingShift: 1 // E_d(N^ab) = E_{d+1}(A_ψ)
522
+ };
523
+ }
524
+ }
525
+
526
+ // ============================================================================
527
+ // ALEXANDER MODULE CLASS
528
+ // ============================================================================
529
+
530
+ /**
531
+ * Complete Alexander Module
532
+ *
533
+ * The ψ-differential module A_ψ for a prime set S.
534
+ * Provides the module-theoretic invariant layer above coupling tensors.
535
+ */
536
+ class AlexanderModule {
537
+ /**
538
+ * Create an Alexander module for a prime set
539
+ *
540
+ * @param {number[]} primes - The prime set S
541
+ * @param {Object} options - Configuration
542
+ * @param {number} options.ell - Base prime ℓ (default: 2)
543
+ * @param {string} options.field - Base field k (default: 'Q')
544
+ */
545
+ constructor(primes, options = {}) {
546
+ this.primes = primes.filter(p => isPrime(p)).sort((a, b) => a - b);
547
+ this.r = this.primes.length;
548
+
549
+ if (this.r < 1) {
550
+ throw new Error('AlexanderModule requires at least 1 prime');
551
+ }
552
+
553
+ this.ell = options.ell || 2;
554
+ this.field = options.field || 'Q';
555
+
556
+ // Compute group-theoretic data
557
+ this._groupData = this._buildGroupData();
558
+ this._crowellSequence = null;
559
+ this._fittingIdeals = new Map();
560
+ this._signature = null;
561
+
562
+ this.metadata = {
563
+ created: Date.now(),
564
+ primeProduct: this.primes.reduce((a, b) => a * b, 1),
565
+ primeSum: this.primes.reduce((a, b) => a + b, 0)
566
+ };
567
+ }
568
+
569
+ /**
570
+ * Build group-theoretic data from prime set
571
+ *
572
+ * The restricted-ramification Galois group G_S(k) = π₁(Spec(O_k) \ S)
573
+ * @private
574
+ */
575
+ _buildGroupData() {
576
+ // For the prime set S = {p₁, ..., p_r}, we build:
577
+ // - G: restricted-ramification group (simplified presentation)
578
+ // - H: maximal abelian quotient
579
+ // - N: kernel of ψ: G → H
580
+
581
+ const generators = this.primes.map((p, i) => ({
582
+ index: i,
583
+ prime: p,
584
+ symbol: `σ_${p}`
585
+ }));
586
+
587
+ // Relations encode ramification structure
588
+ // For simplicity, we use trivial relations here
589
+ const relations = [];
590
+
591
+ // The abelianization H is free abelian of rank r
592
+ const H = {
593
+ rank: this.r,
594
+ generators: generators.slice(),
595
+ isAbelian: true
596
+ };
597
+
598
+ // For abelianization, N = [G, G] (commutator subgroup)
599
+ const N = {
600
+ generators: [], // Computed from commutators
601
+ relations: [],
602
+ rank: 0 // Depends on class field theory
603
+ };
604
+
605
+ return {
606
+ G: { generators, relations },
607
+ H,
608
+ N,
609
+ abelianization: H
610
+ };
611
+ }
612
+
613
+ /**
614
+ * Get the Crowell exact sequence
615
+ */
616
+ get crowellSequence() {
617
+ if (!this._crowellSequence) {
618
+ this._crowellSequence = new CrowellSequence(this._groupData);
619
+ }
620
+ return this._crowellSequence;
621
+ }
622
+
623
+ /**
624
+ * Compute d-th Fitting ideal E_d(A_ψ)
625
+ *
626
+ * @param {number} d - Degree of Fitting ideal
627
+ * @returns {FittingIdeal} The ideal E_d
628
+ */
629
+ computeFittingIdeal(d) {
630
+ if (this._fittingIdeals.has(d)) {
631
+ return this._fittingIdeals.get(d);
632
+ }
633
+
634
+ const ideal = this._computeFitting(d);
635
+ this._fittingIdeals.set(d, ideal);
636
+ return ideal;
637
+ }
638
+
639
+ /**
640
+ * Compute Fitting ideal from presentation matrix
641
+ * @private
642
+ */
643
+ _computeFitting(d) {
644
+ // The d-th Fitting ideal is generated by (n-d) × (n-d) minors
645
+ // of the presentation matrix, where n = number of generators
646
+
647
+ const n = this.r;
648
+
649
+ if (d >= n) {
650
+ // E_d = entire ring for d ≥ n
651
+ return new FittingIdeal(d, [new LaurentPolynomial({ 0: 1 })]);
652
+ }
653
+
654
+ if (d === 0) {
655
+ // E_0 is the principal ideal generated by the Alexander polynomial
656
+ const alexPoly = this._computeAlexanderPolynomial();
657
+ return new FittingIdeal(0, [alexPoly]);
658
+ }
659
+
660
+ // For intermediate d, compute minors
661
+ // This is a simplified version
662
+ const minorSize = n - d;
663
+ const generators = this._computeMinors(minorSize);
664
+ return new FittingIdeal(d, generators);
665
+ }
666
+
667
+ /**
668
+ * Compute Alexander polynomial
669
+ *
670
+ * For a prime set, this is related to the characteristic polynomial
671
+ * of the Iwasawa module when interpreted via class field theory.
672
+ * @private
673
+ */
674
+ _computeAlexanderPolynomial() {
675
+ // For a single prime p, the Alexander polynomial is trivial: 1
676
+ // For multiple primes, it encodes the ramification structure
677
+
678
+ if (this.r === 1) {
679
+ return new LaurentPolynomial({ 0: 1 });
680
+ }
681
+
682
+ // Construct polynomial from prime signatures
683
+ // This is a simplified heuristic based on prime residue classes
684
+ const coeffs = {};
685
+
686
+ // The polynomial structure depends on the Galois group
687
+ // Use prime-derived coefficients as approximation
688
+ for (let i = 0; i <= this.r; i++) {
689
+ const coeff = this._computeAlexanderCoeff(i);
690
+ if (coeff !== 0) {
691
+ coeffs[i] = coeff;
692
+ }
693
+ }
694
+
695
+ // Ensure symmetric (palindromic) structure
696
+ // Alexander polynomials satisfy Δ(t⁻¹) = t^(-deg) Δ(t) up to sign
697
+ const poly = new LaurentPolynomial(coeffs);
698
+ return this._symmetrize(poly);
699
+ }
700
+
701
+ /**
702
+ * Compute Alexander polynomial coefficient
703
+ * @private
704
+ */
705
+ _computeAlexanderCoeff(i) {
706
+ if (i === 0) return 1;
707
+ if (i === this.r) return 1;
708
+
709
+ // Use prime residue structure
710
+ let coeff = 0;
711
+ const combos = this._combinations(this.primes, i);
712
+
713
+ for (const combo of combos) {
714
+ const prod = combo.reduce((a, b) => a * b, 1);
715
+ const sign = this._computeSign(combo);
716
+ coeff += sign;
717
+ }
718
+
719
+ return coeff;
720
+ }
721
+
722
+ /**
723
+ * Compute sign from prime combo
724
+ * @private
725
+ */
726
+ _computeSign(primes) {
727
+ // Based on Legendre symbol structure
728
+ let sign = 1;
729
+ for (let i = 0; i < primes.length; i++) {
730
+ for (let j = i + 1; j < primes.length; j++) {
731
+ const leg = this._legendreSymbol(primes[i], primes[j]);
732
+ sign *= leg;
733
+ }
734
+ }
735
+ return sign;
736
+ }
737
+
738
+ /**
739
+ * Simple Legendre symbol computation
740
+ * @private
741
+ */
742
+ _legendreSymbol(a, p) {
743
+ if (p === 2 || !isPrime(p)) return 0;
744
+ a = ((a % p) + p) % p;
745
+ if (a === 0) return 0;
746
+
747
+ // Euler's criterion
748
+ let result = 1;
749
+ let exp = (p - 1) / 2;
750
+ let base = a;
751
+
752
+ while (exp > 0) {
753
+ if (exp % 2 === 1) {
754
+ result = (result * base) % p;
755
+ }
756
+ base = (base * base) % p;
757
+ exp = Math.floor(exp / 2);
758
+ }
759
+
760
+ return result === 1 ? 1 : -1;
761
+ }
762
+
763
+ /**
764
+ * Make polynomial symmetric/palindromic
765
+ * @private
766
+ */
767
+ _symmetrize(poly) {
768
+ if (poly.isZero) return poly;
769
+
770
+ const min = poly.minPower;
771
+ const max = poly.maxPower;
772
+ const result = new LaurentPolynomial();
773
+
774
+ for (let k = min; k <= max; k++) {
775
+ const c1 = poly.get(k);
776
+ const c2 = poly.get(max + min - k);
777
+ const avg = Math.round((c1 + c2) / 2);
778
+ result.set(k, avg);
779
+ }
780
+
781
+ return result;
782
+ }
783
+
784
+ /**
785
+ * Compute minors of presentation matrix
786
+ * @private
787
+ */
788
+ _computeMinors(size) {
789
+ // Simplified: return generators based on prime structure
790
+ const generators = [];
791
+
792
+ if (size <= 0) {
793
+ generators.push(new LaurentPolynomial({ 0: 1 }));
794
+ return generators;
795
+ }
796
+
797
+ // Each minor corresponds to a subset of relations/generators
798
+ const subsets = this._combinations(this.primes, size);
799
+
800
+ for (const subset of subsets) {
801
+ const minor = this._computeMinorFromSubset(subset);
802
+ if (!minor.isZero) {
803
+ generators.push(minor);
804
+ }
805
+ }
806
+
807
+ if (generators.length === 0) {
808
+ generators.push(new LaurentPolynomial({ 0: 1 }));
809
+ }
810
+
811
+ return generators;
812
+ }
813
+
814
+ /**
815
+ * Compute minor from prime subset
816
+ * @private
817
+ */
818
+ _computeMinorFromSubset(primes) {
819
+ // The minor is a determinant of the Fox derivative matrix
820
+ // For simplified implementation, use product-sum formula
821
+ const coeffs = {};
822
+
823
+ for (let i = 0; i <= primes.length; i++) {
824
+ const sign = (i % 2 === 0) ? 1 : -1;
825
+ const binomial = this._binomial(primes.length, i);
826
+ coeffs[i] = sign * binomial;
827
+ }
828
+
829
+ return new LaurentPolynomial(coeffs);
830
+ }
831
+
832
+ /**
833
+ * Binomial coefficient
834
+ * @private
835
+ */
836
+ _binomial(n, k) {
837
+ if (k < 0 || k > n) return 0;
838
+ if (k === 0 || k === n) return 1;
839
+
840
+ let result = 1;
841
+ for (let i = 0; i < k; i++) {
842
+ result = result * (n - i) / (i + 1);
843
+ }
844
+ return Math.round(result);
845
+ }
846
+
847
+ /**
848
+ * Generate all k-combinations of array
849
+ * @private
850
+ */
851
+ _combinations(arr, k) {
852
+ if (k === 0) return [[]];
853
+ if (arr.length === 0) return [];
854
+
855
+ const [first, ...rest] = arr;
856
+ const withFirst = this._combinations(rest, k - 1).map(c => [first, ...c]);
857
+ const withoutFirst = this._combinations(rest, k);
858
+
859
+ return [...withFirst, ...withoutFirst];
860
+ }
861
+
862
+ /**
863
+ * Get Alexander polynomial Δ₀(A_ψ)
864
+ */
865
+ get alexanderPolynomial() {
866
+ return this.computeFittingIdeal(0).characteristicPolynomial;
867
+ }
868
+
869
+ /**
870
+ * Get all Fitting ideals up to degree d
871
+ */
872
+ getAllFittingIdeals(maxDegree = 3) {
873
+ const ideals = {};
874
+ for (let d = 0; d <= maxDegree; d++) {
875
+ ideals[d] = this.computeFittingIdeal(d);
876
+ }
877
+ return ideals;
878
+ }
879
+
880
+ /**
881
+ * Get module signature Σ_{k,S,ℓ,ψ}
882
+ */
883
+ get signature() {
884
+ if (!this._signature) {
885
+ this._signature = this._computeSignature();
886
+ }
887
+ return this._signature;
888
+ }
889
+
890
+ /**
891
+ * Compute module signature
892
+ * @private
893
+ */
894
+ _computeSignature() {
895
+ const fittingIdeals = this.getAllFittingIdeals();
896
+ const alexPoly = this.alexanderPolynomial;
897
+
898
+ // Signature components
899
+ const signatureData = {
900
+ primes: this.primes.slice(),
901
+ ell: this.ell,
902
+ field: this.field,
903
+ fittingDegrees: {},
904
+ alexanderPolynomial: alexPoly.toString(),
905
+ characteristicValues: [],
906
+ hash: 0
907
+ };
908
+
909
+ // Collect Fitting ideal degrees
910
+ for (const [d, ideal] of Object.entries(fittingIdeals)) {
911
+ signatureData.fittingDegrees[d] = {
912
+ degree: parseInt(d),
913
+ isTrivial: ideal.isTrivial,
914
+ isZero: ideal.isZero,
915
+ generatorDegree: ideal.characteristicPolynomial.degree
916
+ };
917
+ }
918
+
919
+ // Evaluate Alexander polynomial on roots of unity
920
+ const numRoots = 12;
921
+ for (let k = 0; k < numRoots; k++) {
922
+ const theta = (2 * Math.PI * k) / numRoots;
923
+ const val = alexPoly.evaluateOnCircle(theta);
924
+ signatureData.characteristicValues.push({
925
+ k,
926
+ theta,
927
+ abs: val.abs,
928
+ re: val.re,
929
+ im: val.im
930
+ });
931
+ }
932
+
933
+ // Compute signature hash
934
+ signatureData.hash = this._computeSignatureHash(signatureData);
935
+
936
+ return signatureData;
937
+ }
938
+
939
+ /**
940
+ * Compute signature hash
941
+ * @private
942
+ */
943
+ _computeSignatureHash(sig) {
944
+ // Combine prime signature with Alexander polynomial coefficients
945
+ let hash = 0;
946
+
947
+ // Include primes
948
+ for (const p of sig.primes) {
949
+ hash = ((hash << 5) - hash + p) | 0;
950
+ }
951
+
952
+ // Include characteristic values
953
+ for (const cv of sig.characteristicValues) {
954
+ hash = ((hash << 5) - hash + Math.round(cv.abs * 1000)) | 0;
955
+ }
956
+
957
+ return hash >>> 0; // Ensure unsigned
958
+ }
959
+
960
+ /**
961
+ * Check if two Alexander modules have equivalent signatures
962
+ */
963
+ static equivalentSignatures(sig1, sig2, tolerance = 0.01) {
964
+ if (sig1.primes.length !== sig2.primes.length) return false;
965
+ if (sig1.ell !== sig2.ell) return false;
966
+
967
+ // Compare characteristic values
968
+ for (let i = 0; i < sig1.characteristicValues.length; i++) {
969
+ const v1 = sig1.characteristicValues[i];
970
+ const v2 = sig2.characteristicValues[i];
971
+ if (Math.abs(v1.abs - v2.abs) > tolerance) return false;
972
+ }
973
+
974
+ return true;
975
+ }
976
+
977
+ /**
978
+ * Get JSON representation
979
+ */
980
+ toJSON() {
981
+ return {
982
+ primes: this.primes,
983
+ ell: this.ell,
984
+ field: this.field,
985
+ alexanderPolynomial: this.alexanderPolynomial.toString(),
986
+ signature: this.signature,
987
+ metadata: this.metadata
988
+ };
989
+ }
990
+
991
+ /**
992
+ * Create from JSON
993
+ */
994
+ static fromJSON(json) {
995
+ return new AlexanderModule(json.primes, {
996
+ ell: json.ell,
997
+ field: json.field
998
+ });
999
+ }
1000
+
1001
+ /**
1002
+ * Get statistics
1003
+ */
1004
+ get stats() {
1005
+ const alexPoly = this.alexanderPolynomial;
1006
+ const sig = this.signature;
1007
+
1008
+ return {
1009
+ numPrimes: this.r,
1010
+ ell: this.ell,
1011
+ alexanderDegree: alexPoly.degree,
1012
+ signatureHash: sig.hash,
1013
+ meanCharacteristicValue: sig.characteristicValues.reduce(
1014
+ (sum, v) => sum + v.abs, 0
1015
+ ) / sig.characteristicValues.length
1016
+ };
1017
+ }
1018
+ }
1019
+
1020
+ // ============================================================================
1021
+ // MODULE SIGNATURE CLASS
1022
+ // ============================================================================
1023
+
1024
+ /**
1025
+ * Module Signature
1026
+ *
1027
+ * A content-addressable memory key derived from Alexander module invariants.
1028
+ * Provides stable "field memory" for prime sets.
1029
+ *
1030
+ * Uses:
1031
+ * - Content-addressable key (prime-set identifier)
1032
+ * - Resonance attractor fingerprint
1033
+ * - Alignment target for operator evolution
1034
+ */
1035
+ class ModuleSignature {
1036
+ /**
1037
+ * Create a module signature
1038
+ *
1039
+ * @param {AlexanderModule} module - Source Alexander module
1040
+ */
1041
+ constructor(module) {
1042
+ this.module = module;
1043
+ this._data = null;
1044
+ }
1045
+
1046
+ /**
1047
+ * Get signature data
1048
+ */
1049
+ get data() {
1050
+ if (!this._data) {
1051
+ this._data = this.module.signature;
1052
+ }
1053
+ return this._data;
1054
+ }
1055
+
1056
+ /**
1057
+ * Get signature hash (content-addressable key)
1058
+ */
1059
+ get hash() {
1060
+ return this.data.hash;
1061
+ }
1062
+
1063
+ /**
1064
+ * Get primes
1065
+ */
1066
+ get primes() {
1067
+ return this.data.primes;
1068
+ }
1069
+
1070
+ /**
1071
+ * Get Alexander polynomial string
1072
+ */
1073
+ get alexanderPolynomial() {
1074
+ return this.data.alexanderPolynomial;
1075
+ }
1076
+
1077
+ /**
1078
+ * Get characteristic values (for fingerprinting)
1079
+ */
1080
+ get fingerprint() {
1081
+ return this.data.characteristicValues.map(v => v.abs);
1082
+ }
1083
+
1084
+ /**
1085
+ * Compute distance between two signatures
1086
+ */
1087
+ distanceTo(other) {
1088
+ const fp1 = this.fingerprint;
1089
+ const fp2 = other.fingerprint;
1090
+
1091
+ if (fp1.length !== fp2.length) {
1092
+ throw new Error('Fingerprint length mismatch');
1093
+ }
1094
+
1095
+ let sumSq = 0;
1096
+ for (let i = 0; i < fp1.length; i++) {
1097
+ const diff = fp1[i] - fp2[i];
1098
+ sumSq += diff * diff;
1099
+ }
1100
+
1101
+ return Math.sqrt(sumSq);
1102
+ }
1103
+
1104
+ /**
1105
+ * Check if signatures are equivalent
1106
+ */
1107
+ isEquivalentTo(other, tolerance = 0.01) {
1108
+ return AlexanderModule.equivalentSignatures(this.data, other.data, tolerance);
1109
+ }
1110
+
1111
+ /**
1112
+ * Get compact string representation
1113
+ */
1114
+ toString() {
1115
+ return `ModuleSignature[${this.primes.join(',')}|${this.hash.toString(16)}]`;
1116
+ }
1117
+
1118
+ /**
1119
+ * Export as content-addressable memory entry
1120
+ */
1121
+ toMemoryEntry() {
1122
+ return {
1123
+ key: this.hash,
1124
+ primes: this.primes,
1125
+ fingerprint: this.fingerprint,
1126
+ polynomial: this.alexanderPolynomial,
1127
+ created: Date.now()
1128
+ };
1129
+ }
1130
+ }
1131
+
1132
+ // ============================================================================
1133
+ // SIGNATURE MEMORY CLASS
1134
+ // ============================================================================
1135
+
1136
+ /**
1137
+ * Signature Memory
1138
+ *
1139
+ * Content-addressable memory store for module signatures.
1140
+ * Enables resonance-based retrieval and alignment.
1141
+ */
1142
+ class SignatureMemory {
1143
+ constructor() {
1144
+ this.signatures = new Map(); // hash → signature
1145
+ this.primeIndex = new Map(); // prime → [hashes]
1146
+ this.metadata = {
1147
+ created: Date.now(),
1148
+ totalEntries: 0
1149
+ };
1150
+ }
1151
+
1152
+ /**
1153
+ * Store a signature
1154
+ */
1155
+ store(signature) {
1156
+ const hash = signature.hash;
1157
+
1158
+ if (this.signatures.has(hash)) {
1159
+ return { stored: false, reason: 'already exists', hash };
1160
+ }
1161
+
1162
+ this.signatures.set(hash, signature);
1163
+
1164
+ // Index by primes
1165
+ for (const p of signature.primes) {
1166
+ if (!this.primeIndex.has(p)) {
1167
+ this.primeIndex.set(p, []);
1168
+ }
1169
+ this.primeIndex.get(p).push(hash);
1170
+ }
1171
+
1172
+ this.metadata.totalEntries++;
1173
+
1174
+ return { stored: true, hash };
1175
+ }
1176
+
1177
+ /**
1178
+ * Retrieve signature by hash
1179
+ */
1180
+ get(hash) {
1181
+ return this.signatures.get(hash) || null;
1182
+ }
1183
+
1184
+ /**
1185
+ * Check if signature exists
1186
+ */
1187
+ has(hash) {
1188
+ return this.signatures.has(hash);
1189
+ }
1190
+
1191
+ /**
1192
+ * Find signatures containing a specific prime
1193
+ */
1194
+ findByPrime(prime) {
1195
+ const hashes = this.primeIndex.get(prime) || [];
1196
+ return hashes.map(h => this.signatures.get(h)).filter(Boolean);
1197
+ }
1198
+
1199
+ /**
1200
+ * Find closest signature to query
1201
+ */
1202
+ findClosest(querySignature, topK = 5) {
1203
+ const results = [];
1204
+
1205
+ for (const [hash, sig] of this.signatures) {
1206
+ try {
1207
+ const distance = querySignature.distanceTo(sig);
1208
+ results.push({ hash, signature: sig, distance });
1209
+ } catch (e) {
1210
+ // Skip incompatible signatures
1211
+ }
1212
+ }
1213
+
1214
+ results.sort((a, b) => a.distance - b.distance);
1215
+ return results.slice(0, topK);
1216
+ }
1217
+
1218
+ /**
1219
+ * Find equivalent signatures
1220
+ */
1221
+ findEquivalent(querySignature, tolerance = 0.01) {
1222
+ const equivalent = [];
1223
+
1224
+ for (const [hash, sig] of this.signatures) {
1225
+ if (querySignature.isEquivalentTo(sig, tolerance)) {
1226
+ equivalent.push({ hash, signature: sig });
1227
+ }
1228
+ }
1229
+
1230
+ return equivalent;
1231
+ }
1232
+
1233
+ /**
1234
+ * Get all signatures
1235
+ */
1236
+ getAll() {
1237
+ return [...this.signatures.values()];
1238
+ }
1239
+
1240
+ /**
1241
+ * Get memory statistics
1242
+ */
1243
+ get stats() {
1244
+ const allPrimes = new Set();
1245
+ for (const sig of this.signatures.values()) {
1246
+ for (const p of sig.primes) {
1247
+ allPrimes.add(p);
1248
+ }
1249
+ }
1250
+
1251
+ return {
1252
+ totalSignatures: this.signatures.size,
1253
+ uniquePrimes: allPrimes.size,
1254
+ primeIndex: this.primeIndex.size,
1255
+ created: this.metadata.created
1256
+ };
1257
+ }
1258
+
1259
+ /**
1260
+ * Clear all signatures
1261
+ */
1262
+ clear() {
1263
+ this.signatures.clear();
1264
+ this.primeIndex.clear();
1265
+ this.metadata.totalEntries = 0;
1266
+ }
1267
+
1268
+ /**
1269
+ * Export memory to JSON
1270
+ */
1271
+ toJSON() {
1272
+ const entries = [];
1273
+ for (const [hash, sig] of this.signatures) {
1274
+ entries.push({
1275
+ hash,
1276
+ primes: sig.primes,
1277
+ fingerprint: sig.fingerprint,
1278
+ polynomial: sig.alexanderPolynomial
1279
+ });
1280
+ }
1281
+ return { entries, metadata: this.metadata };
1282
+ }
1283
+
1284
+ /**
1285
+ * Import memory from JSON
1286
+ */
1287
+ static fromJSON(json, moduleFactory) {
1288
+ const memory = new SignatureMemory();
1289
+
1290
+ for (const entry of json.entries) {
1291
+ const module = moduleFactory(entry.primes);
1292
+ const signature = new ModuleSignature(module);
1293
+ memory.store(signature);
1294
+ }
1295
+
1296
+ return memory;
1297
+ }
1298
+ }
1299
+
1300
+ // ============================================================================
1301
+ // SIGNATURE EXTRACTOR
1302
+ // ============================================================================
1303
+
1304
+ /**
1305
+ * Signature Extractor
1306
+ *
1307
+ * Extracts module signatures from prime sets and manages
1308
+ * the signature extraction pipeline.
1309
+ */
1310
+ class SignatureExtractor {
1311
+ /**
1312
+ * Create a signature extractor
1313
+ *
1314
+ * @param {Object} options - Configuration
1315
+ * @param {number} options.ell - Base prime (default: 2)
1316
+ * @param {SignatureMemory} options.memory - Optional memory store
1317
+ */
1318
+ constructor(options = {}) {
1319
+ this.ell = options.ell || 2;
1320
+ this.memory = options.memory || new SignatureMemory();
1321
+ this._cache = new Map();
1322
+ }
1323
+
1324
+ /**
1325
+ * Extract signature from prime set
1326
+ *
1327
+ * @param {number[]} primes - Prime set S
1328
+ * @param {Object} options - Extraction options
1329
+ * @returns {ModuleSignature} The extracted signature
1330
+ */
1331
+ extract(primes, options = {}) {
1332
+ const key = primes.sort((a, b) => a - b).join(',');
1333
+
1334
+ if (this._cache.has(key)) {
1335
+ return this._cache.get(key);
1336
+ }
1337
+
1338
+ const module = new AlexanderModule(primes, {
1339
+ ell: options.ell || this.ell,
1340
+ field: options.field || 'Q'
1341
+ });
1342
+
1343
+ const signature = new ModuleSignature(module);
1344
+
1345
+ this._cache.set(key, signature);
1346
+
1347
+ if (options.store !== false) {
1348
+ this.memory.store(signature);
1349
+ }
1350
+
1351
+ return signature;
1352
+ }
1353
+
1354
+ /**
1355
+ * Extract signatures from multiple prime sets
1356
+ */
1357
+ extractBatch(primeSets, options = {}) {
1358
+ return primeSets.map(primes => this.extract(primes, options));
1359
+ }
1360
+
1361
+ /**
1362
+ * Find resonant signatures (closest matches)
1363
+ */
1364
+ findResonant(primes, topK = 5) {
1365
+ const querySig = this.extract(primes, { store: false });
1366
+ return this.memory.findClosest(querySig, topK);
1367
+ }
1368
+
1369
+ /**
1370
+ * Get alignment target for operator evolution
1371
+ * Returns the closest signature in memory.
1372
+ */
1373
+ getAlignmentTarget(primes) {
1374
+ const matches = this.findResonant(primes, 1);
1375
+ return matches.length > 0 ? matches[0].signature : null;
1376
+ }
1377
+
1378
+ /**
1379
+ * Clear cache
1380
+ */
1381
+ clearCache() {
1382
+ this._cache.clear();
1383
+ }
1384
+
1385
+ /**
1386
+ * Get extractor statistics
1387
+ */
1388
+ get stats() {
1389
+ return {
1390
+ cacheSize: this._cache.size,
1391
+ memoryStats: this.memory.stats,
1392
+ ell: this.ell
1393
+ };
1394
+ }
1395
+ }
1396
+
1397
+ // ============================================================================
1398
+ // INTEGRATION UTILITIES
1399
+ // ============================================================================
1400
+
1401
+ /**
1402
+ * Create Alexander module from prime set
1403
+ */
1404
+ function createAlexanderModule(primes, options = {}) {
1405
+ return new AlexanderModule(primes, options);
1406
+ }
1407
+
1408
+ /**
1409
+ * Extract signature from prime set (convenience function)
1410
+ */
1411
+ function extractSignature(primes, options = {}) {
1412
+ const module = new AlexanderModule(primes, options);
1413
+ return new ModuleSignature(module);
1414
+ }
1415
+
1416
+ /**
1417
+ * Create signature memory store
1418
+ */
1419
+ function createSignatureMemory() {
1420
+ return new SignatureMemory();
1421
+ }
1422
+
1423
+ /**
1424
+ * Create signature extractor
1425
+ */
1426
+ function createSignatureExtractor(options = {}) {
1427
+ return new SignatureExtractor(options);
1428
+ }
1429
+
1430
+ // ============================================================================
1431
+ // EXPORTS
1432
+ // ============================================================================
1433
+
1434
+ export {
1435
+ // Polynomial utilities
1436
+ LaurentPolynomial,
1437
+ FittingIdeal,
1438
+
1439
+ // Crowell exact sequence
1440
+ CrowellSequence,
1441
+
1442
+ // Alexander module
1443
+ AlexanderModule,
1444
+
1445
+ // Signature classes
1446
+ ModuleSignature,
1447
+ SignatureMemory,
1448
+ SignatureExtractor,
1449
+
1450
+ // Factory functions
1451
+ createAlexanderModule,
1452
+ extractSignature,
1453
+ createSignatureMemory,
1454
+ createSignatureExtractor
1455
+ };
1456
+
1457
+ export default {
1458
+ LaurentPolynomial,
1459
+ FittingIdeal,
1460
+ CrowellSequence,
1461
+ AlexanderModule,
1462
+ ModuleSignature,
1463
+ SignatureMemory,
1464
+ SignatureExtractor,
1465
+ createAlexanderModule,
1466
+ extractSignature,
1467
+ createSignatureMemory,
1468
+ createSignatureExtractor
1469
+ };