griot-math
Living memory mathematics — West African griot oral tradition as exponential decay, genealogy trees, and federated memory.
What This Does
griot-math implements the mathematics of oral memory systems inspired by West African griots (storytellers, historians, praise singers). It models stories with importance-weighted exponential decay, genealogy trees tracking story lineage, praise names as lossy compression of memory, call-and-response protocols for memory similarity, and federated memory networks where multiple griots sync and merge their memories. Use it for caching systems with cultural decay models, knowledge graph lineage tracking, or distributed consensus on shared narratives.
The Cultural Root
Griots (jali in Mandinka) are West African oral historians who maintain genealogies, histories, and cultural knowledge across generations. Stories told more frequently are remembered better; stories that aren't told decay. The mathematical insight: memory follows exponential decay weighted by retelling frequency — identical to how reinforcement learning weights recent rewards. Praise names compress a griot's entire repertoire into a single dense identifier, like a hash of a merkle tree.
Install
pip install griot-math
Quick Start
from griotmath.memory import Griot, Story
from griotmath.genealogy import genealogy, descendants, tradition_score
from griotmath.praise import generate_praise_name
from griotmath.call_response import call_and_response
from griotmath.federation import Federation
# Create a griot and add stories
griot = Griot(name="village-keeper")
s1 = griot.add_story("The founding of the village", weight=1.0, tags=["history", "origin"])
s2 = griot.add_story("The great flood", weight=0.8, parent_id=s1, tags=["disaster"])
s3 = griot.add_story("Rebuilding after the flood", weight=0.9, parent_id=s2, tags=["recovery"])
# Tell a story — boosts its weight
griot.tell_story(s1)
griot.tell_story(s1) # telling again makes it stronger
# Apply time-based decay
griot.apply_decay(rate=0.01) # decay based on time since each story was last told
# Check memory strengths
strengths = griot.memory_strengths()
# Genealogy — trace story lineage
path = genealogy(griot, s3)
# [s1, s2, s3] — from root to the given story
kids = descendants(griot, s1)
# [s2, s3] — all descendants
score = tradition_score(griot) # 0.0–1.0 depth/breadth score
# Praise name — compress stories into a dense identifier
praise = generate_praise_name(griot, story_ids=[s1, s2, s3], name="Keeper of Origins")
print(f"Compression ratio: {praise.compression_ratio:.2f}")
print(f"Density: {praise.density:.2f}")
# Call and response between griots
griot2 = Griot(name="traveler")
griot2.add_story("The great flood", weight=0.5)
griot2.add_story("A different flood story", weight=0.3)
result = call_and_response(griot, griot2, story_id=s2)
print(f"Similarity: {result.similarity:.2f}")
print(f"Matched: {result.responder_name}")
# Federation — distributed memory
fed = Federation()
fed.add_griot(griot)
fed.add_griot(griot2)
sync = fed.sync_story(from_name="griot-0", to_name="griot-1", story_id=s2)
merge = fed.merge_memories(source_name="griot-0", target_name="griot-1")
print(f"Total stories: {fed.total_stories()}")
API Reference
memory module
Story
@dataclass
class Story:
id: str
content: str
weight: float # Importance (0–∞)
tags: list[str]
parent_id: str | None
tell_count: int # Times told
created_at: float # Timestamp
last_told_at: float
def tell(self) -> None # Increment tell count, boost weight
def age(self) -> float # Seconds since creation
def time_since_told(self) -> float
Griot
class Griot:
def add_story(self, content, weight=1.0, parent_id=None, tags=None) -> str
def get_story(self, story_id) -> Story | None
def tell_story(self, story_id) -> str
def apply_decay(self, rate=0.01, elapsed=None) → None
def memory_strengths(self) → dict[str, float]
def stories_by_tag(self, tag) → list[Story]
def all_tags(self) → set[str]
def story_count(self) → int
genealogy module
genealogy(griot, story_id) → list[str]
All ancestry paths from root to the given story.
descendants(griot, story_id) → list[str]
All descendant story IDs (breadth-first).
tradition_score(griot) → float
0.0–1.0 score based on genealogy tree depth and breadth.
praise module
PraiseName
@dataclass
class PraiseName:
name: str
story_ids: list[str]
compression_ratio: float
density: float
generate_praise_name(griot, story_ids=None, name=None) → PraiseName
Compress selected stories into a praise name. Compression ratio = total weight / count. Density = weight concentration.
call_response module
CallResponse
@dataclass
class CallResponse:
caller_name: str
responder_name: str
caller_story: str
responder_story: str
similarity: float # Jaccard similarity
call_and_response(caller, responder, caller_story_id) → CallResponse
The caller tells a story; the responder finds the closest match by tag overlap (Jaccard similarity).
federation module
Federation
class Federation:
def add_griot(self, griot) → None
def remove_griot(self, name) → None
def get_griot(self, name) → Griot | None
def griot_names(self) → list[str]
def size(self) → int
def sync_story(self, from_name, to_name, story_id) → SyncResult
def merge_memories(self, source_name, target_name) → MergeResult
def total_stories(self) → int
SyncResult
Result of syncing one story between griots.
MergeResult
Result of merging all stories: added, updated, skipped, conflicts.
How It Works
Memory Decay: Each story has a weight that decays exponentially: w(t) = w₀ · e^(−λ·Δt), where λ is the decay rate and Δt is time since last telling. Telling a story boosts its weight by a fixed increment, counteracting decay.
Genealogy: Stories form a tree via parent_id. Genealogy traces ancestry paths; descendants uses BFS. Tradition score normalizes depth × breadth to [0, 1].
Praise Names: A lossy compression of multiple stories into a single identifier. Compression ratio = Σ weights / n. Density = max weight / total weight. A good praise name has high density (concentrated meaning).
Call-and-Response: Uses Jaccard similarity on tag sets: J(A, B) = |A ∩ B| / |A ∪ B|. The responder returns the story with highest tag overlap.
Federation: Distributed memory with sync (copy one story) and merge (copy all with conflict resolution — keep higher weight on conflict).
The Math
Exponential Decay: w(t + Δt) = w(t) · e^(−λΔt). This is the same model as radioactive decay, capacitor discharge, and discount factors in reinforcement learning.
Jaccard Similarity: J(A, B) = |A ∩ B| / |A ∪ B| ∈ [0, 1].
Tradition Score: Based on tree depth and breadth, normalized: score = f(max_depth, max_breadth, n_stories) ∈ [0, 1].
License
MIT
Metadata
Release files for griot-math 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| griot_math-0.1.1.tar.gz | 12.6 kB | Without provenance | Details for griot_math-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| griot_math-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for griot_math-0.1.1-py3-none-any.whl |
Total release size: 24.4 kB
Release files / griot_math-0.1.1.tar.gz
| Download URL | griot_math-0.1.1.tar.gz |
|---|---|
| Size | 12.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
81207ec540211719d87280281bfda6007f0dc2db3ba04be979dcde5411c01869
|
|
BLAKE2b-256 checksum How to use checksums |
82170be7f3dd90bbd191c65d4ad78a95f0c7cf8784e7cce0f1fc888c04d7adf1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.12
|
Release files / griot_math-0.1.1-py3-none-any.whl
| Download URL | griot_math-0.1.1-py3-none-any.whl |
|---|---|
| Size | 11.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
928013a84a19427b6987016dc8f2cf2270b17054250ca4902987615f53c5379b
|
|
BLAKE2b-256 checksum How to use checksums |
db2af9a1f3780204171434b10eba9b3cf6ae0b41d8c878d8ef264a311b90bcbe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.12
|
Security for griot-math 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.