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