@aleph-ai/tinyaleph 1.6.0 → 1.6.2

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.
@@ -0,0 +1,565 @@
1
+ /**
2
+ * Emotion Module - book.pdf Chapter 9
3
+ *
4
+ * Implements Entropy Spectrometry & Emotional Mapping from:
5
+ * "Resonant Foundations of Reality" by Sebastian Schepis
6
+ *
7
+ * Key formalisms:
8
+ * - Feeling Operator: F̂ = Σ_k w_k R_k where w_k ∈ ℝ⁺
9
+ * - Emotional resonance: ⟨ψ|F̂|ψ⟩ = emotional alignment score
10
+ * - Consciousness Primacy: P = 0.4F + 0.3R + 0.2C + 0.1Γ
11
+ * - Emotional state templates with characteristic signatures
12
+ */
13
+
14
+ import { PrimeState, Complex, encodeMemory, PHI } from './hilbert.js';
15
+ import { firstNPrimes } from './prime.js';
16
+
17
+ // ============================================================================
18
+ // EMOTIONAL STATE TEMPLATES (Chapter 9)
19
+ // ============================================================================
20
+
21
+ /**
22
+ * Emotional Template - Archetypal resonance patterns for emotions
23
+ *
24
+ * From book.pdf Chapter 9:
25
+ * Each emotion has characteristic:
26
+ * - Coherence level (phase alignment)
27
+ * - Entropy profile (spread)
28
+ * - Amplitude distribution (localization)
29
+ * - Phase gradient (directional flow)
30
+ */
31
+ const EMOTIONAL_TEMPLATES = {
32
+ love: {
33
+ name: 'Love',
34
+ description: 'High coherence, low entropy, expansive amplitude',
35
+ coherence: 0.9, // High phase alignment
36
+ entropy: 0.2, // Low entropy - ordered
37
+ localization: 0.3, // Distributed across many primes
38
+ phaseGradient: 0.1, // Smooth, gradual phase transitions
39
+ primes: [2, 3, 5], // Fundamental harmonics
40
+ basePhase: 0, // Phase centered at 0
41
+ amplitude: 1.0
42
+ },
43
+
44
+ fear: {
45
+ name: 'Fear',
46
+ description: 'Sharp phase gradient, localized collapse, high entropy',
47
+ coherence: 0.3, // Low phase alignment
48
+ entropy: 0.8, // High entropy - disordered
49
+ localization: 0.9, // Highly localized (collapsed)
50
+ phaseGradient: 0.9, // Sharp, erratic phase changes
51
+ primes: [7, 11, 13], // Higher frequency dissonance
52
+ basePhase: Math.PI, // Inverted phase
53
+ amplitude: 1.5 // Heightened intensity
54
+ },
55
+
56
+ joy: {
57
+ name: 'Joy',
58
+ description: 'High amplitude coherence, resonant harmonics, moderate entropy',
59
+ coherence: 0.85,
60
+ entropy: 0.35,
61
+ localization: 0.4,
62
+ phaseGradient: 0.2,
63
+ primes: [2, 5, 13], // Pleasant harmonic ratios
64
+ basePhase: Math.PI / 4, // Positive phase offset
65
+ amplitude: 1.2
66
+ },
67
+
68
+ grief: {
69
+ name: 'Grief',
70
+ description: 'Disrupted phase structure, entropy release, amplitude decay',
71
+ coherence: 0.25,
72
+ entropy: 0.75,
73
+ localization: 0.6,
74
+ phaseGradient: 0.7,
75
+ primes: [17, 19, 23], // Minor-key primes
76
+ basePhase: -Math.PI / 2,
77
+ amplitude: 0.6 // Diminished intensity
78
+ },
79
+
80
+ awe: {
81
+ name: 'Awe',
82
+ description: 'Golden ratio resonance, maximal coherence spike, transcendent',
83
+ coherence: 0.95,
84
+ entropy: 0.15,
85
+ localization: 0.5,
86
+ phaseGradient: 0.05,
87
+ primes: [5, 13, 89], // Fibonacci primes
88
+ basePhase: 2 * Math.PI / PHI,
89
+ amplitude: 1.618 // Golden ratio amplitude
90
+ },
91
+
92
+ anger: {
93
+ name: 'Anger',
94
+ description: 'High intensity, phase opposition, destructive interference',
95
+ coherence: 0.4,
96
+ entropy: 0.65,
97
+ localization: 0.7,
98
+ phaseGradient: 0.8,
99
+ primes: [3, 7, 11], // Tritone-like dissonance
100
+ basePhase: Math.PI,
101
+ amplitude: 1.8 // High intensity
102
+ },
103
+
104
+ peace: {
105
+ name: 'Peace',
106
+ description: 'Perfect equilibrium, minimal phase gradient, stable resonance',
107
+ coherence: 0.8,
108
+ entropy: 0.25,
109
+ localization: 0.2,
110
+ phaseGradient: 0.0,
111
+ primes: [2, 3, 5, 7], // Perfect harmony
112
+ basePhase: 0,
113
+ amplitude: 0.9
114
+ },
115
+
116
+ curiosity: {
117
+ name: 'Curiosity',
118
+ description: 'Exploratory phase wandering, moderate entropy, seeking',
119
+ coherence: 0.5,
120
+ entropy: 0.55,
121
+ localization: 0.4,
122
+ phaseGradient: 0.5,
123
+ primes: [11, 13, 17, 19],
124
+ basePhase: Math.PI / 6,
125
+ amplitude: 1.0
126
+ }
127
+ };
128
+
129
+ /**
130
+ * Create a PrimeState from an emotional template
131
+ */
132
+ function createEmotionalState(emotionName) {
133
+ const template = EMOTIONAL_TEMPLATES[emotionName.toLowerCase()];
134
+ if (!template) {
135
+ throw new Error(`Unknown emotion: ${emotionName}`);
136
+ }
137
+
138
+ const state = new PrimeState();
139
+ const primes = state.primes;
140
+
141
+ // Build amplitude pattern based on template
142
+ for (let i = 0; i < primes.length; i++) {
143
+ const p = primes[i];
144
+
145
+ // Base amplitude with localization
146
+ const isTemplatePrime = template.primes.includes(p);
147
+ let amp = isTemplatePrime ? template.amplitude : template.amplitude * (1 - template.localization);
148
+
149
+ // Apply decay for non-template primes
150
+ if (!isTemplatePrime) {
151
+ amp *= Math.exp(-0.1 * i);
152
+ }
153
+
154
+ // Phase from template with gradient
155
+ const phase = template.basePhase + template.phaseGradient * Math.log(p);
156
+
157
+ state.set(p, Complex.fromPolar(amp, phase));
158
+ }
159
+
160
+ return state.normalize();
161
+ }
162
+
163
+ // ============================================================================
164
+ // FEELING OPERATOR F̂ (Chapter 9)
165
+ // ============================================================================
166
+
167
+ /**
168
+ * FeelingOperator - Measures emotional resonance with templates
169
+ *
170
+ * From book.pdf Eq. 9.2:
171
+ * F̂ = Σ_k w_k R_k where w_k ∈ ℝ⁺
172
+ * ⟨ψ|F̂|ψ⟩ = emotional resonance score
173
+ *
174
+ * The operator projects a state onto emotional eigenstates and
175
+ * returns the emotional "charge" or intensity.
176
+ */
177
+ class FeelingOperator {
178
+ constructor() {
179
+ // Pre-compute template states
180
+ this.templates = {};
181
+ for (const [name, template] of Object.entries(EMOTIONAL_TEMPLATES)) {
182
+ this.templates[name] = {
183
+ template,
184
+ state: createEmotionalState(name)
185
+ };
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Measure emotional resonance: ⟨ψ|F̂_emotion|ψ⟩
191
+ *
192
+ * @param {PrimeState} state - State to analyze
193
+ * @param {string} emotionName - Emotion to measure against
194
+ * @returns {number} Resonance score [0, 1]
195
+ */
196
+ measure(state, emotionName) {
197
+ const entry = this.templates[emotionName.toLowerCase()];
198
+ if (!entry) {
199
+ throw new Error(`Unknown emotion: ${emotionName}`);
200
+ }
201
+
202
+ const overlap = state.inner(entry.state);
203
+ return overlap.norm();
204
+ }
205
+
206
+ /**
207
+ * Full emotional spectrum analysis
208
+ *
209
+ * @param {PrimeState} state - State to analyze
210
+ * @returns {Object} Scores for all emotions
211
+ */
212
+ spectrum(state) {
213
+ const scores = {};
214
+ let max = { emotion: null, score: 0 };
215
+
216
+ for (const name of Object.keys(this.templates)) {
217
+ const score = this.measure(state, name);
218
+ scores[name] = score;
219
+ if (score > max.score) {
220
+ max = { emotion: name, score };
221
+ }
222
+ }
223
+
224
+ return {
225
+ scores,
226
+ dominant: max.emotion,
227
+ dominantScore: max.score,
228
+ template: EMOTIONAL_TEMPLATES[max.emotion]
229
+ };
230
+ }
231
+
232
+ /**
233
+ * Apply F̂ operator to state (project onto emotional subspace)
234
+ *
235
+ * @param {PrimeState} state - Input state
236
+ * @param {string} emotionName - Target emotion
237
+ * @param {number} strength - Projection strength [0, 1]
238
+ * @returns {PrimeState} Transformed state
239
+ */
240
+ apply(state, emotionName, strength = 0.5) {
241
+ const entry = this.templates[emotionName.toLowerCase()];
242
+ if (!entry) {
243
+ throw new Error(`Unknown emotion: ${emotionName}`);
244
+ }
245
+
246
+ const result = new PrimeState(state.primes);
247
+ const templateState = entry.state;
248
+
249
+ for (const p of state.primes) {
250
+ const current = state.get(p);
251
+ const target = templateState.get(p);
252
+
253
+ // Interpolate toward template
254
+ const newRe = current.re + strength * (target.re - current.re);
255
+ const newIm = current.im + strength * (target.im - current.im);
256
+
257
+ result.set(p, new Complex(newRe, newIm));
258
+ }
259
+
260
+ return result.normalize();
261
+ }
262
+
263
+ /**
264
+ * Emotional transition: smoothly move between emotions
265
+ *
266
+ * @param {PrimeState} state - Current state
267
+ * @param {string} fromEmotion - Starting emotion
268
+ * @param {string} toEmotion - Target emotion
269
+ * @param {number} t - Transition parameter [0, 1]
270
+ * @returns {PrimeState} Intermediate state
271
+ */
272
+ transition(state, fromEmotion, toEmotion, t) {
273
+ const fromState = this.templates[fromEmotion.toLowerCase()].state;
274
+ const toState = this.templates[toEmotion.toLowerCase()].state;
275
+
276
+ const result = new PrimeState(state.primes);
277
+
278
+ for (const p of state.primes) {
279
+ const from = fromState.get(p);
280
+ const to = toState.get(p);
281
+
282
+ // Linear interpolation
283
+ const newRe = from.re + t * (to.re - from.re);
284
+ const newIm = from.im + t * (to.im - from.im);
285
+
286
+ result.set(p, new Complex(newRe, newIm));
287
+ }
288
+
289
+ return result.normalize();
290
+ }
291
+ }
292
+
293
+ // ============================================================================
294
+ // CONSCIOUSNESS PRIMACY METRIC (Chapter 9)
295
+ // ============================================================================
296
+
297
+ /**
298
+ * ConsciousnessPrimacy - Composite measure of conscious state integrity
299
+ *
300
+ * From book.pdf Eq. 9.5:
301
+ * Primacy = 0.4·F + 0.3·R + 0.2·C + 0.1·Γ
302
+ *
303
+ * Where:
304
+ * - F = Feeling (dominant emotional resonance)
305
+ * - R = Resonance (prime resonance strength)
306
+ * - C = Coherence (phase alignment)
307
+ * - Γ = Knowledge resonance (semantic network activation)
308
+ */
309
+ class ConsciousnessPrimacy {
310
+ constructor(weights = null) {
311
+ this.weights = weights || {
312
+ feeling: 0.4,
313
+ resonance: 0.3,
314
+ coherence: 0.2,
315
+ knowledge: 0.1
316
+ };
317
+
318
+ this.feelingOp = new FeelingOperator();
319
+ }
320
+
321
+ /**
322
+ * Calculate primacy metric for a state
323
+ *
324
+ * @param {PrimeState} state - State to evaluate
325
+ * @param {Object} context - Optional context for knowledge calculation
326
+ * @returns {Object} Primacy score and components
327
+ */
328
+ calculate(state, context = {}) {
329
+ // F - Feeling component (dominant emotional resonance)
330
+ const spectrum = this.feelingOp.spectrum(state);
331
+ const F = spectrum.dominantScore;
332
+
333
+ // R - Resonance component (average prime resonance)
334
+ const dominant = state.dominant(3);
335
+ const R = dominant.length > 0
336
+ ? dominant.reduce((sum, d) => sum + d.amp, 0) / dominant.length
337
+ : 0;
338
+
339
+ // C - Coherence component (using phase alignment)
340
+ let C = 0;
341
+ try {
342
+ // Calculate phase coherence directly
343
+ let phaseSum = { re: 0, im: 0 };
344
+ for (const p of state.primes) {
345
+ const amp = state.get(p);
346
+ const norm = amp.norm();
347
+ if (norm > 0.001) {
348
+ phaseSum.re += amp.re / norm;
349
+ phaseSum.im += amp.im / norm;
350
+ }
351
+ }
352
+ C = Math.sqrt(phaseSum.re * phaseSum.re + phaseSum.im * phaseSum.im) / state.primes.length;
353
+ } catch {
354
+ C = 0.5; // Default fallback
355
+ }
356
+
357
+ // Γ - Knowledge resonance (simplified: entropy-based)
358
+ const entropy = state.entropy();
359
+ const maxEntropy = Math.log(state.primes.length);
360
+ const Gamma = 1 - (entropy / maxEntropy); // High order = high knowledge
361
+
362
+ // Composite primacy
363
+ const primacy =
364
+ this.weights.feeling * F +
365
+ this.weights.resonance * R +
366
+ this.weights.coherence * C +
367
+ this.weights.knowledge * Gamma;
368
+
369
+ return {
370
+ primacy,
371
+ components: { F, R, C, Gamma },
372
+ dominant: spectrum.dominant,
373
+ interpretation: this._interpret(primacy, spectrum.dominant)
374
+ };
375
+ }
376
+
377
+ _interpret(primacy, dominantEmotion) {
378
+ if (primacy > 0.8) {
379
+ return `High consciousness primacy with dominant ${dominantEmotion}. Coherent, resonant state.`;
380
+ } else if (primacy > 0.5) {
381
+ return `Moderate primacy with ${dominantEmotion} influence. Stable conscious processing.`;
382
+ } else if (primacy > 0.3) {
383
+ return `Low primacy with ${dominantEmotion} tendency. Fragmented attention.`;
384
+ } else {
385
+ return `Minimal primacy. Dispersed, incoherent state.`;
386
+ }
387
+ }
388
+
389
+ /**
390
+ * Track primacy evolution over time
391
+ *
392
+ * @param {PrimeState} state - Initial state
393
+ * @param {Function} evolver - Evolution function (state) => state
394
+ * @param {number} steps - Number of evolution steps
395
+ * @returns {Array} Primacy trajectory
396
+ */
397
+ trackEvolution(state, evolver, steps) {
398
+ const trajectory = [];
399
+ let current = state.clone();
400
+
401
+ for (let i = 0; i < steps; i++) {
402
+ const primacyData = this.calculate(current);
403
+ trajectory.push({
404
+ step: i,
405
+ primacy: primacyData.primacy,
406
+ emotion: primacyData.dominant,
407
+ components: primacyData.components
408
+ });
409
+
410
+ current = evolver(current);
411
+ }
412
+
413
+ return trajectory;
414
+ }
415
+ }
416
+
417
+ // ============================================================================
418
+ // EMOTIONAL ENTROPY SPECTROMETRY (Chapter 9)
419
+ // ============================================================================
420
+
421
+ /**
422
+ * EmotionalSpectrometer - Analyze emotional content through entropy lens
423
+ *
424
+ * Maps entropy patterns to emotional signatures
425
+ */
426
+ class EmotionalSpectrometer {
427
+ constructor() {
428
+ this.feelingOp = new FeelingOperator();
429
+ }
430
+
431
+ /**
432
+ * Full spectrometric analysis
433
+ *
434
+ * @param {PrimeState|string} input - State or text to analyze
435
+ * @returns {Object} Complete emotional spectrum analysis
436
+ */
437
+ analyze(input) {
438
+ const state = typeof input === 'string' ? encodeMemory(input) : input;
439
+
440
+ const spectrum = this.feelingOp.spectrum(state);
441
+ const entropy = state.entropy();
442
+
443
+ // Calculate coherence locally to avoid cross-reference issues
444
+ let coherence = 0;
445
+ try {
446
+ let phaseSum = { re: 0, im: 0 };
447
+ for (const p of state.primes) {
448
+ const amp = state.get(p);
449
+ const norm = amp.norm();
450
+ if (norm > 0.001) {
451
+ phaseSum.re += amp.re / norm;
452
+ phaseSum.im += amp.im / norm;
453
+ }
454
+ }
455
+ coherence = Math.sqrt(phaseSum.re * phaseSum.re + phaseSum.im * phaseSum.im) / state.primes.length;
456
+ } catch {
457
+ coherence = 0.5;
458
+ }
459
+
460
+ // Entropy-based emotional classification
461
+ const entropyClass = this._classifyEntropy(entropy);
462
+ const coherenceClass = this._classifyCoherence(coherence);
463
+
464
+ // Calculate emotional valence (positive/negative)
465
+ const valence = this._calculateValence(spectrum.scores);
466
+
467
+ // Calculate arousal (high/low energy)
468
+ const arousal = this._calculateArousal(spectrum.scores);
469
+
470
+ return {
471
+ state,
472
+ spectrum: spectrum.scores,
473
+ dominant: spectrum.dominant,
474
+ dominantTemplate: spectrum.template,
475
+ entropy,
476
+ coherence,
477
+ entropyClass,
478
+ coherenceClass,
479
+ valence, // -1 to 1 (negative to positive)
480
+ arousal, // 0 to 1 (calm to excited)
481
+ quadrant: this._getQuadrant(valence, arousal)
482
+ };
483
+ }
484
+
485
+ _classifyEntropy(S) {
486
+ if (S < 0.5) return 'ordered';
487
+ if (S < 1.5) return 'moderate';
488
+ if (S < 2.5) return 'mixed';
489
+ return 'disordered';
490
+ }
491
+
492
+ _classifyCoherence(C) {
493
+ if (C > 0.8) return 'highly_coherent';
494
+ if (C > 0.5) return 'coherent';
495
+ if (C > 0.2) return 'partially_coherent';
496
+ return 'incoherent';
497
+ }
498
+
499
+ _calculateValence(scores) {
500
+ // Positive emotions
501
+ const positive = (scores.love || 0) + (scores.joy || 0) +
502
+ (scores.awe || 0) + (scores.peace || 0);
503
+ // Negative emotions
504
+ const negative = (scores.fear || 0) + (scores.grief || 0) +
505
+ (scores.anger || 0);
506
+
507
+ const total = positive + negative + 0.001; // Avoid division by zero
508
+ return (positive - negative) / total;
509
+ }
510
+
511
+ _calculateArousal(scores) {
512
+ // High arousal emotions
513
+ const high = (scores.fear || 0) + (scores.joy || 0) +
514
+ (scores.anger || 0) + (scores.awe || 0);
515
+ // Low arousal emotions
516
+ const low = (scores.peace || 0) + (scores.grief || 0) +
517
+ (scores.love || 0);
518
+
519
+ const total = high + low + 0.001;
520
+ return high / total;
521
+ }
522
+
523
+ _getQuadrant(valence, arousal) {
524
+ if (valence >= 0 && arousal >= 0.5) return 'excited_positive'; // Joy, Awe
525
+ if (valence >= 0 && arousal < 0.5) return 'calm_positive'; // Love, Peace
526
+ if (valence < 0 && arousal >= 0.5) return 'excited_negative'; // Fear, Anger
527
+ return 'calm_negative'; // Grief
528
+ }
529
+
530
+ /**
531
+ * Compare emotional similarity between two inputs
532
+ */
533
+ compare(input1, input2) {
534
+ const analysis1 = this.analyze(input1);
535
+ const analysis2 = this.analyze(input2);
536
+
537
+ // Compare spectra using cosine similarity
538
+ let dot = 0, norm1 = 0, norm2 = 0;
539
+ for (const emotion of Object.keys(EMOTIONAL_TEMPLATES)) {
540
+ const s1 = analysis1.spectrum[emotion] || 0;
541
+ const s2 = analysis2.spectrum[emotion] || 0;
542
+ dot += s1 * s2;
543
+ norm1 += s1 * s1;
544
+ norm2 += s2 * s2;
545
+ }
546
+
547
+ const similarity = dot / (Math.sqrt(norm1 * norm2) + 0.001);
548
+
549
+ return {
550
+ similarity,
551
+ analysis1,
552
+ analysis2,
553
+ sameQuadrant: analysis1.quadrant === analysis2.quadrant
554
+ };
555
+ }
556
+ }
557
+
558
+ // Export all
559
+ export {
560
+ EMOTIONAL_TEMPLATES,
561
+ createEmotionalState,
562
+ FeelingOperator,
563
+ ConsciousnessPrimacy,
564
+ EmotionalSpectrometer
565
+ };