@aleph-ai/tinyaleph 1.1.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/README.md +230 -2
- package/core/entanglement.js +712 -0
- package/core/events.js +907 -0
- package/core/hypercomplex.js +500 -0
- package/core/index.js +46 -0
- package/core/rformer-layers.js +811 -0
- package/docs/reference/01-core.md +515 -1
- package/docs/reference/02-physics.md +186 -1
- package/package.json +1 -1
- package/physics/index.js +62 -0
- package/physics/kuramoto-coupled-ladder.js +603 -0
- 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/core/hypercomplex.js
CHANGED
|
@@ -130,12 +130,512 @@ class Hypercomplex {
|
|
|
130
130
|
.slice(0, n);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
// ============================================
|
|
134
|
+
// ADVANCED OPERATIONS: exp, log, pow, slerp
|
|
135
|
+
// ============================================
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Get the scalar (real) part
|
|
139
|
+
*/
|
|
140
|
+
scalar() {
|
|
141
|
+
return this.c[0];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Get the vector (imaginary) part as a new Hypercomplex with zero scalar
|
|
146
|
+
*/
|
|
147
|
+
vector() {
|
|
148
|
+
const v = new Hypercomplex(this.dim);
|
|
149
|
+
for (let i = 1; i < this.dim; i++) {
|
|
150
|
+
v.c[i] = this.c[i];
|
|
151
|
+
}
|
|
152
|
+
return v;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Get the norm of the vector part only
|
|
157
|
+
*/
|
|
158
|
+
vectorNorm() {
|
|
159
|
+
let s = 0;
|
|
160
|
+
for (let i = 1; i < this.dim; i++) {
|
|
161
|
+
s += this.c[i] * this.c[i];
|
|
162
|
+
}
|
|
163
|
+
return Math.sqrt(s);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Hypercomplex exponential: e^q
|
|
168
|
+
*
|
|
169
|
+
* For q = a + v (scalar a, vector v):
|
|
170
|
+
* exp(q) = e^a * (cos|v| + v̂·sin|v|)
|
|
171
|
+
*
|
|
172
|
+
* where v̂ = v/|v| is the unit vector direction.
|
|
173
|
+
*
|
|
174
|
+
* This generalizes:
|
|
175
|
+
* - Complex: e^(a+bi) = e^a(cos b + i·sin b)
|
|
176
|
+
* - Quaternion: e^(a+v) = e^a(cos|v| + v̂·sin|v|)
|
|
177
|
+
*
|
|
178
|
+
* @returns {Hypercomplex} The exponential
|
|
179
|
+
*/
|
|
180
|
+
exp() {
|
|
181
|
+
const a = this.c[0]; // scalar part
|
|
182
|
+
const vNorm = this.vectorNorm();
|
|
183
|
+
|
|
184
|
+
const ea = Math.exp(a);
|
|
185
|
+
const result = new Hypercomplex(this.dim);
|
|
186
|
+
|
|
187
|
+
if (vNorm < 1e-10) {
|
|
188
|
+
// Pure scalar: exp(a) = e^a
|
|
189
|
+
result.c[0] = ea;
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// exp(a + v) = e^a * (cos|v| + v̂·sin|v|)
|
|
194
|
+
const cosV = Math.cos(vNorm);
|
|
195
|
+
const sinV = Math.sin(vNorm);
|
|
196
|
+
|
|
197
|
+
result.c[0] = ea * cosV;
|
|
198
|
+
|
|
199
|
+
// Vector part: e^a * sin|v| * v̂ = e^a * sin|v| * v/|v|
|
|
200
|
+
const scale = ea * sinV / vNorm;
|
|
201
|
+
for (let i = 1; i < this.dim; i++) {
|
|
202
|
+
result.c[i] = scale * this.c[i];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Hypercomplex logarithm: log(q)
|
|
210
|
+
*
|
|
211
|
+
* For q = a + v (scalar a, vector v):
|
|
212
|
+
* log(q) = log|q| + v̂·arccos(a/|q|)
|
|
213
|
+
*
|
|
214
|
+
* where v̂ = v/|v| is the unit vector direction.
|
|
215
|
+
*
|
|
216
|
+
* Note: Like complex log, this has branch cuts. We return the principal value.
|
|
217
|
+
*
|
|
218
|
+
* @returns {Hypercomplex} The natural logarithm
|
|
219
|
+
*/
|
|
220
|
+
log() {
|
|
221
|
+
const qNorm = this.norm();
|
|
222
|
+
const vNorm = this.vectorNorm();
|
|
223
|
+
|
|
224
|
+
const result = new Hypercomplex(this.dim);
|
|
225
|
+
|
|
226
|
+
if (qNorm < 1e-10) {
|
|
227
|
+
// log(0) is undefined, return large negative scalar
|
|
228
|
+
result.c[0] = -Infinity;
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Scalar part: log|q|
|
|
233
|
+
result.c[0] = Math.log(qNorm);
|
|
234
|
+
|
|
235
|
+
if (vNorm < 1e-10) {
|
|
236
|
+
// Pure scalar: log(a) = ln(|a|) + π if a < 0
|
|
237
|
+
if (this.c[0] < 0) {
|
|
238
|
+
// Add π in the "first imaginary" direction as convention
|
|
239
|
+
result.c[1] = Math.PI;
|
|
240
|
+
}
|
|
241
|
+
return result;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Vector part: arccos(a/|q|) * v̂
|
|
245
|
+
const theta = Math.acos(Math.max(-1, Math.min(1, this.c[0] / qNorm)));
|
|
246
|
+
const scale = theta / vNorm;
|
|
247
|
+
|
|
248
|
+
for (let i = 1; i < this.dim; i++) {
|
|
249
|
+
result.c[i] = scale * this.c[i];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Hypercomplex power: q^n
|
|
257
|
+
*
|
|
258
|
+
* Computed as: q^n = exp(n * log(q))
|
|
259
|
+
*
|
|
260
|
+
* Works for integer and fractional exponents.
|
|
261
|
+
*
|
|
262
|
+
* @param {number} n - The exponent
|
|
263
|
+
* @returns {Hypercomplex} q raised to power n
|
|
264
|
+
*/
|
|
265
|
+
pow(n) {
|
|
266
|
+
if (n === 0) {
|
|
267
|
+
return Hypercomplex.basis(this.dim, 0, 1); // Return 1
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (n === 1) {
|
|
271
|
+
return this.clone();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (n === -1) {
|
|
275
|
+
return this.inverse();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// General case: q^n = exp(n * log(q))
|
|
279
|
+
return this.log().scale(n).exp();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Integer power using repeated squaring (more numerically stable)
|
|
284
|
+
* @param {number} n - Integer exponent
|
|
285
|
+
* @returns {Hypercomplex} q raised to integer power n
|
|
286
|
+
*/
|
|
287
|
+
powInt(n) {
|
|
288
|
+
if (!Number.isInteger(n)) {
|
|
289
|
+
return this.pow(n);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (n === 0) {
|
|
293
|
+
return Hypercomplex.basis(this.dim, 0, 1);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (n < 0) {
|
|
297
|
+
return this.inverse().powInt(-n);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Repeated squaring
|
|
301
|
+
let result = Hypercomplex.basis(this.dim, 0, 1);
|
|
302
|
+
let base = this.clone();
|
|
303
|
+
|
|
304
|
+
while (n > 0) {
|
|
305
|
+
if (n & 1) {
|
|
306
|
+
result = result.mul(base);
|
|
307
|
+
}
|
|
308
|
+
base = base.mul(base);
|
|
309
|
+
n >>= 1;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Square root: q^(1/2)
|
|
317
|
+
* @returns {Hypercomplex} Principal square root
|
|
318
|
+
*/
|
|
319
|
+
sqrt() {
|
|
320
|
+
return this.pow(0.5);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Spherical Linear Interpolation (SLERP)
|
|
325
|
+
*
|
|
326
|
+
* Interpolates along the shortest arc on the unit hypersphere.
|
|
327
|
+
* Both this and other should be normalized for proper geometric interpretation.
|
|
328
|
+
*
|
|
329
|
+
* slerp(q1, q2, t) = q1 * (q1^-1 * q2)^t
|
|
330
|
+
*
|
|
331
|
+
* Or equivalently:
|
|
332
|
+
* slerp(q1, q2, t) = (sin((1-t)θ)/sin(θ)) * q1 + (sin(tθ)/sin(θ)) * q2
|
|
333
|
+
*
|
|
334
|
+
* where θ = arccos(q1·q2)
|
|
335
|
+
*
|
|
336
|
+
* @param {Hypercomplex} other - Target hypercomplex
|
|
337
|
+
* @param {number} t - Interpolation parameter [0, 1]
|
|
338
|
+
* @returns {Hypercomplex} Interpolated value
|
|
339
|
+
*/
|
|
340
|
+
slerp(other, t) {
|
|
341
|
+
// Compute dot product
|
|
342
|
+
let dot = this.dot(other);
|
|
343
|
+
|
|
344
|
+
// Handle antipodal case (choose shorter path)
|
|
345
|
+
let q2 = other;
|
|
346
|
+
if (dot < 0) {
|
|
347
|
+
q2 = other.scale(-1);
|
|
348
|
+
dot = -dot;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Clamp dot to valid range for acos
|
|
352
|
+
dot = Math.min(1, Math.max(-1, dot));
|
|
353
|
+
|
|
354
|
+
// If very close, use linear interpolation to avoid division by zero
|
|
355
|
+
if (dot > 0.9995) {
|
|
356
|
+
const result = new Hypercomplex(this.dim);
|
|
357
|
+
for (let i = 0; i < this.dim; i++) {
|
|
358
|
+
result.c[i] = this.c[i] + t * (q2.c[i] - this.c[i]);
|
|
359
|
+
}
|
|
360
|
+
return result.normalize();
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Standard slerp formula
|
|
364
|
+
const theta = Math.acos(dot);
|
|
365
|
+
const sinTheta = Math.sin(theta);
|
|
366
|
+
|
|
367
|
+
const s1 = Math.sin((1 - t) * theta) / sinTheta;
|
|
368
|
+
const s2 = Math.sin(t * theta) / sinTheta;
|
|
369
|
+
|
|
370
|
+
const result = new Hypercomplex(this.dim);
|
|
371
|
+
for (let i = 0; i < this.dim; i++) {
|
|
372
|
+
result.c[i] = s1 * this.c[i] + s2 * q2.c[i];
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return result;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Normalized Linear Interpolation (NLERP)
|
|
380
|
+
*
|
|
381
|
+
* Faster but non-constant velocity interpolation.
|
|
382
|
+
*
|
|
383
|
+
* @param {Hypercomplex} other - Target hypercomplex
|
|
384
|
+
* @param {number} t - Interpolation parameter [0, 1]
|
|
385
|
+
* @returns {Hypercomplex} Interpolated value
|
|
386
|
+
*/
|
|
387
|
+
nlerp(other, t) {
|
|
388
|
+
const result = new Hypercomplex(this.dim);
|
|
389
|
+
for (let i = 0; i < this.dim; i++) {
|
|
390
|
+
result.c[i] = (1 - t) * this.c[i] + t * other.c[i];
|
|
391
|
+
}
|
|
392
|
+
return result.normalize();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Spherical Quadrangle Interpolation (SQUAD)
|
|
397
|
+
*
|
|
398
|
+
* Smooth cubic interpolation through a sequence of rotations.
|
|
399
|
+
* Uses De Casteljau construction with slerp.
|
|
400
|
+
*
|
|
401
|
+
* squad(q1, a, b, q2, t) = slerp(slerp(q1, q2, t), slerp(a, b, t), 2t(1-t))
|
|
402
|
+
*
|
|
403
|
+
* The control points a and b are typically computed as:
|
|
404
|
+
* a = q1 * exp(-(log(q1^-1 * q2) + log(q1^-1 * q0)) / 4)
|
|
405
|
+
* b = q2 * exp(-(log(q2^-1 * q3) + log(q2^-1 * q1)) / 4)
|
|
406
|
+
*
|
|
407
|
+
* @param {Hypercomplex} a - First control point
|
|
408
|
+
* @param {Hypercomplex} b - Second control point
|
|
409
|
+
* @param {Hypercomplex} q2 - End point
|
|
410
|
+
* @param {number} t - Interpolation parameter [0, 1]
|
|
411
|
+
* @returns {Hypercomplex} Interpolated value
|
|
412
|
+
*/
|
|
413
|
+
squad(a, b, q2, t) {
|
|
414
|
+
const slerp1 = this.slerp(q2, t);
|
|
415
|
+
const slerp2 = a.slerp(b, t);
|
|
416
|
+
return slerp1.slerp(slerp2, 2 * t * (1 - t));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Compute SQUAD control point for smooth path through [q0, q1, q2]
|
|
421
|
+
*
|
|
422
|
+
* @param {Hypercomplex} q0 - Previous point
|
|
423
|
+
* @param {Hypercomplex} q2 - Next point
|
|
424
|
+
* @returns {Hypercomplex} Control point for q1
|
|
425
|
+
*/
|
|
426
|
+
squadControlPoint(q0, q2) {
|
|
427
|
+
const q1Inv = this.inverse();
|
|
428
|
+
|
|
429
|
+
const log1 = q1Inv.mul(q2).log();
|
|
430
|
+
const log2 = q1Inv.mul(q0).log();
|
|
431
|
+
|
|
432
|
+
const sum = log1.add(log2).scale(-0.25);
|
|
433
|
+
|
|
434
|
+
return this.mul(sum.exp());
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Sandwich product: q * v * q*
|
|
439
|
+
*
|
|
440
|
+
* This is the fundamental rotation/reflection operation.
|
|
441
|
+
* For unit quaternions, this rotates a vector v by the rotation represented by q.
|
|
442
|
+
*
|
|
443
|
+
* @param {Hypercomplex} v - Vector to transform (can have any scalar part)
|
|
444
|
+
* @returns {Hypercomplex} Transformed vector
|
|
445
|
+
*/
|
|
446
|
+
sandwich(v) {
|
|
447
|
+
return this.mul(v).mul(this.conjugate());
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Apply rotation to a pure vector (zero scalar part)
|
|
452
|
+
*
|
|
453
|
+
* For quaternions, this is the standard way to rotate 3D vectors:
|
|
454
|
+
* v' = q * (0 + v) * q*
|
|
455
|
+
*
|
|
456
|
+
* @param {number[]} vec - Vector as array [x, y, z, ...] (length = dim - 1)
|
|
457
|
+
* @returns {number[]} Rotated vector
|
|
458
|
+
*/
|
|
459
|
+
rotateVector(vec) {
|
|
460
|
+
// Create pure vector hypercomplex (zero scalar)
|
|
461
|
+
const v = new Hypercomplex(this.dim);
|
|
462
|
+
for (let i = 0; i < Math.min(vec.length, this.dim - 1); i++) {
|
|
463
|
+
v.c[i + 1] = vec[i];
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Apply sandwich product
|
|
467
|
+
const rotated = this.sandwich(v);
|
|
468
|
+
|
|
469
|
+
// Extract vector part
|
|
470
|
+
const result = new Array(this.dim - 1);
|
|
471
|
+
for (let i = 0; i < this.dim - 1; i++) {
|
|
472
|
+
result[i] = rotated.c[i + 1];
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return result;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Create a rotation hypercomplex from axis-angle representation
|
|
480
|
+
*
|
|
481
|
+
* For quaternions: q = cos(θ/2) + sin(θ/2) * (axis)
|
|
482
|
+
*
|
|
483
|
+
* @param {number} dim - Dimension
|
|
484
|
+
* @param {number[]} axis - Rotation axis (will be normalized)
|
|
485
|
+
* @param {number} angle - Rotation angle in radians
|
|
486
|
+
* @returns {Hypercomplex} Rotation hypercomplex
|
|
487
|
+
*/
|
|
488
|
+
static fromAxisAngle(dim, axis, angle) {
|
|
489
|
+
const h = new Hypercomplex(dim);
|
|
490
|
+
|
|
491
|
+
// Normalize axis
|
|
492
|
+
let axisNorm = 0;
|
|
493
|
+
for (const a of axis) axisNorm += a * a;
|
|
494
|
+
axisNorm = Math.sqrt(axisNorm);
|
|
495
|
+
|
|
496
|
+
if (axisNorm < 1e-10) {
|
|
497
|
+
h.c[0] = 1;
|
|
498
|
+
return h;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const halfAngle = angle / 2;
|
|
502
|
+
const sinHalf = Math.sin(halfAngle);
|
|
503
|
+
const cosHalf = Math.cos(halfAngle);
|
|
504
|
+
|
|
505
|
+
h.c[0] = cosHalf;
|
|
506
|
+
|
|
507
|
+
// Map axis to imaginary components
|
|
508
|
+
const n = Math.min(axis.length, dim - 1);
|
|
509
|
+
for (let i = 0; i < n; i++) {
|
|
510
|
+
h.c[i + 1] = sinHalf * axis[i] / axisNorm;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
return h;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Extract axis and angle from a unit hypercomplex
|
|
518
|
+
*
|
|
519
|
+
* @returns {object} { axis: number[], angle: number }
|
|
520
|
+
*/
|
|
521
|
+
toAxisAngle() {
|
|
522
|
+
const h = this.normalize();
|
|
523
|
+
|
|
524
|
+
// Clamp scalar part for acos
|
|
525
|
+
const cosHalf = Math.max(-1, Math.min(1, h.c[0]));
|
|
526
|
+
const angle = 2 * Math.acos(cosHalf);
|
|
527
|
+
|
|
528
|
+
const sinHalf = Math.sin(angle / 2);
|
|
529
|
+
|
|
530
|
+
const axis = new Array(this.dim - 1);
|
|
531
|
+
if (Math.abs(sinHalf) < 1e-10) {
|
|
532
|
+
// Near identity rotation, axis is arbitrary
|
|
533
|
+
axis.fill(0);
|
|
534
|
+
axis[0] = 1;
|
|
535
|
+
} else {
|
|
536
|
+
for (let i = 0; i < this.dim - 1; i++) {
|
|
537
|
+
axis[i] = h.c[i + 1] / sinHalf;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
return { axis, angle };
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Create rotation between two vectors
|
|
546
|
+
*
|
|
547
|
+
* @param {number} dim - Dimension
|
|
548
|
+
* @param {number[]} from - Source vector
|
|
549
|
+
* @param {number[]} to - Target vector
|
|
550
|
+
* @returns {Hypercomplex} Rotation hypercomplex
|
|
551
|
+
*/
|
|
552
|
+
static rotationBetween(dim, from, to) {
|
|
553
|
+
// Normalize inputs
|
|
554
|
+
let fromNorm = 0, toNorm = 0;
|
|
555
|
+
for (let i = 0; i < from.length; i++) fromNorm += from[i] * from[i];
|
|
556
|
+
for (let i = 0; i < to.length; i++) toNorm += to[i] * to[i];
|
|
557
|
+
fromNorm = Math.sqrt(fromNorm);
|
|
558
|
+
toNorm = Math.sqrt(toNorm);
|
|
559
|
+
|
|
560
|
+
const fromUnit = from.map(x => x / fromNorm);
|
|
561
|
+
const toUnit = to.map(x => x / toNorm);
|
|
562
|
+
|
|
563
|
+
// Compute cross product for axis (works in 3D, generalize for higher)
|
|
564
|
+
// For now, assume 3D cross product
|
|
565
|
+
if (fromUnit.length >= 3 && toUnit.length >= 3) {
|
|
566
|
+
const axis = [
|
|
567
|
+
fromUnit[1] * toUnit[2] - fromUnit[2] * toUnit[1],
|
|
568
|
+
fromUnit[2] * toUnit[0] - fromUnit[0] * toUnit[2],
|
|
569
|
+
fromUnit[0] * toUnit[1] - fromUnit[1] * toUnit[0]
|
|
570
|
+
];
|
|
571
|
+
|
|
572
|
+
// Compute angle from dot product
|
|
573
|
+
let dot = 0;
|
|
574
|
+
for (let i = 0; i < 3; i++) dot += fromUnit[i] * toUnit[i];
|
|
575
|
+
const angle = Math.acos(Math.max(-1, Math.min(1, dot)));
|
|
576
|
+
|
|
577
|
+
return Hypercomplex.fromAxisAngle(dim, axis, angle);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// Fallback: identity rotation
|
|
581
|
+
return Hypercomplex.basis(dim, 0, 1);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Get the angle of rotation (for unit hypercomplex)
|
|
586
|
+
* @returns {number} Rotation angle in radians
|
|
587
|
+
*/
|
|
588
|
+
angle() {
|
|
589
|
+
const cosHalf = Math.max(-1, Math.min(1, this.c[0] / this.norm()));
|
|
590
|
+
return 2 * Math.acos(cosHalf);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Check if this is a unit hypercomplex (norm ≈ 1)
|
|
595
|
+
* @param {number} tolerance - Tolerance for comparison
|
|
596
|
+
*/
|
|
597
|
+
isUnit(tolerance = 1e-6) {
|
|
598
|
+
return Math.abs(this.norm() - 1) < tolerance;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Linear interpolation (component-wise, not normalized)
|
|
603
|
+
* @param {Hypercomplex} other - Target
|
|
604
|
+
* @param {number} t - Interpolation parameter
|
|
605
|
+
*/
|
|
606
|
+
lerp(other, t) {
|
|
607
|
+
const result = new Hypercomplex(this.dim);
|
|
608
|
+
for (let i = 0; i < this.dim; i++) {
|
|
609
|
+
result.c[i] = (1 - t) * this.c[i] + t * other.c[i];
|
|
610
|
+
}
|
|
611
|
+
return result;
|
|
612
|
+
}
|
|
613
|
+
|
|
133
614
|
// Serialization
|
|
134
615
|
toArray() { return [...this.c]; }
|
|
135
616
|
|
|
136
617
|
clone() {
|
|
137
618
|
return new Hypercomplex(this.dim, Float64Array.from(this.c));
|
|
138
619
|
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* String representation
|
|
623
|
+
*/
|
|
624
|
+
toString() {
|
|
625
|
+
const parts = [];
|
|
626
|
+
const labels = ['', 'i', 'j', 'k', 'e4', 'e5', 'e6', 'e7',
|
|
627
|
+
'e8', 'e9', 'e10', 'e11', 'e12', 'e13', 'e14', 'e15'];
|
|
628
|
+
|
|
629
|
+
for (let i = 0; i < this.dim; i++) {
|
|
630
|
+
if (Math.abs(this.c[i]) > 1e-10) {
|
|
631
|
+
const label = labels[i] || `e${i}`;
|
|
632
|
+
const sign = this.c[i] >= 0 && parts.length > 0 ? '+' : '';
|
|
633
|
+
parts.push(`${sign}${this.c[i].toFixed(4)}${label}`);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
return parts.length > 0 ? parts.join('') : '0';
|
|
638
|
+
}
|
|
139
639
|
}
|
|
140
640
|
|
|
141
641
|
module.exports = { Hypercomplex };
|
package/core/index.js
CHANGED
|
@@ -84,6 +84,32 @@ const {
|
|
|
84
84
|
applyResonanceOperator
|
|
85
85
|
} = require('./rformer');
|
|
86
86
|
|
|
87
|
+
// ResoFormer complete layers
|
|
88
|
+
const {
|
|
89
|
+
ResonantMultiHeadAttention,
|
|
90
|
+
PrimeFFN,
|
|
91
|
+
PrimeLayerNorm,
|
|
92
|
+
PositionalPrimeEncoding,
|
|
93
|
+
ResoFormerBlock,
|
|
94
|
+
ResoFormer
|
|
95
|
+
} = require('./rformer-layers');
|
|
96
|
+
|
|
97
|
+
// Prime Entanglement Graph
|
|
98
|
+
const {
|
|
99
|
+
EntanglementEdge,
|
|
100
|
+
PrimeEntanglementGraph,
|
|
101
|
+
createEntanglementGraph
|
|
102
|
+
} = require('./entanglement');
|
|
103
|
+
|
|
104
|
+
// Event system and streaming
|
|
105
|
+
const {
|
|
106
|
+
AlephEventEmitter,
|
|
107
|
+
AlephMonitor,
|
|
108
|
+
EvolutionStream,
|
|
109
|
+
createEvolutionStream,
|
|
110
|
+
createMonitor
|
|
111
|
+
} = require('./events');
|
|
112
|
+
|
|
87
113
|
// TensorFlow.js layers (lazy load - may not be available)
|
|
88
114
|
let rformerTF = null;
|
|
89
115
|
try {
|
|
@@ -155,6 +181,26 @@ module.exports = {
|
|
|
155
181
|
PRGraphMemory,
|
|
156
182
|
applyResonanceOperator,
|
|
157
183
|
|
|
184
|
+
// ResoFormer Complete Layers
|
|
185
|
+
ResonantMultiHeadAttention,
|
|
186
|
+
PrimeFFN,
|
|
187
|
+
PrimeLayerNorm,
|
|
188
|
+
PositionalPrimeEncoding,
|
|
189
|
+
ResoFormerBlock,
|
|
190
|
+
ResoFormer,
|
|
191
|
+
|
|
192
|
+
// Prime Entanglement Graph
|
|
193
|
+
EntanglementEdge,
|
|
194
|
+
PrimeEntanglementGraph,
|
|
195
|
+
createEntanglementGraph,
|
|
196
|
+
|
|
197
|
+
// Event System and Streaming
|
|
198
|
+
AlephEventEmitter,
|
|
199
|
+
AlephMonitor,
|
|
200
|
+
EvolutionStream,
|
|
201
|
+
createEvolutionStream,
|
|
202
|
+
createMonitor,
|
|
203
|
+
|
|
158
204
|
// TensorFlow.js ResoFormer layers (if available)
|
|
159
205
|
...(rformerTF || {}),
|
|
160
206
|
|