quant_iron/components/
state.rs

1use crate::components::{
2    measurement::{MeasurementBasis, MeasurementResult},
3    operator::{
4        CNOT, Hadamard, Identity, Matchgate, Operator, Pauli, PhaseS, PhaseSdag, PhaseShift,
5        PhaseT, PhaseTdag, RotateX, RotateY, RotateZ, SWAP, Toffoli, Unitary2,
6    },
7};
8use crate::errors::Error;
9use num_complex::Complex;
10use once_cell::sync::Lazy;
11use rand::Rng;
12use rayon::prelude::*;
13use std::f64::consts::FRAC_1_SQRT_2;
14use std::ops::{Add, Mul, Sub};
15
16// Helper function to calculate the adjoint (conjugate transpose) of a 2x2 matrix
17fn calculate_adjoint(matrix: &[[Complex<f64>; 2]; 2]) -> [[Complex<f64>; 2]; 2] {
18    [
19        [matrix[0][0].conj(), matrix[1][0].conj()],
20        [matrix[0][1].conj(), matrix[1][1].conj()],
21    ]
22}
23
24/// Bell state vectors
25pub(crate) mod bell_vectors {
26    use super::*;
27
28    pub static PHI_PLUS: Lazy<Vec<Complex<f64>>> = Lazy::new(|| {
29        let amplitude = Complex::new(FRAC_1_SQRT_2, 0.0);
30        vec![
31            amplitude,
32            Complex::new(0.0, 0.0),
33            Complex::new(0.0, 0.0),
34            amplitude,
35        ]
36    });
37
38    pub static PHI_MINUS: Lazy<Vec<Complex<f64>>> = Lazy::new(|| {
39        let amplitude = Complex::new(FRAC_1_SQRT_2, 0.0);
40        vec![
41            amplitude,
42            Complex::new(0.0, 0.0),
43            Complex::new(0.0, 0.0),
44            -amplitude,
45        ]
46    });
47
48    pub static PSI_PLUS: Lazy<Vec<Complex<f64>>> = Lazy::new(|| {
49        let amplitude = Complex::new(FRAC_1_SQRT_2, 0.0);
50        vec![
51            Complex::new(0.0, 0.0),
52            amplitude,
53            amplitude,
54            Complex::new(0.0, 0.0),
55        ]
56    });
57
58    pub static PSI_MINUS: Lazy<Vec<Complex<f64>>> = Lazy::new(|| {
59        let amplitude = Complex::new(FRAC_1_SQRT_2, 0.0);
60        vec![
61            Complex::new(0.0, 0.0),
62            amplitude,
63            -amplitude,
64            Complex::new(0.0, 0.0),
65        ]
66    });
67}
68
69#[derive(Clone)]
70/// Represents the state of a quantum register.
71///
72/// The state is represented as a complex vector, where each element corresponds to a probability amplitude for a particular basis state.
73/// The number of qubits in the system is also stored, which determines the length of the state vector (2^num_qubits).
74pub struct State {
75    /// The state vector of the system, represented as a complex vector.
76    /// Each element of the vector represents a probability amplitude for a particular state.
77    pub state_vector: Vec<Complex<f64>>,
78
79    /// The number of qubits in the system.
80    pub num_qubits: usize,
81}
82
83impl State {
84    /// Creates a new state object with the given state vector.
85    ///
86    /// # Arguments
87    ///
88    /// * `state_vector` - The state vector of the system, represented as a complex vector.
89    ///
90    /// # Returns
91    ///
92    /// * `state` - A result containing the state object if successful, or an error if the state vector is invalid.
93    ///
94    /// # Errors
95    ///
96    /// * Returns an error if the state vector is empty.
97    /// * Returns an error if the state vector is not normalised (i.e., the square norm is not 1).
98    /// * Returns an error if the number of qubits is invalid (i.e., the length of the state vector is not a power of 2).
99    pub fn new(state_vector: Vec<Complex<f64>>) -> Result<Self, Error> {
100        let len = state_vector.len();
101
102        if len == 0 {
103            return Err(Error::InvalidNumberOfQubits(0));
104        }
105
106        // Check if the length of the state vector is a power of 2
107        if !len.is_power_of_two() {
108            // For error reporting, num_qubits can be approximated or a specific error used.
109            return Err(Error::InvalidNumberOfQubits(
110                (len as f64).log2().floor() as usize
111            ));
112        }
113        // num_qubits can be safely calculated as len is non-zero and a power of two.
114        let num_qubits = len.trailing_zeros() as usize;
115
116        // Check if the square norm (probability) of the state vector is 1
117        let norm: f64 = state_vector.par_iter().map(|x| x.norm_sqr()).sum();
118        let tol: f64 = f64::EPSILON * len as f64; // Using len directly
119        if (norm - 1.0).abs() > tol {
120            return Err(Error::StateVectorNotNormalised);
121        }
122
123        Ok(Self {
124            state_vector,
125            num_qubits,
126        })
127    }
128
129    /// Creates a new Hartree-Fock state object with the given number of electrons and orbitals.
130    ///
131    /// # Arguments
132    ///
133    /// * `num_electrons` - The number of electrons in the system.
134    ///
135    /// * `num_orbitals` - The number of orbitals in the system.
136    ///
137    /// # Returns
138    ///
139    /// * `state` - A result containing the state object if successful, or an error if the input is invalid.
140    pub fn new_hartree_fock(num_electrons: usize, num_orbitals: usize) -> Result<Self, Error> {
141        // Validate input (num_orbitals must be > 0 and >= num_electrons)
142        if num_orbitals == 0 || num_orbitals < num_electrons {
143            return Err(Error::InvalidInputValue(num_orbitals));
144        }
145
146        let n = ((1_usize.wrapping_shl(num_electrons as u32)) - 1)
147            .wrapping_shl((num_orbitals - num_electrons) as u32);
148
149        State::new_basis_n(num_orbitals, n)
150    }
151
152    /// Creates a new state object with the given number of qubits initialised to the |0...0> state.
153    ///
154    /// # Arguments
155    ///
156    /// * `num_qubits` - The number of qubits in the system.
157    ///
158    /// # Returns
159    ///
160    /// * `state` - A result containing the state object if successful, or an error if the number of qubits is invalid.
161    ///
162    /// # Errors
163    ///
164    /// * Returns an error if the number of qubits is 0.
165    pub fn new_zero(num_qubits: usize) -> Result<Self, Error> {
166        if num_qubits == 0 {
167            return Err(Error::InvalidNumberOfQubits(num_qubits));
168        }
169
170        let dim: usize = 1 << num_qubits;
171        let mut state_vector: Vec<Complex<f64>> = vec![Complex::new(0.0, 0.0); dim];
172        state_vector[0] = Complex::new(1.0, 0.0); // |0...0> state has amplitude 1.0 at index 0
173
174        Ok(Self {
175            state_vector,
176            num_qubits,
177        })
178    }
179
180    /// Creates a new state object with the given number of qubits initialised to the `n`-th basis state.
181    ///
182    /// # Arguments
183    ///
184    /// * `num_qubits` - The number of qubits in the system.
185    /// * `n` - The index of the basis state to initialise to.
186    ///
187    /// # Returns
188    ///
189    /// * `state` - A result containing a new state object with the specified number of qubits, initialised to the `n`-th basis state or an error if `n` is out of bounds or if the number of qubits is invalid.
190    ///
191    /// # Errors
192    ///
193    /// * Returns an error if the number of qubits is 0 or if `n` is out of bounds for the given number of qubits.
194    pub fn new_basis_n(num_qubits: usize, n: usize) -> Result<Self, Error> {
195        let dim: usize = 1 << num_qubits;
196        if n >= dim {
197            return Err(Error::InvalidQubitIndex(n, num_qubits));
198        }
199        if num_qubits == 0 {
200            return Err(Error::InvalidNumberOfQubits(num_qubits));
201        }
202
203        let mut state_vector: Vec<Complex<f64>> = vec![Complex::new(0.0, 0.0); dim];
204        state_vector[n] = Complex::new(1.0, 0.0); // |n> state has amplitude 1.0 at index n
205
206        Ok(Self {
207            state_vector,
208            num_qubits,
209        })
210    }
211
212    /// Creates a new plus state object with the given number of qubits initialised to the |+...+> state.
213    ///
214    /// # Arguments
215    ///
216    /// * `num_qubits` - The number of qubits in the system.
217    ///
218    /// # Returns
219    ///
220    /// * `state` - A result containing a new state object with the specified number of qubits, initialised to the |+...+> state or an error if the number of qubits is invalid.
221    ///
222    /// # Errors
223    ///
224    /// * Returns an error if the number of qubits is 0.
225    pub fn new_plus(num_qubits: usize) -> Result<Self, Error> {
226        if num_qubits == 0 {
227            return Err(Error::InvalidNumberOfQubits(num_qubits));
228        }
229        let dim: usize = 1 << num_qubits;
230        let amplitude = Complex::new(1.0 / (dim as f64).sqrt(), 0.0);
231        let state_vector: Vec<Complex<f64>> = vec![amplitude; dim];
232
233        Ok(Self {
234            state_vector,
235            num_qubits,
236        })
237    }
238
239    /// Creates a new minus state object with the given number of qubits initialised to the |-...-> state.
240    ///
241    /// # Arguments
242    ///
243    /// * `num_qubits` - The number of qubits in the system.
244    ///
245    /// # Returns
246    ///
247    /// * `state` - A result containing a new state object with the specified number of qubits, initialised to the |-...-> state or an error if the number of qubits is invalid.
248    ///
249    /// # Errors
250    ///
251    /// * Returns an error if the number of qubits is 0.
252    pub fn new_minus(num_qubits: usize) -> Result<Self, Error> {
253        if num_qubits == 0 {
254            return Err(Error::InvalidNumberOfQubits(num_qubits));
255        }
256        let dim: usize = 1 << num_qubits;
257        let amplitude: Complex<f64> = Complex::new(1.0 / (dim as f64).sqrt(), 0.0);
258        const PARALLEL_THRESHOLD: usize = 1 << 6; // Threshold for parallelization
259
260        let state_vector: Vec<Complex<f64>> = if dim > PARALLEL_THRESHOLD {
261            (0..dim)
262                .into_par_iter()
263                .map(|i| {
264                    let num_ones = i.count_ones() as usize;
265                    if num_ones % 2 == 0 {
266                        amplitude
267                    } else {
268                        -amplitude
269                    }
270                })
271                .collect()
272        } else {
273            let mut sv = Vec::with_capacity(dim);
274            for i in 0..dim {
275                let num_ones = i.count_ones() as usize;
276                sv.push(if num_ones % 2 == 0 {
277                    amplitude
278                } else {
279                    -amplitude
280                });
281            }
282            sv
283        };
284
285        Ok(Self {
286            state_vector,
287            num_qubits,
288        })
289    }
290
291    /// Creates a new Greenberger–Horne–Zeilinger state object with the given number of qubits initialised to the |GHZ> state.
292    /// The GHZ state is the maximally entangled state 1/sqrt(2) * (|0...0> + |1...1>).
293    ///
294    /// # Arguments
295    ///
296    /// * `num_qubits` - The number of qubits in the system.
297    ///
298    /// # Returns
299    ///
300    /// * `state` - A result containing a new state object with the specified number of qubits, initialised to the |GHZ> state or an error if the number of qubits is invalid.
301    ///
302    /// # Errors
303    ///
304    /// * Returns an error if the number of qubits is 0.
305    pub fn new_ghz(num_qubits: usize) -> Result<Self, Error> {
306        if num_qubits == 0 {
307            return Err(Error::InvalidNumberOfQubits(num_qubits));
308        }
309        let dim: usize = 1 << num_qubits;
310        let amplitude: Complex<f64> = Complex::new(FRAC_1_SQRT_2, 0.0);
311        let state_vector: Vec<Complex<f64>> = (0..dim)
312            .map(|i| {
313                if i == 0 || i == dim - 1 {
314                    amplitude
315                } else {
316                    Complex::new(0.0, 0.0)
317                }
318            })
319            .collect();
320
321        Ok(Self {
322            state_vector,
323            num_qubits,
324        })
325    }
326
327    /// Creates a new two-qubit Phi plus Bell state |Φ+⟩.
328    ///
329    /// # Returns
330    ///
331    /// * `Self` - A new instance of the two-qubit Bell state |Φ+⟩.
332    pub fn new_phi_plus() -> Self {
333        Self {
334            state_vector: bell_vectors::PHI_PLUS.clone(),
335            num_qubits: 2,
336        }
337    }
338
339    /// Creates a new two-qubit Phi minus Bell state |Φ-⟩.
340    ///
341    /// # Returns
342    ///
343    /// * `Self` - A new instance of the two-qubit Bell state |Φ-⟩.
344    pub fn new_phi_minus() -> Self {
345        Self {
346            state_vector: bell_vectors::PHI_MINUS.clone(),
347            num_qubits: 2,
348        }
349    }
350
351    /// Creates a new two-qubit Psi plus Bell state |Ψ+⟩.
352    ///
353    /// # Returns
354    ///
355    /// * `Self` - A new instance of the two-qubit Bell state |Ψ+⟩.
356    pub fn new_psi_plus() -> Self {
357        Self {
358            state_vector: bell_vectors::PSI_PLUS.clone(),
359            num_qubits: 2,
360        }
361    }
362
363    /// Creates a new two-qubit Psi minus Bell state |Ψ-⟩.
364    ///
365    /// # Returns
366    ///
367    /// * `Self` - A new instance of the two-qubit Bell state |Ψ-⟩.
368    pub fn new_psi_minus() -> Self {
369        Self {
370            state_vector: bell_vectors::PSI_MINUS.clone(),
371            num_qubits: 2,
372        }
373    }
374
375    /// Checks the phase-independent equality of two states
376    ///
377    /// # Arguments
378    ///
379    /// * `other` - The other state to compare with.
380    ///
381    /// # Returns
382    ///
383    /// * `true` if the states are equal (ignoring phase), `false` otherwise.
384    pub fn equals_without_phase(&self, other: &Self) -> bool {
385        if self.num_qubits != other.num_qubits {
386            return false;
387        }
388        // Safe to unwrap since number of qubits is the same
389        (self.inner_product(other).unwrap().norm() - 1.0).abs() < f32::EPSILON.into()
390    }
391
392    /// Returns the Hermitian conjugate (<self|) of the state.
393    ///
394    /// # Returns
395    ///
396    /// * `Self` - The Hermitian conjugate of the state.
397    pub fn conj(&self) -> Self {
398        let state_vector = self.state_vector.iter().map(|amp| amp.conj()).collect();
399        Self {
400            state_vector,
401            num_qubits: self.num_qubits,
402        }
403    }
404
405    /// Returns the probability of a basis state at index `n` in the state vector.
406    ///
407    /// # Arguments
408    ///
409    /// * `n` - The index of the basis state to get the probability for.
410    ///
411    /// # Returns
412    ///
413    /// * `probability` - The probability of the basis state at index `n`.
414    ///
415    /// # Errors
416    ///
417    /// * Returns an error if `n` is out of bounds for the state vector.
418    pub fn probability(&self, n: usize) -> Result<f64, Error> {
419        if n >= self.state_vector.len() {
420            return Err(Error::InvalidQubitIndex(n, self.num_qubits));
421        }
422        let amplitude: Complex<f64> = self.state_vector[n];
423        Ok(amplitude.norm_sqr())
424    }
425
426    /// Returns the number of qubits in the state vector.
427    ///
428    /// # Returns
429    ///
430    /// * `num_qubits` - The number of qubits in the state vector.
431    pub fn num_qubits(&self) -> usize {
432        self.num_qubits
433    }
434
435    /// Returns the amplitude of the basis state at index `n` in the state vector.
436    ///     
437    /// # Arguments
438    ///
439    /// * `n` - The index of the basis state to get the amplitude for.
440    ///
441    /// # Returns
442    ///
443    /// * `amplitude` - The amplitude of the basis state at index `n`.
444    ///
445    /// # Errors
446    ///
447    /// * Returns an error if `n` is out of bounds for the state vector.
448    pub fn amplitude(&self, n: usize) -> Result<Complex<f64>, Error> {
449        if n >= self.state_vector.len() {
450            return Err(Error::InvalidQubitIndex(n, self.num_qubits));
451        }
452        Ok(self.state_vector[n])
453    }
454
455    /// Returns the Fubini-Study metric distance between two normalised quantum states.
456    /// Expressed as `D = arccos(<Self|Other>) = arccos(F^0.5)`.
457    ///
458    /// # Arguments
459    ///
460    /// * `other` - The other quantum state to compare against.
461    ///
462    /// # Returns
463    ///
464    /// * `distance` - The Fubini-Study metric distance between the two states.
465    ///
466    /// # Errors
467    ///
468    /// Returns an error if the inner product calculation fails (ie. if one of the state vectors is empty, or if the dimensions do not match)
469    /// Returns an error is the normalisation of either of the states fails (ie. if one of the states has zero norm).
470    pub fn fs_dist(&self, other: &Self) -> Result<f64, Error> {
471        // Normalise states
472        let normalised_self = self.normalise()?;
473        let normalised_other = other.normalise()?;
474
475        Ok(normalised_self
476            .inner_product(&normalised_other)?
477            .norm()
478            .acos())
479    }
480
481    /// Returns the Fubini-Study fidelity metric between two quantum states.
482    /// Expressed as `F = |<Self|Other>|^2 = cos^2(D)`.
483    ///
484    /// # Arguments
485    ///
486    /// * `other` - The other quantum state to compare against.
487    ///
488    /// # Errors
489    ///
490    /// Returns an error if the inner product calculation fails (ie. if one of the state vectors is empty, or if the dimensions do not match)
491    /// Returns an error if the normalisation of either of the states fails (ie. if one of the states has zero norm).
492    pub fn fs_fidelity(&self, other: &Self) -> Result<f64, Error> {
493        // Normalise states
494        let normalised_self = self.normalise()?;
495        let normalised_other = other.normalise()?;
496
497        Ok(normalised_self.inner_product(&normalised_other)?.norm_sqr())
498    }
499
500    // ***** MEASUREMENT FUNCTIONS *****
501
502    fn _measure_computational(
503        &self,
504        measured_qubits: &[usize],
505    ) -> Result<MeasurementResult, Error> {
506        self.measure(MeasurementBasis::Computational, measured_qubits)
507    }
508
509    /// Measures the state vector in the specified basis and returns the measurement result.
510    ///
511    /// # Arguments
512    ///
513    /// * `basis` - The basis to measure in.
514    /// * `indices` - The indices of the qubits to measure. If `indices` is empty, all qubits are measured.
515    ///
516    /// # Returns
517    ///
518    /// * `result` - A result containing the measurement result if successful, or an error if the measurement fails.
519    ///
520    /// # Errors
521    ///
522    /// * Returns an error if the measurement fails.
523    /// * Returns an error if the number of qubits is invalid.
524    /// * Returns an error if the indices are out of bounds for the state vector.
525    pub fn measure(
526        &self,
527        basis: MeasurementBasis,
528        measured_qubits: &[usize],
529    ) -> Result<MeasurementResult, Error> {
530        // If no indices are provided, measure all qubits
531        let all_qubits: Vec<usize> = if measured_qubits.is_empty() {
532            (0..self.num_qubits).collect()
533        } else {
534            Vec::new()
535        };
536
537        let actual_measured_qubits: &[usize] = if measured_qubits.is_empty() {
538            &all_qubits
539        } else {
540            measured_qubits
541        };
542
543        // Check for valid indices
544        let num_measured: usize = actual_measured_qubits.len();
545        if num_measured > self.num_qubits {
546            return Err(Error::InvalidNumberOfQubits(self.num_qubits));
547        }
548        for &index in actual_measured_qubits {
549            if index >= self.num_qubits {
550                return Err(Error::InvalidQubitIndex(index, self.num_qubits));
551            }
552        }
553
554        match basis {
555            MeasurementBasis::Computational => {
556                let num_outcomes: usize = 1 << num_measured;
557
558                // Calculate probabilities for each outcome (outcome as a single integer 0..num_outcomes-1)
559                let probabilities: Vec<f64> = self
560                    .state_vector
561                    .par_iter()
562                    .enumerate()
563                    .fold(
564                        || vec![0.0; num_outcomes], // Thread-local accumulator
565                        |mut acc_probs, (idx, amplitude)| {
566                            let mut outcome_val_for_this_state = 0;
567                            // Extract the bits corresponding to measured_qubits to form the outcome value
568                            for (bit_idx, &qubit_pos) in actual_measured_qubits.iter().enumerate() {
569                                if (idx >> qubit_pos) & 1 != 0 {
570                                    outcome_val_for_this_state |= 1 << bit_idx;
571                                }
572                            }
573                            // Ensure outcome_val_for_this_state is within bounds (0 to num_outcomes-1)
574                            if outcome_val_for_this_state < num_outcomes {
575                                acc_probs[outcome_val_for_this_state] += amplitude.norm_sqr();
576                            }
577                            acc_probs
578                        },
579                    )
580                    .reduce(
581                        || vec![0.0; num_outcomes], // Initialiser for combining thread-local results
582                        |mut total_probs, local_probs| {
583                            for i in 0..num_outcomes {
584                                total_probs[i] += local_probs[i];
585                            }
586                            total_probs
587                        },
588                    );
589
590                // Normalise probabilities
591                let total_probability: f64 = probabilities.iter().sum();
592                if total_probability < f64::EPSILON {
593                    return Err(Error::UnknownError);
594                }
595                let normalised_probabilities: Vec<f64> = probabilities
596                    .iter()
597                    .map(|&prob| prob / total_probability)
598                    .collect();
599
600                // Sample an outcome based on the probabilities
601                let mut rng = rand::rng();
602                let random_value: f64 = rng.random_range(0.0..1.0);
603
604                let mut cumulative_probability: f64 = 0.0;
605                let mut sampled_outcome_int: usize = 0;
606
607                // Sample loop
608                for (i, &prob) in normalised_probabilities.iter().enumerate() {
609                    cumulative_probability += prob;
610                    // Sample if random_value falls into the cumulative probability bin
611                    if random_value < cumulative_probability {
612                        sampled_outcome_int = i;
613                        break; // Found the outcome, exit loop
614                    }
615                }
616                // If, due to floating point issues, no outcome was selected, select the last one.
617                if random_value >= cumulative_probability && !normalised_probabilities.is_empty() {
618                    sampled_outcome_int = normalised_probabilities.len() - 1;
619                }
620
621                // Collapse the state vector into a new vector
622                let mut collapsed_state_data: Vec<Complex<f64>> =
623                    vec![Complex::new(0.0, 0.0); self.state_vector.len()];
624
625                let normalisation_sq: f64 = collapsed_state_data
626                    .par_iter_mut()
627                    .enumerate()
628                    .zip(self.state_vector.par_iter()) // Zip with original state vector amplitudes
629                    .map(|((idx, collapsed_amp_ref), &original_amp)| {
630                        let mut current_outcome_val_for_this_state = 0;
631                        // Extract the bits corresponding to measured_qubits
632                        for (bit_idx, &qubit_pos) in actual_measured_qubits.iter().enumerate() {
633                            if (idx >> qubit_pos) & 1 != 0 {
634                                current_outcome_val_for_this_state |= 1 << bit_idx;
635                            }
636                        }
637
638                        if current_outcome_val_for_this_state == sampled_outcome_int {
639                            *collapsed_amp_ref = original_amp;
640                            original_amp.norm_sqr() // Contribution to normalisation_sq
641                        } else {
642                            // *collapsed_amp_ref remains Complex::new(0.0, 0.0)
643                            0.0 // No contribution
644                        }
645                    })
646                    .sum(); // Sums up all contributions to get total normalisation_sq
647
648                // Renormalise the new collapsed state vector
649                if normalisation_sq > f64::EPSILON {
650                    let norm_factor: f64 = normalisation_sq.sqrt();
651                    for amplitude in collapsed_state_data.iter_mut() {
652                        *amplitude /= norm_factor;
653                    }
654                }
655
656                // Convert the sampled integer outcome to a Vec<u8>
657                let mut outcome_binary_vec: Vec<u8> = vec![0; num_measured];
658                for (i, qubit_pos) in outcome_binary_vec.iter_mut().enumerate() {
659                    *qubit_pos = ((sampled_outcome_int >> i) & 1) as u8;
660                }
661
662                // Create the measurement result
663                Ok(MeasurementResult {
664                    basis,
665                    indices: actual_measured_qubits.to_vec(),
666                    outcomes: outcome_binary_vec,
667                    new_state: State::new(collapsed_state_data)?,
668                })
669            }
670            MeasurementBasis::X => {
671                // Apply Hadamard to measured qubits
672                let transformed_state = self.h_multi(actual_measured_qubits)?;
673                // Measure in computational basis
674                let computational_measurement_result =
675                    transformed_state._measure_computational(actual_measured_qubits)?;
676                // Transform the new state back by applying Hadamard again
677                let final_state = computational_measurement_result
678                    .new_state
679                    .h_multi(actual_measured_qubits)?;
680                Ok(MeasurementResult {
681                    basis: MeasurementBasis::X,
682                    indices: computational_measurement_result.indices,
683                    outcomes: computational_measurement_result.outcomes,
684                    new_state: final_state,
685                })
686            }
687            MeasurementBasis::Y => {
688                // Apply Sdg then H to measured qubits
689                let state_after_sdag = self.s_dag_multi(actual_measured_qubits)?;
690                let transformed_state = state_after_sdag.h_multi(actual_measured_qubits)?;
691                // Measure in computational basis
692                let computational_measurement_result =
693                    transformed_state._measure_computational(actual_measured_qubits)?;
694                // Transform the new state back by applying H then S
695                let state_after_h = computational_measurement_result
696                    .new_state
697                    .h_multi(actual_measured_qubits)?;
698                let final_state = state_after_h.s_multi(actual_measured_qubits)?;
699                Ok(MeasurementResult {
700                    basis: MeasurementBasis::Y,
701                    indices: computational_measurement_result.indices,
702                    outcomes: computational_measurement_result.outcomes,
703                    new_state: final_state,
704                })
705            }
706            MeasurementBasis::Custom(u_matrix) => {
707                // Apply the custom unitary U to measured qubits
708                let transformed_state = self.unitary_multi(actual_measured_qubits, u_matrix)?;
709
710                // Measure in computational basis
711                let computational_measurement_result =
712                    transformed_state._measure_computational(actual_measured_qubits)?;
713
714                // Calculate U_dagger (adjoint of u_matrix)
715                let u_dagger_matrix = calculate_adjoint(&u_matrix);
716
717                // Transform the new state back by applying U_dagger
718                let final_state = computational_measurement_result
719                    .new_state
720                    .unitary_multi(actual_measured_qubits, u_dagger_matrix)?;
721
722                Ok(MeasurementResult {
723                    basis: MeasurementBasis::Custom(u_matrix),
724                    indices: computational_measurement_result.indices,
725                    outcomes: computational_measurement_result.outcomes,
726                    new_state: final_state,
727                })
728            }
729        }
730    }
731
732    /// Measures the state vector `n` times in the specified basis and returns the measurement results.
733    ///
734    /// # Arguments
735    ///
736    /// * `basis` - The basis to measure in.
737    /// * `indices` - The indices of the qubits to measure. If `indices` is empty, all qubits are measured.
738    /// * `n` - The number of measurements to perform.
739    ///
740    /// # Returns
741    ///
742    /// * `results` - A result containing a vector of measurement results if successful, or an error if the measurement fails.
743    ///
744    /// # Errors
745    ///
746    /// * Returns an error if the measurement fails.
747    /// * Returns an error if the number of qubits is invalid.
748    /// * Returns an error if the indices are out of bounds for the state vector.
749    /// * Returns an error if `n` is 0.
750    pub fn measure_n(
751        &self,
752        basis: MeasurementBasis,
753        measured_qubits: &[usize],
754        n: usize,
755    ) -> Result<Vec<MeasurementResult>, Error> {
756        if n == 0 {
757            return Err(Error::InvalidNumberOfMeasurements(0));
758        }
759
760        // If no indices are provided, measure all qubits
761        let all_indices: Vec<usize> = (0..self.num_qubits).collect();
762        let actual_measured_qubits: &[usize] = if measured_qubits.is_empty() {
763            &all_indices
764        } else {
765            measured_qubits
766        };
767
768        // Check for valid indices
769        let num_measured: usize = actual_measured_qubits.len();
770        if num_measured > self.num_qubits {
771            return Err(Error::InvalidNumberOfQubits(self.num_qubits));
772        }
773        for &index in actual_measured_qubits {
774            if index >= self.num_qubits {
775                return Err(Error::InvalidQubitIndex(index, self.num_qubits));
776            }
777        }
778
779        let results: Vec<MeasurementResult> = (0..n)
780            .into_par_iter()
781            .map(|_| self.measure(basis, actual_measured_qubits))
782            .collect::<Result<Vec<MeasurementResult>, Error>>()?;
783        Ok(results)
784    }
785
786    /// Performs a tensor product of two state vectors and returns the resulting state.
787    /// Uses parallel computation if the resulting dimension is large enough.
788    ///
789    /// # Arguments
790    ///
791    /// * `other` - The other state vector to perform the tensor product with.
792    ///
793    /// # Returns
794    ///
795    /// * `result` - A result containing the new state object if successful, or an error if the operation fails.
796    ///
797    /// # Errors
798    ///
799    /// * Returns an error if either state vector is empty.
800    /// * Returns an error if either state vector has an invalid number of qubits.
801    pub fn tensor_product(&self, other: &Self) -> Result<Self, Error> {
802        if self.num_qubits == 0 || other.num_qubits == 0 {
803            return Err(Error::InvalidNumberOfQubits(0));
804        }
805
806        let new_num_qubits: usize = self.num_qubits + other.num_qubits;
807        let new_dim: usize = 1 << new_num_qubits;
808        let other_dim: usize = 1 << other.num_qubits; // Cache dimension of other state
809
810        // Threshold for using parallel computation
811        const PARALLEL_THRESHOLD: usize = 1 << 6; // Parallelise when dimension is larger than 64
812
813        let new_state_vector: Vec<Complex<f64>> = if new_dim > PARALLEL_THRESHOLD {
814            // Parallel calculation for large states
815            (0..new_dim)
816                .into_par_iter()
817                .map(|new_index| {
818                    let i: usize = new_index >> other.num_qubits; // Index for self.state_vector
819                    let j: usize = new_index & (other_dim - 1); // Index for other.state_vector
820                    self.state_vector[i] * other.state_vector[j]
821                })
822                .collect()
823        } else {
824            // Sequential calculation for smaller states
825            let mut temp_state_vector: Vec<Complex<f64>> = vec![Complex::new(0.0, 0.0); new_dim];
826            for i in 0..self.state_vector.len() {
827                for j in 0..other.state_vector.len() {
828                    temp_state_vector[(i * other_dim) + j] =
829                        self.state_vector[i] * other.state_vector[j];
830                }
831            }
832            temp_state_vector
833        };
834
835        Self::new(new_state_vector) // For normalisation check
836    }
837
838    /// Performs a tensor product of two state vectors without checking for validity.
839    #[allow(dead_code)]
840    pub(crate) fn tensor_product_unchecked(&self, other: &Self) -> Self {
841        let new_num_qubits: usize = self.num_qubits + other.num_qubits;
842        let new_dim: usize = 1 << new_num_qubits;
843        let other_dim: usize = 1 << other.num_qubits; // Cache dimension of other state
844
845        // Threshold for using parallel computation
846        const PARALLEL_THRESHOLD: usize = 1 << 6; // Parallelise when dimension is larger than 64
847
848        let new_state_vector: Vec<Complex<f64>> = if new_dim > PARALLEL_THRESHOLD {
849            // Parallel calculation for large states
850            (0..new_dim)
851                .into_par_iter()
852                .map(|new_index| {
853                    let i: usize = new_index >> other.num_qubits; // Index for self.state_vector
854                    let j: usize = new_index & (other_dim - 1); // Index for other.state_vector
855                    self.state_vector[i] * other.state_vector[j]
856                })
857                .collect()
858        } else {
859            // Sequential calculation for smaller states
860            let mut temp_state_vector: Vec<Complex<f64>> = vec![Complex::new(0.0, 0.0); new_dim];
861            for i in 0..self.state_vector.len() {
862                for j in 0..other.state_vector.len() {
863                    temp_state_vector[(i * other_dim) + j] =
864                        self.state_vector[i] * other.state_vector[j];
865                }
866            }
867            temp_state_vector
868        };
869
870        Self {
871            state_vector: new_state_vector,
872            num_qubits: new_num_qubits,
873        }
874    }
875
876    /// Performs an inner product of two state vectors (<Self | Other>) and returns the resulting complex number.
877    ///
878    /// # Arguments
879    ///
880    /// * `other` - The other state vector to perform the inner product with.
881    ///
882    /// # Returns
883    ///
884    /// * `result` - A result containing the inner product as a complex number if successful, or an error if the operation fails.
885    ///
886    /// # Errors
887    ///
888    /// * Returns an error if either state vector is empty.
889    /// * Returns an error if the state vectors have different dimensions.
890    pub fn inner_product(&self, other: &Self) -> Result<Complex<f64>, Error> {
891        if self.num_qubits == 0 || other.num_qubits == 0 {
892            return Err(Error::InvalidNumberOfQubits(0));
893        }
894
895        if self.state_vector.len() != other.state_vector.len() {
896            return Err(Error::InvalidNumberOfQubits(self.num_qubits));
897        }
898
899        const PARALLEL_THRESHOLD: usize = 1 << 6; // Threshold for parallelisation
900        let len = self.state_vector.len();
901
902        let inner_product: Complex<f64> = if len > PARALLEL_THRESHOLD {
903            self.state_vector
904                .par_iter()
905                .zip(other.state_vector.par_iter())
906                .map(|(a, b)| a.conj() * b)
907                .sum()
908        } else {
909            self.state_vector
910                .iter()
911                .zip(other.state_vector.iter())
912                .map(|(a, b)| a.conj() * b)
913                .sum()
914        };
915
916        Ok(inner_product)
917    }
918
919    /// Normalises the state vector and returns the state.
920    ///
921    /// # Returns
922    ///
923    /// * `Result<State, Error>` - The resulting state after normalisation, or an error if the operation fails.
924    pub fn normalise(&self) -> Result<Self, Error> {
925        let norm = self
926            .state_vector
927            .iter()
928            .map(|x| x.norm_sqr())
929            .sum::<f64>()
930            .sqrt();
931        if norm == 0.0 {
932            return Err(Error::ZeroNorm);
933        }
934        if norm == 1.0 {
935            return Ok(self.clone());
936        }
937
938        let new_state_vector: Vec<Complex<f64>> =
939            self.state_vector.iter().map(|x| x / norm).collect();
940
941        Ok(Self {
942            state_vector: new_state_vector,
943            num_qubits: self.num_qubits,
944        })
945    }
946
947    // ***** OPERATION FUNCTIONS *****
948
949    /// Applies a unitary operation to the state vector.
950    ///
951    /// # Arguments
952    ///
953    /// * `unitary` - The unitary operation to apply, represented as an `Operator` trait object.
954    ///
955    /// * target_qubits - The indices of the qubits to apply the unitary operation to.
956    ///
957    /// * control_qubits - The indices of the control qubits for the unitary operation, if any.
958    ///
959    /// # Returns
960    ///
961    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
962    ///
963    /// # Errors
964    ///
965    /// * Returns an error if the unitary operation is invalid.
966    ///
967    /// * Returns an error if the number of qubits provided is invalid.
968    ///
969    /// * Returns an error if the indices are out of bounds for the state vector.
970    pub fn operate(
971        &self,
972        unitary: impl Operator,
973        target_qubits: &[usize],
974        control_qubits: &[usize],
975    ) -> Result<Self, Error> {
976        // Check for valid indices
977        let num_target: usize = target_qubits.len();
978        let num_control: usize = control_qubits.len();
979
980        if unitary.base_qubits() != (num_target + num_control) {
981            return Err(Error::InvalidNumberOfQubits(unitary.base_qubits()));
982        }
983
984        if num_target > self.num_qubits {
985            return Err(Error::InvalidNumberOfQubits(self.num_qubits));
986        }
987
988        for &index in target_qubits {
989            if index >= self.num_qubits {
990                return Err(Error::InvalidQubitIndex(index, self.num_qubits));
991            }
992        }
993
994        for &index in control_qubits {
995            if index >= self.num_qubits {
996                return Err(Error::InvalidQubitIndex(index, self.num_qubits));
997            }
998        }
999
1000        // Apply the unitary operation to the state vector and return the new state
1001        unitary.apply(self, target_qubits, control_qubits)
1002    }
1003
1004    // -- SINGLE-QUBIT GATES --
1005
1006    /// Applies the Hadamard gate to the specified qubit in the state vector.
1007    ///
1008    /// # Arguments
1009    ///
1010    /// * `index` - The index of the qubit to apply the Hadamard gate to.
1011    ///
1012    /// # Returns
1013    ///
1014    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1015    ///
1016    /// # Errors
1017    ///
1018    /// * Returns an error if the index is out of bounds for the state vector.
1019    pub fn h(&self, index: usize) -> Result<Self, Error> {
1020        Hadamard {}.apply(self, &[index], &[])
1021    }
1022
1023    /// Applies the Hadamard gate to the specified qubits in the state vector in the given order.
1024    ///
1025    /// # Arguments
1026    ///
1027    /// * `qubits` - The indices of the qubits to apply the Hadamard gate to.
1028    ///
1029    /// # Returns
1030    ///
1031    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1032    ///
1033    /// * # Errors
1034    ///
1035    /// * Returns an error if the number of qubits provided is invalid.
1036    ///
1037    /// * Returns an error if the indices are out of bounds for the state vector.
1038    pub fn h_multi(&self, qubits: &[usize]) -> Result<Self, Error> {
1039        let mut new_state: State = self.clone();
1040        let h: Hadamard = Hadamard {};
1041        for &qubit in qubits {
1042            new_state = h.apply(&new_state, &[qubit], &[])?;
1043        }
1044        Ok(new_state)
1045    }
1046
1047    /// Applies the controlled Hadamard gate to the specified qubits in the state vector in the given order.
1048    ///
1049    /// # Arguments
1050    ///
1051    /// * `target_qubits` - The indices of the target qubits to apply the controlled Hadamard gate to.
1052    ///
1053    /// * `control_qubits` - The indices of the control qubits for the controlled Hadamard gate.
1054    ///
1055    /// # Returns
1056    ///
1057    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1058    ///
1059    /// * # Errors
1060    ///
1061    /// * Returns an error if the number of qubits provided is invalid.
1062    ///
1063    /// * Returns an error if the indices are out of bounds for the state vector.
1064    ///
1065    /// * Returns an error if the control qubits and target qubits overlap.
1066    pub fn ch_multi(
1067        &self,
1068        target_qubits: &[usize],
1069        control_qubits: &[usize],
1070    ) -> Result<Self, Error> {
1071        let mut new_state: State = self.clone();
1072        let h: Hadamard = Hadamard {};
1073        for &qubit in target_qubits {
1074            new_state = h.apply(&new_state, &[qubit], control_qubits)?;
1075        }
1076        Ok(new_state)
1077    }
1078
1079    /// Applies the Pauli-X (NOT) gate to the specified qubit in the state vector.
1080    ///
1081    /// # Arguments
1082    ///
1083    /// * `index` - The index of the qubit to apply the Pauli-X gate to.
1084    ///
1085    /// # Returns
1086    ///
1087    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1088    ///
1089    /// # Errors
1090    ///
1091    /// * Returns an error if the index is out of bounds for the state vector.
1092    pub fn x(&self, index: usize) -> Result<Self, Error> {
1093        Pauli::X.apply(self, &[index], &[])
1094    }
1095
1096    /// Applies the Pauli-X (NOT) gate to the specified qubits in the state vector in the given order.
1097    ///
1098    /// # Arguments
1099    ///
1100    /// * `qubits` - The indices of the qubits to apply the Pauli-X gate to.
1101    ///
1102    /// # Returns
1103    ///
1104    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1105    ///
1106    /// # Errors
1107    ///
1108    /// * Returns an error if the number of qubits provided is invalid.
1109    ///
1110    /// * Returns an error if the indices are out of bounds for the state vector.
1111    pub fn x_multi(&self, qubits: &[usize]) -> Result<Self, Error> {
1112        let mut new_state: State = self.clone();
1113        let x: Pauli = Pauli::X;
1114        for &qubit in qubits {
1115            new_state = x.apply(&new_state, &[qubit], &[])?;
1116        }
1117        Ok(new_state)
1118    }
1119
1120    /// Applies the controlled Pauli-X (NOT) gate to the specified qubits in the state vector in the given order.
1121    ///
1122    /// # Arguments
1123    ///
1124    /// * `target_qubits` - The indices of the target qubits to apply the controlled Pauli-X gate to.
1125    /// * `control_qubits` - The indices of the control qubits for the controlled Pauli-X gate.
1126    ///
1127    /// # Returns
1128    ///
1129    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1130    ///
1131    /// # Errors
1132    ///
1133    /// * Returns an error if the number of qubits provided is invalid.
1134    /// * Returns an error if the indices are out of bounds for the state vector.
1135    /// * Returns an error if the control qubits and target qubits overlap.
1136    pub fn cx_multi(
1137        &self,
1138        target_qubits: &[usize],
1139        control_qubits: &[usize],
1140    ) -> Result<Self, Error> {
1141        let mut new_state: State = self.clone();
1142        let x: Pauli = Pauli::X;
1143        for &qubit in target_qubits {
1144            new_state = x.apply(&new_state, &[qubit], control_qubits)?;
1145        }
1146        Ok(new_state)
1147    }
1148
1149    /// Applies the Pauli-Y gate to the specified qubit in the state vector.
1150    ///
1151    /// # Arguments
1152    ///
1153    /// * `index` - The index of the qubit to apply the Pauli-Y gate to.
1154    ///
1155    /// # Returns
1156    ///
1157    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1158    ///
1159    /// # Errors
1160    ///
1161    /// * Returns an error if the index is out of bounds for the state vector.
1162    pub fn y(&self, index: usize) -> Result<Self, Error> {
1163        Pauli::Y.apply(self, &[index], &[])
1164    }
1165
1166    /// Applies the Pauli-Y gate to the specified qubits in the state vector in the given order.
1167    ///
1168    /// # Arguments
1169    ///
1170    /// * `qubits` - The indices of the qubits to apply the Pauli-Y gate to.
1171    ///
1172    /// # Returns
1173    ///
1174    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1175    ///
1176    /// # Errors
1177    ///
1178    /// * Returns an error if the number of qubits provided is invalid.
1179    ///
1180    /// * Returns an error if the indices are out of bounds for the state vector.
1181    pub fn y_multi(&self, qubits: &[usize]) -> Result<Self, Error> {
1182        let mut new_state: State = self.clone();
1183        let y: Pauli = Pauli::Y;
1184        for &qubit in qubits {
1185            new_state = y.apply(&new_state, &[qubit], &[])?;
1186        }
1187        Ok(new_state)
1188    }
1189
1190    /// Applies the controlled Pauli-Y gate to the specified qubits in the state vector in the given order.
1191    ///
1192    /// # Arguments
1193    ///
1194    /// * `target_qubits` - The indices of the target qubits to apply the controlled Pauli-Y gate to.
1195    /// * `control_qubits` - The indices of the control qubits for the controlled Pauli-Y gate.
1196    ///
1197    /// # Returns
1198    ///
1199    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1200    ///
1201    /// # Errors
1202    ///
1203    /// * Returns an error if the number of qubits provided is invalid.
1204    /// * Returns an error if the indices are out of bounds for the state vector.
1205    /// * Returns an error if the control qubits and target qubits overlap.
1206    pub fn cy_multi(
1207        &self,
1208        target_qubits: &[usize],
1209        control_qubits: &[usize],
1210    ) -> Result<Self, Error> {
1211        let mut new_state: State = self.clone();
1212        let y: Pauli = Pauli::Y;
1213        for &qubit in target_qubits {
1214            new_state = y.apply(&new_state, &[qubit], control_qubits)?;
1215        }
1216        Ok(new_state)
1217    }
1218
1219    /// Applies the Pauli-Z gate to the specified qubit in the state vector.
1220    ///
1221    /// # Arguments
1222    ///
1223    /// * `index` - The index of the qubit to apply the Pauli-Z gate to.
1224    ///
1225    /// # Returns
1226    ///
1227    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1228    ///
1229    /// # Errors
1230    ///
1231    /// * Returns an error if the index is out of bounds for the state vector.
1232    pub fn z(&self, index: usize) -> Result<Self, Error> {
1233        Pauli::Z.apply(self, &[index], &[])
1234    }
1235
1236    /// Applies the Pauli-Z gate to the specified qubits in the state vector in the given order.
1237    ///
1238    /// # Arguments
1239    ///
1240    /// * `qubits` - The indices of the qubits to apply the Pauli-Z gate to.
1241    ///
1242    /// # Returns
1243    ///
1244    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1245    ///
1246    /// # Errors
1247    ///
1248    /// * Returns an error if the number of qubits provided is invalid.
1249    ///
1250    /// * Returns an error if the indices are out of bounds for the state vector.
1251    pub fn z_multi(&self, qubits: &[usize]) -> Result<Self, Error> {
1252        let mut new_state: State = self.clone();
1253        let z: Pauli = Pauli::Z;
1254        for &qubit in qubits {
1255            new_state = z.apply(&new_state, &[qubit], &[])?;
1256        }
1257        Ok(new_state)
1258    }
1259
1260    /// Applies the controlled Pauli-Z gate to the specified qubits in the state vector in the given order.
1261    ///
1262    /// # Arguments
1263    ///
1264    /// * `target_qubits` - The indices of the target qubits to apply the controlled Pauli-Z gate to.
1265    /// * `control_qubits` - The indices of the control qubits for the controlled Pauli-Z gate.
1266    ///
1267    /// # Returns
1268    ///
1269    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1270    ///
1271    /// # Errors
1272    ///
1273    /// * Returns an error if the number of qubits provided is invalid.
1274    /// * Returns an error if the indices are out of bounds for the state vector.
1275    /// * Returns an error if the control qubits and target qubits overlap.
1276    pub fn cz_multi(
1277        &self,
1278        target_qubits: &[usize],
1279        control_qubits: &[usize],
1280    ) -> Result<Self, Error> {
1281        let mut new_state: State = self.clone();
1282        let z: Pauli = Pauli::Z;
1283        for &qubit in target_qubits {
1284            new_state = z.apply(&new_state, &[qubit], control_qubits)?;
1285        }
1286        Ok(new_state)
1287    }
1288
1289    /// Applies the Identity gate to the state vector.
1290    ///
1291    /// # Arguments
1292    ///
1293    /// * `qubit` - The index of the qubit to apply the Identity gate to.
1294    ///
1295    /// # Returns
1296    ///
1297    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1298    ///
1299    /// # Errors
1300    ///
1301    /// * Returns an error if the index is out of bounds for the state vector.
1302    pub fn i(&self, qubit: usize) -> Result<Self, Error> {
1303        Identity {}.apply(self, &[qubit], &[])
1304    }
1305
1306    /// Applies the Identity gate to the state vector for multiple qubits in the given order.
1307    ///
1308    /// # Arguments
1309    ///
1310    /// * `qubits` - The indices of the qubits to apply the Identity gate to.
1311    ///
1312    /// # Returns
1313    ///
1314    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1315    ///
1316    /// # Errors
1317    ///
1318    /// * Returns an error if the number of qubits provided is invalid.
1319    ///
1320    /// * Returns an error if the indices are out of bounds for the state vector.
1321    pub fn i_multi(&self, qubits: &[usize]) -> Result<Self, Error> {
1322        let mut new_state: State = self.clone();
1323        let i: Identity = Identity {};
1324        for &qubit in qubits {
1325            new_state = i.apply(&new_state, &[qubit], &[])?;
1326        }
1327        Ok(new_state)
1328    }
1329
1330    /// Applies the controlled Identity gate to the state vector for multiple qubits in the given order.
1331    ///
1332    /// # Arguments
1333    ///
1334    /// * `target_qubits` - The indices of the target qubits to apply the controlled Identity gate to.
1335    /// * `control_qubits` - The indices of the control qubits for the controlled Identity gate.
1336    ///
1337    /// # Returns
1338    ///
1339    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1340    ///
1341    /// # Errors
1342    ///
1343    /// * Returns an error if the number of qubits provided is invalid.
1344    /// * Returns an error if the indices are out of bounds for the state vector.
1345    /// * Returns an error if the control qubits and target qubits overlap.
1346    pub fn ci_multi(
1347        &self,
1348        target_qubits: &[usize],
1349        control_qubits: &[usize],
1350    ) -> Result<Self, Error> {
1351        let mut new_state: State = self.clone();
1352        let i: Identity = Identity {};
1353        for &qubit in target_qubits {
1354            new_state = i.apply(&new_state, &[qubit], control_qubits)?;
1355        }
1356        Ok(new_state)
1357    }
1358
1359    /// Applies the Phase S gate to the specified qubit in the state vector.
1360    ///
1361    /// # Arguments
1362    ///
1363    /// * `index` - The index of the qubit to apply the Phase S gate to.
1364    ///
1365    /// # Returns
1366    ///
1367    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1368    ///
1369    /// # Errors
1370    ///
1371    /// * Returns an error if the index is out of bounds for the state vector.
1372    pub fn s(&self, index: usize) -> Result<Self, Error> {
1373        PhaseS {}.apply(self, &[index], &[])
1374    }
1375
1376    /// Applies the Phase S gate to the specified qubits in the state vector in the given order.
1377    ///
1378    /// # Arguments
1379    ///
1380    /// * `qubits` - The indices of the qubits to apply the Phase S gate to.
1381    ///
1382    /// # Returns
1383    ///
1384    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1385    ///
1386    /// # Errors
1387    ///
1388    /// * Returns an error if the number of qubits provided is invalid.
1389    ///
1390    /// * Returns an error if the indices are out of bounds for the state vector.
1391    pub fn s_multi(&self, qubits: &[usize]) -> Result<Self, Error> {
1392        let mut new_state: State = self.clone();
1393        let s_gate: PhaseS = PhaseS {};
1394        for &qubit in qubits {
1395            new_state = s_gate.apply(&new_state, &[qubit], &[])?;
1396        }
1397        Ok(new_state)
1398    }
1399
1400    /// Applies the controlled Phase S gate to the specified qubits in the state vector in the given order.
1401    ///
1402    /// # Arguments
1403    ///
1404    /// * `target_qubits` - The indices of the target qubits to apply the controlled Phase S gate to.
1405    /// * `control_qubits` - The indices of the control qubits for the controlled Phase S gate.
1406    ///
1407    /// # Returns
1408    ///
1409    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1410    ///
1411    /// # Errors
1412    ///
1413    /// * Returns an error if the number of qubits provided is invalid.
1414    /// * Returns an error if the indices are out of bounds for the state vector.
1415    /// * Returns an error if the control qubits and target qubits overlap.
1416    pub fn cs_multi(
1417        &self,
1418        target_qubits: &[usize],
1419        control_qubits: &[usize],
1420    ) -> Result<Self, Error> {
1421        let mut new_state: State = self.clone();
1422        let s_gate: PhaseS = PhaseS {};
1423        for &qubit in target_qubits {
1424            new_state = s_gate.apply(&new_state, &[qubit], control_qubits)?;
1425        }
1426        Ok(new_state)
1427    }
1428
1429    /// Applies the Phase T gate to the specified qubit in the state vector.
1430    ///
1431    /// # Arguments
1432    ///
1433    /// * `index` - The index of the qubit to apply the Phase T gate to.
1434    ///
1435    /// # Returns
1436    ///
1437    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1438    ///
1439    /// # Errors
1440    ///
1441    /// * Returns an error if the index is out of bounds for the state vector.
1442    pub fn t(&self, index: usize) -> Result<Self, Error> {
1443        PhaseT {}.apply(self, &[index], &[])
1444    }
1445
1446    /// Applies the Phase T gate to the specified qubits in the state vector in the given order.
1447    ///
1448    /// # Arguments
1449    ///
1450    /// * `qubits` - The indices of the qubits to apply the Phase T gate to.
1451    ///
1452    /// # Returns
1453    ///
1454    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1455    ///
1456    /// # Errors
1457    ///
1458    /// * Returns an error if the number of qubits provided is invalid.
1459    ///
1460    /// * Returns an error if the indices are out of bounds for the state vector.
1461    pub fn t_multi(&self, qubits: &[usize]) -> Result<Self, Error> {
1462        let mut new_state: State = self.clone();
1463        let t_gate: PhaseT = PhaseT {};
1464        for &qubit in qubits {
1465            new_state = t_gate.apply(&new_state, &[qubit], &[])?;
1466        }
1467        Ok(new_state)
1468    }
1469
1470    /// Applies the controlled Phase T gate to the specified qubits in the state vector in the given order.
1471    ///
1472    /// # Arguments
1473    ///
1474    /// * `target_qubits` - The indices of the target qubits to apply the controlled Phase T gate to.
1475    /// * `control_qubits` - The indices of the control qubits for the controlled Phase T gate.
1476    ///
1477    /// # Returns
1478    ///
1479    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1480    ///
1481    /// # Errors
1482    ///
1483    /// * Returns an error if the number of qubits provided is invalid.
1484    /// * Returns an error if the indices are out of bounds for the state vector.
1485    /// * Returns an error if the control qubits and target qubits overlap.
1486    pub fn ct_multi(
1487        &self,
1488        target_qubits: &[usize],
1489        control_qubits: &[usize],
1490    ) -> Result<Self, Error> {
1491        let mut new_state: State = self.clone();
1492        let t_gate: PhaseT = PhaseT {};
1493        for &qubit in target_qubits {
1494            new_state = t_gate.apply(&new_state, &[qubit], control_qubits)?;
1495        }
1496        Ok(new_state)
1497    }
1498
1499    /// Applies the Phase S dagger gate to the specified qubit in the state vector.
1500    ///
1501    /// # Arguments
1502    ///
1503    /// * `index` - The index of the qubit to apply the Phase S dagger gate to.
1504    ///
1505    /// # Returns
1506    ///
1507    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1508    ///
1509    /// # Errors
1510    ///
1511    /// * Returns an error if the index is out of bounds for the state vector.
1512    pub fn s_dag(&self, index: usize) -> Result<Self, Error> {
1513        PhaseSdag {}.apply(self, &[index], &[])
1514    }
1515
1516    /// Applies the Phase S dagger gate to the specified qubits in the state vector in the given order.
1517    ///
1518    /// # Arguments
1519    ///
1520    /// * `qubits` - The indices of the qubits to apply the Phase S dagger gate to.
1521    ///
1522    /// # Returns
1523    ///
1524    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1525    ///
1526    /// # Errors
1527    ///
1528    /// * Returns an error if the number of qubits provided is invalid.
1529    ///
1530    /// * Returns an error if the indices are out of bounds for the state vector.
1531    pub fn s_dag_multi(&self, qubits: &[usize]) -> Result<Self, Error> {
1532        let mut new_state: State = self.clone();
1533        let sdag_gate: PhaseSdag = PhaseSdag {};
1534        for &qubit in qubits {
1535            new_state = sdag_gate.apply(&new_state, &[qubit], &[])?;
1536        }
1537        Ok(new_state)
1538    }
1539
1540    /// Applies the controlled Phase S dagger gate to the specified qubits in the state vector in the given order.
1541    ///
1542    /// # Arguments
1543    ///
1544    /// * `target_qubits` - The indices of the target qubits to apply the controlled Phase S dagger gate to.
1545    /// * `control_qubits` - The indices of the control qubits for the controlled Phase S dagger gate.
1546    ///
1547    /// # Returns
1548    ///
1549    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1550    ///
1551    /// # Errors
1552    ///
1553    /// * Returns an error if the number of qubits provided is invalid.
1554    /// * Returns an error if the indices are out of bounds for the state vector.
1555    /// * Returns an error if the control qubits and target qubits overlap.
1556    pub fn cs_dag_multi(
1557        &self,
1558        target_qubits: &[usize],
1559        control_qubits: &[usize],
1560    ) -> Result<Self, Error> {
1561        let mut new_state: State = self.clone();
1562        let sdag_gate: PhaseSdag = PhaseSdag {};
1563        for &qubit in target_qubits {
1564            new_state = sdag_gate.apply(&new_state, &[qubit], control_qubits)?;
1565        }
1566        Ok(new_state)
1567    }
1568
1569    /// Applies the Phase T dagger gate to the specified qubit in the state vector.
1570    ///
1571    /// # Arguments
1572    ///
1573    /// * `index` - The index of the qubit to apply the Phase T dagger gate to.
1574    ///
1575    /// # Returns
1576    ///
1577    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1578    ///
1579    /// # Errors
1580    ///
1581    /// * Returns an error if the index is out of bounds for the state vector.
1582    pub fn t_dag(&self, index: usize) -> Result<Self, Error> {
1583        PhaseTdag {}.apply(self, &[index], &[])
1584    }
1585
1586    /// Applies the Phase T dagger gate to the specified qubits in the state vector in the given order.
1587    ///
1588    /// # Arguments
1589    ///
1590    /// * `qubits` - The indices of the qubits to apply the Phase T dagger gate to.
1591    ///
1592    /// # Returns
1593    ///
1594    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1595    ///
1596    /// # Errors
1597    ///
1598    /// * Returns an error if the number of qubits provided is invalid.
1599    ///
1600    /// * Returns an error if the indices are out of bounds for the state vector.
1601    pub fn t_dag_multi(&self, qubits: &[usize]) -> Result<Self, Error> {
1602        let mut new_state: State = self.clone();
1603        let tdag_gate: PhaseTdag = PhaseTdag {};
1604        for &qubit in qubits {
1605            new_state = tdag_gate.apply(&new_state, &[qubit], &[])?;
1606        }
1607        Ok(new_state)
1608    }
1609
1610    /// Applies the controlled Phase T dagger gate to the specified qubits in the state vector in the given order.
1611    ///
1612    /// # Arguments
1613    ///
1614    /// * `target_qubits` - The indices of the target qubits to apply the controlled Phase T dagger gate to.
1615    /// * `control_qubits` - The indices of the control qubits for the controlled Phase T dagger gate.
1616    ///
1617    /// # Returns
1618    ///
1619    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1620    ///
1621    /// # Errors
1622    ///
1623    /// * Returns an error if the number of qubits provided is invalid.
1624    /// * Returns an error if the indices are out of bounds for the state vector.
1625    /// * Returns an error if the control qubits and target qubits overlap.
1626    pub fn ct_dag_multi(
1627        &self,
1628        target_qubits: &[usize],
1629        control_qubits: &[usize],
1630    ) -> Result<Self, Error> {
1631        let mut new_state: State = self.clone();
1632        let tdag_gate: PhaseTdag = PhaseTdag {};
1633        for &qubit in target_qubits {
1634            new_state = tdag_gate.apply(&new_state, &[qubit], control_qubits)?;
1635        }
1636        Ok(new_state)
1637    }
1638
1639    /// Applies the Phase Shift gate with the specified angle to the given qubit.
1640    ///
1641    /// # Arguments
1642    ///
1643    /// * `index` - The index of the qubit to apply the Phase Shift gate to.
1644    /// * `angle` - The phase shift angle in radians.
1645    ///
1646    /// # Returns
1647    ///
1648    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1649    ///
1650    /// # Errors
1651    ///
1652    /// * Returns an error if the index is out of bounds for the state vector.
1653    pub fn p(&self, index: usize, angle: f64) -> Result<Self, Error> {
1654        PhaseShift::new(angle).apply(self, &[index], &[])
1655    }
1656
1657    /// Applies the Phase Shift gate with the specified angle to the given qubits in order.
1658    ///
1659    /// # Arguments
1660    ///
1661    /// * `qubits` - The indices of the qubits to apply the Phase Shift gate to.
1662    ///
1663    /// * `angle` - The phase shift angle in radians.
1664    ///
1665    /// # Returns
1666    ///
1667    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1668    ///
1669    /// # Errors
1670    ///
1671    /// * Returns an error if the number of qubits provided is invalid.
1672    ///
1673    /// * Returns an error if the indices are out of bounds for the state vector.
1674    pub fn p_multi(&self, qubits: &[usize], angle: f64) -> Result<Self, Error> {
1675        let mut new_state: State = self.clone();
1676        let phase_shift_gate: PhaseShift = PhaseShift::new(angle);
1677        for &qubit in qubits {
1678            new_state = phase_shift_gate.apply(&new_state, &[qubit], &[])?;
1679        }
1680        Ok(new_state)
1681    }
1682
1683    /// Applies the controlled Phase Shift gate with the specified angle to the given qubits in order.
1684    ///
1685    /// # Arguments
1686    ///
1687    /// * `target_qubits` - The indices of the target qubits to apply the controlled Phase Shift gate to.
1688    /// * `control_qubits` - The indices of the control qubits for the controlled Phase Shift gate.
1689    /// * `angle` - The phase shift angle in radians.
1690    ///
1691    /// # Returns
1692    ///
1693    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1694    ///
1695    /// # Errors
1696    ///
1697    /// * Returns an error if the number of qubits provided is invalid.
1698    /// * Returns an error if the indices are out of bounds for the state vector.
1699    /// * Returns an error if the control qubits and target qubits overlap.
1700    pub fn cp_multi(
1701        &self,
1702        target_qubits: &[usize],
1703        control_qubits: &[usize],
1704        angle: f64,
1705    ) -> Result<Self, Error> {
1706        let mut new_state: State = self.clone();
1707        let phase_shift_gate: PhaseShift = PhaseShift::new(angle);
1708        for &qubit in target_qubits {
1709            new_state = phase_shift_gate.apply(&new_state, &[qubit], control_qubits)?;
1710        }
1711        Ok(new_state)
1712    }
1713
1714    /// Applies the RotateX gate with the specified angle to the given qubit.
1715    ///
1716    /// # Arguments
1717    ///
1718    /// * `index` - The index of the qubit to apply the RotateX gate to.
1719    /// * `angle` - The rotation angle in radians.
1720    ///
1721    /// # Returns
1722    ///
1723    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1724    ///
1725    /// # Errors
1726    ///
1727    /// * Returns an error if the index is out of bounds for the state vector.
1728    pub fn rx(&self, index: usize, angle: f64) -> Result<Self, Error> {
1729        RotateX::new(angle).apply(self, &[index], &[])
1730    }
1731
1732    /// Applies the RotateX gate with the specified angle to the given qubits in order.
1733    ///
1734    /// # Arguments
1735    ///
1736    /// * `qubits` - The indices of the qubits to apply the RotateX gate to.
1737    ///
1738    /// * `angle` - The rotation angle in radians.
1739    ///
1740    /// # Returns
1741    ///
1742    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1743    ///
1744    /// # Errors
1745    ///
1746    /// * Returns an error if the number of qubits provided is invalid.
1747    ///
1748    /// * Returns an error if the indices are out of bounds for the state vector.
1749    pub fn rx_multi(&self, qubits: &[usize], angle: f64) -> Result<Self, Error> {
1750        let mut new_state: State = self.clone();
1751        let rotate_x_gate: RotateX = RotateX::new(angle);
1752        for &qubit in qubits {
1753            new_state = rotate_x_gate.apply(&new_state, &[qubit], &[])?;
1754        }
1755        Ok(new_state)
1756    }
1757
1758    /// Applies the controlled RotateX gate with the specified angle to the given qubits in order.
1759    ///
1760    /// # Arguments
1761    ///
1762    /// * `target_qubits` - The indices of the target qubits to apply the controlled RotateX gate to.
1763    /// * `control_qubits` - The indices of the control qubits for the controlled RotateX gate.
1764    /// * `angle` - The rotation angle in radians.
1765    ///
1766    /// # Returns
1767    ///
1768    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1769    ///
1770    /// # Errors
1771    ///
1772    /// * Returns an error if the number of qubits provided is invalid.
1773    /// * Returns an error if the indices are out of bounds for the state vector.
1774    /// * Returns an error if the control qubits and target qubits overlap.
1775    pub fn crx_multi(
1776        &self,
1777        target_qubits: &[usize],
1778        control_qubits: &[usize],
1779        angle: f64,
1780    ) -> Result<Self, Error> {
1781        let mut new_state: State = self.clone();
1782        let rotate_x_gate: RotateX = RotateX::new(angle);
1783        for &qubit in target_qubits {
1784            new_state = rotate_x_gate.apply(&new_state, &[qubit], control_qubits)?;
1785        }
1786        Ok(new_state)
1787    }
1788
1789    /// Applies the RotateY gate with the specified angle to the given qubit.
1790    ///
1791    /// # Arguments
1792    ///
1793    /// * `index` - The index of the qubit to apply the RotateY gate to.
1794    /// * `angle` - The rotation angle in radians.
1795    ///
1796    /// # Returns
1797    ///
1798    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1799    ///
1800    /// # Errors
1801    ///
1802    /// * Returns an error if the index is out of bounds for the state vector.
1803    pub fn ry(&self, index: usize, angle: f64) -> Result<Self, Error> {
1804        RotateY::new(angle).apply(self, &[index], &[])
1805    }
1806
1807    /// Applies the RotateY gate with the specified angle to the given qubits in order.
1808    ///
1809    /// # Arguments
1810    ///
1811    /// * `qubits` - The indices of the qubits to apply the RotateY gate to.
1812    ///
1813    /// * `angle` - The rotation angle in radians.
1814    ///
1815    /// # Returns
1816    ///
1817    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1818    ///
1819    /// # Errors
1820    ///
1821    /// * Returns an error if the number of qubits provided is invalid.
1822    ///
1823    /// * Returns an error if the indices are out of bounds for the state vector.
1824    pub fn ry_multi(&self, qubits: &[usize], angle: f64) -> Result<Self, Error> {
1825        let mut new_state: State = self.clone();
1826        let rotate_y_gate: RotateY = RotateY::new(angle);
1827        for &qubit in qubits {
1828            new_state = rotate_y_gate.apply(&new_state, &[qubit], &[])?;
1829        }
1830        Ok(new_state)
1831    }
1832
1833    /// Applies the controlled RotateY gate with the specified angle to the given qubits in order.
1834    ///
1835    /// # Arguments
1836    ///
1837    /// * `target_qubits` - The indices of the target qubits to apply the controlled RotateY gate to.
1838    /// * `control_qubits` - The indices of the control qubits for the controlled RotateY gate.
1839    /// * `angle` - The rotation angle in radians.
1840    ///
1841    /// # Returns
1842    ///
1843    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1844    ///
1845    /// # Errors
1846    ///
1847    /// * Returns an error if the number of qubits provided is invalid.
1848    /// * Returns an error if the indices are out of bounds for the state vector.
1849    /// * Returns an error if the control qubits and target qubits overlap.
1850    pub fn cry_multi(
1851        &self,
1852        target_qubits: &[usize],
1853        control_qubits: &[usize],
1854        angle: f64,
1855    ) -> Result<Self, Error> {
1856        let mut new_state: State = self.clone();
1857        let rotate_y_gate: RotateY = RotateY::new(angle);
1858        for &qubit in target_qubits {
1859            new_state = rotate_y_gate.apply(&new_state, &[qubit], control_qubits)?;
1860        }
1861        Ok(new_state)
1862    }
1863
1864    /// Applies the RotateZ gate with the specified angle to the given qubit.
1865    ///
1866    /// # Arguments
1867    ///
1868    /// * `index` - The index of the qubit to apply the RotateZ gate to.
1869    /// * `angle` - The rotation angle in radians.
1870    ///
1871    /// # Returns
1872    ///
1873    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1874    ///
1875    /// # Errors
1876    ///
1877    /// * Returns an error if the index is out of bounds for the state vector.
1878    pub fn rz(&self, index: usize, angle: f64) -> Result<Self, Error> {
1879        RotateZ::new(angle).apply(self, &[index], &[])
1880    }
1881
1882    /// Applies the RotateZ gate with the specified angle to the given qubits in order.
1883    ///
1884    /// # Arguments
1885    ///
1886    /// * `qubits` - The indices of the qubits to apply the RotateZ gate to.
1887    ///
1888    /// * `angle` - The rotation angle in radians.
1889    ///
1890    /// # Returns
1891    ///
1892    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1893    ///
1894    /// # Errors
1895    ///
1896    /// * Returns an error if the number of qubits provided is invalid.
1897    ///
1898    /// * Returns an error if the indices are out of bounds for the state vector.
1899    pub fn rz_multi(&self, qubits: &[usize], angle: f64) -> Result<Self, Error> {
1900        let mut new_state: State = self.clone();
1901        let rotate_z_gate: RotateZ = RotateZ::new(angle);
1902        for &qubit in qubits {
1903            new_state = rotate_z_gate.apply(&new_state, &[qubit], &[])?;
1904        }
1905        Ok(new_state)
1906    }
1907
1908    /// Applies the controlled RotateZ gate with the specified angle to the given qubits in order.
1909    ///
1910    /// # Arguments
1911    ///
1912    /// * `target_qubits` - The indices of the target qubits to apply the controlled RotateZ gate to.
1913    /// * `control_qubits` - The indices of the control qubits for the controlled RotateZ gate.
1914    /// * `angle` - The rotation angle in radians.
1915    ///
1916    /// # Returns
1917    ///
1918    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1919    ///
1920    /// # Errors
1921    ///
1922    /// * Returns an error if the number of qubits provided is invalid.
1923    /// * Returns an error if the indices are out of bounds for the state vector.
1924    /// * Returns an error if the control qubits and target qubits overlap.
1925    pub fn crz_multi(
1926        &self,
1927        target_qubits: &[usize],
1928        control_qubits: &[usize],
1929        angle: f64,
1930    ) -> Result<Self, Error> {
1931        let mut new_state: State = self.clone();
1932        let rotate_z_gate: RotateZ = RotateZ::new(angle);
1933        for &qubit in target_qubits {
1934            new_state = rotate_z_gate.apply(&new_state, &[qubit], control_qubits)?;
1935        }
1936        Ok(new_state)
1937    }
1938
1939    /// Applies the unitary gate to the specified qubit in the state vector.
1940    ///
1941    /// # Arguments
1942    ///
1943    /// * `index` - The index of the qubit to apply the unitary gate to.
1944    ///
1945    /// * `unitary` - The unitary matrix to apply.
1946    ///
1947    /// # Returns
1948    ///
1949    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1950    ///
1951    /// # Errors
1952    ///
1953    /// * Returns an error if the index is out of bounds for the state vector.
1954    ///
1955    /// * Returns an error if the unitary matrix is not unitary.
1956    pub fn unitary(&self, index: usize, unitary: [[Complex<f64>; 2]; 2]) -> Result<Self, Error> {
1957        let mut new_state: State = self.clone();
1958        let unitary_gate: Unitary2 = Unitary2::new(unitary)?;
1959        new_state = unitary_gate.apply(&new_state, &[index], &[])?;
1960        Ok(new_state)
1961    }
1962
1963    /// Applies the unitary gate to the specified qubits in the state vector in the given order.
1964    ///
1965    /// # Arguments
1966    ///
1967    /// * `qubits` - The indices of the qubits to apply the unitary gate to.
1968    ///
1969    /// * `unitary` - The unitary matrix to apply.
1970    ///
1971    /// # Returns
1972    ///
1973    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
1974    ///
1975    /// # Errors
1976    ///
1977    /// * Returns an error if the number of qubits provided is invalid.
1978    ///
1979    /// * Returns an error if the indices are out of bounds for the state vector.
1980    ///
1981    /// * Returns an error if the unitary matrix is not unitary.
1982    pub fn unitary_multi(
1983        &self,
1984        qubits: &[usize],
1985        unitary: [[Complex<f64>; 2]; 2],
1986    ) -> Result<Self, Error> {
1987        let mut new_state: State = self.clone();
1988        let unitary_gate: Unitary2 = Unitary2::new(unitary)?;
1989        for &qubit in qubits {
1990            new_state = unitary_gate.apply(&new_state, &[qubit], &[])?;
1991        }
1992        Ok(new_state)
1993    }
1994
1995    /// Applies the controlled unitary gate to the specified qubits in the state vector in the given order.
1996    ///
1997    /// # Arguments
1998    ///
1999    /// * `target_qubits` - The indices of the target qubits to apply the controlled unitary gate to.
2000    ///
2001    /// * `control_qubits` - The indices of the control qubits for the controlled unitary gate.
2002    ///
2003    /// * `unitary` - The unitary matrix to apply.
2004    ///
2005    /// # Returns
2006    ///
2007    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2008    ///
2009    /// # Errors
2010    ///
2011    /// * Returns an error if the number of qubits provided is invalid.
2012    ///
2013    /// * Returns an error if the indices are out of bounds for the state vector.
2014    ///
2015    /// * Returns an error if the control qubits and target qubits overlap.
2016    ///
2017    /// * Returns an error if the unitary matrix is not unitary.
2018    pub fn cunitary_multi(
2019        &self,
2020        target_qubits: &[usize],
2021        control_qubits: &[usize],
2022        unitary: [[Complex<f64>; 2]; 2],
2023    ) -> Result<Self, Error> {
2024        let mut new_state: State = self.clone();
2025        let unitary_gate: Unitary2 = Unitary2::new(unitary)?;
2026        for &qubit in target_qubits {
2027            new_state = unitary_gate.apply(&new_state, &[qubit], control_qubits)?;
2028        }
2029        Ok(new_state)
2030    }
2031
2032    /// Applies the Unitary (constructed from rotation angle and phase shift) to the specified qubit in the state vector.
2033    ///
2034    /// # Arguments
2035    ///
2036    /// * `index` - The index of the qubit to apply the Unitary gate to.
2037    ///
2038    /// * `angle` - The rotation angle in radians.
2039    ///
2040    /// * `phase` - The phase shift angle in radians.
2041    ///
2042    /// # Returns
2043    ///
2044    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2045    ///
2046    /// # Errors
2047    ///
2048    /// * Returns an error if the index is out of bounds for the state vector.
2049    pub fn ry_phase(&self, index: usize, angle: f64, phase: f64) -> Result<Self, Error> {
2050        Unitary2::from_ry_phase(angle, phase).apply(self, &[index], &[])
2051    }
2052
2053    /// Applies the Unitary (constructed from rotation angle and phase shift) to the specified qubits in the state vector in the given order.
2054    ///
2055    /// # Arguments
2056    ///
2057    /// * `qubits` - The indices of the qubits to apply the Unitary gate to.
2058    ///
2059    /// * `angle` - The rotation angle in radians.
2060    ///
2061    /// * `phase` - The phase shift angle in radians.
2062    ///
2063    /// # Returns
2064    ///
2065    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2066    ///
2067    /// # Errors
2068    ///
2069    /// * Returns an error if the number of qubits provided is invalid.
2070    ///
2071    /// * Returns an error if the indices are out of bounds for the state vector.
2072    pub fn ry_phase_multi(&self, qubits: &[usize], angle: f64, phase: f64) -> Result<Self, Error> {
2073        let mut new_state: State = self.clone();
2074        let unitary_gate: Unitary2 = Unitary2::from_ry_phase(angle, phase);
2075        for &qubit in qubits {
2076            new_state = unitary_gate.apply(&new_state, &[qubit], &[])?;
2077        }
2078        Ok(new_state)
2079    }
2080
2081    /// Applies the controlled Unitary (constructed from rotation angle and phase shift) to the specified qubits in the state vector in the given order.
2082    ///
2083    /// # Arguments
2084    ///
2085    /// * `target_qubits` - The indices of the target qubits to apply the controlled Unitary gate to.
2086    ///
2087    /// * `control_qubits` - The indices of the control qubits for the controlled Unitary gate.
2088    ///
2089    /// * `angle` - The rotation angle in radians.
2090    ///
2091    /// * * `phase` - The phase shift angle in radians.
2092    ///
2093    /// # Returns
2094    ///
2095    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2096    ///
2097    /// # Errors
2098    ///
2099    /// * Returns an error if the number of qubits provided is invalid.
2100    ///
2101    /// * Returns an error if the indices are out of bounds for the state vector.
2102    ///
2103    /// * Returns an error if the control qubits and target qubits overlap.
2104    pub fn cry_phase_gates(
2105        &self,
2106        target_qubits: &[usize],
2107        control_qubits: &[usize],
2108        angle: f64,
2109        phase: f64,
2110    ) -> Result<Self, Error> {
2111        let mut new_state: State = self.clone();
2112        let unitary_gate: Unitary2 = Unitary2::from_ry_phase(angle, phase);
2113        for &qubit in target_qubits {
2114            new_state = unitary_gate.apply(&new_state, &[qubit], control_qubits)?;
2115        }
2116        Ok(new_state)
2117    }
2118
2119    /// Applies the Unitary (constructed from rotation angle and phase shift) to the specified qubit in the state vector.
2120    /// This is the adjoint of the ry_phase operation.
2121    ///
2122    /// # Arguments
2123    ///
2124    /// * `qubit` - The index of the qubit to apply the adjoint operation to.
2125    ///
2126    /// * `angle` - The rotation angle in radians.
2127    ///
2128    /// * `phase` - The phase shift angle in radians.
2129    ///
2130    /// # Returns
2131    ///
2132    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2133    ///
2134    /// # Errors
2135    ///
2136    /// * Returns an error if the target qubit is out of bounds for the state vector
2137    pub fn ry_phase_dag(&self, qubit: usize, angle: f64, phase: f64) -> Result<Self, Error> {
2138        Unitary2::from_ry_phase_dagger(angle, phase).apply(self, &[qubit], &[])
2139    }
2140
2141    /// Applies the Unitary (constructed from rotation angle and phase shift) to the specified qubits in the state vector in the given order.
2142    /// This is the adjoint of the ry_phase operation.
2143    ///
2144    /// # Arguments
2145    ///
2146    /// * `qubits` - The indices of the qubits to apply the adjoint ry_phase operation to.
2147    ///
2148    /// * `angle` - The rotation angle in radians.
2149    ///
2150    /// * `phase` - The phase shift angle in radians.
2151    ///
2152    /// # Returns
2153    ///
2154    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2155    ///
2156    /// # Errors
2157    ///
2158    /// * Returns an error if the number of qubits provided is invalid.
2159    ///
2160    /// * Returns an error if the indices are out of bounds for the state vector.
2161    pub fn ry_phase_dag_multi(
2162        &self,
2163        qubits: &[usize],
2164        angle: f64,
2165        phase: f64,
2166    ) -> Result<Self, Error> {
2167        let mut new_state: State = self.clone();
2168        let unitary_gate: Unitary2 = Unitary2::from_ry_phase_dagger(angle, phase);
2169        for &qubit in qubits {
2170            new_state = unitary_gate.apply(&new_state, &[qubit], &[])?;
2171        }
2172        Ok(new_state)
2173    }
2174
2175    /// Applies the controlled Unitary (constructed from rotation angle and phase shift) to the specified qubits in the state vector in the given order.
2176    /// This is the controlled adjoint of the ry_phase operation.
2177    ///
2178    /// # Arguments
2179    ///
2180    /// * `target_qubits` - The index of the target qubit.
2181    ///
2182    /// * `control_qubits` - The indices of the control qubits.
2183    ///
2184    /// * `angle` - The rotation angle in radians.
2185    ///
2186    /// * `phase` - The phase shift angle in radians.
2187    ///
2188    /// # Returns
2189    ///
2190    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2191    ///
2192    /// # Errors
2193    ///
2194    /// * Returns an error if the number of qubits provided is invalid.
2195    ///
2196    /// * Returns an error if the indices are out of bounds for the state vector.
2197    ///
2198    /// * Returns an error if the control qubits and target qubits overlap.
2199    pub fn cry_phase_dag_gates(
2200        &self,
2201        target_qubits: &[usize],
2202        control_qubits: &[usize],
2203        angle: f64,
2204        phase: f64,
2205    ) -> Result<Self, Error> {
2206        let mut new_state: State = self.clone();
2207        let unitary_gate: Unitary2 = Unitary2::from_ry_phase_dagger(angle, phase);
2208        for &qubit in target_qubits {
2209            new_state = unitary_gate.apply(&new_state, &[qubit], control_qubits)?;
2210        }
2211        Ok(new_state)
2212    }
2213
2214    // -- MULTI-QUBIT GATES --
2215
2216    /// Applies the CNOT (Controlled-NOT) gate to the state vector.
2217    ///
2218    /// # Arguments
2219    ///
2220    /// * `control` - The index of the control qubit.
2221    /// * `target` - The index of the target qubit.
2222    ///
2223    /// # Returns
2224    ///
2225    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2226    ///
2227    /// # Errors
2228    ///
2229    /// * Returns an error if any index is out of bounds for the state vector.
2230    pub fn cnot(&self, control: usize, target: usize) -> Result<Self, Error> {
2231        CNOT {}.apply(self, &[target], &[control])
2232    }
2233
2234    /// Applies the SWAP gate to the state vector.
2235    ///
2236    /// # Arguments
2237    ///
2238    /// * `qubit1` - The index of the first qubit to swap.
2239    /// * `qubit2` - The index of the second qubit to swap.
2240    ///
2241    /// # Returns
2242    ///
2243    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2244    ///
2245    /// # Errors
2246    ///
2247    /// * Returns an error if any index is out of bounds for the state vector.
2248    pub fn swap(&self, qubit1: usize, qubit2: usize) -> Result<Self, Error> {
2249        SWAP {}.apply(self, &[qubit1, qubit2], &[])
2250    }
2251
2252    /// Applies the controlled SWAP gate to the state vector.
2253    ///
2254    /// # Arguments
2255    ///
2256    /// * `target1` - The index of the first target qubit to swap.
2257    /// * `target2` - The index of the second target qubit to swap.
2258    /// * `controls` - The indices of the control qubits.
2259    ///
2260    /// # Returns
2261    ///
2262    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2263    ///
2264    /// # Errors
2265    ///
2266    /// * Returns an error if any index is out of bounds for the state vector.
2267    /// * Returns an error if target or control qubits overlap.
2268    pub fn cswap(&self, target1: usize, target2: usize, controls: &[usize]) -> Result<Self, Error> {
2269        SWAP {}.apply(self, &[target1, target2], controls)
2270    }
2271
2272    /// Applies the Matchgate to the state vector
2273    ///
2274    /// # Arguments
2275    ///
2276    /// * `target` - The index of the first target qubit. The second target qubit is automatically determined to be the next qubit.
2277    /// * `theta` - The rotation angle in radians
2278    /// * `phi1` - The first phase angle in radians
2279    /// * `phi2` - The second phase angle in radians
2280    ///
2281    /// # Returns
2282    ///
2283    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2284    ///
2285    /// # Errors
2286    ///
2287    /// * Returns an error if any index is out of bounds for the state vector.
2288    /// * Returns an error if target or control qubits overlap.
2289    pub fn matchgate(
2290        &self,
2291        target: usize,
2292        theta: f64,
2293        phi1: f64,
2294        phi2: f64,
2295    ) -> Result<State, Error> {
2296        Matchgate { theta, phi1, phi2 }.apply(self, &[target], &[])
2297    }
2298
2299    /// Applies the controlled Matchgate to the state vector
2300    ///
2301    /// # Arguments
2302    ///
2303    /// * `target` - The index of the first target qubit. The second target qubit is automatically determined to be the next qubit.
2304    /// * `theta` - The rotation angle in radians
2305    /// * `phi1` - The first phase angle in radians
2306    /// * `phi2` - The second phase angle in radians
2307    /// * `controls` - The indices of the control qubits
2308    ///
2309    /// # Returns
2310    ///
2311    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2312    ///
2313    /// # Errors
2314    ///
2315    /// * Returns an error if any index is out of bounds for the state vector.
2316    /// * Returns an error if target or control qubits overlap.
2317    pub fn cmatchgate(
2318        &self,
2319        target: usize,
2320        theta: f64,
2321        phi1: f64,
2322        phi2: f64,
2323        controls: &[usize],
2324    ) -> Result<State, Error> {
2325        Matchgate { theta, phi1, phi2 }.apply(self, &[target], controls)
2326    }
2327
2328    /// Applies the Toffoli (Controlled-Controlled-NOT) gate to the state vector.
2329    ///
2330    /// # Arguments
2331    ///
2332    /// * `control1` - The index of the first control qubit.
2333    /// * `control2` - The index of the second control qubit.
2334    /// * `target` - The index of the target qubit.
2335    ///
2336    /// # Returns
2337    ///
2338    /// * `Result` - A result containing the new state object if successful, or an error if the operation fails.
2339    ///
2340    /// # Errors
2341    ///
2342    /// * Returns an error if any index is out of bounds for the state vector.
2343    pub fn toffoli(&self, control1: usize, control2: usize, target: usize) -> Result<Self, Error> {
2344        Toffoli {}.apply(self, &[target], &[control1, control2])
2345    }
2346}
2347
2348impl PartialEq for State {
2349    fn eq(&self, other: &Self) -> bool {
2350        // Check if the number of qubits is the same
2351        if self.num_qubits != other.num_qubits {
2352            return false;
2353        }
2354
2355        // Check if the state vectors have the same length (should be redundant with num_qubits check)
2356        if self.state_vector.len() != other.state_vector.len() {
2357            return false;
2358        }
2359
2360        // Check if each element in the state vectors is approximately equal within epsilon
2361        for (a, b) in self.state_vector.iter().zip(other.state_vector.iter()) {
2362            let real_diff = (a.re - b.re).abs();
2363            let imag_diff = (a.im - b.im).abs();
2364
2365            if real_diff > f32::EPSILON.into() || imag_diff > f32::EPSILON.into() {
2366                return false;
2367            }
2368        }
2369
2370        true
2371    }
2372}
2373
2374/// A trait to enable chainable operations on Result<State, Error>
2375pub trait ChainableState {
2376    // -- SINGLE QUBIT GATES --
2377
2378    /// Applies the Hadamard gate to the specified qubit in the state vector.
2379    fn h(self, index: usize) -> Result<State, Error>;
2380
2381    /// Applies the Hadamard gate to the specified qubits in the state vector in the given order.
2382    fn h_multi(self, qubits: &[usize]) -> Result<State, Error>;
2383
2384    /// Applies the controlled Hadamard gate to the specified qubits in the state vector in the given order.
2385    fn ch_multi(self, target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2386
2387    /// Applies the Pauli-X (NOT) gate to the specified qubit in the state vector.
2388    fn x(self, index: usize) -> Result<State, Error>;
2389
2390    /// Applies the Pauli-X (NOT) gate to the specified qubits in the state vector in the given order.
2391    fn x_multi(self, qubits: &[usize]) -> Result<State, Error>;
2392
2393    /// Applies the controlled Pauli-X (NOT) gate to the specified qubits in the state vector in the given order.
2394    fn cx_multi(self, target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2395
2396    /// Applies the Pauli-Y gate to the specified qubit in the state vector.
2397    fn y(self, index: usize) -> Result<State, Error>;
2398
2399    /// Applies the Pauli-Y gate to the specified qubits in the state vector in the given order.
2400    fn y_multi(self, qubits: &[usize]) -> Result<State, Error>;
2401
2402    /// Applies the controlled Pauli-Y gate to the specified qubits in the state vector in the given order.
2403    fn cy_multi(self, target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2404
2405    /// Applies the Pauli-Z gate to the specified qubit in the state vector.
2406    fn z(self, index: usize) -> Result<State, Error>;
2407
2408    /// Applies the Pauli-Z gate to the specified qubits in the state vector in the given order.
2409    fn z_multi(self, qubits: &[usize]) -> Result<State, Error>;
2410
2411    /// Applies the controlled Pauli-Z gate to the specified qubits in the state vector in the given order.
2412    fn cz_multi(self, target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2413
2414    /// Applies the Identity gate to the state vector.
2415    fn i(self, qubit: usize) -> Result<State, Error>;
2416
2417    /// Applies the Identity gate to the state vector for multiple qubits in the given order.
2418    fn i_multi(self, qubits: &[usize]) -> Result<State, Error>;
2419
2420    /// Applies the controlled Identity gate to the state vector for multiple qubits in the given order.
2421    fn ci_multi(self, target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2422
2423    /// Applies the Phase S gate to the specified qubit in the state vector.
2424    fn s(self, index: usize) -> Result<State, Error>;
2425    /// Applies the Phase S gate to the specified qubits in the state vector in the given order.
2426    fn s_multi(self, qubits: &[usize]) -> Result<State, Error>;
2427
2428    /// Applies the controlled Phase S gate to the specified qubits in the state vector in the given order.
2429    fn cs_multi(self, target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2430
2431    /// Applies the Phase T gate to the specified qubit in the state vector.
2432    fn t(self, index: usize) -> Result<State, Error>;
2433    /// Applies the Phase T gate to the specified qubits in the state vector in the given order.
2434    fn t_multi(self, qubits: &[usize]) -> Result<State, Error>;
2435
2436    /// Applies the controlled Phase T gate to the specified qubits in the state vector in the given order.
2437    fn ct_multi(self, target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2438
2439    /// Applies the Phase S dagger gate to the specified qubit in the state vector.
2440    fn s_dag(self, index: usize) -> Result<State, Error>;
2441    /// Applies the Phase S dagger gate to the specified qubits in the state vector in the given order.
2442    fn s_dag_multi(self, qubits: &[usize]) -> Result<State, Error>;
2443
2444    /// Applies the controlled Phase S dagger gate to the specified qubits in the state vector in the given order.
2445    fn cs_dag_multi(
2446        self,
2447        target_qubits: &[usize],
2448        control_qubits: &[usize],
2449    ) -> Result<State, Error>;
2450
2451    /// Applies the Phase T dagger gate to the specified qubit in the state vector.
2452    fn t_dag(self, index: usize) -> Result<State, Error>;
2453    /// Applies the Phase T dagger gate to the specified qubits in the state vector in the given order.
2454    fn t_dag_multi(self, qubits: &[usize]) -> Result<State, Error>;
2455
2456    /// Applies the controlled Phase T dagger gate to the specified qubits in the state vector in the given order.
2457    fn ct_dag_multi(
2458        self,
2459        target_qubits: &[usize],
2460        control_qubits: &[usize],
2461    ) -> Result<State, Error>;
2462
2463    /// Applies the Phase Shift gate with the specified angle to the given qubit.
2464    fn p(self, index: usize, angle: f64) -> Result<State, Error>;
2465    /// Applies the Phase Shift gate with the specified angle to the given qubits in order.
2466    fn p_multi(self, qubits: &[usize], angle: f64) -> Result<State, Error>;
2467
2468    /// Applies the controlled Phase Shift gate with the specified angle to the given qubits in order.
2469    fn cp_multi(
2470        self,
2471        target_qubits: &[usize],
2472        control_qubits: &[usize],
2473        angle: f64,
2474    ) -> Result<State, Error>;
2475
2476    /// Applies the RotateX gate with the specified angle to the given qubit.
2477    fn rx(self, index: usize, angle: f64) -> Result<State, Error>;
2478    /// Applies the RotateX gate with the specified angle to the given qubits in order.
2479    fn rx_multi(self, qubits: &[usize], angle: f64) -> Result<State, Error>;
2480
2481    /// Applies the controlled RotateX gate with the specified angle to the given qubits in order.
2482    fn crx_multi(
2483        self,
2484        target_qubits: &[usize],
2485        control_qubits: &[usize],
2486        angle: f64,
2487    ) -> Result<State, Error>;
2488
2489    /// Applies the RotateY gate with the specified angle to the given qubit.
2490    fn ry(self, index: usize, angle: f64) -> Result<State, Error>;
2491    /// Applies the RotateY gate with the specified angle to the given qubits in order.
2492    fn ry_multi(self, qubits: &[usize], angle: f64) -> Result<State, Error>;
2493
2494    /// Applies the controlled RotateY gate with the specified angle to the given qubits in order.
2495    fn cry_multi(
2496        self,
2497        target_qubits: &[usize],
2498        control_qubits: &[usize],
2499        angle: f64,
2500    ) -> Result<State, Error>;
2501
2502    /// Applies the RotateZ gate with the specified angle to the given qubit.
2503    fn rz(self, index: usize, angle: f64) -> Result<State, Error>;
2504    /// Applies the RotateZ gate with the specified angle to the given qubits in order.
2505    fn rz_multi(self, qubits: &[usize], angle: f64) -> Result<State, Error>;
2506
2507    /// Applies the controlled RotateZ gate with the specified angle to the given qubits in order.
2508    fn crz_multi(
2509        self,
2510        target_qubits: &[usize],
2511        control_qubits: &[usize],
2512        angle: f64,
2513    ) -> Result<State, Error>;
2514
2515    /// Applies the unitary gate to the specified qubit in the state vector.
2516    fn unitary(self, index: usize, unitary: [[Complex<f64>; 2]; 2]) -> Result<State, Error>;
2517
2518    /// Applies the unitary gate to the specified qubits in the state vector in the given order.
2519    fn unitary_multi(
2520        self,
2521        qubits: &[usize],
2522        unitary: [[Complex<f64>; 2]; 2],
2523    ) -> Result<State, Error>;
2524
2525    /// Applies the controlled unitary gate to the specified qubits in the state vector in the given order.
2526    fn cunitary_multi(
2527        self,
2528        target_qubits: &[usize],
2529        control_qubits: &[usize],
2530        unitary: [[Complex<f64>; 2]; 2],
2531    ) -> Result<State, Error>;
2532
2533    /// Applies the Unitary (constructed from rotation angle and phase shift) to the specified qubit in the state vector.
2534    fn ry_phase(self, index: usize, angle: f64, phase: f64) -> Result<State, Error>;
2535    /// Applies the Unitary (constructed from rotation angle and phase shift) to the specified qubits in the state vector in the given order.
2536    fn ry_phase_multi(self, qubits: &[usize], angle: f64, phase: f64) -> Result<State, Error>;
2537    /// Applies the controlled Unitary (constructed from rotation angle and phase shift) to the specified qubits in the state vector in the given order.
2538    fn cry_phase_gates(
2539        self,
2540        target_qubits: &[usize],
2541        control_qubits: &[usize],
2542        angle: f64,
2543        phase: f64,
2544    ) -> Result<State, Error>;
2545    /// Applies the adjoint of the Unitary (constructed from rotation angle and phase shift) to the specified qubit in the state vector.
2546    fn ry_phase_dag(self, index: usize, angle: f64, phase: f64) -> Result<State, Error>;
2547    /// Applies the adjoint of the Unitary (constructed from rotation angle and phase shift) to the specified qubits in the state vector in the given order.
2548    fn ry_phase_dag_multi(self, qubits: &[usize], angle: f64, phase: f64) -> Result<State, Error>;
2549    /// Applies the controlled adjoint of the Unitary (constructed from rotation angle and phase shift) to the specified qubits in the state vector in the given order.
2550    fn cry_phase_dag_gates(
2551        self,
2552        target_qubits: &[usize],
2553        control_qubits: &[usize],
2554        angle: f64,
2555        phase: f64,
2556    ) -> Result<State, Error>;
2557
2558    // -- MULTI-QUBIT GATES --
2559
2560    /// Applies the CNOT (Controlled-NOT) gate to the state vector.
2561    fn cnot(self, control: usize, target: usize) -> Result<State, Error>;
2562
2563    /// Applies the SWAP gate to the state vector.
2564    fn swap(self, qubit1: usize, qubit2: usize) -> Result<State, Error>;
2565
2566    /// Applies the controlled SWAP gate to the state vector.
2567    fn cswap(self, target1: usize, target2: usize, controls: &[usize]) -> Result<State, Error>;
2568
2569    /// Applies the Toffoli (Controlled-Controlled-NOT) gate to the state vector.
2570    fn toffoli(self, control1: usize, control2: usize, target: usize) -> Result<State, Error>;
2571
2572    /// Applies the Matchgate to the state vector.
2573    fn matchgate(self, target: usize, theta: f64, phi1: f64, phi2: f64) -> Result<State, Error>;
2574
2575    /// Applies the controlled Matchgate to the state vector.
2576    fn cmatchgate(
2577        self,
2578        target: usize,
2579        theta: f64,
2580        phi1: f64,
2581        phi2: f64,
2582        controls: &[usize],
2583    ) -> Result<State, Error>;
2584
2585    /// Applies a unitary operation to the state vector.
2586    fn operate(
2587        self,
2588        unitary: impl Operator,
2589        target_qubits: &[usize],
2590        control_qubits: &[usize],
2591    ) -> Result<State, Error>;
2592
2593    // -- MEASUREMENT --
2594
2595    /// Measures the state vector in the specified basis and returns the measurement result.
2596    fn measure(
2597        self,
2598        basis: MeasurementBasis,
2599        measured_qubits: &[usize],
2600    ) -> Result<MeasurementResult, Error>;
2601
2602    /// Measures the state vector `n` times in the specified basis and returns the measurement results.
2603    fn measure_n(
2604        self,
2605        basis: MeasurementBasis,
2606        measured_qubits: &[usize],
2607        n: usize,
2608    ) -> Result<Vec<MeasurementResult>, Error>;
2609}
2610
2611macro_rules! impl_chainable_state {
2612    ($($method:ident($($arg:ident: $arg_type:ty),*) -> $return_type:ty);* $(;)?) => {
2613        impl ChainableState for Result<State, Error> {
2614            $(
2615                fn $method(self, $($arg: $arg_type),*) -> $return_type {
2616                    self.and_then(|state| state.$method($($arg),*))
2617                }
2618            )*
2619        }
2620    };
2621}
2622
2623impl_chainable_state! {
2624    // -- SINGLE QUBIT GATES --
2625    h(index: usize) -> Result<State, Error>;
2626    h_multi(qubits: &[usize]) -> Result<State, Error>;
2627    ch_multi(target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2628    x(index: usize) -> Result<State, Error>;
2629    x_multi(qubits: &[usize]) -> Result<State, Error>;
2630    cx_multi(target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2631    y(index: usize) -> Result<State, Error>;
2632    y_multi(qubits: &[usize]) -> Result<State, Error>;
2633    cy_multi(target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2634    z(index: usize) -> Result<State, Error>;
2635    z_multi(qubits: &[usize]) -> Result<State, Error>;
2636    cz_multi(target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2637    i(qubit: usize) -> Result<State, Error>;
2638    i_multi(qubits: &[usize]) -> Result<State, Error>;
2639    ci_multi(target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2640    s(index: usize) -> Result<State, Error>;
2641    s_multi(qubits: &[usize]) -> Result<State, Error>;
2642    cs_multi(target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2643    t(index: usize) -> Result<State, Error>;
2644    t_multi(qubits: &[usize]) -> Result<State, Error>;
2645    ct_multi(target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2646    s_dag(index: usize) -> Result<State, Error>;
2647    s_dag_multi(qubits: &[usize]) -> Result<State, Error>;
2648    cs_dag_multi(target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2649    t_dag(index: usize) -> Result<State, Error>;
2650    t_dag_multi(qubits: &[usize]) -> Result<State, Error>;
2651    ct_dag_multi(target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2652    p(index: usize, angle: f64) -> Result<State, Error>;
2653    p_multi(qubits: &[usize], angle: f64) -> Result<State, Error>;
2654    cp_multi(target_qubits: &[usize], control_qubits: &[usize], angle: f64) -> Result<State, Error>;
2655    rx(index: usize, angle: f64) -> Result<State, Error>;
2656    rx_multi(qubits: &[usize], angle: f64) -> Result<State, Error>;
2657    crx_multi(target_qubits: &[usize], control_qubits: &[usize], angle: f64) -> Result<State, Error>;
2658    ry(index: usize, angle: f64) -> Result<State, Error>;
2659    ry_multi(qubits: &[usize], angle: f64) -> Result<State, Error>;
2660    cry_multi(target_qubits: &[usize], control_qubits: &[usize], angle: f64) -> Result<State, Error>;
2661    rz(index: usize, angle: f64) -> Result<State, Error>;
2662    rz_multi(qubits: &[usize], angle: f64) -> Result<State, Error>;
2663    crz_multi(target_qubits: &[usize], control_qubits: &[usize], angle: f64) -> Result<State, Error>;
2664    unitary(index: usize, unitary: [[Complex<f64>; 2]; 2]) -> Result<State, Error>;
2665    unitary_multi(qubits: &[usize], unitary: [[Complex<f64>; 2]; 2]) -> Result<State, Error>;
2666    cunitary_multi(target_qubits: &[usize], control_qubits: &[usize], unitary: [[Complex<f64>; 2]; 2]) -> Result<State, Error>;
2667    ry_phase(index: usize, angle: f64, phase: f64) -> Result<State, Error>;
2668    ry_phase_multi(qubits: &[usize], angle: f64, phase: f64) -> Result<State, Error>;
2669    cry_phase_gates(target_qubits: &[usize], control_qubits: &[usize], angle: f64, phase: f64) -> Result<State, Error>;
2670    ry_phase_dag(index: usize, angle: f64, phase: f64) -> Result<State, Error>;
2671    ry_phase_dag_multi(qubits: &[usize], angle: f64, phase: f64) -> Result<State, Error>;
2672    cry_phase_dag_gates(target_qubits: &[usize], control_qubits: &[usize], angle: f64, phase: f64) -> Result<State, Error>;
2673
2674    // -- MULTI-QUBIT GATES --
2675    cnot(control: usize, target: usize) -> Result<State, Error>;
2676    swap(qubit1: usize, qubit2: usize) -> Result<State, Error>;
2677    cswap(target1: usize, target2: usize, controls: &[usize]) -> Result<State, Error>;
2678    toffoli(control1: usize, control2: usize, target: usize) -> Result<State, Error>;
2679    matchgate(target: usize, theta: f64, phi1: f64, phi2: f64) -> Result<State, Error>;
2680    cmatchgate(target: usize, theta: f64, phi1: f64, phi2: f64, controls: &[usize]) -> Result<State, Error>;
2681    operate(unitary: impl Operator, target_qubits: &[usize], control_qubits: &[usize]) -> Result<State, Error>;
2682    measure(basis: MeasurementBasis, measured_qubits: &[usize]) -> Result<MeasurementResult, Error>;
2683    measure_n(basis: MeasurementBasis, measured_qubits: &[usize], n: usize) -> Result<Vec<MeasurementResult>, Error>;
2684}
2685
2686// Implement multiplication by Complex<f64>
2687impl Mul<Complex<f64>> for State {
2688    type Output = Self;
2689
2690    /// Multiplies each amplitude in the state vector by a complex scalar.
2691    /// Note: This operation typically results in an unnormalised state.
2692    fn mul(self, rhs: Complex<f64>) -> Self::Output {
2693        let new_state_vector: Vec<Complex<f64>> = self
2694            .state_vector
2695            .into_par_iter() // Use parallel iterator for potential performance gain
2696            .map(|amplitude| amplitude * rhs)
2697            .collect();
2698
2699        // Create a new State directly, bypassing the normalization check in `new`
2700        State {
2701            state_vector: new_state_vector,
2702            num_qubits: self.num_qubits,
2703        }
2704    }
2705}
2706
2707// Implement multiplication by f64
2708impl Mul<f64> for State {
2709    type Output = Self;
2710
2711    /// Multiplies each amplitude in the state vector by a real scalar.
2712    /// Note: This operation typically results in an unnormalised state.
2713    fn mul(self, rhs: f64) -> Self::Output {
2714        let complex_rhs = Complex::new(rhs, 0.0); // Convert f64 to Complex<f64>
2715        let new_state_vector: Vec<Complex<f64>> = self
2716            .state_vector
2717            .into_par_iter() // Use parallel iterator
2718            .map(|amplitude| amplitude * complex_rhs)
2719            .collect();
2720
2721        // Create a new State directly
2722        State {
2723            state_vector: new_state_vector,
2724            num_qubits: self.num_qubits,
2725        }
2726    }
2727}
2728
2729// Implement multiplication State = f64 * State
2730impl Mul<State> for f64 {
2731    type Output = State;
2732
2733    /// Multiplies each amplitude in the state vector by a real scalar from the left.
2734    /// Note: This operation typically results in an unnormalised state.
2735    fn mul(self, rhs: State) -> Self::Output {
2736        let complex_lhs = Complex::new(self, 0.0); // Convert f64 to Complex<f64>
2737        let new_state_vector: Vec<Complex<f64>> = rhs
2738            .state_vector
2739            .into_par_iter() // Use parallel iterator
2740            .map(|amplitude| complex_lhs * amplitude)
2741            .collect();
2742
2743        // Create a new State directly
2744        State {
2745            state_vector: new_state_vector,
2746            num_qubits: rhs.num_qubits,
2747        }
2748    }
2749}
2750
2751// Implement multiplication State = Complex<f64> * State
2752impl Mul<State> for Complex<f64> {
2753    type Output = State;
2754
2755    /// Multiplies each amplitude in the state vector by a complex scalar from the left.
2756    /// Note: This operation typically results in an unnormalised state.
2757    fn mul(self, rhs: State) -> Self::Output {
2758        let new_state_vector: Vec<Complex<f64>> = rhs
2759            .state_vector
2760            .into_par_iter() // Use parallel iterator
2761            .map(|amplitude| self * amplitude)
2762            .collect();
2763
2764        // Create a new State directly
2765        State {
2766            state_vector: new_state_vector,
2767            num_qubits: rhs.num_qubits,
2768        }
2769    }
2770}
2771
2772// Implement addition for State + State
2773impl Add<State> for State {
2774    type Output = Self;
2775
2776    /// Adds two state vectors element-wise.
2777    /// Panics if the states do not have the same number of qubits.
2778    /// Note: This operation typically results in an unnormalised state.
2779    fn add(self, rhs: State) -> Self::Output {
2780        if self.num_qubits != rhs.num_qubits {
2781            panic!(
2782                "Cannot add states with different numbers of qubits: {} != {}",
2783                self.num_qubits, rhs.num_qubits
2784            );
2785        }
2786
2787        let new_state_vector: Vec<Complex<f64>> = self
2788            .state_vector
2789            .into_par_iter()
2790            .zip(rhs.state_vector.into_par_iter())
2791            .map(|(a, b)| a + b)
2792            .collect();
2793
2794        // Create a new State directly
2795        State {
2796            state_vector: new_state_vector,
2797            num_qubits: self.num_qubits,
2798        }
2799    }
2800}
2801
2802// Implement sum for State
2803impl std::iter::Sum for State {
2804    fn sum<I>(mut iter: I) -> Self
2805    where
2806        I: Iterator<Item = Self>,
2807    {
2808        // Take the first state as the initial accumulator.
2809        let mut accumulator = match iter.next() {
2810            Some(first_state) => first_state,
2811            None => {
2812                panic!(
2813                    "Cannot sum an empty iterator of State objects: num_qubits for the sum is undefined."
2814                );
2815            }
2816        };
2817
2818        // Fold the rest of the states into the accumulator.
2819        // The `Add` impl for `State` handles element-wise addition and
2820        // panics if `num_qubits` do not match.
2821        for state in iter {
2822            if accumulator.num_qubits != state.num_qubits {
2823                panic!(
2824                    "Cannot sum states with different numbers of qubits: {} != {}",
2825                    accumulator.num_qubits, state.num_qubits
2826                );
2827            }
2828            accumulator = accumulator + state; // Uses the implemented Add for State
2829        }
2830        accumulator
2831    }
2832}
2833
2834// Implement subtraction for State - State
2835impl Sub<State> for State {
2836    type Output = Self;
2837
2838    /// Subtracts the right-hand state vector from the left-hand state vector element-wise.
2839    /// Panics if the states do not have the same number of qubits.
2840    /// Note: This operation typically results in an unnormalised state.
2841    fn sub(self, rhs: State) -> Self::Output {
2842        if self.num_qubits != rhs.num_qubits {
2843            panic!(
2844                "Cannot subtract states with different numbers of qubits: {} != {}",
2845                self.num_qubits, rhs.num_qubits
2846            );
2847        }
2848
2849        let new_state_vector: Vec<Complex<f64>> = self
2850            .state_vector
2851            .into_par_iter()
2852            .zip(rhs.state_vector.into_par_iter())
2853            .map(|(a, b)| a - b)
2854            .collect();
2855
2856        // Create a new State directly
2857        State {
2858            state_vector: new_state_vector,
2859            num_qubits: self.num_qubits,
2860        }
2861    }
2862}
2863
2864impl std::fmt::Debug for State {
2865    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2866        let mut state_str = String::new();
2867        state_str.push_str(format!("State with {} qubits:\n[", self.num_qubits).as_str());
2868        for amplitude in &self.state_vector {
2869            let amplitude_string: String = if amplitude.im == 0.0 {
2870                format!("{:.2}", amplitude.re)
2871            } else if amplitude.re == 0.0 {
2872                format!("{:.2}i", amplitude.im)
2873            } else {
2874                format!("{:.2} + {:.2}i", amplitude.re, amplitude.im)
2875            };
2876            // Add the amplitude to the string representations
2877            state_str.push_str(format!("{}, ", amplitude_string).as_str());
2878        }
2879        state_str.pop(); // Remove the last comma
2880        state_str.pop(); // Remove the last space
2881        state_str.push(']');
2882        write!(f, "{}", state_str)
2883    }
2884}