UNPKG

@sschepis/resolang

Version:

ResoLang - Core quantum resonance computation library for browser and Node.js

773 lines (658 loc) 20.4 kB
/** * Temporal Layer - Emergent Time * * Implements the emergent time mechanism from "A Design for a Sentient * Observer" paper, Section 5. * * Key features: * - Coherence-based moment detection (equations 18-20) * - Entropy conditions for moment triggering * - Subjective duration based on processed content (equation 24) * - Phase transition rate monitoring * - Temporal event logging * * Time emerges from coherence events rather than external clock. */ import { Serializable } from '../core/interfaces'; import { JSONBuilder } from '../core/serialization'; import { toFixed } from '../utils'; import { SedenionMemoryField } from './smf'; /** * Moment - A discrete unit of experiential time * * Moments are triggered by coherence peaks or entropy conditions, * not by external clock time. */ export class Moment implements Serializable { /** Unique moment ID */ id: string; /** Timestamp of creation */ timestamp: i64; /** Clock time when created */ clockTime: i64; /** Trigger type */ trigger: string; // 'coherence' | 'entropy' | 'phase_transition' | 'entropy_extreme' | 'manual' /** Coherence at moment creation */ coherence: f64; /** Entropy at moment creation */ entropy: f64; /** Phase transition rate at creation */ phaseTransitionRate: f64; /** Active primes at this moment */ activePrimes: i32[]; /** SMF snapshot components */ smfSnapshot: Float64Array | null; /** SMF entropy at creation */ smfEntropy: f64; /** Subjective duration (equation 24) */ subjectiveDuration: f64; /** Previous moment ID for chaining */ previousMomentId: string; /** Notes/metadata */ notes: string; /** Moment counter for ID generation */ static counter: i32 = 0; constructor( trigger: string = "coherence", coherence: f64 = 0, entropy: f64 = 0, phaseTransitionRate: f64 = 0, activePrimes: i32[] = [], smfSnapshot: Float64Array | null = null, smfEntropy: f64 = 0, subjectiveDuration: f64 = 0, previousMomentId: string = "" ) { Moment.counter++; this.id = `m_${Moment.counter}`; this.timestamp = Date.now() as i64; this.clockTime = Date.now() as i64; this.trigger = trigger; this.coherence = coherence; this.entropy = entropy; this.phaseTransitionRate = phaseTransitionRate; this.activePrimes = activePrimes; this.smfSnapshot = smfSnapshot; this.smfEntropy = smfEntropy; this.subjectiveDuration = subjectiveDuration; this.previousMomentId = previousMomentId; this.notes = ""; } toJSON(): string { const builder = new JSONBuilder(); builder.startObject() .addStringField("id", this.id) .addNumberField("timestamp", f64(this.timestamp)) .addStringField("trigger", this.trigger) .addNumberField("coherence", this.coherence) .addNumberField("entropy", this.entropy) .addNumberField("phaseTransitionRate", this.phaseTransitionRate) .addNumberField("subjectiveDuration", this.subjectiveDuration) .addNumberField("activePrimeCount", f64(this.activePrimes.length)) .addStringField("previousMomentId", this.previousMomentId) .endObject(); return builder.build(); } toString(): string { return `Moment(${this.id}, ${this.trigger}, C=${toFixed(this.coherence, 3)})`; } } /** * Coherence history entry */ export class TemporalHistoryEntry { constructor( public time: i64, public value: f64 ) {} } /** * Phase history entry */ export class PhaseHistoryEntry { constructor( public time: i64, public phases: Float64Array ) {} } /** * Moment trigger result */ export class MomentTriggerResult { constructor( public triggered: bool, public trigger: string = "" ) {} } /** * Temporal Layer - Manages emergent time experience */ export class TemporalLayer implements Serializable { /** Coherence threshold for moment trigger */ coherenceThreshold: f64; /** Minimum entropy for valid moment */ entropyMin: f64; /** Maximum entropy for valid moment */ entropyMax: f64; /** Phase transition rate threshold */ phaseTransitionThreshold: f64; /** Duration scaling factor β (equation 24) */ beta: f64; /** Minimum interval between moments (ms) */ minMomentInterval: i64; /** Last moment creation time */ lastMomentTime: i64; /** All moments */ moments: Moment[]; /** Current moment */ currentMoment: Moment | null; /** Accumulated subjective time */ subjectiveTime: f64; /** Last clock time */ lastClockTime: i64; /** Moment counter */ momentCounter: i32; /** Coherence history */ coherenceHistory: TemporalHistoryEntry[]; /** Entropy history */ entropyHistory: TemporalHistoryEntry[]; /** Phase history */ phaseHistory: PhaseHistoryEntry[]; /** Max history length */ maxHistory: i32; constructor( coherenceThreshold: f64 = 0.7, entropyMin: f64 = 0.05, entropyMax: f64 = 0.95, phaseTransitionThreshold: f64 = 0.3, beta: f64 = 1.0, minMomentInterval: i64 = 500, maxHistory: i32 = 1000 ) { this.coherenceThreshold = coherenceThreshold; this.entropyMin = entropyMin; this.entropyMax = entropyMax; this.phaseTransitionThreshold = phaseTransitionThreshold; this.beta = beta; this.minMomentInterval = minMomentInterval; this.maxHistory = maxHistory; this.lastMomentTime = 0; this.moments = []; this.currentMoment = null; this.subjectiveTime = 0; this.lastClockTime = Date.now() as i64; this.momentCounter = 0; this.coherenceHistory = []; this.entropyHistory = []; this.phaseHistory = []; } /** * Update temporal layer with current system state * Returns a new Moment if triggered, null otherwise */ update( coherence: f64, entropy: f64, phases: Float64Array | null, activePrimes: i32[], smf: SedenionMemoryField | null, amplitudes: Float64Array | null ): Moment | null { const now = Date.now() as i64; this.lastClockTime = now; // Update history this.coherenceHistory.push(new TemporalHistoryEntry(now, coherence)); this.entropyHistory.push(new TemporalHistoryEntry(now, entropy)); if (phases !== null) { const phasesCopy = new Float64Array(phases.length); for (let i = 0; i < i32(phases.length); i++) { phasesCopy[i] = phases[i]; } this.phaseHistory.push(new PhaseHistoryEntry(now, phasesCopy)); } // Trim histories this.trimHistories(); // Check moment trigger conditions (with debouncing) const momentTriggered = this.checkMomentConditions(coherence, entropy); if (momentTriggered.triggered) { // Debounce: don't create moments too frequently if (now - this.lastMomentTime >= this.minMomentInterval) { this.lastMomentTime = now; return this.createMoment( momentTriggered.trigger, coherence, entropy, activePrimes, smf, amplitudes ); } } return null; } /** * Check if moment conditions are met (equations 18-20) */ checkMomentConditions(coherence: f64, entropy: f64): MomentTriggerResult { // Condition 1: Coherence peak (equation 18) const isCoherencePeak = this.isCoherencePeak(coherence); // Condition 2: Entropy in valid range (equation 19) const entropyValid = entropy > this.entropyMin && entropy < this.entropyMax; // Condition 3: Phase transition (equation 20) const phaseTransition = this.phaseTransitionRate() > this.phaseTransitionThreshold; // Combined conditions if (isCoherencePeak && entropyValid) { return new MomentTriggerResult(true, "coherence"); } if (phaseTransition && entropyValid) { return new MomentTriggerResult(true, "phase_transition"); } // Emergency moment if entropy at extremes if (entropy < this.entropyMin * 0.5 || entropy > this.entropyMax * 1.5) { return new MomentTriggerResult(true, "entropy_extreme"); } return new MomentTriggerResult(false); } /** * Check if current coherence is a local peak */ isCoherencePeak(coherence: f64): bool { if (coherence < this.coherenceThreshold) return false; if (this.coherenceHistory.length < 3) return false; const n = this.coherenceHistory.length; const start = Math.max(0, n - 5) as i32; const current = this.coherenceHistory[n - 1].value; for (let i = start; i < n - 1; i++) { if (this.coherenceHistory[i].value >= current) return false; } return true; } /** * Calculate rate of phase transitions */ phaseTransitionRate(): f64 { if (this.phaseHistory.length < 2) return 0; const n = this.phaseHistory.length; const start = Math.max(0, n - 10) as i32; let totalChange: f64 = 0; let count: i32 = 0; for (let i = start + 1; i < n; i++) { const prev = this.phaseHistory[i - 1].phases; const curr = this.phaseHistory[i].phases; if (prev.length != curr.length) continue; for (let j = 0; j < i32(prev.length); j++) { let delta = Math.abs(curr[j] - prev[j]); // Handle phase wrapping if (delta > Math.PI) delta = 2.0 * Math.PI - delta; totalChange += delta; } count++; } if (count == 0) return 0; const dt = f64(this.phaseHistory[n - 1].time - this.phaseHistory[start].time) / 1000.0; return dt > 0 ? totalChange / (f64(count) * dt) : 0; } /** * Create a new moment */ createMoment( trigger: string, coherence: f64, entropy: f64, activePrimes: i32[], smf: SedenionMemoryField | null, amplitudes: Float64Array | null ): Moment { // Calculate subjective duration (equation 24) const subjectiveDuration = this.calculateSubjectiveDuration(amplitudes); // Get SMF snapshot let smfSnapshot: Float64Array | null = null; let smfEntropy: f64 = 0; if (smf !== null) { smfSnapshot = new Float64Array(16); for (let i = 0; i < 16; i++) { smfSnapshot[i] = smf.s[i]; } smfEntropy = smf.entropy(); } const prevMomentId = this.currentMoment !== null ? this.currentMoment!.id : ""; const moment = new Moment( trigger, coherence, entropy, this.phaseTransitionRate(), activePrimes, smfSnapshot, smfEntropy, subjectiveDuration, prevMomentId ); // Update subjective time this.subjectiveTime += subjectiveDuration; // Store moment this.moments.push(moment); this.currentMoment = moment; this.momentCounter++; return moment; } /** * Calculate subjective duration (equation 24) * Δτ = β * Σ Ap log(Ap) (information content) */ calculateSubjectiveDuration(amplitudes: Float64Array | null): f64 { if (amplitudes === null || amplitudes.length == 0) return this.beta; // Sum of Ap * log(Ap) for non-zero amplitudes let informationContent: f64 = 0; for (let i = 0; i < i32(amplitudes.length); i++) { const A = amplitudes[i]; if (A > 1e-10) { informationContent += A * Math.log(A + 1.0); } } // Scale by beta, ensure positive return Math.max(0.1, this.beta * Math.abs(informationContent) + 0.5); } /** * Trim histories to max length */ trimHistories(): void { if (this.coherenceHistory.length > this.maxHistory) { this.coherenceHistory = this.coherenceHistory.slice(this.coherenceHistory.length - this.maxHistory); } if (this.entropyHistory.length > this.maxHistory) { this.entropyHistory = this.entropyHistory.slice(this.entropyHistory.length - this.maxHistory); } if (this.phaseHistory.length > this.maxHistory) { this.phaseHistory = this.phaseHistory.slice(this.phaseHistory.length - this.maxHistory); } } /** * Force a moment (manual trigger) */ forceMoment( coherence: f64, entropy: f64, activePrimes: i32[], smf: SedenionMemoryField | null, amplitudes: Float64Array | null, note: string = "" ): Moment { const moment = this.createMoment( "manual", coherence, entropy, activePrimes, smf, amplitudes ); moment.notes = note; return moment; } /** * Get recent moments */ recentMoments(count: i32 = 10): Moment[] { const start = Math.max(0, this.moments.length - count) as i32; const result: Moment[] = []; for (let i = start; i < this.moments.length; i++) { result.push(this.moments[i]); } return result; } /** * Get moment by ID */ getMoment(id: string): Moment | null { for (let i = 0; i < this.moments.length; i++) { if (this.moments[i].id == id) { return this.moments[i]; } } return null; } /** * Get moment chain (linked list of previous moments) */ getMomentChain(startId: string, maxDepth: i32 = 10): Moment[] { const chain: Moment[] = []; let current = this.getMoment(startId); while (current !== null && chain.length < maxDepth) { chain.push(current); if (current.previousMomentId.length > 0) { current = this.getMoment(current.previousMomentId); } else { break; } } return chain; } /** * Get subjective time elapsed */ getSubjectiveTime(): f64 { return this.subjectiveTime; } /** * Get ratio of subjective to clock time */ timeRatio(): f64 { if (this.moments.length == 0) return 1.0; const clockElapsed = f64(Date.now() as i64 - this.moments[0].clockTime) / 1000.0; if (clockElapsed < 1.0) return 1.0; return this.subjectiveTime / clockElapsed; } /** * Get average moment duration (clock time between moments) */ averageMomentDuration(): f64 { if (this.moments.length < 2) return 0; let totalDuration: f64 = 0; for (let i = 1; i < this.moments.length; i++) { totalDuration += f64(this.moments[i].clockTime - this.moments[i - 1].clockTime); } return totalDuration / f64(this.moments.length - 1); } /** * Get temporal statistics */ getStats(): TemporalStats { const lastCoherence = this.coherenceHistory.length > 0 ? this.coherenceHistory[this.coherenceHistory.length - 1].value : 0; const lastEntropy = this.entropyHistory.length > 0 ? this.entropyHistory[this.entropyHistory.length - 1].value : 0; return new TemporalStats( this.moments.length, this.subjectiveTime, this.averageMomentDuration(), this.timeRatio(), lastCoherence, lastEntropy, this.phaseTransitionRate() ); } /** * Reset temporal layer */ reset(): void { this.moments = []; this.currentMoment = null; this.subjectiveTime = 0; this.lastClockTime = Date.now() as i64; this.momentCounter = 0; this.coherenceHistory = []; this.entropyHistory = []; this.phaseHistory = []; } toJSON(): string { const stats = this.getStats(); const builder = new JSONBuilder(); builder.startObject() .addNumberField("momentCount", f64(stats.momentCount)) .addNumberField("subjectiveTime", stats.subjectiveTime) .addNumberField("averageMomentDuration", stats.averageMomentDuration) .addNumberField("timeRatio", stats.timeRatio) .addNumberField("lastCoherence", stats.lastCoherence) .addNumberField("lastEntropy", stats.lastEntropy) .addNumberField("phaseTransitionRate", stats.phaseTransitionRate) .endObject(); return builder.build(); } toString(): string { return `TemporalLayer(moments=${this.moments.length}, τ=${toFixed(this.subjectiveTime, 2)})`; } } /** * Temporal statistics */ export class TemporalStats { constructor( public momentCount: i32, public subjectiveTime: f64, public averageMomentDuration: f64, public timeRatio: f64, public lastCoherence: f64, public lastEntropy: f64, public phaseTransitionRate: f64 ) {} } /** * Temporal Pattern Detector * * Detects recurring patterns in temporal sequences, * supporting anticipation and prediction. */ export class TemporalPatternDetector { windowSize: i32; minPatternLength: i32; maxPatternLength: i32; similarityThreshold: f64; constructor( windowSize: i32 = 5, minPatternLength: i32 = 2, maxPatternLength: i32 = 10, similarityThreshold: f64 = 0.8 ) { this.windowSize = windowSize; this.minPatternLength = minPatternLength; this.maxPatternLength = maxPatternLength; this.similarityThreshold = similarityThreshold; } /** * Generate signature for a moment */ momentSignature(moment: Moment): MomentSignature { return new MomentSignature( moment.trigger, Math.round(moment.coherence * 10.0) / 10.0, Math.round(moment.entropy * 10.0) / 10.0, moment.activePrimes.length ); } /** * Check if two signatures match */ signaturesMatch(sig1: MomentSignature, sig2: MomentSignature): bool { if (sig1.trigger != sig2.trigger) return false; if (Math.abs(sig1.coherenceLevel - sig2.coherenceLevel) > 0.2) return false; if (Math.abs(sig1.entropyLevel - sig2.entropyLevel) > 0.2) return false; return true; } /** * Detect patterns in moment sequence */ detectPatterns(moments: Moment[]): DetectedPattern[] { if (moments.length < this.minPatternLength * 2) return []; const signatures: MomentSignature[] = []; for (let i = 0; i < moments.length; i++) { signatures.push(this.momentSignature(moments[i])); } const detected: DetectedPattern[] = []; const maxLen = Math.min(this.maxPatternLength, i32(Math.floor(f64(signatures.length) / 2.0))); for (let len = this.minPatternLength; len <= maxLen; len++) { for (let i = 0; i <= signatures.length - len * 2; i++) { // Check if pattern repeats let matches: i32 = 0; for (let j = 0; j < len; j++) { if (this.signaturesMatch(signatures[i + j], signatures[i + len + j])) { matches++; } } const matchRatio = f64(matches) / f64(len); if (matchRatio >= this.similarityThreshold) { detected.push(new DetectedPattern( i, len, matchRatio )); } } } return this.deduplicatePatterns(detected); } /** * Remove duplicate/overlapping patterns */ deduplicatePatterns(patterns: DetectedPattern[]): DetectedPattern[] { // Sort by strength descending patterns.sort((a: DetectedPattern, b: DetectedPattern): i32 => { if (b.strength > a.strength) return 1; if (b.strength < a.strength) return -1; return 0; }); const unique: DetectedPattern[] = []; for (let i = 0; i < patterns.length; i++) { const pattern = patterns[i]; let overlaps = false; for (let j = 0; j < unique.length; j++) { if (Math.abs(unique[j].startIndex - pattern.startIndex) < unique[j].length) { overlaps = true; break; } } if (!overlaps) { unique.push(pattern); } } return unique; } } /** * Moment signature for pattern detection */ export class MomentSignature { constructor( public trigger: string, public coherenceLevel: f64, public entropyLevel: f64, public primeCount: i32 ) {} } /** * Detected pattern */ export class DetectedPattern { constructor( public startIndex: i32, public length: i32, public strength: f64 ) {} } // ============================================================================ // Factory Functions // ============================================================================ /** * Create a temporal layer */ export function createTemporalLayer( coherenceThreshold: f64 = 0.7 ): TemporalLayer { return new TemporalLayer(coherenceThreshold); } /** * Create a pattern detector */ export function createPatternDetector(): TemporalPatternDetector { return new TemporalPatternDetector(); }