[![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."*

[!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 depsgleam_stdlib only
Tests 522 passing on both Erlang and JavaScript targets
Domain Affective computing, dynamical systems, info theory, optimal transport
Public APIviva_math/{scalar,common,vector,cusp,free_energy,attractor,entropy,ou,transport,ode,statistics,distributions,…}

⚑ Quick Start

gleam add viva_math
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
}
πŸ“‹ Prerequisites | 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.

πŸ—οΈ 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, …)        β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
πŸ“‹ Core modules | 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 |

🧬 Theoretical Background

PAD Model β€” Mehrabian (1996)

Emotions live as points in 3D vector space:

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 entropyH_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 affectVec3 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

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

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

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

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:

Guide Topic
PAD Emotional Model The Vec3 type, 8 basic emotion attractors, Mehrabian (1996)
Ornstein-Uhlenbeck Mood Dynamics Doob exact kernel, closed-form moments, Vec3 PAD dynamics
Wasserstein Distance 1D empirical W₁/Wβ‚‚, Gaussian closed form, sliced PAD pseudo-metric
Numerical Accuracy 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

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 for guidelines.


πŸ“– References


🌌 VIVA Ecosystem

Package Purpose
viva_mathMathematical 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

**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*