@aleph-ai/tinyaleph 1.2.0 → 1.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aleph-ai/tinyaleph",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Prime-resonant semantic computing framework - hypercomplex algebra, oscillator dynamics, and entropy-minimizing reasoning",
5
5
  "main": "index.js",
6
6
  "types": "types/index.d.ts",
package/physics/index.js CHANGED
@@ -68,6 +68,15 @@ const {
68
68
  createAdiabaticSchedule
69
69
  } = require('./primeon_z_ladder_multi');
70
70
 
71
+ // Kuramoto-coupled ladder (hybrid quantum + oscillator dynamics)
72
+ const {
73
+ KuramotoCoupledLadder,
74
+ createKuramotoLadder,
75
+ runCollapsePressureExperiment,
76
+ kuramotoOrderParameter,
77
+ getPhase
78
+ } = require('./kuramoto-coupled-ladder');
79
+
71
80
  module.exports = {
72
81
  // Oscillators
73
82
  Oscillator,
@@ -103,6 +112,13 @@ module.exports = {
103
112
  createMultiChannelLadder,
104
113
  createAdiabaticSchedule,
105
114
 
115
+ // Kuramoto-coupled ladder (hybrid model)
116
+ KuramotoCoupledLadder,
117
+ createKuramotoLadder,
118
+ runCollapsePressureExperiment,
119
+ kuramotoOrderParameter,
120
+ getPhase,
121
+
106
122
  // Entropy & Information
107
123
  shannonEntropy,
108
124
  stateEntropy,
@@ -0,0 +1,603 @@
1
+ /**
2
+ * Kuramoto-Coupled Primeon Z-Ladder
3
+ *
4
+ * Hybrid model combining:
5
+ * - Quantum ladder hopping dynamics
6
+ * - Kuramoto oscillator synchronization on rung phases
7
+ * - Z-flux interpreted as "collapse pressure"
8
+ *
9
+ * Physics interpretation:
10
+ * - Each rung ψ_n = |ψ_n| e^(iθ_n) has phase θ_n acting as oscillator
11
+ * - Kuramoto coupling promotes phase coherence between rungs
12
+ * - Z-flux accumulation represents decoherence/collapse pressure
13
+ * - When collapse pressure exceeds threshold, measurement triggers
14
+ *
15
+ * Key concepts:
16
+ * - Order parameter r = |⟨e^(iθ)⟩| measures global synchronization
17
+ * - High sync (r→1) = quantum coherence preserved
18
+ * - Low sync (r→0) = decoherence, collapse pressure builds
19
+ * - Collapse events reduce uncertainty but reset sync
20
+ */
21
+
22
+ 'use strict';
23
+
24
+ const {
25
+ PrimeonZLadderMulti,
26
+ ZChannel,
27
+ createMultiChannelLadder,
28
+ createAdiabaticSchedule
29
+ } = require('./primeon_z_ladder_multi');
30
+
31
+ const {
32
+ C,
33
+ shannonEntropyNats,
34
+ probsOf,
35
+ normalize
36
+ } = require('./primeon_z_ladder_u');
37
+
38
+ /**
39
+ * Extract phase from complex number
40
+ * @param {C} z - Complex number
41
+ * @returns {number} Phase in radians
42
+ */
43
+ function getPhase(z) {
44
+ return Math.atan2(z.im, z.re);
45
+ }
46
+
47
+ /**
48
+ * Compute Kuramoto order parameter from phases
49
+ * @param {number[]} phases - Array of phases
50
+ * @returns {{r: number, psi: number}} Order parameter magnitude and mean phase
51
+ */
52
+ function kuramotoOrderParameter(phases) {
53
+ if (phases.length === 0) return { r: 0, psi: 0 };
54
+
55
+ let sumCos = 0, sumSin = 0;
56
+ for (const theta of phases) {
57
+ sumCos += Math.cos(theta);
58
+ sumSin += Math.sin(theta);
59
+ }
60
+
61
+ const r = Math.sqrt(sumCos * sumCos + sumSin * sumSin) / phases.length;
62
+ const psi = Math.atan2(sumSin, sumCos);
63
+
64
+ return { r, psi };
65
+ }
66
+
67
+ /**
68
+ * KuramotoCoupledLadder - Hybrid quantum ladder with Kuramoto synchronization
69
+ *
70
+ * @extends PrimeonZLadderMulti
71
+ */
72
+ class KuramotoCoupledLadder extends PrimeonZLadderMulti {
73
+ /**
74
+ * @param {object} opts
75
+ * @param {number} opts.N - Number of rungs
76
+ * @param {number} [opts.J=0.25] - Quantum hopping strength
77
+ * @param {number} [opts.K=0.1] - Kuramoto coupling strength
78
+ * @param {number[]} [opts.frequencies=null] - Natural frequencies per rung
79
+ * @param {number} [opts.collapseThreshold=1.0] - Collapse pressure threshold
80
+ * @param {number} [opts.collapseDecay=0.1] - Pressure decay rate
81
+ * @param {boolean} [opts.autoCollapse=false] - Auto-trigger collapse
82
+ * @param {object[]} [opts.zChannels] - Z channel configurations
83
+ */
84
+ constructor(opts) {
85
+ super(opts);
86
+
87
+ // Kuramoto parameters
88
+ this.K = opts.K ?? 0.1;
89
+
90
+ // Natural frequencies (default: prime-based)
91
+ if (opts.frequencies) {
92
+ this.frequencies = opts.frequencies.slice(0, this.N);
93
+ while (this.frequencies.length < this.N) {
94
+ this.frequencies.push(1.0);
95
+ }
96
+ } else {
97
+ // Prime-based frequencies
98
+ this.frequencies = this._generatePrimeFrequencies();
99
+ }
100
+
101
+ // Collapse pressure dynamics
102
+ this.collapsePressure = 0;
103
+ this.collapseThreshold = opts.collapseThreshold ?? 1.0;
104
+ this.collapseDecay = opts.collapseDecay ?? 0.1;
105
+ this.autoCollapse = opts.autoCollapse ?? false;
106
+
107
+ // Tracking
108
+ this.collapseEvents = [];
109
+ this.orderParameterHistory = [];
110
+ this.maxHistoryLength = opts.maxHistory ?? 1000;
111
+ }
112
+
113
+ /**
114
+ * Generate prime-based natural frequencies
115
+ * @private
116
+ */
117
+ _generatePrimeFrequencies() {
118
+ const primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47];
119
+ const frequencies = [];
120
+
121
+ for (let n = 0; n < this.N; n++) {
122
+ // Use log of prime for smoother distribution
123
+ const primeIdx = n % primes.length;
124
+ frequencies.push(Math.log(primes[primeIdx]) / Math.log(2));
125
+ }
126
+
127
+ return frequencies;
128
+ }
129
+
130
+ /**
131
+ * Get phases of all rungs
132
+ */
133
+ getRungPhases() {
134
+ const phases = [];
135
+
136
+ for (let n = 0; n < this.N; n++) {
137
+ // Use dominant component within rung
138
+ let maxAmp = 0;
139
+ let phase = 0;
140
+
141
+ for (let k = 0; k < this.d; k++) {
142
+ const i = n * this.d + k;
143
+ const amp = C.abs2(this.psi[i]);
144
+ if (amp > maxAmp) {
145
+ maxAmp = amp;
146
+ phase = getPhase(this.psi[i]);
147
+ }
148
+ }
149
+
150
+ phases.push(phase);
151
+ }
152
+
153
+ return phases;
154
+ }
155
+
156
+ /**
157
+ * Get amplitudes of all rungs
158
+ */
159
+ getRungAmplitudes() {
160
+ const amplitudes = [];
161
+
162
+ for (let n = 0; n < this.N; n++) {
163
+ let amp2 = 0;
164
+ for (let k = 0; k < this.d; k++) {
165
+ const i = n * this.d + k;
166
+ amp2 += C.abs2(this.psi[i]);
167
+ }
168
+ amplitudes.push(Math.sqrt(amp2));
169
+ }
170
+
171
+ return amplitudes;
172
+ }
173
+
174
+ /**
175
+ * Compute current order parameter
176
+ */
177
+ orderParameter() {
178
+ const phases = this.getRungPhases();
179
+ const amplitudes = this.getRungAmplitudes();
180
+
181
+ // Weight by amplitude (weighted order parameter)
182
+ let sumCos = 0, sumSin = 0, totalWeight = 0;
183
+
184
+ for (let n = 0; n < this.N; n++) {
185
+ const weight = amplitudes[n];
186
+ sumCos += weight * Math.cos(phases[n]);
187
+ sumSin += weight * Math.sin(phases[n]);
188
+ totalWeight += weight;
189
+ }
190
+
191
+ if (totalWeight === 0) return { r: 0, psi: 0, weighted: true };
192
+
193
+ const r = Math.sqrt(sumCos * sumCos + sumSin * sumSin) / totalWeight;
194
+ const psi = Math.atan2(sumSin, sumCos);
195
+
196
+ return { r, psi, weighted: true };
197
+ }
198
+
199
+ /**
200
+ * One time step with Kuramoto phase coupling
201
+ * @param {number} [dt=0.01] - Time step size
202
+ */
203
+ step(dt = 0.01) {
204
+ // --- 1) Kuramoto phase dynamics ---
205
+ this._applyKuramotoCoupling(dt);
206
+
207
+ // --- 2) Standard ladder dynamics (hopping + Z-flux) ---
208
+ const parentMetrics = super.step(dt);
209
+
210
+ // --- 3) Update collapse pressure from Z-flux ---
211
+ this._updateCollapsePressure(dt);
212
+
213
+ // --- 4) Check for auto-collapse ---
214
+ if (this.autoCollapse && this.collapsePressure >= this.collapseThreshold) {
215
+ this._triggerCollapse();
216
+ }
217
+
218
+ // --- 5) Track order parameter ---
219
+ const orderParam = this.orderParameter();
220
+ this.orderParameterHistory.push({
221
+ t: this.t,
222
+ r: orderParam.r,
223
+ psi: orderParam.psi
224
+ });
225
+
226
+ if (this.orderParameterHistory.length > this.maxHistoryLength) {
227
+ this.orderParameterHistory.shift();
228
+ }
229
+
230
+ return this.metrics();
231
+ }
232
+
233
+ /**
234
+ * Apply Kuramoto phase coupling to ladder
235
+ * @private
236
+ */
237
+ _applyKuramotoCoupling(dt) {
238
+ const N = this.N;
239
+ const phases = this.getRungPhases();
240
+ const amplitudes = this.getRungAmplitudes();
241
+
242
+ // Compute phase increments
243
+ const deltaPhase = new Array(N).fill(0);
244
+
245
+ for (let n = 0; n < N; n++) {
246
+ // Natural frequency evolution
247
+ deltaPhase[n] += this.frequencies[n] * dt;
248
+
249
+ // Kuramoto coupling
250
+ let coupling = 0;
251
+ for (let m = 0; m < N; m++) {
252
+ if (m !== n) {
253
+ // Weight coupling by amplitude product
254
+ const weight = amplitudes[n] * amplitudes[m];
255
+ coupling += weight * Math.sin(phases[m] - phases[n]);
256
+ }
257
+ }
258
+
259
+ deltaPhase[n] += (this.K / N) * coupling * dt;
260
+ }
261
+
262
+ // Apply phase increments
263
+ for (let n = 0; n < N; n++) {
264
+ for (let k = 0; k < this.d; k++) {
265
+ const i = n * this.d + k;
266
+ const amp = Math.sqrt(C.abs2(this.psi[i]));
267
+ const currentPhase = getPhase(this.psi[i]);
268
+ const newPhase = currentPhase + deltaPhase[n];
269
+
270
+ // Update with new phase, preserving amplitude
271
+ this.psi[i] = new C(
272
+ amp * Math.cos(newPhase),
273
+ amp * Math.sin(newPhase)
274
+ );
275
+ }
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Update collapse pressure from Z-flux
281
+ * @private
282
+ */
283
+ _updateCollapsePressure(dt) {
284
+ // Sum recent Z-flux from all channels
285
+ let totalFlux = 0;
286
+ for (const channel of this.channels.values()) {
287
+ totalFlux += channel.lastFlux;
288
+ }
289
+
290
+ // Flux increases pressure, with decay
291
+ this.collapsePressure += totalFlux;
292
+ this.collapsePressure *= (1 - this.collapseDecay * dt);
293
+
294
+ // Clamp to non-negative
295
+ this.collapsePressure = Math.max(0, this.collapsePressure);
296
+ }
297
+
298
+ /**
299
+ * Trigger a collapse event
300
+ * @private
301
+ */
302
+ _triggerCollapse() {
303
+ const preBefore = this.rungProbabilities();
304
+ const orderBefore = this.orderParameter();
305
+
306
+ // Perform measurement
307
+ const result = this.measure();
308
+
309
+ // Record event
310
+ this.collapseEvents.push({
311
+ t: this.t,
312
+ step: this.stepCount,
313
+ pressure: this.collapsePressure,
314
+ orderBefore: orderBefore.r,
315
+ outcome: result.outcome,
316
+ probability: result.probability
317
+ });
318
+
319
+ // Reset collapse pressure after collapse
320
+ this.collapsePressure = 0;
321
+
322
+ return result;
323
+ }
324
+
325
+ /**
326
+ * Manually trigger collapse
327
+ */
328
+ triggerCollapse() {
329
+ return this._triggerCollapse();
330
+ }
331
+
332
+ /**
333
+ * Get synchronization metrics
334
+ */
335
+ syncMetrics() {
336
+ const orderParam = this.orderParameter();
337
+ const phases = this.getRungPhases();
338
+ const amplitudes = this.getRungAmplitudes();
339
+
340
+ // Compute phase variance
341
+ let phaseVariance = 0;
342
+ const meanPhase = orderParam.psi;
343
+
344
+ for (let n = 0; n < this.N; n++) {
345
+ let diff = phases[n] - meanPhase;
346
+ // Wrap to [-π, π]
347
+ while (diff > Math.PI) diff -= 2 * Math.PI;
348
+ while (diff < -Math.PI) diff += 2 * Math.PI;
349
+ phaseVariance += diff * diff * amplitudes[n];
350
+ }
351
+
352
+ const totalAmp = amplitudes.reduce((a, b) => a + b, 0);
353
+ phaseVariance = totalAmp > 0 ? phaseVariance / totalAmp : 0;
354
+
355
+ // Estimate critical coupling
356
+ const freqSpread = Math.max(...this.frequencies) - Math.min(...this.frequencies);
357
+ const criticalK = freqSpread * 2 / Math.PI;
358
+
359
+ return {
360
+ orderParameter: orderParam.r,
361
+ meanPhase: orderParam.psi,
362
+ phaseVariance,
363
+ phaseStdDev: Math.sqrt(phaseVariance),
364
+ synchronization: orderParam.r,
365
+ criticalCoupling: criticalK,
366
+ supercritical: this.K > criticalK,
367
+ collapsePressure: this.collapsePressure,
368
+ pressureRatio: this.collapsePressure / this.collapseThreshold
369
+ };
370
+ }
371
+
372
+ /**
373
+ * Get collapse pressure dynamics
374
+ */
375
+ collapseDynamics() {
376
+ return {
377
+ pressure: this.collapsePressure,
378
+ threshold: this.collapseThreshold,
379
+ ratio: this.collapsePressure / this.collapseThreshold,
380
+ willCollapse: this.collapsePressure >= this.collapseThreshold,
381
+ events: this.collapseEvents.slice(-10),
382
+ totalCollapses: this.collapseEvents.length
383
+ };
384
+ }
385
+
386
+ /**
387
+ * Combined metrics
388
+ */
389
+ metrics() {
390
+ const base = super.metrics();
391
+ const sync = this.syncMetrics();
392
+
393
+ return {
394
+ ...base,
395
+ kuramoto: {
396
+ K: this.K,
397
+ frequencies: this.frequencies,
398
+ ...sync
399
+ }
400
+ };
401
+ }
402
+
403
+ /**
404
+ * Reset state and history
405
+ */
406
+ reset() {
407
+ super.reset();
408
+ this.collapsePressure = 0;
409
+ this.collapseEvents = [];
410
+ this.orderParameterHistory = [];
411
+ }
412
+
413
+ /**
414
+ * Run with sync tracking
415
+ * @param {number} steps - Number of steps
416
+ * @param {number} [dt=0.01] - Time step
417
+ * @returns {object} Trajectory and sync data
418
+ */
419
+ runWithSync(steps, dt = 0.01) {
420
+ const trajectory = [];
421
+ const syncHistory = [];
422
+
423
+ for (let i = 0; i < steps; i++) {
424
+ this.step(dt);
425
+ trajectory.push(this.metrics());
426
+ syncHistory.push({
427
+ t: this.t,
428
+ ...this.syncMetrics()
429
+ });
430
+ }
431
+
432
+ return {
433
+ trajectory,
434
+ syncHistory,
435
+ collapseEvents: this.collapseEvents.slice()
436
+ };
437
+ }
438
+
439
+ /**
440
+ * Detect synchronization transition
441
+ * @param {number} windowSize - Window for averaging
442
+ */
443
+ detectSyncTransition(windowSize = 50) {
444
+ if (this.orderParameterHistory.length < windowSize * 2) {
445
+ return { detected: false, reason: 'insufficient_data' };
446
+ }
447
+
448
+ const history = this.orderParameterHistory;
449
+ const n = history.length;
450
+
451
+ // Compare early and late windows
452
+ const earlyWindow = history.slice(n - windowSize * 2, n - windowSize);
453
+ const lateWindow = history.slice(n - windowSize);
454
+
455
+ const earlyMean = earlyWindow.reduce((s, h) => s + h.r, 0) / windowSize;
456
+ const lateMean = lateWindow.reduce((s, h) => s + h.r, 0) / windowSize;
457
+
458
+ const change = lateMean - earlyMean;
459
+ const threshold = 0.2;
460
+
461
+ if (Math.abs(change) > threshold) {
462
+ return {
463
+ detected: true,
464
+ direction: change > 0 ? 'synchronizing' : 'desynchronizing',
465
+ earlyR: earlyMean,
466
+ lateR: lateMean,
467
+ change
468
+ };
469
+ }
470
+
471
+ return {
472
+ detected: false,
473
+ earlyR: earlyMean,
474
+ lateR: lateMean,
475
+ change
476
+ };
477
+ }
478
+
479
+ /**
480
+ * Get full snapshot including Kuramoto state
481
+ */
482
+ snapshot() {
483
+ const base = super.snapshot();
484
+
485
+ return {
486
+ ...base,
487
+ K: this.K,
488
+ frequencies: this.frequencies.slice(),
489
+ collapsePressure: this.collapsePressure,
490
+ collapseThreshold: this.collapseThreshold,
491
+ collapseEvents: this.collapseEvents.slice(),
492
+ orderParameterHistory: this.orderParameterHistory.slice(-100)
493
+ };
494
+ }
495
+
496
+ /**
497
+ * Restore from snapshot
498
+ */
499
+ restore(snap) {
500
+ super.restore(snap);
501
+
502
+ this.K = snap.K;
503
+ this.frequencies = snap.frequencies.slice();
504
+ this.collapsePressure = snap.collapsePressure;
505
+ this.collapseEvents = snap.collapseEvents?.slice() || [];
506
+ this.orderParameterHistory = snap.orderParameterHistory?.slice() || [];
507
+ }
508
+ }
509
+
510
+ /**
511
+ * Create a Kuramoto-coupled ladder with prime resonances
512
+ * @param {number[]} primes - Primes for rung excitation
513
+ * @param {object} [opts={}] - Options
514
+ */
515
+ function createKuramotoLadder(primes, opts = {}) {
516
+ const N = opts.N ?? Math.max(16, Math.max(...primes) + 1);
517
+
518
+ const ladder = new KuramotoCoupledLadder({
519
+ N,
520
+ d: opts.d ?? 1,
521
+ J: opts.J ?? 0.25,
522
+ K: opts.K ?? 0.1,
523
+ frequencies: opts.frequencies,
524
+ collapseThreshold: opts.collapseThreshold ?? 1.0,
525
+ collapseDecay: opts.collapseDecay ?? 0.1,
526
+ autoCollapse: opts.autoCollapse ?? false,
527
+ periodic: opts.periodic ?? true,
528
+ zChannels: opts.zChannels,
529
+ Jt: opts.Jt
530
+ });
531
+
532
+ if (primes.length > 0) {
533
+ ladder.excitePrimes(primes, opts.ampScale ?? 1);
534
+ }
535
+
536
+ return ladder;
537
+ }
538
+
539
+ /**
540
+ * Run a collapse pressure experiment
541
+ * Track how Z-flux builds collapse pressure until threshold
542
+ *
543
+ * @param {object} opts - Experiment options
544
+ * @returns {object} Experiment results
545
+ */
546
+ function runCollapsePressureExperiment(opts = {}) {
547
+ const {
548
+ N = 16,
549
+ primes = [2, 3, 5, 7],
550
+ J = 0.25,
551
+ K = 0.1,
552
+ collapseThreshold = 0.5,
553
+ maxSteps = 1000,
554
+ dt = 0.01
555
+ } = opts;
556
+
557
+ const ladder = createKuramotoLadder(primes, {
558
+ N, J, K,
559
+ collapseThreshold,
560
+ autoCollapse: true,
561
+ collapseDecay: 0.05
562
+ });
563
+
564
+ const results = {
565
+ trajectory: [],
566
+ collapses: [],
567
+ finalState: null
568
+ };
569
+
570
+ for (let step = 0; step < maxSteps; step++) {
571
+ ladder.step(dt);
572
+
573
+ if (step % 10 === 0) {
574
+ results.trajectory.push({
575
+ step,
576
+ t: ladder.t,
577
+ orderParameter: ladder.orderParameter().r,
578
+ collapsePressure: ladder.collapsePressure,
579
+ entropy: ladder.coreMetrics().entropy
580
+ });
581
+ }
582
+
583
+ // Check for new collapses
584
+ if (ladder.collapseEvents.length > results.collapses.length) {
585
+ results.collapses.push(
586
+ ladder.collapseEvents[ladder.collapseEvents.length - 1]
587
+ );
588
+ }
589
+ }
590
+
591
+ results.finalState = ladder.metrics();
592
+ results.syncTransition = ladder.detectSyncTransition();
593
+
594
+ return results;
595
+ }
596
+
597
+ module.exports = {
598
+ KuramotoCoupledLadder,
599
+ createKuramotoLadder,
600
+ runCollapsePressureExperiment,
601
+ kuramotoOrderParameter,
602
+ getPhase
603
+ };