Files

252 lines
8.6 KiB
Rust

//! Basic Coherence Example
//!
//! This example demonstrates the core sheaf coherence concepts:
//! - Creating a small sheaf graph with nodes
//! - Adding edges with restriction maps
//! - Computing coherence energy
//! - Comparing coherent vs incoherent scenarios
//!
//! Run with: `cargo run --example basic_coherence`
use prime_radiant::substrate::{SheafEdgeBuilder, SheafGraph, SheafNodeBuilder, StateVector};
fn main() {
println!("=== Prime-Radiant: Basic Coherence Example ===\n");
// Example 1: Coherent Sheaf Graph
// When all nodes have consistent states, energy is low
println!("--- Example 1: Coherent Graph ---");
run_coherent_example();
println!();
// Example 2: Incoherent Sheaf Graph
// When nodes have contradictory states, energy is high
println!("--- Example 2: Incoherent Graph ---");
run_incoherent_example();
println!();
// Example 3: Mixed coherence with different edge weights
println!("--- Example 3: Weighted Edges ---");
run_weighted_example();
}
/// Demonstrates a coherent sheaf graph where all nodes agree
fn run_coherent_example() {
// Create a new sheaf graph
let graph = SheafGraph::new();
// Create nodes with similar state vectors
// In a coherent system, connected nodes should have consistent states
// that satisfy the restriction map constraints
// Node A: represents a "fact" with embedding [1.0, 0.5, 0.0, 0.2]
let node_a = SheafNodeBuilder::new()
.state(StateVector::new(vec![1.0, 0.5, 0.0, 0.2]))
.label("fact_a")
.node_type("assertion")
.namespace("knowledge")
.build();
let id_a = graph.add_node(node_a);
// Node B: represents a related "fact" with very similar embedding
let node_b = SheafNodeBuilder::new()
.state(StateVector::new(vec![1.0, 0.5, 0.0, 0.2])) // Same as A = coherent
.label("fact_b")
.node_type("assertion")
.namespace("knowledge")
.build();
let id_b = graph.add_node(node_b);
// Node C: also consistent with A and B
let node_c = SheafNodeBuilder::new()
.state(StateVector::new(vec![1.0, 0.5, 0.0, 0.2])) // Same state
.label("fact_c")
.node_type("assertion")
.namespace("knowledge")
.build();
let id_c = graph.add_node(node_c);
// Add edges with identity restriction maps
// Identity restriction means: source state should equal target state
let edge_ab = SheafEdgeBuilder::new(id_a, id_b)
.identity_restrictions(4) // 4-dimensional identity map
.weight(1.0)
.edge_type("semantic")
.build();
graph.add_edge(edge_ab).expect("Failed to add edge A->B");
let edge_bc = SheafEdgeBuilder::new(id_b, id_c)
.identity_restrictions(4)
.weight(1.0)
.edge_type("semantic")
.build();
graph.add_edge(edge_bc).expect("Failed to add edge B->C");
let edge_ca = SheafEdgeBuilder::new(id_c, id_a)
.identity_restrictions(4)
.weight(1.0)
.edge_type("semantic")
.build();
graph.add_edge(edge_ca).expect("Failed to add edge C->A");
// Compute coherence energy
let energy = graph.compute_energy();
println!("Graph with 3 coherent nodes and 3 edges:");
println!(" Nodes: fact_a, fact_b, fact_c (all identical states)");
println!(" Edges: A<->B, B<->C, C<->A (identity restrictions)");
println!();
println!("Coherence Results:");
println!(" Total Energy: {:.6}", energy.total_energy);
println!(" Node Count: {}", graph.node_count());
println!(" Edge Count: {}", energy.edge_count);
println!();
// Energy should be 0 or very close to 0 for perfectly coherent system
if energy.total_energy < 0.01 {
println!(" Status: COHERENT (energy near zero)");
} else {
println!(" Status: Some incoherence detected");
}
}
/// Demonstrates an incoherent sheaf graph where nodes contradict
fn run_incoherent_example() {
let graph = SheafGraph::new();
// Node A: represents one "fact"
let node_a = SheafNodeBuilder::new()
.state(StateVector::new(vec![1.0, 0.0, 0.0, 0.0]))
.label("claim_positive")
.node_type("assertion")
.namespace("knowledge")
.build();
let id_a = graph.add_node(node_a);
// Node B: represents a CONTRADICTORY "fact"
// This embedding is opposite to Node A
let node_b = SheafNodeBuilder::new()
.state(StateVector::new(vec![-1.0, 0.0, 0.0, 0.0])) // Opposite!
.label("claim_negative")
.node_type("assertion")
.namespace("knowledge")
.build();
let id_b = graph.add_node(node_b);
// Node C: partially different
let node_c = SheafNodeBuilder::new()
.state(StateVector::new(vec![0.0, 1.0, 0.0, 0.0])) // Orthogonal
.label("claim_other")
.node_type("assertion")
.namespace("knowledge")
.build();
let id_c = graph.add_node(node_c);
// Add edges - these constrain that states should be equal
// But they're NOT equal, so residual energy will be high
let edge_ab = SheafEdgeBuilder::new(id_a, id_b)
.identity_restrictions(4)
.weight(1.0)
.edge_type("contradiction")
.build();
graph.add_edge(edge_ab).expect("Failed to add edge A->B");
let edge_bc = SheafEdgeBuilder::new(id_b, id_c)
.identity_restrictions(4)
.weight(1.0)
.edge_type("mismatch")
.build();
graph.add_edge(edge_bc).expect("Failed to add edge B->C");
// Compute coherence energy
let energy = graph.compute_energy();
println!("Graph with 3 incoherent nodes:");
println!(" Node A: [1.0, 0.0, 0.0, 0.0] (positive claim)");
println!(" Node B: [-1.0, 0.0, 0.0, 0.0] (contradictory)");
println!(" Node C: [0.0, 1.0, 0.0, 0.0] (orthogonal)");
println!();
println!("Coherence Results:");
println!(" Total Energy: {:.6}", energy.total_energy);
println!(" Node Count: {}", graph.node_count());
println!(" Edge Count: {}", energy.edge_count);
println!();
// Show per-edge energy breakdown
println!(" Per-Edge Energy:");
for (edge_id, edge_energy) in &energy.edge_energies {
println!(" Edge {}: {:.6}", edge_id, edge_energy);
}
println!();
// Energy should be high for incoherent system
if energy.total_energy > 0.5 {
println!(" Status: INCOHERENT (high energy indicates contradiction)");
} else {
println!(" Status: Mostly coherent");
}
}
/// Demonstrates how edge weights affect coherence energy
fn run_weighted_example() {
let graph = SheafGraph::new();
// Create nodes with different states
let node_a = SheafNodeBuilder::new()
.state(StateVector::new(vec![1.0, 0.5, 0.0, 0.0]))
.label("primary")
.build();
let id_a = graph.add_node(node_a);
let node_b = SheafNodeBuilder::new()
.state(StateVector::new(vec![0.8, 0.6, 0.1, 0.0])) // Slightly different
.label("secondary")
.build();
let id_b = graph.add_node(node_b);
let node_c = SheafNodeBuilder::new()
.state(StateVector::new(vec![0.0, 0.0, 1.0, 0.0])) // Very different
.label("tertiary")
.build();
let id_c = graph.add_node(node_c);
// Edge A->B: LOW weight (we don't care much if they match)
let edge_ab = SheafEdgeBuilder::new(id_a, id_b)
.identity_restrictions(4)
.weight(0.1) // Low weight
.edge_type("weak_constraint")
.build();
graph.add_edge(edge_ab).expect("Failed to add edge A->B");
// Edge A->C: HIGH weight (important constraint)
let edge_ac = SheafEdgeBuilder::new(id_a, id_c)
.identity_restrictions(4)
.weight(5.0) // High weight
.edge_type("strong_constraint")
.build();
graph.add_edge(edge_ac).expect("Failed to add edge A->C");
let energy = graph.compute_energy();
println!("Graph demonstrating weighted edges:");
println!(" Node A: [1.0, 0.5, 0.0, 0.0]");
println!(" Node B: [0.8, 0.6, 0.1, 0.0] (slightly different)");
println!(" Node C: [0.0, 0.0, 1.0, 0.0] (very different)");
println!();
println!(" Edge A->B: weight 0.1 (weak constraint)");
println!(" Edge A->C: weight 5.0 (strong constraint)");
println!();
println!("Coherence Results:");
println!(" Total Energy: {:.6}", energy.total_energy);
println!();
println!(" Per-Edge Energy:");
for (edge_id, edge_energy) in &energy.edge_energies {
println!(" Edge {}: {:.6}", edge_id, edge_energy);
}
println!();
println!(" Notice: The high-weight edge contributes much more to total energy,");
println!(" even though A->B has a smaller residual (state difference).");
}