viva_glyph/association
Association - Hebbian learning for glyph-context mapping
VIVA learns which glyphs to “speak” in which situations through Hebbian association: “neurons that fire together wire together”
Theory
Based on Hebbian learning (Hebb, 1949) with Oja’s rule (Oja, 1982):
- When context C and glyph G co-occur with positive outcome, strengthen C→G
- Connections decay over time without reinforcement
- Winner-takes-all selection for output
Oja’s Rule (DeepSeek R1 validated)
Δw = η × (x × y - w × y²)
This provides:
- Automatic weight normalization (prevents explosion)
- Competitive learning (stronger connections dominate)
- Biologically plausible synaptic scaling
References
- Hebb (1949). The Organization of Behavior. Wiley.
- Oja (1982). Simplified neuron model as a principal component analyzer.
Types
Association between context and glyph
pub type Association {
Association(
context: Int,
glyph: glyph.Glyph,
strength: Float,
fire_count: Int,
)
}
Constructors
-
Association( context: Int, glyph: glyph.Glyph, strength: Float, fire_count: Int, )Arguments
- context
-
Context identifier
- glyph
-
Associated glyph
- strength
-
Connection strength [0.0, 1.0]
- fire_count
-
Number of times this association fired
Collection of learned associations
pub type AssociationMemory {
AssociationMemory(
associations: List(Association),
learning_rate: Float,
decay_rate: Float,
prune_threshold: Float,
learning_rule: LearningRule,
)
}
Constructors
-
AssociationMemory( associations: List(Association), learning_rate: Float, decay_rate: Float, prune_threshold: Float, learning_rule: LearningRule, )Arguments
- associations
-
All learned associations
- learning_rate
-
Learning rate for strengthening
- decay_rate
-
Decay rate per tick
- prune_threshold
-
Minimum strength before pruning
- learning_rule
-
Learning rule (Classic or Oja)
Learning rule selection
pub type LearningRule {
ClassicHebbian
OjaRule
}
Constructors
-
ClassicHebbianClassic Hebbian: Δw = η × (1 - w)
-
OjaRuleOja’s rule: Δw = η × (x × y - w × y²) - more stable
Values
pub fn contexts_for_glyph(
memory: AssociationMemory,
glyph: glyph.Glyph,
) -> List(Association)
Get associations for specific glyph (reverse lookup)
pub fn learn(
memory: AssociationMemory,
context: Int,
glyph: glyph.Glyph,
) -> AssociationMemory
Learn: reinforce context-glyph association using configured rule
pub fn memory_with_config(
learning_rate: Float,
decay_rate: Float,
prune_threshold: Float,
) -> AssociationMemory
Create association memory with custom config
pub fn memory_with_rule(
learning_rate: Float,
decay_rate: Float,
prune_threshold: Float,
rule: LearningRule,
) -> AssociationMemory
Create memory with specific learning rule
pub fn new_association(
context: Int,
glyph: glyph.Glyph,
) -> Association
Create new association
pub fn new_memory() -> AssociationMemory
Create empty association memory with default config (Oja’s rule)
pub fn recall(
memory: AssociationMemory,
context: Int,
) -> option.Option(glyph.Glyph)
Find best glyph for context (winner-takes-all)
pub fn recall_all(
memory: AssociationMemory,
context: Int,
) -> List(Association)
Find all glyphs for context, sorted by strength
pub fn strengthen(assoc: Association, rate: Float) -> Association
Strengthen an association (Classic Hebbian) Δw = η × (1 - w) - asymptotes to 1.0
pub fn strengthen_oja(
assoc: Association,
rate: Float,
) -> Association
Strengthen using Oja’s rule (more stable) Δw = η × (x × y - w × y²) For binary activation (x=1, y=1): Δw = η × (1 - w) This provides automatic normalization and competitive learning
pub fn strongest(
memory: AssociationMemory,
n: Int,
) -> List(Association)
Get strongest associations across all contexts
pub fn tick(memory: AssociationMemory) -> AssociationMemory
Tick: apply decay to all associations and prune weak ones