Files
el/ql/test/field_test.el
T
Will Anderson 0b480cfb6b El data studio: 10-loop improvement pass — full Engram DB explorer
Full-featured terminal explorer for the Engram knowledge graph built
natively in El. Features:
- ANSI-colored TUI with box-drawing borders and salience bars
- All API endpoints: stats, nodes by type/tier, search, edges,
  spreading activation, node detail with neighbor traversal
- Text report export via fs_write
- Offline/unreachable mode with helpful startup messages
- Interactive mode command reference
- ENGRAM_URL env var for connecting to non-default servers
- Uses json_get_raw for nested JSON object traversal
2026-04-29 04:39:40 -05:00

244 lines
11 KiB
EmacsLisp

// field_test.el Proof of concept: Hebbian field model
//
// Tests the core mechanics:
// 1. Nodes with 2D semantic positions and temporal coordinates
// 2. Edges with weights that grow via co-activation (Hebb's rule)
// 3. Spreading activation with path strength
// 4. Temporal decay in path strength
// 5. Epistemic confidence = node confidence * path strength
//
// No storage pure in-memory demonstration using print output.
// Math helpers
fn clamp_f(v: Float, lo: Float, hi: Float) -> Float {
if v < lo {
return lo
}
if v > hi {
return hi
}
return v
}
// L2 distance squared no sqrt needed for proximity comparison
fn dist_sq(ax: Float, ay: Float, bx: Float, by: Float) -> Float {
let dx: Float = ax - bx
let dy: Float = ay - by
return dx * dx + dy * dy
}
// Proximity score: 1 / (1 + dist_sq) range (0, 1], closer = higher
fn proximity(ax: Float, ay: Float, bx: Float, by: Float) -> Float {
let d: Float = dist_sq(ax, ay, bx, by)
return 1.0 / (1.0 + d)
}
// Linear temporal decay: 1.0 at t=0, decaying toward 0
// decay_rate: fraction lost per time unit
fn temporal_decay(age: Float, decay_rate: Float) -> Float {
let d: Float = 1.0 - decay_rate * age
return clamp_f(d, 0.0, 1.0)
}
// Hebbian learning
// New edge weight after co-activation event
// w_new = clamp(w + lr * a_i * a_j, 0, 1)
fn hebbian_update(weight: Float, act_i: Float, act_j: Float, lr: Float) -> Float {
let delta: Float = lr * act_i * act_j
return clamp_f(weight + delta, 0.0, 1.0)
}
// Edge decay between activations
// w_new = w * (1 - decay_rate)
fn edge_decay(weight: Float, decay_rate: Float) -> Float {
return clamp_f(weight * (1.0 - decay_rate), 0.0, 1.0)
}
// Path strength
// Path strength = edge_weight * temporal_decay(node_age)
// This is the confidence qualifier on a retrieval result
fn path_strength(edge_weight: Float, node_age: Float, decay_rate: Float) -> Float {
let td: Float = temporal_decay(node_age, decay_rate)
return edge_weight * td
}
// Epistemic confidence = node_confidence * path_strength
fn epistemic_confidence(node_confidence: Float, ps: Float) -> Float {
return node_confidence * ps
}
// Simulation
fn run_test() -> String {
println("=== Engram Field Model — Proof of Concept ===")
println("")
// Nodes
// Each node: id, label, semantic position (x, y), temporal coordinate, confidence
// Semantic space: 2D for demonstration
// x=0..1: concreteabstract
// y=0..1: negativepositive valence
println("── Nodes ──────────────────────────────────────")
println("A: 'patient has fever' pos=(0.2, 0.4) t=100")
println("B: 'influenza' pos=(0.3, 0.5) t=90")
println("C: 'drug interaction warning' pos=(0.6, 0.3) t=10 (old, unactivated)")
println("D: 'ibuprofen' pos=(0.65, 0.3) t=10 (old, unactivated)")
println("")
// Semantic positions
let ax: Float = 0.2
let ay: Float = 0.4
let bx: Float = 0.3
let by: Float = 0.5
let cx: Float = 0.6
let cy: Float = 0.3
let dx_pos: Float = 0.65
let dy_pos: Float = 0.3
// Initial proximity (latent gradient implicit from positions)
let prox_ab: Float = proximity(ax, ay, bx, by)
let prox_ac: Float = proximity(ax, ay, cx, cy)
let prox_cd: Float = proximity(cx, cy, dx_pos, dy_pos)
println("── Initial latent gradients (proximity) ───────")
println("A↔B proximity: " + float_to_str(prox_ab) + " (semantically close — fever/flu)")
println("A↔C proximity: " + float_to_str(prox_ac) + " (semantically distant)")
println("C↔D proximity: " + float_to_str(prox_cd) + " (close — drug interaction/ibuprofen)")
println("")
// Initial edge weights (all start near zero no co-activation yet)
let w_ab: Float = 0.0
let w_ac: Float = 0.0
let w_cd: Float = 0.0
println("── Initial edge weights ────────────────────────")
println("A→B: " + float_to_str(w_ab) + " (no co-activation yet)")
println("A→C: " + float_to_str(w_ac))
println("C→D: " + float_to_str(w_cd))
println("")
// Co-activation events
// The doctor CGI processes a patient with fever.
// A (fever) and B (influenza) co-activate the diagnosis fires both.
// Learning rate: 0.3
let lr: Float = 0.3
let act_strength: Float = 1.0 // full activation
println("── Co-activation event 1: patient with fever → flu diagnosis ──")
let w_ab_1: Float = hebbian_update(w_ab, act_strength, act_strength, lr)
println("A and B fire together (strength=1.0)")
println("A→B weight: " + float_to_str(w_ab) + "" + float_to_str(w_ab_1))
println("")
println("── Co-activation event 2: another flu case ──")
let w_ab_2: Float = hebbian_update(w_ab_1, act_strength, act_strength, lr)
println("A and B fire together again")
println("A→B weight: " + float_to_str(w_ab_1) + "" + float_to_str(w_ab_2))
println("")
println("── Co-activation event 3: third flu case ──")
let w_ab_3: Float = hebbian_update(w_ab_2, act_strength, act_strength, lr)
println("A and B fire together again")
println("A→B weight: " + float_to_str(w_ab_2) + "" + float_to_str(w_ab_3))
println("")
// C and D have never been activated in this context weights stay near zero
// (In practice, proximity means a latent gradient exists, but no learned edge yet)
// Query: activate A (fever), what spreads?
println("── Query: activate A (fever) ───────────────────")
println("Spreading activation from A...")
println("")
// Decay rates
let temporal_decay_rate: Float = 0.005 // per time unit
let current_t: Int = 200
// Node ages (current_t - node_t)
let age_b: Float = 110.0 // t=90, current=200
let age_c: Float = 190.0 // t=10, current=200
let age_d: Float = 190.0 // t=10, current=200
// Path strength to B: strong edge, recently relevant
let ps_b: Float = path_strength(w_ab_3, age_b, temporal_decay_rate)
let conf_b: Float = epistemic_confidence(0.9, ps_b)
// Path strength to C: no learned edge only latent proximity gradient
// Spreading activation from A can weakly reach C via proximity alone
let latent_ac: Float = prox_ac * 0.1 // proximity contributes small initial signal
let ps_c: Float = path_strength(latent_ac, age_c, temporal_decay_rate)
let conf_c: Float = epistemic_confidence(0.9, ps_c)
// Path strength to D via C: chain of weak signals
let ps_d: Float = path_strength(latent_ac * prox_cd * 0.1, age_d, temporal_decay_rate)
let conf_d: Float = epistemic_confidence(0.9, ps_d)
println("Result: B (influenza)")
println(" Edge weight: " + float_to_str(w_ab_3))
println(" Node age: " + float_to_str(age_b) + " time units")
println(" Temporal decay: " + float_to_str(temporal_decay(age_b, temporal_decay_rate)))
println(" Path strength: " + float_to_str(ps_b))
println(" Confidence: " + float_to_str(conf_b))
println(" → STRONG: B surfaces with high confidence")
println("")
println("Result: C (drug interaction warning)")
println(" Edge weight: " + float_to_str(latent_ac) + " (latent only — never co-activated)")
println(" Node age: " + float_to_str(age_c) + " time units")
println(" Temporal decay: " + float_to_str(temporal_decay(age_c, temporal_decay_rate)))
println(" Path strength: " + float_to_str(ps_c))
println(" Confidence: " + float_to_str(conf_c))
println(" → WEAK: C is distant and old — attenuated path triggers refresh signal")
println("")
println("Result: D (ibuprofen) via C")
println(" Path strength: " + float_to_str(ps_d))
println(" Confidence: " + float_to_str(conf_d))
println(" → VERY WEAK: chain of attenuated edges")
println("")
// Refresh trigger
println("── Attenuation trigger ─────────────────────────")
let threshold: Float = 0.2
println("Confidence threshold: " + float_to_str(threshold))
if conf_c < threshold {
println("C is below threshold (" + float_to_str(conf_c) + " < " + float_to_str(threshold) + ")")
println("→ Trigger: 'drug interaction warning node found but path is weak.")
println(" Last activated " + float_to_str(age_c) + " time units ago.")
println(" Recommend fetching current information before acting.'")
}
println("")
// After refresh: C and D co-activate with A
println("── Refresh: doctor looks up drug interactions ──")
println("A, C, D all co-activate during research")
let w_ac_new: Float = hebbian_update(0.0, act_strength, act_strength, lr)
let w_cd_new: Float = hebbian_update(0.0, act_strength, act_strength, lr)
let age_c_new: Float = 0.0 // just activated
let age_d_new: Float = 0.0
let ps_c_new: Float = path_strength(w_ac_new, age_c_new, temporal_decay_rate)
let conf_c_new: Float = epistemic_confidence(0.9, ps_c_new)
println("A→C weight after refresh: " + float_to_str(w_ac_new))
println("C→D weight after refresh: " + float_to_str(w_cd_new))
println("C confidence after refresh: " + float_to_str(conf_c_new))
println("→ Edges strengthened. Drug interaction now reachable with high confidence.")
println("")
println("=== Result ===")
println("Perfect memory: all nodes present throughout.")
println("Calibrated confidence: B (flu) high, C/D (drug interaction) low until refreshed.")
println("Self-correcting: attenuation triggered fetch, fetch strengthened edges.")
println("The field works.")
return "ok"
}
let result: String = run_test()