quant_iron/components/
state.rs

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