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;