ket/process/
measure.rs

1// SPDX-FileCopyrightText: 2025 Evandro Chagas Ribeiro da Rosa <evandro@quantuloop.com>
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use crate::{
6    error::Result,
7    execution::{Capability, LiveExecution, QuantumExecution},
8    ir::qubit::LogicalQubit,
9    prelude::Hamiltonian,
10};
11
12use super::{ExecutionProtocol, Process};
13
14impl Process {
15    fn live_execution_or_none<F, T>(&mut self, call: F) -> Option<T>
16    where
17        F: Fn(&mut Box<dyn LiveExecution>) -> T,
18    {
19        if let Some(QuantumExecution::Live(execution)) = self.quantum_execution.as_mut() {
20            Some(call(execution))
21        } else {
22            None
23        }
24    }
25
26    pub fn measure(&mut self, qubits: &[LogicalQubit]) -> Result<usize> {
27        self.non_gate_checks(Some(qubits), self.features.measure)?;
28        self.execute_gate_queue(0);
29
30        let index = self.measurements.len();
31
32        self.logical_circuit.measure(qubits, index);
33
34        let result = self.live_execution_or_none(|execution| execution.measure(qubits));
35        self.measurements.push(result);
36
37        for qubit in qubits {
38            self.valid_qubit.insert(*qubit, true);
39        }
40
41        if !matches!(
42            self.execution_target.execution_protocol,
43            ExecutionProtocol::ManagedByTarget {
44                measure: Capability::Advanced,
45                ..
46            }
47        ) {
48            for qubit in qubits {
49                self.valid_qubit.insert(*qubit, false);
50            }
51        }
52        Ok(index)
53    }
54
55    pub fn sample(&mut self, qubits: &[LogicalQubit], shots: usize) -> Result<usize> {
56        self.non_gate_checks(Some(qubits), self.features.sample)?;
57        self.execute_gate_queue(0);
58
59        let index = self.samples.len();
60
61        self.logical_circuit.sample(qubits, shots, index);
62
63        let result = self.live_execution_or_none(|execution| execution.sample(qubits, shots));
64        self.samples.push(result);
65
66        if self.execute_after_sample() {
67            self.execute()?
68        }
69
70        Ok(index)
71    }
72
73    pub fn exp_value(&mut self, hamiltonian: Hamiltonian<LogicalQubit>) -> Result<usize> {
74        let qubits = hamiltonian.qubits().cloned().collect::<Vec<_>>();
75        self.non_gate_checks(Some(&qubits), self.features.exp_value)?;
76        self.execute_gate_queue(0);
77
78        let index = self.exp_values.len();
79
80        let result = self.live_execution_or_none(|execution| execution.exp_value(&hamiltonian));
81        self.exp_values.push(result);
82
83        self.logical_circuit.exp_value(hamiltonian, index);
84
85        if self.execute_after_exp_value() {
86            self.execute()?;
87        }
88
89        Ok(index)
90    }
91
92    pub fn dump(&mut self, qubits: &[LogicalQubit]) -> Result<usize> {
93        self.non_gate_checks(Some(qubits), self.features.dump)?;
94        self.execute_gate_queue(0);
95
96        let index = self.dumps.len();
97
98        self.logical_circuit.dump(qubits, index);
99
100        let result = self.live_execution_or_none(|execution| execution.dump(qubits));
101        self.dumps.push(result);
102
103        if self.execute_after_dump() {
104            self.execute()?;
105        }
106
107        Ok(index)
108    }
109}