diff --git a/docs/cognitive-frontier/federated-strange-loops.md b/docs/cognitive-frontier/federated-strange-loops.md new file mode 100644 index 00000000..728e6eac --- /dev/null +++ b/docs/cognitive-frontier/federated-strange-loops.md @@ -0,0 +1,437 @@ +# Federated Strange Loops: Multiple Systems Observing Each Other + +## Overview + +Federated Strange Loops extend the single-system self-observation pattern to **multiple autonomous graph systems** that observe, model, and influence each other. This creates emergent collective intelligence through mutual meta-cognition. + +## Core Concept + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ FEDERATED STRANGE LOOP NETWORK │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ │ CLUSTER A │ │ CLUSTER B │ │ CLUSTER C │ +│ │ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │ +│ │ │ Level 2 │◄─┼────────►│ │ Level 2 │◄─┼────────►│ │ Level 2 │ │ +│ │ │ (Meta) │ │ OBSERVE │ │ (Meta) │ │ OBSERVE │ │ (Meta) │ │ +│ │ └─────┬─────┘ │ │ └─────┬─────┘ │ │ └─────┬─────┘ │ +│ │ │ │ │ │ │ │ │ │ +│ │ ┌─────▼─────┐ │ │ ┌─────▼─────┐ │ │ ┌─────▼─────┐ │ +│ │ │ Level 1 │ │ │ │ Level 1 │ │ │ │ Level 1 │ │ +│ │ │ (Observer)│ │ │ │ (Observer)│ │ │ │ (Observer)│ │ +│ │ └─────┬─────┘ │ │ └─────┬─────┘ │ │ └─────┬─────┘ │ +│ │ │ │ │ │ │ │ │ │ +│ │ ┌─────▼─────┐ │ │ ┌─────▼─────┐ │ │ ┌─────▼─────┐ │ +│ │ │ Level 0 │ │ │ │ Level 0 │ │ │ │ Level 0 │ │ +│ │ │ (Graph) │ │ │ │ (Graph) │ │ │ │ (Graph) │ │ +│ │ └───────────┘ │ │ └───────────┘ │ │ └───────────┘ │ +│ └─────────────────┘ └─────────────────┘ └─────────────────┘ +│ │ │ │ +│ └──────────────────────────┴──────────────────────────┘ +│ │ +│ ┌─────────────▼─────────────┐ +│ │ FEDERATION META-LOOP │ +│ │ • Observes all clusters │ +│ │ • Detects global patterns│ +│ │ • Coordinates actions │ +│ └───────────────────────────┘ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +## Architecture + +### 1. Cluster-Level Strange Loop (Existing) + +Each cluster maintains its own strange loop: +- **Level 0**: Object graph (nodes, edges, hyperedges) +- **Level 1**: Observer SNN (spikes encode graph statistics) +- **Level 2**: Meta-neurons (decide strengthen/prune/restructure) + +### 2. Federation Observation Layer + +New layer that observes other clusters' Level 2 outputs: + +```rust +// crates/ruvector-graph/src/distributed/federated_loop.rs + +/// Observation of a remote cluster's meta-state +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ClusterObservation { + /// Source cluster ID + pub cluster_id: ClusterId, + /// Timestamp of observation + pub timestamp: DateTime, + /// Level 2 meta-neuron states + pub meta_states: Vec, + /// Recent actions taken + pub recent_actions: Vec, + /// MinCut value + pub mincut: f64, + /// Global synchrony + pub synchrony: f64, + /// Graph statistics + pub stats: GraphStats, +} + +/// Federation-level strange loop +pub struct FederatedStrangeLoop { + /// Local cluster's strange loop + local_loop: MetaCognitiveMinCut, + + /// Registry of remote clusters + cluster_registry: ClusterRegistry, + + /// Observations of remote clusters + remote_observations: HashMap>, + + /// Federation-level meta-neurons (Level 3) + federation_meta: Vec, + + /// Cross-cluster influence matrix + cross_influence: CrossClusterInfluence, + + /// Consensus protocol for coordinated actions + consensus: FederationConsensus, +} +``` + +### 3. Observation Protocol + +```rust +/// Protocol for clusters observing each other +pub struct ObservationProtocol { + /// Observation frequency (ms) + pub interval_ms: u64, + /// Maximum observation history per cluster + pub max_history: usize, + /// Observation timeout + pub timeout_ms: u64, + /// Encryption for observations + pub encrypt: bool, +} + +impl FederatedStrangeLoop { + /// Observe a remote cluster + pub async fn observe_cluster(&mut self, cluster_id: &ClusterId) -> Result { + let cluster = self.cluster_registry.get_cluster(cluster_id)?; + + // Request observation via RPC + let response = self.rpc_client.observe(&cluster.endpoint).await?; + + let observation = ClusterObservation { + cluster_id: cluster_id.clone(), + timestamp: Utc::now(), + meta_states: response.meta_states, + recent_actions: response.recent_actions, + mincut: response.mincut, + synchrony: response.synchrony, + stats: response.stats, + }; + + // Store observation + self.remote_observations + .entry(cluster_id.clone()) + .or_insert_with(VecDeque::new) + .push_back(observation.clone()); + + Ok(observation) + } + + /// Expose local state for remote observation + pub fn expose_for_observation(&self) -> ObservationResponse { + let (l0, l1, l2) = self.local_loop.level_summary(); + + ObservationResponse { + meta_states: self.local_loop.meta_neurons() + .iter() + .map(|m| m.state) + .collect(), + recent_actions: self.local_loop.action_history() + .iter() + .rev() + .take(10) + .cloned() + .collect(), + mincut: l0, + synchrony: l1, + stats: self.local_loop.graph().stats(), + } + } +} +``` + +### 4. Federation Meta-Neurons (Level 3) + +```rust +/// Meta-neuron that observes multiple clusters +pub struct FederationMetaNeuron { + /// Neuron ID + pub id: usize, + /// Weights for each cluster's observation + pub cluster_weights: HashMap, + /// Internal state + pub state: f64, + /// Decision threshold + pub threshold: f64, + /// History of cross-cluster correlations + pub correlation_history: VecDeque, +} + +impl FederationMetaNeuron { + /// Process observations from all clusters + pub fn process_observations( + &mut self, + observations: &HashMap, + ) -> FederationAction { + // Compute weighted sum of cluster states + let mut weighted_sum = 0.0; + let mut total_weight = 0.0; + + for (cluster_id, obs) in observations { + let weight = self.cluster_weights.get(cluster_id).copied().unwrap_or(1.0); + let cluster_state: f64 = obs.meta_states.iter().sum::() + / obs.meta_states.len() as f64; + + weighted_sum += weight * cluster_state; + total_weight += weight; + } + + self.state = if total_weight > 0.0 { + weighted_sum / total_weight + } else { + 0.0 + }; + + // Compute cross-cluster correlations + let correlation = self.compute_cross_correlation(observations); + self.correlation_history.push_back(correlation); + + // Decide federation-level action + self.decide_action() + } + + fn decide_action(&self) -> FederationAction { + if self.state > self.threshold { + // Clusters are diverging - coordinate + FederationAction::Coordinate(CoordinationStrategy::Align) + } else if self.state < -self.threshold { + // Clusters are converging - allow specialization + FederationAction::Coordinate(CoordinationStrategy::Specialize) + } else if self.detect_oscillation() { + // Unstable dynamics - dampen + FederationAction::Coordinate(CoordinationStrategy::Dampen) + } else { + FederationAction::NoOp + } + } +} +``` + +### 5. Cross-Cluster Influence + +```rust +/// How clusters influence each other +pub struct CrossClusterInfluence { + /// Influence matrix: cluster_i → cluster_j + pub influence: HashMap<(ClusterId, ClusterId), f64>, + /// Learning rate for influence updates + pub learning_rate: f64, +} + +impl CrossClusterInfluence { + /// Update influence based on observed correlations + pub fn update(&mut self, correlations: &[CrossClusterCorrelation]) { + for corr in correlations { + let key = (corr.cluster_a.clone(), corr.cluster_b.clone()); + let current = self.influence.get(&key).copied().unwrap_or(0.0); + + // STDP-like update: strengthen if correlated actions succeed + let delta = self.learning_rate * corr.success_correlation; + self.influence.insert(key, current + delta); + } + } + + /// Get recommended action for cluster based on federation state + pub fn recommend_action( + &self, + cluster_id: &ClusterId, + federation_state: &FederationState, + ) -> Option { + // Find most influential cluster + let mut max_influence = 0.0; + let mut influential_cluster = None; + + for ((from, to), &influence) in &self.influence { + if to == cluster_id && influence > max_influence { + max_influence = influence; + influential_cluster = Some(from.clone()); + } + } + + // Recommend action similar to influential cluster + if let Some(inf_cluster) = influential_cluster { + federation_state.last_action(&inf_cluster) + } else { + None + } + } +} +``` + +### 6. Consensus for Coordinated Actions + +```rust +/// Consensus protocol for federation-wide actions +pub struct FederationConsensus { + /// Consensus algorithm + pub algorithm: ConsensusAlgorithm, + /// Quorum size + pub quorum: usize, + /// Timeout for consensus + pub timeout_ms: u64, +} + +pub enum ConsensusAlgorithm { + /// Simple majority voting + Majority, + /// Raft-based consensus + Raft, + /// Byzantine fault tolerant + PBFT, + /// Spike-timing based (novel!) + SpikeConsensus, +} + +impl FederationConsensus { + /// Propose a federation-wide action + pub async fn propose(&self, action: FederationAction) -> Result { + match self.algorithm { + ConsensusAlgorithm::SpikeConsensus => { + // Novel: use spike synchrony for consensus + self.spike_consensus(action).await + } + _ => self.traditional_consensus(action).await, + } + } + + /// Spike-timing based consensus + /// Clusters "vote" by emitting spikes; synchronized spikes = agreement + async fn spike_consensus(&self, action: FederationAction) -> Result { + // Broadcast proposal as spike pattern + let proposal_spikes = self.encode_action_as_spikes(&action); + self.broadcast_spikes(&proposal_spikes).await?; + + // Collect response spikes from all clusters + let response_spikes = self.collect_response_spikes().await?; + + // Compute synchrony of responses + let synchrony = compute_cross_cluster_synchrony(&response_spikes); + + if synchrony > 0.8 { + Ok(ConsensusResult::Agreed(action)) + } else if synchrony > 0.5 { + Ok(ConsensusResult::PartialAgreement(action, synchrony)) + } else { + Ok(ConsensusResult::Rejected) + } + } +} +``` + +### 7. Emergent Collective Behaviors + +```rust +/// Emergent patterns in federated strange loops +pub enum EmergentPattern { + /// All clusters converge to similar structure + GlobalConvergence, + /// Clusters specialize into complementary roles + Specialization { roles: HashMap }, + /// Periodic coordinated oscillation + CollectiveOscillation { period_ms: u64 }, + /// Hierarchical organization emerges + Hierarchy { leader: ClusterId, followers: Vec }, + /// Chaotic dynamics (no stable pattern) + Chaos, +} + +impl FederatedStrangeLoop { + /// Detect emergent patterns across federation + pub fn detect_emergent_pattern(&self) -> EmergentPattern { + let observations = self.collect_all_observations(); + + // Check for convergence + if self.is_converging(&observations) { + return EmergentPattern::GlobalConvergence; + } + + // Check for specialization + if let Some(roles) = self.detect_specialization(&observations) { + return EmergentPattern::Specialization { roles }; + } + + // Check for oscillation + if let Some(period) = self.detect_collective_oscillation(&observations) { + return EmergentPattern::CollectiveOscillation { period_ms: period }; + } + + // Check for hierarchy + if let Some((leader, followers)) = self.detect_hierarchy(&observations) { + return EmergentPattern::Hierarchy { leader, followers }; + } + + EmergentPattern::Chaos + } +} +``` + +## Implementation Phases + +### Phase 1: Observation Infrastructure +- [ ] Implement `ClusterObservation` RPC protocol +- [ ] Add observation endpoints to federation layer +- [ ] Create observation history storage +- [ ] Implement basic health-aware observation + +### Phase 2: Federation Meta-Neurons +- [ ] Implement `FederationMetaNeuron` structure +- [ ] Create cross-cluster correlation computation +- [ ] Add federation-level decision logic +- [ ] Implement influence matrix learning + +### Phase 3: Consensus Integration +- [ ] Implement spike-based consensus protocol +- [ ] Add traditional fallback consensus +- [ ] Create action coordination pipeline +- [ ] Test multi-cluster agreement + +### Phase 4: Emergent Pattern Detection +- [ ] Implement pattern detection algorithms +- [ ] Add pattern-based adaptive behavior +- [ ] Create visualization for patterns +- [ ] Benchmark collective dynamics + +## Key Metrics + +| Metric | Target | Description | +|--------|--------|-------------| +| Observation Latency | < 10ms | Time to observe remote cluster | +| Consensus Time | < 100ms | Time to reach agreement | +| Pattern Detection | < 1s | Time to identify emergent pattern | +| Cross-Cluster Sync | > 0.7 | Spike synchrony across federation | + +## Novel Research Contributions + +1. **Spike-Based Distributed Consensus**: Using neural synchrony instead of message passing +2. **Emergent Role Specialization**: Clusters naturally specialize based on mutual observation +3. **Hierarchical Self-Organization**: Leadership emerges from strange loop dynamics +4. **Collective Meta-Cognition**: Federation-level self-awareness + +## References + +- Hofstadter, D. (1979). *Gödel, Escher, Bach: An Eternal Golden Braid* +- Minsky, M. (1986). *The Society of Mind* +- Baars, B. (1988). *A Cognitive Theory of Consciousness* +- Tononi, G. (2008). *Consciousness as Integrated Information* diff --git a/docs/cognitive-frontier/temporal-hypergraphs.md b/docs/cognitive-frontier/temporal-hypergraphs.md new file mode 100644 index 00000000..0773e149 --- /dev/null +++ b/docs/cognitive-frontier/temporal-hypergraphs.md @@ -0,0 +1,614 @@ +# Temporal Hypergraphs: Time-Varying Hyperedges with Causal Constraints + +## Overview + +Temporal Hypergraphs extend standard hyperedges with **time-varying validity**, **causal ordering constraints**, and **spike-timing based temporal reasoning**. This enables modeling of complex temporal relationships where multiple entities participate in events that have duration, ordering, and causal dependencies. + +## Core Concept + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ TEMPORAL HYPERGRAPH │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ TIME ──────────────────────────────────────────────────────────────────► │ +│ t₀ t₁ t₂ t₃ t₄ t₅ │ +│ │ │ │ │ │ │ │ +│ ┌─────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────┐ │ +│ │ HYPEREDGE H₁ │ │ +│ │ ┌───────────────────────────────────────┐ │ │ +│ │ │ Nodes: {A, B, C} │ │ │ +│ │ │ Valid: [t₀, t₃) │ │ │ +│ │ │ Type: "MEETING" │ │ │ +│ │ └───────────────────────────────────────┘ │ │ +│ │ │ │ │ +│ │ │ CAUSES (Δt = t₂ - t₀) │ │ +│ │ ▼ │ │ +│ │ ┌───────────────────────────────────────────────────┐ │ │ +│ │ │ HYPEREDGE H₂ │ │ │ +│ │ │ Nodes: {B, D, E} │ │ │ +│ │ │ Valid: [t₂, t₅) │ │ │ +│ │ │ Type: "PROJECT" │ │ │ +│ │ │ Constraint: AFTER(H₁) │ │ │ +│ │ └───────────────────────────────────────────────────┘ │ │ +│ └──────────────────────────────────────────────────────────────┘ │ +│ │ +│ CAUSAL GRAPH: H₁ ───causes───► H₂ ───prevents───► H₃ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +## Data Structures + +### 1. Temporal Hyperedge + +```rust +// crates/ruvector-graph/src/temporal/hyperedge.rs + +use chrono::{DateTime, Utc, Duration}; + +/// Temporal validity interval +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TemporalInterval { + /// Start time (inclusive) + pub start: DateTime, + /// End time (exclusive), None = ongoing + pub end: Option>, + /// Validity type + pub validity: ValidityType, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum ValidityType { + /// Hyperedge exists during interval + Exists, + /// Hyperedge is valid/active during interval + Valid, + /// Hyperedge is scheduled for interval + Scheduled, + /// Hyperedge was true during interval (historical) + Historical, +} + +impl TemporalInterval { + /// Check if interval contains a point in time + pub fn contains(&self, t: DateTime) -> bool { + t >= self.start && self.end.map(|e| t < e).unwrap_or(true) + } + + /// Check if intervals overlap + pub fn overlaps(&self, other: &TemporalInterval) -> bool { + let self_end = self.end.unwrap_or(DateTime::::MAX_UTC); + let other_end = other.end.unwrap_or(DateTime::::MAX_UTC); + + self.start < other_end && other.start < self_end + } + + /// Allen's interval algebra relations + pub fn relation(&self, other: &TemporalInterval) -> AllenRelation { + // Implement all 13 Allen relations + // before, meets, overlaps, starts, during, finishes, equals, etc. + todo!() + } +} + +/// Hyperedge with temporal dimension +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TemporalHyperedge { + /// Base hyperedge + pub hyperedge: Hyperedge, + + /// Temporal validity intervals (can have multiple) + pub intervals: Vec, + + /// Causal constraints + pub causal_constraints: Vec, + + /// Temporal properties (can vary over time) + pub temporal_properties: HashMap, + + /// Version history + pub versions: Vec, + + /// Spike-timing metadata (for SNN integration) + pub spike_metadata: Option, +} + +/// Causal constraint between hyperedges +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CausalConstraint { + /// Type of causal relationship + pub constraint_type: CausalConstraintType, + /// Target hyperedge ID + pub target: HyperedgeId, + /// Minimum time delay + pub min_delay: Option, + /// Maximum time delay + pub max_delay: Option, + /// Causal strength (learned from SNN) + pub strength: f64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum CausalConstraintType { + /// This hyperedge must come AFTER target + After, + /// This hyperedge must come BEFORE target + Before, + /// This hyperedge CAUSES target + Causes, + /// This hyperedge PREVENTS target + Prevents, + /// This hyperedge must OVERLAP with target + Overlaps, + /// This hyperedge must be CONTAINED in target + During, + /// This hyperedge ENABLES target (necessary but not sufficient) + Enables, +} +``` + +### 2. Time Series Properties + +```rust +/// Time-varying property value +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TimeSeries { + /// Property name + pub name: String, + /// Time-value pairs + pub points: Vec<(DateTime, PropertyValue)>, + /// Interpolation method + pub interpolation: Interpolation, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Interpolation { + /// Step function (constant until next point) + Step, + /// Linear interpolation + Linear, + /// No interpolation (only exact points) + None, +} + +impl TimeSeries { + /// Get value at specific time + pub fn value_at(&self, t: DateTime) -> Option { + match self.interpolation { + Interpolation::Step => { + self.points.iter() + .rev() + .find(|(pt, _)| *pt <= t) + .map(|(_, v)| v.clone()) + } + Interpolation::Linear => { + // Find surrounding points and interpolate + let before = self.points.iter().rev().find(|(pt, _)| *pt <= t); + let after = self.points.iter().find(|(pt, _)| *pt > t); + + match (before, after) { + (Some((t1, v1)), Some((t2, v2))) => { + // Linear interpolation + self.interpolate_linear(*t1, v1, *t2, v2, t) + } + (Some((_, v)), None) => Some(v.clone()), + (None, Some((_, v))) => Some(v.clone()), + (None, None) => None, + } + } + Interpolation::None => { + self.points.iter() + .find(|(pt, _)| *pt == t) + .map(|(_, v)| v.clone()) + } + } + } +} +``` + +### 3. Spike-Timing Integration + +```rust +/// Spike metadata for temporal hyperedges +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SpikeMetadata { + /// Neuron ID representing this hyperedge + pub neuron_id: usize, + /// Spike times when hyperedge was activated + pub spike_times: Vec, + /// Learned causal weights to other hyperedges + pub causal_weights: HashMap, +} + +/// SNN-based temporal hypergraph analyzer +pub struct TemporalHypergraphSNN { + /// Causal discovery SNN + causal_snn: CausalDiscoverySNN, + /// Mapping: hyperedge → neuron + hyperedge_neurons: HashMap, + /// Reverse mapping: neuron → hyperedge + neuron_hyperedges: HashMap, +} + +impl TemporalHypergraphSNN { + /// Convert hyperedge event to spike + pub fn hyperedge_to_spike(&self, hyperedge: &TemporalHyperedge, event_time: f64) -> Spike { + let neuron_id = self.hyperedge_neurons + .get(&hyperedge.hyperedge.id) + .copied() + .unwrap_or(0); + + Spike { + neuron_id, + time: event_time, + } + } + + /// Learn causal relationships from spike timing + pub fn learn_causality(&mut self, spikes: &[Spike]) { + for spike in spikes { + let event = GraphEvent { + event_type: GraphEventType::HyperedgeActivation, + vertex: None, + edge: None, + data: spike.neuron_id as f64, + }; + self.causal_snn.observe_event(event, spike.time); + } + } + + /// Extract learned causal graph between hyperedges + pub fn extract_hyperedge_causality(&self) -> HashMap<(HyperedgeId, HyperedgeId), f64> { + let causal_graph = self.causal_snn.extract_causal_graph(); + let mut result = HashMap::new(); + + for edge in causal_graph.edges() { + if let (Some(src_he), Some(tgt_he)) = ( + self.neuron_hyperedges.get(&edge.source), + self.neuron_hyperedges.get(&edge.target), + ) { + result.insert((src_he.clone(), tgt_he.clone()), edge.strength); + } + } + + result + } +} +``` + +## Temporal Query Language + +### 4. Extended Cypher for Temporal Hypergraphs + +```rust +/// Temporal Cypher query extensions +pub enum TemporalCypherExtension { + /// Query at specific time point + /// MATCH (n)-[r]->(m) AT TIME '2024-01-15T10:00:00Z' + AtTime(DateTime), + + /// Query during interval + /// MATCH (n)-[r]->(m) DURING ['2024-01-01', '2024-02-01'] + During(TemporalInterval), + + /// Query with temporal ordering + /// MATCH (h1:Hyperedge) BEFORE (h2:Hyperedge) + Before(HyperedgePattern, HyperedgePattern), + + /// Query causal relationships + /// MATCH (h1:Hyperedge) CAUSES (h2:Hyperedge) + Causes(HyperedgePattern, HyperedgePattern), + + /// Query temporal evolution + /// MATCH (n) EVOLVES FROM '2024-01-01' TO '2024-12-31' + Evolves { start: DateTime, end: DateTime }, + + /// Query with Allen relations + /// MATCH (h1) OVERLAPS (h2) + AllenRelation(AllenRelation, HyperedgePattern, HyperedgePattern), +} + +/// Temporal query executor +pub struct TemporalCypherExecutor { + graph: TemporalHypergraphDB, + snn: TemporalHypergraphSNN, +} + +impl TemporalCypherExecutor { + /// Execute temporal Cypher query + pub fn execute(&self, query: &str) -> Result { + let parsed = self.parse_temporal_cypher(query)?; + + match parsed.temporal_extension { + Some(TemporalCypherExtension::AtTime(t)) => { + self.execute_at_time(&parsed.base_query, t) + } + Some(TemporalCypherExtension::Causes(src, tgt)) => { + self.execute_causal_query(&src, &tgt) + } + Some(TemporalCypherExtension::Evolves { start, end }) => { + self.execute_evolution_query(&parsed.base_query, start, end) + } + _ => self.execute_base_query(&parsed.base_query), + } + } + + /// Execute causal query using SNN + fn execute_causal_query( + &self, + source: &HyperedgePattern, + target: &HyperedgePattern, + ) -> Result { + // Find matching hyperedges + let source_hyperedges = self.graph.match_pattern(source)?; + let target_hyperedges = self.graph.match_pattern(target)?; + + // Query causal relationships from SNN + let causality = self.snn.extract_hyperedge_causality(); + + let mut results = Vec::new(); + for src in &source_hyperedges { + for tgt in &target_hyperedges { + if let Some(&strength) = causality.get(&(src.id.clone(), tgt.id.clone())) { + if strength > 0.1 { + results.push(CausalMatch { + source: src.clone(), + target: tgt.clone(), + strength, + delay: self.estimate_causal_delay(src, tgt), + }); + } + } + } + } + + Ok(TemporalQueryResult::Causal(results)) + } +} +``` + +### 5. Example Queries + +```cypher +-- Find all meetings that caused project formations +MATCH (meeting:Hyperedge {type: 'MEETING'}) + CAUSES + (project:Hyperedge {type: 'PROJECT'}) +WHERE meeting.duration > 60 +RETURN meeting, project, causal_strength, causal_delay + +-- Find hyperedges valid during Q1 2024 +MATCH (h:Hyperedge) +DURING ['2024-01-01', '2024-03-31'] +RETURN h.type, count(*) AS count + +-- Trace temporal evolution of a relationship +MATCH (team:Hyperedge {id: 'team-alpha'}) +EVOLVES FROM '2024-01-01' TO '2024-12-31' +RETURN timestamp, team.members, team.confidence + +-- Find overlapping events +MATCH (h1:Hyperedge {type: 'MEETING'}) + OVERLAPS + (h2:Hyperedge {type: 'MEETING'}) +WHERE h1 <> h2 +RETURN h1, h2, overlap_duration + +-- Counterfactual query +MATCH (cause:Hyperedge) + CAUSES + (effect:Hyperedge {outcome: 'failure'}) +COUNTERFACTUAL NOT cause +PREDICT effect.outcome +``` + +## MinCut Integration + +### 6. Temporal MinCut + +```rust +/// MinCut on temporal hypergraphs +pub struct TemporalMinCut { + /// Static MinCut analyzer + static_analyzer: RuVectorGraphAnalyzer, + /// Time window for snapshot + window: Duration, +} + +impl TemporalMinCut { + /// Compute MinCut at specific time + pub fn mincut_at(&self, t: DateTime) -> u64 { + // Build snapshot graph at time t + let snapshot = self.build_snapshot(t); + + let mut analyzer = RuVectorGraphAnalyzer::new(snapshot); + analyzer.min_cut() + } + + /// Compute MinCut evolution over time + pub fn mincut_evolution( + &self, + start: DateTime, + end: DateTime, + step: Duration, + ) -> Vec<(DateTime, u64)> { + let mut results = Vec::new(); + let mut t = start; + + while t <= end { + results.push((t, self.mincut_at(t))); + t = t + step; + } + + results + } + + /// Find time of minimum connectivity + pub fn find_vulnerability_window( + &self, + start: DateTime, + end: DateTime, + ) -> Option { + let evolution = self.mincut_evolution(start, end, Duration::hours(1)); + + // Find minimum mincut value + let min_idx = evolution.iter() + .enumerate() + .min_by_key(|(_, (_, v))| *v)? + .0; + + // Expand window around minimum + let window_start = evolution.get(min_idx.saturating_sub(1)) + .map(|(t, _)| *t) + .unwrap_or(start); + let window_end = evolution.get(min_idx + 1) + .map(|(t, _)| *t); + + Some(TemporalInterval { + start: window_start, + end: window_end, + validity: ValidityType::Valid, + }) + } + + /// Build graph snapshot at time t + fn build_snapshot(&self, t: DateTime) -> Arc { + let graph = Arc::new(DynamicGraph::new()); + + // Add only hyperedges valid at time t + for hyperedge in self.get_valid_hyperedges(t) { + // Convert hyperedge to clique in graph + for i in 0..hyperedge.hyperedge.nodes.len() { + for j in (i + 1)..hyperedge.hyperedge.nodes.len() { + let u = self.node_to_vertex(&hyperedge.hyperedge.nodes[i]); + let v = self.node_to_vertex(&hyperedge.hyperedge.nodes[j]); + let _ = graph.insert_edge(u, v, hyperedge.hyperedge.confidence as f64); + } + } + } + + graph + } +} +``` + +### 7. Causal MinCut + +```rust +/// MinCut on the causal graph between hyperedges +pub struct CausalMinCut { + snn: TemporalHypergraphSNN, +} + +impl CausalMinCut { + /// Find minimum intervention to prevent an outcome + pub fn minimum_intervention( + &self, + source_hyperedges: &[HyperedgeId], + target_outcome: &HyperedgeId, + ) -> Vec { + // Build causal graph + let causality = self.snn.extract_hyperedge_causality(); + let causal_graph = self.build_causal_graph(&causality); + + // Compute MinCut between sources and target + let mut analyzer = RuVectorGraphAnalyzer::new(causal_graph); + let (side_a, side_b) = analyzer.partition().unwrap(); + + // Find hyperedges in the cut + let cut_hyperedges = self.find_cut_hyperedges(&side_a, &side_b); + + cut_hyperedges + } + + /// Find critical causal paths + pub fn critical_causal_paths( + &self, + outcome: &HyperedgeId, + ) -> Vec { + let causality = self.snn.extract_hyperedge_causality(); + + // Trace back all causal paths to outcome + let mut paths = Vec::new(); + self.trace_causal_paths(outcome, &causality, &mut Vec::new(), &mut paths); + + // Rank by causal strength + paths.sort_by(|a, b| b.total_strength.partial_cmp(&a.total_strength).unwrap()); + + paths + } +} +``` + +## Implementation Phases + +### Phase 1: Core Data Structures +- [ ] Implement `TemporalInterval` with Allen's algebra +- [ ] Create `TemporalHyperedge` structure +- [ ] Add `TimeSeries` for temporal properties +- [ ] Implement version history + +### Phase 2: Storage and Indexing +- [ ] Create temporal index (B-tree on intervals) +- [ ] Implement efficient time-range queries +- [ ] Add versioned storage backend +- [ ] Create snapshot generation + +### Phase 3: SNN Integration +- [ ] Map hyperedges to neurons +- [ ] Implement spike-timing causal learning +- [ ] Create causal constraint inference +- [ ] Add strength estimation + +### Phase 4: Query Language +- [ ] Extend Cypher parser for temporal operators +- [ ] Implement AT TIME queries +- [ ] Add CAUSES/PREVENTS queries +- [ ] Create evolution queries + +### Phase 5: MinCut Integration +- [ ] Implement temporal MinCut snapshots +- [ ] Add MinCut evolution tracking +- [ ] Create causal MinCut for interventions +- [ ] Build vulnerability detection + +## Key Metrics + +| Metric | Target | Description | +|--------|--------|-------------| +| Temporal Query Latency | < 50ms | Time-range query performance | +| Snapshot Generation | < 10ms | Build graph at point in time | +| Causal Inference | < 100ms | Learn causality from spikes | +| MinCut Evolution | < 1s | Compute MinCut over time range | + +## Novel Research Contributions + +1. **Spike-Timing Hyperedge Causality**: Using STDP to learn causal relationships between N-ary events +2. **Temporal MinCut**: Extending subpolynomial MinCut to time-varying graphs +3. **Causal Intervention Planning**: Using MinCut to find minimum changes to prevent outcomes +4. **Allen Algebra + Causality**: Combining temporal logic with causal constraints + +## Use Cases + +### 1. Event Sequence Analysis +Model complex events (meetings, projects, decisions) as temporal hyperedges and discover causal chains. + +### 2. Temporal Knowledge Graphs +Represent facts that change over time with automatic causality detection. + +### 3. Process Mining +Analyze business processes as temporal hypergraphs with causal constraints. + +### 4. Predictive Maintenance +Model system states as hyperedges and predict failures through causal analysis. + +### 5. Social Network Dynamics +Track group formations/dissolutions over time with causal explanations. + +## References + +- Allen, J. (1983). *Maintaining Knowledge about Temporal Intervals* +- Maier, D. (2010). *Semantics of Temporal Queries* +- Pearl, J. (2009). *Causality: Models, Reasoning, and Inference* +- Sporns, O. (2010). *Networks of the Brain*