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