| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| export type ComponentType = |
| | "neural_logic_engine" |
| | "hierarchical_memory" |
| | "lyapunov_controller" |
| | "causal_reasoner" |
| | "autonomy_logger" |
| | "jepa_enhancer"; |
|
|
| export interface MetabolismState { |
| timestamp: number; |
| frustration: number; |
| effectiveFrustration: number; |
| surprise: number; |
| componentActivities: Record<ComponentType, number>; |
| totalMetabolicRate: number; |
| activatedComponents: ComponentType[]; |
| skippedComponents: ComponentType[]; |
| reason: string; |
| } |
|
|
| export class SparseMetabolism { |
| |
| private baseMetabolism: Record<ComponentType, number> = { |
| neural_logic_engine: 0.15, |
| hierarchical_memory: 0.2, |
| lyapunov_controller: 0.05, |
| causal_reasoner: 0.1, |
| autonomy_logger: 0.02, |
| jepa_enhancer: 0.08, |
| }; |
|
|
| |
| private frustrationMultipliers: Record<ComponentType, number> = { |
| neural_logic_engine: 1.5, |
| hierarchical_memory: 2.0, |
| lyapunov_controller: 3.0, |
| causal_reasoner: 1.8, |
| autonomy_logger: 1.0, |
| jepa_enhancer: 2.0, |
| }; |
|
|
| |
| private activationThresholds: Record<ComponentType, number> = { |
| neural_logic_engine: 0.0, |
| hierarchical_memory: 0.4, |
| lyapunov_controller: 0.3, |
| causal_reasoner: 0.6, |
| autonomy_logger: 0.0, |
| jepa_enhancer: 0.2, |
| }; |
|
|
| private lastState: MetabolismState | null = null; |
| private activationHistory: number[] = []; |
| private readonly HISTORY_SIZE = 50; |
| private smoothedFrustration = 0; |
| private lastObservedFrustration: number | null = null; |
|
|
| constructor() { |
| console.log("[Metabolism] Sparse metabolism initialized"); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| computeMetabolism(frustration: number): MetabolismState { |
| const timestamp = Date.now(); |
| const surprise = |
| this.lastObservedFrustration === null |
| ? 0 |
| : Math.abs(frustration - this.lastObservedFrustration); |
| this.smoothedFrustration = |
| this.lastObservedFrustration === null |
| ? frustration |
| : Math.max(0, Math.min(1, 0.78 * this.smoothedFrustration + 0.22 * frustration)); |
| this.lastObservedFrustration = frustration; |
| const effectiveFrustration = this.smoothedFrustration; |
| const componentActivities: Record<ComponentType, number> = { |
| neural_logic_engine: 0, |
| hierarchical_memory: 0, |
| lyapunov_controller: 0, |
| causal_reasoner: 0, |
| autonomy_logger: 0, |
| jepa_enhancer: 0, |
| }; |
|
|
| const activatedComponents: ComponentType[] = []; |
| const skippedComponents: ComponentType[] = []; |
|
|
| |
| for (const [component, baseActivity] of Object.entries(this.baseMetabolism) as [ |
| ComponentType, |
| number, |
| ][]) { |
| if (this.shouldActivateComponent(component, effectiveFrustration, surprise)) { |
| |
| const multiplier = this.frustrationMultipliers[component]; |
| const activity = baseActivity * (1 + effectiveFrustration * multiplier); |
|
|
| |
| componentActivities[component] = Math.min(1, activity); |
| activatedComponents.push(component); |
| } else { |
| componentActivities[component] = 0; |
| skippedComponents.push(component); |
| } |
| } |
|
|
| |
| const totalMetabolicRate = |
| Object.values(componentActivities).reduce((s, v) => s + v, 0) / |
| Object.keys(componentActivities).length; |
|
|
| |
| this.activationHistory.push(totalMetabolicRate); |
| if (this.activationHistory.length > this.HISTORY_SIZE) { |
| this.activationHistory.shift(); |
| } |
|
|
| |
| let reason = ""; |
| if (effectiveFrustration < 0.2) { |
| reason = "Low frustration: minimal metabolism"; |
| } else if (effectiveFrustration < 0.5) { |
| reason = "Moderate frustration: selective component activation"; |
| } else if (effectiveFrustration < 0.8) { |
| reason = "High frustration: aggressive activation"; |
| } else { |
| reason = "CRITICAL frustration: full metabolic engagement"; |
| } |
|
|
| const state: MetabolismState = { |
| timestamp, |
| frustration, |
| effectiveFrustration, |
| surprise, |
| componentActivities, |
| totalMetabolicRate, |
| activatedComponents, |
| skippedComponents, |
| reason, |
| }; |
|
|
| this.lastState = state; |
| return state; |
| } |
|
|
| private shouldActivateComponent( |
| component: ComponentType, |
| effectiveFrustration: number, |
| surprise: number, |
| ): boolean { |
| switch (component) { |
| case "neural_logic_engine": |
| case "autonomy_logger": |
| return true; |
| case "hierarchical_memory": |
| return effectiveFrustration >= 0.44 || (effectiveFrustration >= 0.28 && surprise >= 0.12); |
| case "lyapunov_controller": |
| return effectiveFrustration >= 0.3 || surprise >= 0.18; |
| case "causal_reasoner": |
| return (effectiveFrustration >= 0.65 && surprise <= 0.18) || effectiveFrustration >= 0.82; |
| case "jepa_enhancer": |
| return effectiveFrustration >= 0.2 || surprise >= 0.08; |
| default: |
| return effectiveFrustration >= this.activationThresholds[component]; |
| } |
| } |
|
|
| |
| |
| |
| |
| shouldActivate(component: ComponentType): boolean { |
| if (!this.lastState) return true; |
|
|
| return this.lastState.activatedComponents.includes(component); |
| } |
|
|
| |
| |
| |
| |
| getDutyCycle(component: ComponentType): number { |
| if (!this.lastState) return 0.5; |
| return this.lastState.componentActivities[component]; |
| } |
|
|
| |
| |
| |
| predictFutureMetabolism(frustrationAhead: number): { |
| estimatedMetabolicRate: number; |
| predictedActivations: ComponentType[]; |
| } { |
| const metabolismState = this.computeMetabolism(frustrationAhead); |
| return { |
| estimatedMetabolicRate: metabolismState.totalMetabolicRate, |
| predictedActivations: metabolismState.activatedComponents, |
| }; |
| } |
|
|
| |
| |
| |
| explain(): string { |
| if (!this.lastState) { |
| return "[Metabolism] No metabolism computed. Call computeMetabolism() first."; |
| } |
|
|
| const state = this.lastState; |
| const avgMetabolism = |
| this.activationHistory.reduce((s, v) => s + v, 0) / |
| Math.max(1, this.activationHistory.length); |
| const trend = this._calculateTrend(); |
|
|
| let report = `[Sparse Metabolism Report]\n`; |
| report += ` Frustration: ${(state.frustration * 100).toFixed(1)}%\n`; |
| report += ` Effective frustration: ${(state.effectiveFrustration * 100).toFixed(1)}%\n`; |
| report += ` Surprise: ${(state.surprise * 100).toFixed(1)}%\n`; |
| report += ` Total Metabolic Rate: ${(state.totalMetabolicRate * 100).toFixed(1)}%\n`; |
| report += ` Activated Components: ${state.activatedComponents.length}/${Object.keys(state.componentActivities).length}\n`; |
| report += ` ${state.activatedComponents.join(", ")}\n`; |
| if (state.skippedComponents.length > 0) { |
| report += ` Skipped: ${state.skippedComponents.join(", ")}\n`; |
| } |
| report += `\n Component Activities:\n`; |
|
|
| for (const [comp, activity] of Object.entries(state.componentActivities)) { |
| const bar = |
| "█".repeat(Math.round(activity * 10)) + "░".repeat(10 - Math.round(activity * 10)); |
| report += ` ${comp}: [${bar}] ${(activity * 100).toFixed(0)}%\n`; |
| } |
|
|
| report += `\n Metrics:\n`; |
| report += ` Avg metabolic rate (last ${this.activationHistory.length} cycles): ${(avgMetabolism * 100).toFixed(1)}%\n`; |
| report += ` Trend: ${trend > 0 ? "📈" : trend < 0 ? "📉" : "➡️"} ${(trend * 100).toFixed(1)}% per cycle\n`; |
| report += `\n Reason: ${state.reason}`; |
|
|
| return report; |
| } |
|
|
| |
| |
| |
| private _calculateTrend(): number { |
| if (this.activationHistory.length < 2) return 0; |
|
|
| const n = this.activationHistory.length; |
| const x = Array.from({ length: n }, (_, i) => i); |
| const y = this.activationHistory; |
|
|
| const xMean = x.reduce((s, v) => s + v, 0) / n; |
| const yMean = y.reduce((s, v) => s + v, 0) / n; |
|
|
| const numerator = x.reduce((s, xi, i) => s + (xi - xMean) * (y[i] - yMean), 0); |
| const denominator = x.reduce((s, xi) => s + (xi - xMean) ** 2, 0); |
|
|
| return denominator === 0 ? 0 : numerator / denominator; |
| } |
|
|
| |
| |
| |
| getStats() { |
| return { |
| lastMetaborlicRate: this.lastState?.totalMetabolicRate ?? 0, |
| avgMetabolicRate: |
| this.activationHistory.reduce((s, v) => s + v, 0) / |
| Math.max(1, this.activationHistory.length), |
| maxMetabolicRate: Math.max(...this.activationHistory, 0), |
| minMetabolicRate: Math.min(...this.activationHistory, 1), |
| trend: this._calculateTrend(), |
| historySize: this.activationHistory.length, |
| }; |
| } |
| } |
|
|
| |
| |
| |
| let metabolismInstance: SparseMetabolism | null = null; |
|
|
| export function getSparseMetabolism(): SparseMetabolism { |
| if (!metabolismInstance) { |
| metabolismInstance = new SparseMetabolism(); |
| } |
| return metabolismInstance; |
| } |
|
|
| export function initializeSparseMetabolism(): SparseMetabolism { |
| metabolismInstance = new SparseMetabolism(); |
| return metabolismInstance; |
| } |
|
|