paulistrings/
circuit.rs

1//! [`Circuit<W>`], an ordered list of channels.
2
3use crate::channel::Channel;
4
5/// An ordered list of channels on `num_qubits` qubits, user-defined [`crate::Channel`] impls included.
6///
7/// [`crate::Direction::Forward`] applies it in order, [`crate::Direction::Heisenberg`] in reverse with each channel's adjoint.
8pub struct Circuit<const W: usize> {
9    pub(crate) num_qubits: usize,
10    /// In application order.
11    pub(crate) channels: Vec<Box<dyn Channel<W>>>,
12}
13
14impl<const W: usize> Circuit<W> {
15    /// Empty circuit on `num_qubits` qubits.
16    pub fn new(num_qubits: usize) -> Self {
17        Self { num_qubits, channels: Vec::new() }
18    }
19
20    /// Append a channel to the circuit.
21    ///
22    /// # Panics
23    ///
24    /// If the channel's support reaches a qubit at or above [`num_qubits`](Self::num_qubits).
25    pub fn push<C: Channel<W> + 'static>(&mut self, channel: C) {
26        self.push_boxed(Box::new(channel));
27    }
28
29    /// Append an already boxed channel, as [`push`](Self::push) does.
30    ///
31    /// # Panics
32    ///
33    /// If the channel's support reaches a qubit at or above [`num_qubits`](Self::num_qubits).
34    pub fn push_boxed(&mut self, channel: Box<dyn Channel<W>>) {
35        let support = channel.support();
36        if let Some(word) = (0..W).rev().find(|&w| support[w] != 0) {
37            let highest = 64 * word + 63 - support[word].leading_zeros() as usize;
38            assert!(
39                highest < self.num_qubits,
40                "Circuit::push: {} acts on qubit {highest}, outside this {}-qubit circuit",
41                channel.debug_name(),
42                self.num_qubits,
43            );
44        }
45        self.channels.push(channel);
46    }
47
48    /// Number of qubits this circuit acts on.
49    pub fn num_qubits(&self) -> usize {
50        self.num_qubits
51    }
52
53    /// The channels in application order.
54    pub fn channels(&self) -> &[Box<dyn Channel<W>>] {
55        &self.channels
56    }
57
58    /// Number of channels in the circuit.
59    pub fn len(&self) -> usize {
60        self.channels.len()
61    }
62
63    /// `true` iff no channels have been pushed.
64    pub fn is_empty(&self) -> bool {
65        self.channels.is_empty()
66    }
67}
68
69#[cfg(test)]
70mod tests;