/** * AffinityODESolver — Strogatz-Rinaldi relational dynamics for HoloScript. * * ## Mathematical Formulation * * Models social/affective dynamics as coupled ODEs, extending the * Strogatz-Rinaldi (1988) love dynamics model with Sternberg's * Triangular Theory state vector [I, P, C] (Intimacy, Passion, * Commitment). * * **Linear coupled ODE (Strogatz 1988):** * * dR/dt = -a_R * R + b_RJ * J + f_R(t) * dJ/dt = -a_J * J + b_JR * R + f_J(t) * * where: * R(t), J(t) = feeling states of partner R and partner J * a_R, a_J = emotional damping / forgetting rates * b_RJ, b_JR = cross-coupling (attraction / reactance) * f_R(t), f_J(t) = external forcing (events, environment) * * **Extended nonlinear model (Rinaldi et al., 2015):** * * Adds Sternberg's triangular state vector [Intimacy, Passion, Commitment] * with nonlinear reaction terms: * * dI/dt = -a_I * I + b_I * reaction(R, J) + f_I(t) * dP/dt = -a_P * P + b_P * arousal(R, J) - d_P * P^2 + f_P(t) * dC/dt = -a_C * C + b_C * commitment(I, P) + f_C(t) * * **Personality archetypes** (from Strogatz parameter space): * - Eager beaver: +a (self-amplifying), +b (partner-responsive) * - Cautious lover: -a (self-dampening), +b (partner-responsive) * - Narcissistic: +a (self-amplifying), -b (partner-ignoring) * - Hermit: -a (self-dampening), -b (partner-ignoring) * * **Nash-equilibrium effort control inputs:** * Each agent adjusts effort (investment) to optimize a payoff function * that balances personal well-being against relational contribution. * Equilibrium efforts converge when neither agent benefits from * unilateral deviation. * * ## Numerical Method * * RK4 (4th-order Runge-Kutta) for ODE integration — matches the * infrastructure pattern of ThermalSolver (explicit time-stepping) * but operates on a state vector rather than a spatial field. * * ## Known Limitations * * - Fixed personality parameters per run (no within-run adaptation) * - No stochastic forcing (deterministic only; add noise externally) * - Single dyad only (2 agents); multi-agent networks require * coupling via CouplingManagerV2 * * ## References * * - Strogatz, S.H. (1988). "Love Affairs and Differential Equations." * Mathematics Magazine, 61(1), 35. * - Rinaldi, S., Della Rossa, F., & Landi, P. (2015). * "Modeling Love Dynamics." World Scientific. * - Sternberg, R.J. (1986). "A Triangular Theory of Love." * Psychological Review, 93(2), 119-135. * - PLOS ONE (2021). "Controlling Forever Love." * * @see SimSolver — generic solver interface * @see CouplingManagerV2 — multi-solver coupling */ export type PersonalityArchetype = 'eager_beaver' | 'cautious_lover' | 'narcissistic' | 'hermit' | 'custom'; export interface AgentParams { /** Unique agent identifier */ id: string; /** Emotional damping / forgetting rate (decay toward baseline). Positive = self-amplifying, negative = self-dampening */ dampingRate: number; /** Cross-coupling coefficient: how much this agent responds to the partner's feeling. Positive = attracted, negative = repelled */ couplingToPartner: number; /** Personality archetype (sets dampingRate/couplingToPartner if provided instead of numeric params) */ archetype?: PersonalityArchetype; /** External forcing function f(t). Receives current time, returns forcing value */ forcing?: (t: number) => number; } export interface SternbergParams { /** Intimacy decay rate */ intimacyDecay: number; /** Intimacy coupling to feelings */ intimacyCoupling: number; /** Passion decay rate */ passionDecay: number; /** Passion arousal coefficient */ passionArousal: number; /** Passion saturation coefficient (nonlinear damping on P^2) */ passionSaturation: number; /** Commitment decay rate */ commitmentDecay: number; /** Commitment coupling to intimacy+passion */ commitmentCoupling: number; } export interface NashEffortParams { /** Enable Nash-equilibrium effort control */ enabled: boolean; /** Personal well-being weight in payoff */ wellBeingWeight: number; /** Relational contribution weight in payoff */ relationalWeight: number; /** Maximum effort per agent */ maxEffort: number; /** Effort adaptation rate (how fast agents adjust) */ adaptationRate: number; } export interface AffinityConfig { /** Two agents in the dyad */ agents: [AgentParams, AgentParams]; /** Initial feeling states [R_0, J_0] */ initialFeelings?: [number, number]; /** Enable Sternberg triangular state vector [I, P, C] */ enableSternberg?: boolean; /** Sternberg model parameters (required if enableSternberg=true) */ sternberg?: SternbergParams; /** Initial Sternberg state [I_0, P_0, C_0] */ initialSternbergState?: [number, number, number]; /** Nash-equilibrium effort control */ nashEffort?: NashEffortParams; /** Integration time step (seconds) */ timeStep: number; /** Maximum integration time (for steady-state detection) */ maxTime?: number; } export interface AffinityState { /** Current time */ time: number; /** Partner R feeling state */ R: number; /** Partner J feeling state */ J: number; /** Sternberg Intimacy (NaN if disabled) */ intimacy: number; /** Sternberg Passion (NaN if disabled) */ passion: number; /** Sternberg Commitment (NaN if disabled) */ commitment: number; /** Nash effort for agent R (NaN if disabled) */ effortR: number; /** Nash effort for agent J (NaN if disabled) */ effortJ: number; /** Number of integration steps taken */ stepCount: number; /** Solver wall-clock time for last step (ms) */ lastStepMs: number; } export interface AffinityStats extends AffinityState { /** Feeling states as Float32Array [R, J, I, P, C, effortR, effortJ] */ stateVector: Float32Array; /** Whether Sternberg extension is active */ sternbergEnabled: boolean; /** Whether Nash effort control is active */ nashEnabled: boolean; } export declare class AffinityODESolver { private aR; private bRJ; private aJ; private bJR; private sternberg; private useSternberg; private nash; private useNash; private R; private J; private I; private P; private C; private effortR; private effortJ; private config; private simulationTime; private stepCount; private lastStepMs; private fR; private fJ; constructor(config: AffinityConfig); /** * Derivatives for the coupled feeling ODEs (Strogatz-Rinaldi). * * dR/dt = -a_R * R + b_RJ * J + f_R(t) * dJ/dt = -a_J * J + b_JR * R + f_J(t) */ private feelingDerivatives; /** * Derivatives for the Sternberg triangular model. * * dI/dt = -decay_I * I + coupling_I * reaction(R,J) * dP/dt = -decay_P * P + arousal_P * |R*J|^0.5 - sat_P * P^2 * dC/dt = -decay_C * C + coupling_C * commitment(I, P) */ private sternbergDerivatives; /** * Nash-equilibrium effort adaptation. * * Each agent adjusts effort to balance personal well-being against * relational contribution. Best-response dynamics converge to * Nash equilibrium where neither agent benefits from unilateral deviation. */ private adaptEffort; /** * Advance the relational state by dt seconds using RK4 integration. */ step(dt: number): void; /** Get current state as a snapshot */ getState(): AffinityState; /** Get state vector as Float32Array: [R, J, I, P, C, effortR, effortJ] */ getStateVector(): Float32Array; /** Get solver statistics (implements SimSolver contract) */ getStats(): AffinityStats; /** Point query: feeling state at current time */ getFeelings(): { R: number; J: number; }; /** Point query: Sternberg state at current time (throws if not enabled) */ getSternbergState(): { intimacy: number; passion: number; commitment: number; }; /** Apply an impulse (external event) to one or both agents */ applyImpulse(deltaR: number, deltaJ: number): void; /** Update forcing function for an agent at runtime */ setForcing(agentIndex: 0 | 1, fn: (t: number) => number): void; /** Update coupling parameters at runtime (e.g., personality shift) */ setCoupling(agentIndex: 0 | 1, dampingRate: number, couplingToPartner: number): void; dispose(): void; } //# sourceMappingURL=AffinityODESolver.d.ts.map