Packages

Core mathematical functions for VIVA - sentient digital life. PAD emotions, Cusp catastrophe, Free Energy Principle, attractor dynamics.

Current section

Files

Jump to
viva_math README.md
Raw

README.md

<div align="center">
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:7C3AED,100:1A1A1A&height=200&section=header&text=viva_math&fontSize=64&fontColor=fff&animation=twinkling&fontAlignY=35&desc=The%20math%20behind%20sentient%20digital%20life&descSize=18&descAlignY=55" width="100%"/>
[![Gleam](https://img.shields.io/badge/Gleam-FFAFF3?style=for-the-badge&logo=gleam&logoColor=black)](https://gleam.run/)
[![BEAM](https://img.shields.io/badge/BEAM-A90533?style=for-the-badge&logo=erlang&logoColor=white)](https://www.erlang.org/)
[![Erlang+JS](https://img.shields.io/badge/Erlang_%2B_JS-4B275F?style=for-the-badge)](https://gleam.run/news/multi-target-compilation/)
[![Hex](https://img.shields.io/badge/hex.pm-viva__math-A678DD?style=for-the-badge&logo=hex&logoColor=white)](https://hex.pm/packages/viva_math)
[![PAD](https://img.shields.io/badge/PAD-Mehrabian_1996-7C3AED?style=for-the-badge)](https://en.wikipedia.org/wiki/PAD_emotional_state_model)
[![Tests](https://img.shields.io/badge/tests-522_passing-00875A?style=for-the-badge)](./test)
[![Targets](https://img.shields.io/badge/targets-Erlang_%2B_JS-4B275F?style=for-the-badge)](./gleam.toml)
[![Version](https://img.shields.io/badge/version-1.2.102-CD5C5C?style=for-the-badge)](./CHANGELOG.md)
[![Docs](https://img.shields.io/badge/docs-hexdocs-7C3AED?style=for-the-badge)](https://hexdocs.pm/viva_math)
[![License](https://img.shields.io/badge/license-MIT-228B22?style=for-the-badge)](./LICENSE)
---
*"Numbers feel. Catastrophes are smooth. The BEAM thinks in PAD."*
</div>
---
> [!IMPORTANT]
> **viva_math IS NOT JUST A MATH LIB.**
> It is the **kernel of VIVA's affective computing stack** β€” PAD emotional
> space, Cusp catastrophe for mood transitions, Friston's Free Energy
> Principle, attractor dynamics, and information theory β€” all expressed as
> small, type-safe Gleam functions.
>
> Self-contained: depends only on `gleam_stdlib` at runtime. All
> transcendentals route through `viva_math/scalar` (Erlang `:math` BIFs).
> Targets the **BEAM (Erlang)**.
---
## 🎯 Overview
Core mathematical foundations for **VIVA** β€” a sentient digital life research
project. The library models emotional dynamics as a dynamical system: PAD
state vectors, Cusp catastrophe for sudden mood shifts, Free Energy for
interoception, and Shannon-family entropy for affective complexity.
The math is small, deliberate, and grounded in real papers (Mehrabian 1996,
Thom 1972, Friston 2010, Shannon 1948).
| Property | Value |
|:---------------|:---------------------------------------------------------------|
| **Language** | Pure Gleam (type-safe functional) |
| **Targets** | Erlang (BEAM) + JavaScript |
| **Runtime deps** | `gleam_stdlib` only |
| **Tests** | 522 passing on **both** Erlang and JavaScript targets |
| **Domain** | Affective computing, dynamical systems, info theory, optimal transport |
| **Public API** | `viva_math/{scalar,common,vector,cusp,free_energy,attractor,entropy,ou,transport,ode,statistics,distributions,…}` |
---
## ⚑ Quick Start
```sh
gleam add viva_math
```
```gleam
import viva_math/attractor
import viva_math/cusp
import viva_math/free_energy
import viva_math/ou
import viva_math/random
import viva_math/transport
import viva_math/vector
pub fn main() {
// PAD emotional state: Pleasure / Arousal / Dominance
let state = vector.pad(-0.3, 0.7, -0.2)
// Nearest discrete emotion
let _ = attractor.classify_emotion(state)
// -> "fear"
// Bistability check β€” sudden mood transition possible?
let cusp_params = cusp.from_arousal_dominance(0.7, -0.2)
let _ = cusp.is_bistable(cusp_params)
// -> True
// Free energy (prediction error vs baseline).
let baseline = vector.pad(0.0, 0.0, 0.0)
let fe = free_energy.compute_state_simple(baseline, state, baseline, 0.1)
// fe.feeling -> Alarmed | Overwhelmed
// Ornstein-Uhlenbeck mood dynamics β€” mean-reverting noise.
let ou_params = ou.OUParams1D(theta: 1.0, mu: 0.5, sigma: 0.2)
let seed = random.from_int(42)
let #(trajectory, _) = ou.simulate(ou_params, 0.0, 0.01, 1000, seed)
// trajectory: List(Float) of length 1000
// Wasserstein distance between two populations.
let assert Ok(w2) =
transport.wasserstein_2_empirical([0.0, 0.5, 1.0], [0.2, 0.4, 0.8])
// w2 β‰ˆ 0.158
}
```
<details>
<summary><strong>πŸ“‹ Prerequisites</strong></summary>
| Tool | Version | Required for |
|:-----------|:---------|:-----------------|
| Gleam | `>= 1.4` | Build / runtime |
| Erlang/OTP | `>= 26` | BEAM target |
| Node.js | `>= 18` | JS target (opt.) |
Zero NIFs. Zero C dependencies. Pure functional.
</details>
---
## πŸ—οΈ Architecture
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Gleam application code β”‚
β”‚ viva_math/{common,vector,...} β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ viva_math modules β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ common β”‚ β”‚ vector β”‚ β”‚ cusp β”‚ β”‚ free_energy β”‚ β”‚
β”‚ β”‚ clamp β”‚ β”‚ Vec3 β”‚ β”‚ Thom β”‚ β”‚ Friston β”‚ β”‚
β”‚ β”‚ sigmoidβ”‚ β”‚ PAD ℝ³ β”‚ β”‚ 1972 β”‚ β”‚ 2010 β”‚ β”‚
β”‚ β”‚ noise β”‚ β”‚ ops β”‚ β”‚ stoch. β”‚ β”‚ homeostasis β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ attractor β”‚ β”‚ entropy β”‚ β”‚
β”‚ β”‚ Mehrabian β”‚ β”‚ Shannon Β· KL β”‚ β”‚
β”‚ β”‚ 1996 β”‚ β”‚ JS Β· RΓ©nyi β”‚ β”‚
β”‚ β”‚ 8 emotions β”‚ β”‚ hybrid affect. β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ gleam_community_maths (trig, stats, …) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
<details>
<summary><strong>πŸ“‹ Core modules</strong></summary>
| Module | Purpose |
|:------------------------|:--------------------------------------------------------------------------|
| `viva_math/common` | `clamp`, `sigmoid`, `softmax`, `lerp`, `smoothstep`, Wiener noise, decays |
| `viva_math/vector` | `Vec3` PAD type β€” Pleasure / Arousal / Dominance space |
| `viva_math/cusp` | Cusp catastrophe (Thom 1972) + Stochastic Cusp (Euler-Maruyama) |
| `viva_math/free_energy` | Free Energy Principle (Friston 2010) β€” interoception |
| `viva_math/attractor` | 8 basic-emotion attractors in PAD space (Mehrabian 1996) |
| `viva_math/entropy` | Shannon, KL divergence, Jensen-Shannon, RΓ©nyi, hybrid affective |
</details>
---
## 🧬 Theoretical Background
### PAD Model β€” Mehrabian (1996)
Emotions live as points in 3D vector space:
- **Pleasure** `[-1, 1]` β€” sadness ↔ joy
- **Arousal** `[-1, 1]` β€” calm ↔ excitement
- **Dominance** `[-1, 1]` β€” submission ↔ control
### Cusp Catastrophe β€” Thom (1972)
Sudden mood transitions modeled by the potential:
```
V(x) = x⁴/4 + αx²/2 + βx
```
When arousal pushes `Ξ± < 0` and the discriminant `Ξ” > 0`, the system goes
**bistable** β€” tiny perturbations trigger discrete mood jumps. The stochastic
variant adds Wiener noise (`dV/dx + σξ(t)`) integrated via Euler-Maruyama.
### Free Energy Principle β€” Friston (2010)
Agents minimize "surprise" via prediction:
```
F β‰ˆ Prediction_ErrorΒ² + Complexity
```
Low free energy β†’ predictions match reality (homeostasis).
High free energy β†’ significant mismatch (alarm).
### Attractor Dynamics
Eight basic emotions form attractors in PAD space:
| Emotion | P | A | D |
|:-----------|--------:|--------:|--------:|
| Joy | `+0.76` | `+0.48` | `+0.35` |
| Sadness | `-0.63` | `-0.27` | `-0.33` |
| Fear | `-0.64` | `+0.60` | `-0.43` |
| Anger | `-0.51` | `+0.59` | `+0.25` |
| Trust | `+0.58` | `-0.23` | `+0.42` |
| Disgust | `-0.60` | `+0.35` | `+0.11` |
| Serenity | `+0.45` | `-0.42` | `+0.21` |
| Excitement | `+0.62` | `+0.75` | `+0.38` |
### Information Theory β€” Shannon (1948) + extensions
Shannon entropy `H(p)`, KL divergence `D(pβ€–q)`, Jensen-Shannon `JS(p,q)`,
RΓ©nyi `H_Ξ±`, and a **hybrid affective entropy**
`H_hybrid = Ξ±H₁ + (1-Ξ±)Hβ‚‚` for mixed emotional states.
---
## 🎨 Design Principles
| Principle | Description |
|:--------------------------------|:--------------------------------------------------------------|
| **Math grounded in papers** | Every function cites the source (Thom, Friston, Mehrabian, …) |
| **Type-safe affect** | `Vec3` constructor enforces PAD axis order at compile time |
| **Multi-target** | Same code runs on BEAM and in the browser via JS target |
| **Small surface, deep meaning** | 6 modules, ~60 public functions β€” nothing speculative |
| **Zero runtime deps** | Builds only on `gleam_stdlib` (self-contained since 1.2.101) |
---
## πŸ“š Public API Highlights
### Vec3 / PAD space
```gleam
import viva_math/vector
let v = vector.pad(0.5, -0.2, 0.7)
let mag = vector.magnitude(v)
let unit = vector.normalize(v)
let dist = vector.euclidean(v, vector.pad(0.0, 0.0, 0.0))
```
### Cusp catastrophe β€” deterministic + stochastic
```gleam
import viva_math/cusp
let params = cusp.from_arousal_dominance(0.7, -0.2)
let v = cusp.potential(params, 0.3) // V(x)
let g = cusp.gradient(params, 0.3) // dV/dx
// Stochastic mood walk
let trajectory =
cusp.simulate_stochastic(
cusp.StochasticCuspParams(params, sigma: 0.05, seed: 42),
start: 0.0,
steps: 1000,
dt: 0.01,
)
```
### Free Energy
```gleam
import viva_math/free_energy
import viva_math/vector
let expected = vector.pad(0.0, 0.0, 0.0)
let actual = vector.pad(-0.3, 0.7, -0.2)
let state = free_energy.compute_state(expected, actual, expected, 0.1)
// state.feeling -> Calm | Surprised | Alarmed
// state.free_energy -> Float
```
### Entropy and divergence
```gleam
import viva_math/entropy
let h = entropy.shannon([0.2, 0.3, 0.5])
let d = entropy.kl_divergence([0.2, 0.8], [0.5, 0.5])
let js = entropy.jensen_shannon([0.2, 0.8], [0.5, 0.5])
let r = entropy.renyi([0.2, 0.3, 0.5], alpha: 2.0)
```
---
## πŸ“š Guides
Conceptual guides published alongside the API reference on
[hexdocs.pm/viva_math](https://hexdocs.pm/viva_math):
| Guide | Topic |
|---|---|
| [PAD Emotional Model](./docs/pad-model.md) | The `Vec3` type, 8 basic emotion attractors, Mehrabian (1996) |
| [Ornstein-Uhlenbeck Mood Dynamics](./docs/ou-dynamics.md) | Doob exact kernel, closed-form moments, Vec3 PAD dynamics |
| [Wasserstein Distance](./docs/wasserstein.md) | 1D empirical W₁/Wβ‚‚, Gaussian closed form, sliced PAD pseudo-metric |
| [Numerical Accuracy](./docs/numerical-accuracy.md) | Tolerance regimes, cancellation defences, measured precision per function |
---
## πŸ—ΊοΈ Roadmap
| Phase | Status |
|:-----------------------------------------------------|:------:|
| PAD vector space + emotion attractors | βœ… |
| Deterministic Cusp catastrophe | βœ… |
| Stochastic Cusp (Wiener + Euler-Maruyama) | βœ… |
| Free Energy Principle (basic interoception) | βœ… |
| Shannon / KL / Jensen-Shannon / RΓ©nyi entropy | βœ… |
| Hybrid affective entropy | βœ… |
| Arousal-weighted KL sensitivity | βœ… |
| Ornstein-Uhlenbeck mood dynamics | βœ… |
| Variational Free Energy (deeper Bayesian model) | βœ… |
| Wasserstein distance between affective distributions | βœ… |
| Property-based tests on every closed form | βœ… |
| Multivariate Wasserstein (log-domain Sinkhorn + early stop) | βœ… |
| ULP-by-ULP `mpmath` reference validation | βœ… |
| JavaScript target β€” full module coverage | βœ… |
| `digamma` ≀5 ULP precision | βœ… |
---
## 🀝 Contributing
```bash
git checkout -b feature/your-feature
gleam test # 522 tests (Erlang, default)
gleam test --target javascript # 522 tests (JavaScript)
gleam format --check src test
gleam docs build
```
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
---
## πŸ“– References
- Mehrabian (1996) β€” *Pleasure-arousal-dominance: A general framework*
- Thom (1972) β€” *Structural Stability and Morphogenesis*
- Friston (2010) β€” *The free-energy principle: a unified brain theory?*
- Grasman et al. (2009) β€” *Fitting the Cusp Catastrophe in R*
- Oravecz et al. (2009) β€” *Ornstein-Uhlenbeck Process in Affective Dynamics*
- Shannon (1948) β€” *A Mathematical Theory of Communication*
---
## 🌌 VIVA Ecosystem
| Package | Purpose |
|:-----------------|:--------------------------------------------|
| **`viva_math`** | **Mathematical foundations (this package)** |
| `viva_emotion` | PAD emotional dynamics |
| `viva_tensor` | FP8 LLM inference on the BEAM |
| `viva_telemetry` | Observability suite |
| `viva_aion` | Time perception |
| `viva_glyph` | Symbolic language |
---
<div align="center">
**Star if math should feel like something ⭐**
[![GitHub stars](https://img.shields.io/github/stars/gabrielmaialva33/viva_math?style=social)](https://github.com/gabrielmaialva33/viva_math)
*Created by Gabriel Maia Β· MIT License*
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:1A1A1A,100:7C3AED&height=100&section=footer" width="100%"/>
</div>