File size: 5,675 Bytes
80d7559
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// CARRY Quantum FSM Module
// Formal State Machine governing quantum execution cycles.
// Transition DAG: INIT → PREPARE → ENTANGLE → COMPUTE → MEASURE → VERIFY → COMMIT

use std::fmt;

/// Quantum FSM states.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum QuantumFSMState {
    Init,
    Prepare,
    Entangle,
    Compute,
    Measure,
    Verify,
    Commit,
    Halted,
    CycleLimit,
}

impl fmt::Display for QuantumFSMState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            QuantumFSMState::Init => write!(f, "INIT"),
            QuantumFSMState::Prepare => write!(f, "PREPARE"),
            QuantumFSMState::Entangle => write!(f, "ENTANGLE"),
            QuantumFSMState::Compute => write!(f, "COMPUTE"),
            QuantumFSMState::Measure => write!(f, "MEASURE"),
            QuantumFSMState::Verify => write!(f, "VERIFY"),
            QuantumFSMState::Commit => write!(f, "COMMIT"),
            QuantumFSMState::Halted => write!(f, "HALTED"),
            QuantumFSMState::CycleLimit => write!(f, "CYCLE_LIMIT"),
        }
    }
}

/// Transition context record required for every FSM transition.
#[derive(Debug, Clone)]
pub struct TransitionRecord {
    pub cycle: usize,
    pub agent_id: String,
    pub qubits: Vec<usize>,
    pub precondition: String,
    pub operation: String,
    pub postcondition: String,
    pub result: String,
    pub verification_state: String,
}

/// Quantum FSM Controller.
#[derive(Debug, Clone)]
pub struct QuantumFSM {
    pub state: QuantumFSMState,
    pub current_cycle: usize,
    pub max_cycle: usize,
    pub history: Vec<TransitionRecord>,
}

impl QuantumFSM {
    pub fn new(max_cycle: usize) -> Self {
        Self {
            state: QuantumFSMState::Init,
            current_cycle: 0,
            max_cycle,
            history: Vec::new(),
        }
    }

    /// Advance FSM to the specified next state with precondition/postcondition verification.
    pub fn transition(
        &mut self,
        target_state: QuantumFSMState,
        agent_id: impl Into<String>,
        qubits: Vec<usize>,
        op: impl Into<String>,
        precondition: impl Into<String>,
        postcondition: impl Into<String>,
    ) -> Result<QuantumFSMState, String> {
        let agent_str = agent_id.into();
        let op_str = op.into();
        let pre_str = precondition.into();
        let post_str = postcondition.into();

        // Terminal states are absorbing — no transition out of Halted or CycleLimit
        if matches!(self.state, QuantumFSMState::Halted | QuantumFSMState::CycleLimit) {
            return Err(format!(
                "FSM_TERMINAL: cannot transition from {:?}",
                self.state
            ));
        }

        // Hard cycle limit check
        if self.current_cycle >= self.max_cycle {
            self.state = QuantumFSMState::CycleLimit;
            return Err(format!(
                "CYCLE_LIMIT_REACHED: cycle {} >= max_cycle {}",
                self.current_cycle, self.max_cycle
            ));
        }

        // Validate allowed state transitions in the quantum pipeline DAG
        let valid = match (self.state, target_state) {
            (QuantumFSMState::Init, QuantumFSMState::Prepare) => true,
            (QuantumFSMState::Prepare, QuantumFSMState::Entangle) => true,
            (QuantumFSMState::Entangle, QuantumFSMState::Compute) => true,
            (QuantumFSMState::Compute, QuantumFSMState::Measure) => true,
            (QuantumFSMState::Measure, QuantumFSMState::Verify) => true,
            (QuantumFSMState::Verify, QuantumFSMState::Commit) => true,
            (QuantumFSMState::Commit, QuantumFSMState::Prepare) => true, // Loop for next quantum cycle
            (QuantumFSMState::Commit, QuantumFSMState::Commit) => true,  // Terminal commit
            (_, QuantumFSMState::Halted) => true,                       // Emergency halt allowed from any state
            _ => false,
        };

        if !valid {
            // CE-3 fix: capture source state before mutating it so the error
            // message reports the actual invalid source, not the post-halt state.
            let from_state = self.state;
            self.state = QuantumFSMState::Halted;
            return Err(format!(
                "INVALID_FSM_TRANSITION: Cannot transition from {:?} to {:?}",
                from_state, target_state
            ));
        }

        self.current_cycle += 1;
        self.state = target_state;

        let record = TransitionRecord {
            cycle: self.current_cycle,
            agent_id: agent_str,
            qubits,
            precondition: pre_str,
            operation: op_str,
            postcondition: post_str,
            result: format!("TRANSITION_SUCCESS_{:?}", self.state),
            verification_state: "VERIFIED_OK".to_string(),
        };

        self.history.push(record);
        Ok(self.state)
    }

    pub fn halt(&mut self, reason: impl Into<String>) {
        self.state = QuantumFSMState::Halted;
        let record = TransitionRecord {
            cycle: self.current_cycle,
            agent_id: "SYSTEM_GATE".to_string(),
            qubits: vec![],
            precondition: "ANY".to_string(),
            operation: "HALT".to_string(),
            postcondition: "HALTED".to_string(),
            result: format!("HALT: {}", reason.into()),
            verification_state: "HALT_REJECT".to_string(),
        };
        self.history.push(record);
    }
}