@aleph-ai/tinyaleph 1.0.2 → 1.2.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.
- package/README.md +449 -2
- package/core/entanglement.js +712 -0
- package/core/events.js +907 -0
- package/core/hypercomplex.js +500 -0
- package/core/index.js +129 -1
- package/core/lambda.js +845 -0
- package/core/reduction.js +741 -0
- package/core/rformer-layers.js +811 -0
- package/core/types.js +913 -0
- package/docs/README.md +84 -0
- package/docs/design/ALEPH_CHAT_ARCHITECTURE.md +1 -1
- package/docs/design/AUTONOMOUS_LEARNING_DESIGN.md +1492 -0
- package/docs/design/WHITEPAPER_GAP_ANALYSIS.md +171 -4
- package/docs/reference/01-core.md +515 -1
- package/docs/reference/02-physics.md +186 -1
- package/docs/reference/README.md +277 -1
- package/docs/theory/03-phase-synchronization.md +196 -0
- package/docs/theory/README.md +47 -0
- package/package.json +2 -2
- package/physics/index.js +76 -10
- package/physics/primeon_z_ladder_multi.js +669 -0
- package/physics/primeon_z_ladder_u.js +493 -0
- package/physics/stochastic-kuramoto.js +566 -0
- package/physics/sync-models.js +770 -0
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Primeon Z-Ladder with Canonical U Evolution
|
|
3
|
+
*
|
|
4
|
+
* Minimal canonical U implementation representing a ladder with:
|
|
5
|
+
* - core sector ψ ∈ ℂ^d (quantum state)
|
|
6
|
+
* - Z sector z ∈ ℂ^dz (closure/sink/bookkeeping channel)
|
|
7
|
+
*
|
|
8
|
+
* Provides reproducible stepping, measurable Z-flux signal,
|
|
9
|
+
* and stable hooks for entropy and coherence metrics.
|
|
10
|
+
*/
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Minimal Complex number helpers (intentionally tiny for predictable perf).
|
|
15
|
+
*/
|
|
16
|
+
class C {
|
|
17
|
+
constructor(re = 0, im = 0) {
|
|
18
|
+
this.re = re;
|
|
19
|
+
this.im = im;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static add(a, b) {
|
|
23
|
+
return new C(a.re + b.re, a.im + b.im);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static sub(a, b) {
|
|
27
|
+
return new C(a.re - b.re, a.im - b.im);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static mul(a, b) {
|
|
31
|
+
return new C(
|
|
32
|
+
a.re * b.re - a.im * b.im,
|
|
33
|
+
a.re * b.im + a.im * b.re
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static scale(a, s) {
|
|
38
|
+
return new C(a.re * s, a.im * s);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static conj(a) {
|
|
42
|
+
return new C(a.re, -a.im);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static abs2(a) {
|
|
46
|
+
return a.re * a.re + a.im * a.im;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static exp(theta) {
|
|
50
|
+
return new C(Math.cos(theta), Math.sin(theta));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static zero() {
|
|
54
|
+
return new C(0, 0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
clone() {
|
|
58
|
+
return new C(this.re, this.im);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function clamp01(x) {
|
|
63
|
+
return Math.max(0, Math.min(1, x));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Shannon entropy on probabilities (base e).
|
|
68
|
+
* @param {number[]} probs - Array of probabilities
|
|
69
|
+
* @returns {number} Entropy in nats
|
|
70
|
+
*/
|
|
71
|
+
function shannonEntropyNats(probs) {
|
|
72
|
+
let h = 0;
|
|
73
|
+
for (const p of probs) {
|
|
74
|
+
if (p > 1e-15) h -= p * Math.log(p);
|
|
75
|
+
}
|
|
76
|
+
return h;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Normalize complex vector in-place; returns norm.
|
|
81
|
+
* @param {C[]} vec - Complex vector
|
|
82
|
+
* @returns {number} The norm before normalization
|
|
83
|
+
*/
|
|
84
|
+
function normalize(vec) {
|
|
85
|
+
let s = 0;
|
|
86
|
+
for (const v of vec) s += C.abs2(v);
|
|
87
|
+
const n = Math.sqrt(s) || 1;
|
|
88
|
+
const inv = 1 / n;
|
|
89
|
+
for (let i = 0; i < vec.length; i++) {
|
|
90
|
+
vec[i] = C.scale(vec[i], inv);
|
|
91
|
+
}
|
|
92
|
+
return n;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Computes probabilities |amp|^2 normalized.
|
|
97
|
+
* @param {C[]} vec - Complex vector
|
|
98
|
+
* @returns {number[]} Probability distribution
|
|
99
|
+
*/
|
|
100
|
+
function probsOf(vec) {
|
|
101
|
+
let s = 0;
|
|
102
|
+
const p = new Array(vec.length);
|
|
103
|
+
for (let i = 0; i < vec.length; i++) {
|
|
104
|
+
const a2 = C.abs2(vec[i]);
|
|
105
|
+
p[i] = a2;
|
|
106
|
+
s += a2;
|
|
107
|
+
}
|
|
108
|
+
const inv = 1 / (s || 1);
|
|
109
|
+
for (let i = 0; i < p.length; i++) p[i] *= inv;
|
|
110
|
+
return p;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Compute total norm of complex vector.
|
|
115
|
+
* @param {C[]} vec - Complex vector
|
|
116
|
+
* @returns {number} L2 norm
|
|
117
|
+
*/
|
|
118
|
+
function normOf(vec) {
|
|
119
|
+
let s = 0;
|
|
120
|
+
for (const v of vec) s += C.abs2(v);
|
|
121
|
+
return Math.sqrt(s);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* PrimeonZLadderU - A minimal "canonical U" for a ladder system.
|
|
126
|
+
*
|
|
127
|
+
* - Core ψ is coupled to nearest neighbors via a hopping term
|
|
128
|
+
* - Z channel receives controlled leakage from core each step
|
|
129
|
+
*
|
|
130
|
+
* Designed to be:
|
|
131
|
+
* - Easy to simulate
|
|
132
|
+
* - Easy to measure
|
|
133
|
+
* - Easy to integrate with tinyaleph's existing entropy tooling
|
|
134
|
+
*/
|
|
135
|
+
class PrimeonZLadderU {
|
|
136
|
+
/**
|
|
137
|
+
* @param {object} opts
|
|
138
|
+
* @param {number} opts.N Number of ladder rungs
|
|
139
|
+
* @param {number} [opts.d=1] Core internal dimension per rung
|
|
140
|
+
* @param {number} [opts.dz=1] Z internal dimension per rung
|
|
141
|
+
* @param {number} [opts.J=0.25] Nearest-neighbor coupling strength (core)
|
|
142
|
+
* @param {number} [opts.leak=0.05] Fraction of amplitude leaked core->Z per step (0..1)
|
|
143
|
+
* @param {boolean} [opts.closeZ=true] If true, Z is projected out each step (closure)
|
|
144
|
+
* @param {boolean} [opts.periodic=true] Periodic boundary conditions
|
|
145
|
+
*/
|
|
146
|
+
constructor(opts) {
|
|
147
|
+
this.N = opts.N;
|
|
148
|
+
this.d = opts.d ?? 1;
|
|
149
|
+
this.dz = opts.dz ?? 1;
|
|
150
|
+
this.J = opts.J ?? 0.25;
|
|
151
|
+
this.leak = clamp01(opts.leak ?? 0.05);
|
|
152
|
+
this.closeZ = opts.closeZ ?? true;
|
|
153
|
+
this.periodic = opts.periodic ?? true;
|
|
154
|
+
|
|
155
|
+
// State arrays: ψ and z as [N][d] and [N][dz] flattened
|
|
156
|
+
this.psi = Array.from({ length: this.N * this.d }, () => C.zero());
|
|
157
|
+
this.z = Array.from({ length: this.N * this.dz }, () => C.zero());
|
|
158
|
+
|
|
159
|
+
// Metrics
|
|
160
|
+
this.t = 0;
|
|
161
|
+
this.lastZFlux = 0; // "how much moved into Z this step"
|
|
162
|
+
this.totalZFlux = 0; // accumulated over all steps
|
|
163
|
+
this.stepCount = 0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Reset state to vacuum (all zeros).
|
|
168
|
+
*/
|
|
169
|
+
reset() {
|
|
170
|
+
for (let i = 0; i < this.psi.length; i++) {
|
|
171
|
+
this.psi[i] = C.zero();
|
|
172
|
+
}
|
|
173
|
+
for (let i = 0; i < this.z.length; i++) {
|
|
174
|
+
this.z[i] = C.zero();
|
|
175
|
+
}
|
|
176
|
+
this.t = 0;
|
|
177
|
+
this.lastZFlux = 0;
|
|
178
|
+
this.totalZFlux = 0;
|
|
179
|
+
this.stepCount = 0;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Initialize ψ with a localized excitation at rung n.
|
|
184
|
+
* @param {number} n - Rung index
|
|
185
|
+
* @param {C} [amp] - Complex amplitude (default: 1+0i)
|
|
186
|
+
* @param {number} [k=0] - Internal index within rung
|
|
187
|
+
*/
|
|
188
|
+
exciteRung(n, amp = new C(1, 0), k = 0) {
|
|
189
|
+
const i = ((n % this.N) + this.N) % this.N * this.d + (k % this.d);
|
|
190
|
+
this.psi[i] = amp;
|
|
191
|
+
normalize(this.psi);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Excite multiple rungs uniformly.
|
|
196
|
+
* @param {number[]} rungs - Array of rung indices
|
|
197
|
+
* @param {number} [ampScale=1] - Amplitude scale
|
|
198
|
+
*/
|
|
199
|
+
exciteRungs(rungs, ampScale = 1) {
|
|
200
|
+
for (const n of rungs) {
|
|
201
|
+
const idx = ((n % this.N) + this.N) % this.N;
|
|
202
|
+
const i = idx * this.d;
|
|
203
|
+
this.psi[i] = C.add(this.psi[i], new C(ampScale, 0));
|
|
204
|
+
}
|
|
205
|
+
normalize(this.psi);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Prime-friendly helper: excite multiple rungs from a prime list.
|
|
210
|
+
* Map primes -> rung index via mod N (simple, deterministic).
|
|
211
|
+
* @param {number[]} primes - Array of prime numbers
|
|
212
|
+
* @param {number} [ampScale=1] - Amplitude scale for each excitation
|
|
213
|
+
*/
|
|
214
|
+
excitePrimes(primes, ampScale = 1) {
|
|
215
|
+
for (const p of primes) {
|
|
216
|
+
const idx = ((p % this.N) + this.N) % this.N;
|
|
217
|
+
const i = idx * this.d;
|
|
218
|
+
this.psi[i] = C.add(this.psi[i], new C(ampScale, 0));
|
|
219
|
+
}
|
|
220
|
+
normalize(this.psi);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* One time step using a simple split operator:
|
|
225
|
+
* 1) Core hopping (discrete Schrödinger-like update)
|
|
226
|
+
* 2) Leak core->Z
|
|
227
|
+
* 3) Closure rule (optional)
|
|
228
|
+
*
|
|
229
|
+
* @param {number} [dt=0.01] - Time step size
|
|
230
|
+
* @returns {object} Current metrics
|
|
231
|
+
*/
|
|
232
|
+
step(dt = 0.01) {
|
|
233
|
+
const N = this.N;
|
|
234
|
+
const d = this.d;
|
|
235
|
+
|
|
236
|
+
// --- 1) Core hopping: ψ_i <- ψ_i - i dt J (ψ_{i+1} + ψ_{i-1} - 2ψ_i)
|
|
237
|
+
// Minimal stable discretization (not "perfect unitary", but well-behaved for small dt).
|
|
238
|
+
const next = Array.from({ length: N * d }, () => C.zero());
|
|
239
|
+
|
|
240
|
+
for (let n = 0; n < N; n++) {
|
|
241
|
+
const nL = (n === 0) ? (this.periodic ? N - 1 : 0) : n - 1;
|
|
242
|
+
const nR = (n === N - 1) ? (this.periodic ? 0 : N - 1) : n + 1;
|
|
243
|
+
|
|
244
|
+
for (let k = 0; k < d; k++) {
|
|
245
|
+
const i = n * d + k;
|
|
246
|
+
const iL = nL * d + k;
|
|
247
|
+
const iR = nR * d + k;
|
|
248
|
+
|
|
249
|
+
const psi = this.psi[i];
|
|
250
|
+
const psiL = this.psi[iL];
|
|
251
|
+
const psiR = this.psi[iR];
|
|
252
|
+
|
|
253
|
+
// Discrete Laplacian: (psiL - psi) + (psiR - psi) = psiL + psiR - 2*psi
|
|
254
|
+
const lap = C.add(
|
|
255
|
+
C.sub(psiL, psi),
|
|
256
|
+
C.sub(psiR, psi)
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
// -i * (dt*J) * lap == multiply lap by (0, -dt*J)
|
|
260
|
+
const delta = C.mul(lap, new C(0, -dt * this.J));
|
|
261
|
+
next[i] = C.add(psi, delta);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
this.psi = next;
|
|
266
|
+
|
|
267
|
+
// --- 2) Leak core->Z (explicit Z-sector coupling)
|
|
268
|
+
let zFlux = 0;
|
|
269
|
+
const leak = this.leak;
|
|
270
|
+
|
|
271
|
+
for (let i = 0; i < this.psi.length; i++) {
|
|
272
|
+
const a = this.psi[i];
|
|
273
|
+
const moved = C.scale(a, leak);
|
|
274
|
+
|
|
275
|
+
// Subtract moved from core
|
|
276
|
+
this.psi[i] = C.sub(a, moved);
|
|
277
|
+
|
|
278
|
+
// Add moved into Z (fold core index into Z index)
|
|
279
|
+
const zi = i % (this.N * this.dz);
|
|
280
|
+
this.z[zi] = C.add(this.z[zi], moved);
|
|
281
|
+
|
|
282
|
+
zFlux += C.abs2(moved);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// --- 3) Closure rule
|
|
286
|
+
// If closeZ: project out Z (record flux), renormalize core.
|
|
287
|
+
// If keep Z: Z acts as persistent "closure memory".
|
|
288
|
+
if (this.closeZ) {
|
|
289
|
+
// Optionally wipe Z after recording:
|
|
290
|
+
// for (let i = 0; i < this.z.length; i++) this.z[i] = C.zero();
|
|
291
|
+
normalize(this.psi);
|
|
292
|
+
} else {
|
|
293
|
+
// Normalize combined energy lightly to avoid blowup
|
|
294
|
+
normalize(this.psi);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
this.lastZFlux = zFlux;
|
|
298
|
+
this.totalZFlux += zFlux;
|
|
299
|
+
this.t += dt;
|
|
300
|
+
this.stepCount++;
|
|
301
|
+
|
|
302
|
+
return this.metrics();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Run multiple steps.
|
|
307
|
+
* @param {number} steps - Number of steps to run
|
|
308
|
+
* @param {number} [dt=0.01] - Time step size
|
|
309
|
+
* @returns {object[]} Array of metrics for each step
|
|
310
|
+
*/
|
|
311
|
+
run(steps, dt = 0.01) {
|
|
312
|
+
const trajectory = [];
|
|
313
|
+
for (let i = 0; i < steps; i++) {
|
|
314
|
+
trajectory.push(this.step(dt));
|
|
315
|
+
}
|
|
316
|
+
return trajectory;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Coherence proxy: inverse entropy of |ψ|^2 distribution.
|
|
321
|
+
* Low entropy => localized / coherent; high entropy => spread / incoherent
|
|
322
|
+
* @returns {object} Current metrics
|
|
323
|
+
*/
|
|
324
|
+
metrics() {
|
|
325
|
+
const p = probsOf(this.psi);
|
|
326
|
+
const H = shannonEntropyNats(p);
|
|
327
|
+
|
|
328
|
+
// "Coherence" as 1/(1+H) for a stable 0..1-ish number
|
|
329
|
+
const coherence = 1 / (1 + H);
|
|
330
|
+
|
|
331
|
+
// Z sector metrics
|
|
332
|
+
const pZ = probsOf(this.z);
|
|
333
|
+
const HZ = shannonEntropyNats(pZ);
|
|
334
|
+
const zNorm = normOf(this.z);
|
|
335
|
+
|
|
336
|
+
// Compute order parameter (mean field amplitude)
|
|
337
|
+
let meanRe = 0, meanIm = 0;
|
|
338
|
+
for (const v of this.psi) {
|
|
339
|
+
meanRe += v.re;
|
|
340
|
+
meanIm += v.im;
|
|
341
|
+
}
|
|
342
|
+
const orderParameter = Math.sqrt(meanRe * meanRe + meanIm * meanIm) / this.psi.length;
|
|
343
|
+
|
|
344
|
+
return {
|
|
345
|
+
t: this.t,
|
|
346
|
+
stepCount: this.stepCount,
|
|
347
|
+
coherence,
|
|
348
|
+
entropy: H,
|
|
349
|
+
orderParameter,
|
|
350
|
+
zFlux: this.lastZFlux,
|
|
351
|
+
zFluxTotal: this.totalZFlux,
|
|
352
|
+
zEntropy: HZ,
|
|
353
|
+
zNorm
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Get full state snapshot for serialization/inspection.
|
|
359
|
+
* @returns {object} Complete state snapshot
|
|
360
|
+
*/
|
|
361
|
+
snapshot() {
|
|
362
|
+
return {
|
|
363
|
+
t: this.t,
|
|
364
|
+
stepCount: this.stepCount,
|
|
365
|
+
N: this.N,
|
|
366
|
+
d: this.d,
|
|
367
|
+
dz: this.dz,
|
|
368
|
+
J: this.J,
|
|
369
|
+
leak: this.leak,
|
|
370
|
+
closeZ: this.closeZ,
|
|
371
|
+
periodic: this.periodic,
|
|
372
|
+
psi: this.psi.map(v => ({ re: v.re, im: v.im })),
|
|
373
|
+
z: this.z.map(v => ({ re: v.re, im: v.im })),
|
|
374
|
+
...this.metrics()
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Restore state from a snapshot.
|
|
380
|
+
* @param {object} snap - Snapshot object from snapshot()
|
|
381
|
+
*/
|
|
382
|
+
restore(snap) {
|
|
383
|
+
this.t = snap.t;
|
|
384
|
+
this.stepCount = snap.stepCount;
|
|
385
|
+
this.psi = snap.psi.map(v => new C(v.re, v.im));
|
|
386
|
+
this.z = snap.z.map(v => new C(v.re, v.im));
|
|
387
|
+
this.totalZFlux = snap.zFluxTotal;
|
|
388
|
+
this.lastZFlux = snap.zFlux;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Get probability distribution over rungs.
|
|
393
|
+
* @returns {number[]} Probability for each rung
|
|
394
|
+
*/
|
|
395
|
+
rungProbabilities() {
|
|
396
|
+
const probs = new Array(this.N).fill(0);
|
|
397
|
+
for (let n = 0; n < this.N; n++) {
|
|
398
|
+
for (let k = 0; k < this.d; k++) {
|
|
399
|
+
const i = n * this.d + k;
|
|
400
|
+
probs[n] += C.abs2(this.psi[i]);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
const total = probs.reduce((a, b) => a + b, 0) || 1;
|
|
404
|
+
return probs.map(p => p / total);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Sample a rung index according to |ψ|^2 distribution.
|
|
409
|
+
* @returns {number} Sampled rung index
|
|
410
|
+
*/
|
|
411
|
+
sampleRung() {
|
|
412
|
+
const probs = this.rungProbabilities();
|
|
413
|
+
const r = Math.random();
|
|
414
|
+
let cumulative = 0;
|
|
415
|
+
for (let n = 0; n < this.N; n++) {
|
|
416
|
+
cumulative += probs[n];
|
|
417
|
+
if (r <= cumulative) return n;
|
|
418
|
+
}
|
|
419
|
+
return this.N - 1;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Collapse state to a specific rung (measurement).
|
|
424
|
+
* @param {number} n - Rung index to collapse to
|
|
425
|
+
*/
|
|
426
|
+
collapseToRung(n) {
|
|
427
|
+
const idx = ((n % this.N) + this.N) % this.N;
|
|
428
|
+
|
|
429
|
+
// Zero out all rungs except the collapsed one
|
|
430
|
+
for (let i = 0; i < this.psi.length; i++) {
|
|
431
|
+
const rungIdx = Math.floor(i / this.d);
|
|
432
|
+
if (rungIdx !== idx) {
|
|
433
|
+
this.psi[i] = C.zero();
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
normalize(this.psi);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Perform a measurement: sample and collapse.
|
|
441
|
+
* @returns {object} Measurement result
|
|
442
|
+
*/
|
|
443
|
+
measure() {
|
|
444
|
+
const probsBefore = this.rungProbabilities();
|
|
445
|
+
const sampledRung = this.sampleRung();
|
|
446
|
+
const probability = probsBefore[sampledRung];
|
|
447
|
+
|
|
448
|
+
this.collapseToRung(sampledRung);
|
|
449
|
+
|
|
450
|
+
return {
|
|
451
|
+
outcome: sampledRung,
|
|
452
|
+
probability,
|
|
453
|
+
probsBefore,
|
|
454
|
+
metricsAfter: this.metrics()
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Factory function for creating ladder with prime-based configuration.
|
|
461
|
+
* @param {number[]} primes - Prime numbers to use for initialization
|
|
462
|
+
* @param {object} [opts={}] - Additional options
|
|
463
|
+
* @returns {PrimeonZLadderU} Configured ladder instance
|
|
464
|
+
*/
|
|
465
|
+
function createPrimeonLadder(primes, opts = {}) {
|
|
466
|
+
const N = opts.N ?? Math.max(16, Math.max(...primes) + 1);
|
|
467
|
+
const ladder = new PrimeonZLadderU({
|
|
468
|
+
N,
|
|
469
|
+
d: opts.d ?? 1,
|
|
470
|
+
dz: opts.dz ?? 1,
|
|
471
|
+
J: opts.J ?? 0.25,
|
|
472
|
+
leak: opts.leak ?? 0.05,
|
|
473
|
+
closeZ: opts.closeZ ?? true,
|
|
474
|
+
periodic: opts.periodic ?? true
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
if (primes.length > 0) {
|
|
478
|
+
ladder.excitePrimes(primes, opts.ampScale ?? 1);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return ladder;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
module.exports = {
|
|
485
|
+
PrimeonZLadderU,
|
|
486
|
+
createPrimeonLadder,
|
|
487
|
+
// Export helpers for potential reuse in entropy tooling
|
|
488
|
+
shannonEntropyNats,
|
|
489
|
+
probsOf,
|
|
490
|
+
normalize,
|
|
491
|
+
// Export Complex class for advanced usage
|
|
492
|
+
C
|
|
493
|
+
};
|