|
13 | 13 | use num_complex::Complex64; |
14 | 14 | use std::f64::consts::FRAC_1_SQRT_2; |
15 | 15 |
|
16 | | -// Ensure necessary imports are present |
17 | | -use ndarray::Array2; |
18 | | - |
19 | 16 | use crate::util::{ |
20 | 17 | C_M_ONE, C_ONE, C_ZERO, GateArray0Q, GateArray1Q, GateArray2Q, GateArray3Q, GateArray4Q, IM, |
21 | 18 | M_IM, c64, |
@@ -519,82 +516,3 @@ pub fn xx_plus_yy_gate(theta: f64, beta: f64) -> GateArray2Q { |
519 | 516 | [C_ZERO, C_ZERO, C_ZERO, C_ONE], |
520 | 517 | ] |
521 | 518 | } |
522 | | -/// Compute the unitary matrix for a PauliProductRotation gate. |
523 | | -/// |
524 | | -/// The gate implements: exp(-i * theta/2 * P) = cos(theta/2)*I - i*sin(theta/2)*P |
525 | | -/// where P is the tensor product of Pauli operators given by `pauli_str`. |
526 | | -/// |
527 | | -/// # Arguments |
528 | | -/// * `theta` - Rotation angle in radians (f64) |
529 | | -/// * `pauli_str` - Pauli string label e.g. "XYZ", "ZZ", "X" (rightmost = qubit 0) |
530 | | -/// |
531 | | -/// # Returns |
532 | | -/// Dense 2^n × 2^n complex unitary matrix as `Array2<Complex64>` |
533 | | -
|
534 | | -pub fn pauli_zx_to_dense_matrix(z: &[bool], x: &[bool]) -> Array2<Complex64> { |
535 | | - assert_eq!(z.len(), x.len()); |
536 | | - |
537 | | - let pauli_i = Array2::from_shape_vec( |
538 | | - (2, 2), |
539 | | - vec![c64(1., 0.), c64(0., 0.), c64(0., 0.), c64(1., 0.)], |
540 | | - ) |
541 | | - .unwrap(); |
542 | | - let pauli_x = Array2::from_shape_vec( |
543 | | - (2, 2), |
544 | | - vec![c64(0., 0.), c64(1., 0.), c64(1., 0.), c64(0., 0.)], |
545 | | - ) |
546 | | - .unwrap(); |
547 | | - let pauli_y = Array2::from_shape_vec( |
548 | | - (2, 2), |
549 | | - vec![c64(0., 0.), c64(0., -1.), c64(0., 1.), c64(0., 0.)], |
550 | | - ) |
551 | | - .unwrap(); |
552 | | - let pauli_z = Array2::from_shape_vec( |
553 | | - (2, 2), |
554 | | - vec![c64(1., 0.), c64(0., 0.), c64(0., 0.), c64(-1., 0.)], |
555 | | - ) |
556 | | - .unwrap(); |
557 | | - |
558 | | - let single_pauli = |z_bit: bool, x_bit: bool| match (z_bit, x_bit) { |
559 | | - (false, false) => pauli_i.clone(), |
560 | | - (false, true) => pauli_x.clone(), |
561 | | - (true, true) => pauli_y.clone(), |
562 | | - (true, false) => pauli_z.clone(), |
563 | | - }; |
564 | | - |
565 | | - let first = single_pauli(z[0], x[0]); |
566 | | - |
567 | | - (1..z.len()).fold(first, |acc, i| { |
568 | | - let next = single_pauli(z[i], x[i]); |
569 | | - kron(&next, &acc) |
570 | | - }) |
571 | | -} |
572 | | - |
573 | | -pub fn pauli_product_rotation_matrix(angle: f64, z: &[bool], x: &[bool]) -> Array2<Complex64> { |
574 | | - let pauli_mat = pauli_zx_to_dense_matrix(z, x); |
575 | | - let dim = pauli_mat.shape()[0]; |
576 | | - let identity: Array2<Complex64> = Array2::eye(dim).mapv(|v: f64| c64(v, 0.)); |
577 | | - |
578 | | - let cos_val = (angle / 2.0).cos(); |
579 | | - let sin_val = (angle / 2.0).sin(); |
580 | | - |
581 | | - identity.mapv(|v| v * c64(cos_val, 0.)) + pauli_mat.mapv(|v| v * c64(0., -sin_val)) |
582 | | -} |
583 | | - |
584 | | -/// Kronecker (tensor) product of two complex matrices. |
585 | | -fn kron(a: &Array2<Complex64>, b: &Array2<Complex64>) -> Array2<Complex64> { |
586 | | - let (ra, ca) = a.dim(); |
587 | | - let (rb, cb) = b.dim(); |
588 | | - let mut out = Array2::zeros((ra * rb, ca * cb)); |
589 | | - for i in 0..ra { |
590 | | - for j in 0..ca { |
591 | | - let aij = a[[i, j]]; |
592 | | - for p in 0..rb { |
593 | | - for q in 0..cb { |
594 | | - out[[i * rb + p, j * cb + q]] = aij * b[[p, q]]; |
595 | | - } |
596 | | - } |
597 | | - } |
598 | | - } |
599 | | - out |
600 | | -} |
0 commit comments