# viva_emotion
[](https://github.com/gabrielmaialva33/viva_emotion/actions)
[](https://hex.pm/packages/viva_emotion)
[](https://hexdocs.pm/viva_emotion/)
Type-safe emotional core for digital consciousness. PAD model, Ornstein-Uhlenbeck dynamics, and Cusp catastrophe - all with exhaustive pattern matching.
## Installation
```sh
gleam add viva_emotion@1
```
## Quick Start
```gleam
import viva_emotion
import viva_emotion/stimulus
import viva_emotion/emotion
pub fn main() {
// Create emotional state
let state = viva_emotion.new()
// Feel success
let state = viva_emotion.feel(state, stimulus.Success, 1.0)
// Evolve over time
let #(state, jumped) = viva_emotion.tick(state, 0.1)
// Classify current emotion
let classified = viva_emotion.classify(state)
// classified.emotion == emotion.Joy
}
```
## Features
- **PAD Model**: Pleasure-Arousal-Dominance emotional space (Mehrabian 1996)
- **Exhaustive Stimuli**: 14 stimulus types with compile-time coverage
- **O-U Dynamics**: Ornstein-Uhlenbeck mean-reverting process
- **Cusp Catastrophe**: Sudden emotional transitions under stress
- **Emotion Fusion**: Combine Need, Past, and Personality sources (Borotschnig 2025)
- **Long-term Mood**: Exponential Moving Average for emotional stability
- **Big Bounce**: Mood continuity across death/rebirth cycles
- **Configurable Personality**: Custom thresholds, weights, and dynamics
## Platform Support
This library targets the Erlang platform and is compatible with:
- Erlang/OTP 26 and higher
- Gleam 1.4.0 and higher
## Personality Configuration
```gleam
import viva_emotion
import viva_emotion/dynamics
import viva_emotion/emotion
import viva_emotion/stimulus
import viva_emotion/pad
// Anxious personality: lower threshold for existential states
let anxious_classification = emotion.ClassificationConfig(
high_threshold: 0.2,
low_threshold: -0.2,
existential_arousal: 0.5, // Triggers easier
existential_pleasure: -0.2,
)
// Stoic personality: rejection hurts less
let stoic_weights = stimulus.default_weights()
|> stimulus.weight(stimulus.Rejection, pad.new(-0.1, 0.1, 0.0))
// Volatile personality: easier cusp triggers
let volatile_dynamics = dynamics.DynamicsConfig(
..dynamics.default_config(),
cusp_dominance_trigger: -0.1,
cusp_flip_pleasure_damp: 0.95,
)
// Combine into full personality
let anxious_viva = viva_emotion.with_full_config(
pad.new(-0.1, 0.2, -0.1), // baseline
volatile_dynamics,
anxious_classification,
stoic_weights,
)
```
## Emotion Fusion
Combine multiple emotional sources with adaptive weighting:
```gleam
import viva_emotion
import viva_emotion/fusion
import viva_emotion/pad
// Need-based emotion (from interoception/hardware)
let need = pad.new(-0.3, 0.4, -0.2)
// Past-based emotion (from memory retrieval)
let past = pad.new(0.2, 0.1, 0.3)
// Context for adaptive weights
let context = fusion.FusionContext(
arousal: 0.4, // Current arousal → affects need weight
confidence: 0.7, // Memory confidence → affects past weight
novelty: 0.3, // Situation novelty → affects personality weight
)
// Fuse sources
let state = viva_emotion.new()
let state = viva_emotion.fuse(state, need, past, context)
// Check for emotional conflict
let has_conflict = viva_emotion.has_emotional_conflict(state, need, past)
let coherence = viva_emotion.emotional_coherence(state, need, past)
```
## Long-term Mood
Track mood over time with Exponential Moving Average:
```gleam
import viva_emotion
import viva_emotion/mood
import viva_emotion/stimulus
// Create state with mood tracking
let state = viva_emotion.new_with_mood()
// Feel emotions and update mood
let state = viva_emotion.EmotionalStateWithMood(
..state,
emotion: viva_emotion.feel(state.emotion, stimulus.Success, 1.0),
)
let state = viva_emotion.update_mood(state)
// Check mood
let is_happy = viva_emotion.mood_is_positive(state)
let valence = viva_emotion.mood_valence(state)
// Big Bounce: carry mood across death (80% decay)
let reborn = viva_emotion.bounce_mood(state, 0.8)
```
## Stochastic Mode
Inject external entropy for organic emotional evolution:
```gleam
// Get noise from Rust/hardware
let noise = pad.new(random_p, random_a, random_d)
// Stochastic tick
let #(state, jumped) = viva_emotion.tick_with_noise(state, 0.1, noise)
// Deterministic mode (for testing/replay)
let #(state, jumped) = viva_emotion.tick_with_noise(state, 0.1, pad.neutral())
```
## Development
```sh
gleam test # Run tests
gleam format src test # Format code
gleam build # Build
```
## Community
For questions and discussions, check:
- [GitHub Issues](https://github.com/gabrielmaialva33/viva_emotion/issues)
- [VIVA Project](https://github.com/gabrielmaialva33/viva)
## License
MIT - see [LICENSE](LICENSE) for details.