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