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