phase_rs/
ket.rs

1//! Structure for representing primitive states in ket notation.
2
3use std::f64::consts::FRAC_1_SQRT_2;
4
5use faer::{Mat, mat};
6use num_complex::Complex;
7use pretty::RcDoc;
8use winnow::{
9    LocatingSlice, ModalResult, Parser,
10    combinator::{alt, delimited, repeat},
11};
12
13use crate::text::{HasParser, ToDoc};
14
15/// Holds the value of a ket pattern.
16#[derive(Clone, Copy, Debug, PartialEq)]
17pub enum KetState {
18    /// |0> pattern
19    Zero,
20    /// |1> pattern
21    One,
22    /// |+> pattern
23    Plus,
24    /// |-> pattern
25    Minus,
26}
27
28const CISQRT2: Complex<f64> = Complex::new(FRAC_1_SQRT_2, 0.0);
29
30impl KetState {
31    /// Returns the complement of the state.
32    /// `state` and `state.compl()` from a basis of C^2
33    pub fn compl(self) -> Self {
34        match self {
35            KetState::Zero => KetState::One,
36            KetState::One => KetState::Zero,
37            KetState::Plus => KetState::Minus,
38            KetState::Minus => KetState::Plus,
39        }
40    }
41
42    /// Returns the character needed to print this ket state.
43    pub fn to_char(&self) -> char {
44        match self {
45            KetState::Zero => '0',
46            KetState::One => '1',
47            KetState::Plus => '+',
48            KetState::Minus => '-',
49        }
50    }
51    /// Returns the vector this `KetState` represents.
52    pub fn to_state(self) -> Mat<Complex<f64>> {
53        match self {
54            KetState::Zero => mat![[Complex::ONE], [Complex::ZERO]],
55            KetState::One => mat![[Complex::ZERO], [Complex::ONE]],
56            KetState::Plus => mat![[CISQRT2], [CISQRT2]],
57            KetState::Minus => mat![[CISQRT2], [-CISQRT2]],
58        }
59    }
60}
61
62/// Holds a composite ket state of the form '|("0"|"1"|"+"|"-")+>'
63#[derive(Clone, Debug, PartialEq)]
64pub struct CompKetState(Vec<KetState>);
65
66impl CompKetState {
67    /// Get the number of qubits this state needs to be stored.
68    pub fn qubits(&self) -> usize {
69        self.0.len()
70    }
71
72    /// An iterator over the individual states for each qubit.
73    pub fn iter(&self) -> impl Iterator<Item = &KetState> {
74        self.0.iter()
75    }
76
77    /// Create a new composite ket state from a `Vec` of `KetState`
78    pub fn new(states: Vec<KetState>) -> Self {
79        CompKetState(states)
80    }
81
82    /// Create a new composite ket state from a single `KetState`
83    pub fn single(state: KetState) -> Self {
84        CompKetState::new(vec![state])
85    }
86}
87
88impl ToDoc for CompKetState {
89    fn to_doc(&self) -> RcDoc<'_> {
90        RcDoc::text("|")
91            .append(self.0.iter().map(KetState::to_char).collect::<String>())
92            .append(">")
93    }
94}
95
96impl HasParser for CompKetState {
97    fn parser(input: &mut LocatingSlice<&str>) -> ModalResult<Self> {
98        delimited(
99            "|",
100            repeat(
101                1..,
102                alt((
103                    "0".value(KetState::Zero),
104                    "1".value(KetState::One),
105                    "+".value(KetState::Plus),
106                    "-".value(KetState::Minus),
107                )),
108            ),
109            ">",
110        )
111        .map(CompKetState)
112        .parse_next(input)
113    }
114}