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