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