// CARRY Quantum Execution DAG Module // DAG representation of quantum multi-agent computation with strict node provenance. use std::collections::HashMap; /// Quantum DAG Node Type. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum QuantumDAGNodeType { Input, StatePreparation, Entanglement, AgentComputation, PartnerVerification, QuantumOperation, Measurement, ICPGate, Commit, } /// Quantum DAG Node with provenance and metadata. #[derive(Debug, Clone)] pub struct QuantumDAGNode { pub id: usize, pub node_type: QuantumDAGNodeType, pub label: String, pub agent_id: String, pub target_qubits: Vec, pub provenance_hash: String, pub parent_ids: Vec, } /// Quantum DAG Graph structure. #[derive(Debug, Clone)] pub struct QuantumDAG { pub nodes: HashMap, pub next_node_id: usize, pub execution_order: Vec, } impl QuantumDAG { pub fn new() -> Self { Self { nodes: HashMap::new(), next_node_id: 1, execution_order: Vec::new(), } } /// Add a node to the DAG with edge provenance validation. pub fn add_node( &mut self, node_type: QuantumDAGNodeType, label: impl Into, agent_id: impl Into, target_qubits: Vec, parent_ids: Vec, ) -> Result { let label_str = label.into(); let agent_str = agent_id.into(); // Validate parents exist for &parent_id in &parent_ids { if !self.nodes.contains_key(&parent_id) { return Err(format!("DAG_ERROR: Parent node {} does not exist", parent_id)); } } // Validate canonical DAG sequence invariants if node_type == QuantumDAGNodeType::Commit { let has_icp_parent = parent_ids.iter().any(|&p| { self.nodes.get(&p).map(|n| n.node_type) == Some(QuantumDAGNodeType::ICPGate) }); if !has_icp_parent { return Err("INVALID_DAG_PATH: Commit node must be preceded by an ICP Gate node".into()); } } let id = self.next_node_id; self.next_node_id += 1; // Compute provenance hash let provenance_hash = format!( "NODE_{:?}_AG_{}_Q{:?}_P{:?}", node_type, agent_str, target_qubits, parent_ids ); let node = QuantumDAGNode { id, node_type, label: label_str, agent_id: agent_str, target_qubits, provenance_hash, parent_ids, }; self.nodes.insert(id, node); self.execution_order.push(id); Ok(id) } /// Validate complete execution path from Input to Commit. pub fn validate_path(&self) -> Result<(), String> { if self.execution_order.is_empty() { return Err("DAG is empty".into()); } let first = self.nodes.get(&self.execution_order[0]).unwrap(); if first.node_type != QuantumDAGNodeType::Input { return Err("DAG path must start with Input node".into()); } let last = self.nodes.get(self.execution_order.last().unwrap()).unwrap(); if last.node_type != QuantumDAGNodeType::Commit { return Err("DAG path must terminate with Commit node".into()); } Ok(()) } }