microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
source/noisy_simulator/src/operation/tests.rs
144lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | use nalgebra::dmatrix; |
| 5 | use num_complex::{Complex, ComplexFloat}; |
| 6 | |
| 7 | use crate::{ |
| 8 | SquareMatrix, |
| 9 | operation::{Operation, operation}, |
| 10 | tests::assert_approx_eq, |
| 11 | }; |
| 12 | |
| 13 | /// Constructs an operation using dense kraus matrices, to allow an exhaustive |
| 14 | /// testing of the inner linear operations used to construct the `Operator`. |
| 15 | fn dense_operation() -> Operation { |
| 16 | const I: Complex<f64> = Complex::I; |
| 17 | |
| 18 | // Construct an operation from two kraus matrices. |
| 19 | operation!( |
| 20 | [ |
| 21 | 0., 1., 2., 4.; |
| 22 | 1., 2., 3., 4.; |
| 23 | 1., 1., 3., 5.; |
| 24 | 3., 1., 1., 2.; |
| 25 | ], |
| 26 | [ |
| 27 | 0.1 * I, 1. + I, 2., 4.; |
| 28 | 1., 2. - I, 3., 4.; |
| 29 | 1. + 0.50 * I, 1., 3., 5.; |
| 30 | 3. + 0.25 * I, 1., 1., 2.; |
| 31 | ] |
| 32 | ) |
| 33 | .expect("operation should be valid") |
| 34 | } |
| 35 | |
| 36 | #[test] |
| 37 | fn check_operation_number_of_qubits_is_computed_correctly() { |
| 38 | let op = operation!( |
| 39 | [ |
| 40 | 0., 0.; |
| 41 | 0., 0.; |
| 42 | ] |
| 43 | ) |
| 44 | .expect("operation should be valid"); |
| 45 | |
| 46 | assert_eq!(1, op.number_of_qubits()); |
| 47 | } |
| 48 | |
| 49 | #[test] |
| 50 | fn check_non_square_kraus_operator_does_not_panic() { |
| 51 | let op = operation!( |
| 52 | [ |
| 53 | 0., 0.; |
| 54 | ] |
| 55 | ); |
| 56 | |
| 57 | assert!(matches!( |
| 58 | op, |
| 59 | Err(crate::Error::FailedToConstructOperation(_)) |
| 60 | )); |
| 61 | } |
| 62 | |
| 63 | /// Check that the inner matrices of the instrument are constructed correctly. |
| 64 | #[test] |
| 65 | fn check_effect_matrix_is_computed_correctly() { |
| 66 | const I: Complex<f64> = Complex::I; |
| 67 | let op = dense_operation(); |
| 68 | |
| 69 | // Check that the effect matrix is the sum of the individual effect matrices |
| 70 | // of each kraus operator. |
| 71 | let eff0 = dmatrix![ |
| 72 | 11., 6., 9., 15.; |
| 73 | 6., 7., 12., 19.; |
| 74 | 9., 12., 23., 37.; |
| 75 | 15., 19., 37., 61.; |
| 76 | ] |
| 77 | .map(std::convert::Into::into); |
| 78 | |
| 79 | let eff1 = dmatrix! [ |
| 80 | 11.3225 + 0. * I, 6.1 - 1.85 * I, 9. - 1.95 * I, 15. - 3.4 * I; |
| 81 | 6.1 + 1.85 * I, 9. + 0. * I, 12. + 1. * I, 19. + 0. * I; |
| 82 | 9. + 1.95 * I, 12. - 1. * I, 23. + 0. * I, 37. + 0. * I; |
| 83 | 15. + 3.4 * I, 19. + 0. * I, 37. + 0. * I, 61. + 0. * I; |
| 84 | ]; |
| 85 | |
| 86 | let eff = eff0 + eff1; |
| 87 | |
| 88 | for (x0, x1) in eff.iter().zip(op.effect_matrix().iter()) { |
| 89 | assert_approx_eq(0., (x0 - x1.conj()).abs()); |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | #[test] |
| 94 | fn check_operation_matrix_is_computed_correctly() { |
| 95 | const I: Complex<f64> = Complex::I; |
| 96 | let op = dense_operation(); |
| 97 | |
| 98 | // Check that the operation matrix is the sum of the individual operation matrices |
| 99 | // of each kraus operator. |
| 100 | let op0: SquareMatrix = dmatrix![ |
| 101 | 0., 0., 0., 0. , 0., 1., 2., 4. , 0., 2., 4., 8. , 0. , 4. , 8. , 16.; |
| 102 | 0., 0., 0., 0. , 1., 2., 3., 4. , 2., 4., 6., 8. , 4. , 8. , 12., 16.; |
| 103 | 0., 0., 0., 0. , 1., 1., 3., 5. , 2., 2., 6., 10., 4. , 4. , 12., 20.; |
| 104 | 0., 0., 0., 0. , 3., 1., 1., 2. , 6., 2., 2., 4. , 12., 4. , 4. , 8. ; |
| 105 | 0., 1., 2., 4. , 0., 2., 4., 8. , 0., 3., 6., 12., 0. , 4. , 8. , 16.; |
| 106 | 1., 2., 3., 4. , 2., 4., 6., 8. , 3., 6., 9., 12., 4. , 8. , 12., 16.; |
| 107 | 1., 1., 3., 5. , 2., 2., 6., 10., 3., 3., 9., 15., 4. , 4. , 12., 20.; |
| 108 | 3., 1., 1., 2. , 6., 2., 2., 4. , 9., 3., 3., 6. , 12., 4. , 4. , 8. ; |
| 109 | 0., 1., 2., 4. , 0., 1., 2., 4. , 0., 3., 6., 12., 0. , 5. , 10., 20.; |
| 110 | 1., 2., 3., 4. , 1., 2., 3., 4. , 3., 6., 9., 12., 5. , 10., 15., 20.; |
| 111 | 1., 1., 3., 5. , 1., 1., 3., 5. , 3., 3., 9., 15., 5. , 5. , 15., 25.; |
| 112 | 3., 1., 1., 2. , 3., 1., 1., 2. , 9., 3., 3., 6. , 15., 5. , 5. , 10.; |
| 113 | 0., 3., 6., 12., 0., 1., 2., 4. , 0., 1., 2., 4. , 0. , 2. , 4. , 8. ; |
| 114 | 3., 6., 9., 12., 1., 2., 3., 4. , 1., 2., 3., 4. , 2. , 4. , 6. , 8. ; |
| 115 | 3., 3., 9., 15., 1., 1., 3., 5. , 1., 1., 3., 5. , 2. , 2. , 6. , 10.; |
| 116 | 9., 3., 3., 6. , 3., 1., 1., 2. , 3., 1., 1., 2. , 6. , 2. , 2. , 4. ; |
| 117 | ] |
| 118 | .map(std::convert::Into::into); |
| 119 | |
| 120 | let op1 = dmatrix![ |
| 121 | 0.01 + 0. * I, 0.1 + 0.1 * I, 0. + 0.2 * I, 0. + 0.4 * I, 0.1 - 0.1 * I, 2. + 0. * I, 2. + 2. * I, 4. + 4. * I, 0. - 0.2 * I, 2. - 2. * I, 4. + 0. * I, 8. + 0. * I, 0. - 0.4 * I, 4. - 4. * I, 8. + 0. * I, 16. + 0. * I; |
| 122 | 0. + 0.1 * I, -0.1 + 0.2 * I, 0. + 0.3 * I, 0. + 0.4 * I, 1. + 1. * I, 1. + 3. * I, 3. + 3. * I, 4. + 4. * I, 2. + 0. * I, 4. + 2. * I, 6. + 0. * I, 8. + 0. * I, 4. + 0. * I, 8. + 4. * I, 12. + 0. * I, 16. + 0. * I; |
| 123 | 0.05 + 0.1 * I, 0. + 0.1 * I, 0. + 0.3 * I, 0. + 0.5 * I, 1.5 + 0.5 * I, 1. + 1. * I, 3. + 3. * I, 5. + 5. * I, 2. - 1. * I, 2. + 0. * I, 6. + 0. * I, 10. + 0. * I, 4. - 2. * I, 4. + 0. * I, 12. + 0. * I, 20. + 0. * I; |
| 124 | 0.025 + 0.3 * I, 0. + 0.1 * I, 0. + 0.1 * I, 0. + 0.2 * I, 3.25 + 2.75 * I, 1. + 1. * I, 1. + 1. * I, 2. + 2. * I, 6. - 0.5 * I, 2. + 0. * I, 2. + 0. * I, 4. + 0. * I, 12. - 1. * I, 4. + 0. * I, 4. + 0. * I, 8. + 0. * I; |
| 125 | 0. - 0.1 * I, 1. - 1. * I, 2. + 0. * I, 4. + 0. * I, -0.1 - 0.2 * I, 1. - 3. * I, 4. - 2. * I, 8. - 4. * I, 0. - 0.3 * I, 3. - 3. * I, 6. + 0. * I, 12. + 0. * I, 0. - 0.4 * I, 4. - 4. * I, 8. + 0. * I, 16. + 0. * I; |
| 126 | 1. + 0. * I, 2. + 1. * I, 3. + 0. * I, 4. + 0. * I, 2. - 1. * I, 5. + 0. * I, 6. - 3. * I, 8. - 4. * I, 3. + 0. * I, 6. + 3. * I, 9. + 0. * I, 12. + 0. * I, 4. + 0. * I, 8. + 4. * I, 12. + 0. * I, 16. + 0. * I; |
| 127 | 1. - 0.5 * I, 1. + 0. * I, 3. + 0. * I, 5. + 0. * I, 1.5 - 2. * I, 2. - 1. * I, 6. - 3. * I, 10. - 5. * I, 3. - 1.5 * I, 3. + 0. * I, 9. + 0. * I, 15. + 0. * I, 4. - 2. * I, 4. + 0. * I, 12. + 0. * I, 20. + 0. * I; |
| 128 | 3. - 0.25 * I, 1. + 0. * I, 1. + 0. * I, 2. + 0. * I, 5.75 - 3.5 * I, 2. - 1. * I, 2. - 1. * I, 4. - 2. * I, 9. - 0.75 * I, 3. + 0. * I, 3. + 0. * I, 6. + 0. * I, 12. - 1. * I, 4. + 0. * I, 4. + 0. * I, 8. + 0. * I; |
| 129 | 0.05 - 0.1 * I, 1.5 - 0.5 * I, 2. + 1. * I, 4. + 2. * I, 0. - 0.1 * I, 1. - 1. * I, 2. + 0. * I, 4. + 0. * I, 0. - 0.3 * I, 3. - 3. * I, 6. + 0. * I, 12. + 0. * I, 0. - 0.5 * I, 5. - 5. * I, 10. + 0. * I, 20. + 0. * I; |
| 130 | 1. + 0.5 * I, 1.5 + 2. * I, 3. + 1.5 * I, 4. + 2. * I, 1. + 0. * I, 2. + 1. * I, 3. + 0. * I, 4. + 0. * I, 3. + 0. * I, 6. + 3. * I, 9. + 0. * I, 12. + 0. * I, 5. + 0. * I, 10. + 5. * I, 15. + 0. * I, 20. + 0. * I; |
| 131 | 1.25 + 0. * I, 1. + 0.5 * I, 3. + 1.5 * I, 5. + 2.5 * I, 1. - 0.5 * I, 1. + 0. * I, 3. + 0. * I, 5. + 0. * I, 3. - 1.5 * I, 3. + 0. * I, 9. + 0. * I, 15. + 0. * I, 5. - 2.5 * I, 5. + 0. * I, 15. + 0. * I, 25. + 0. * I; |
| 132 | 3.125 + 1.25 * I, 1. + 0.5 * I, 1. + 0.5 * I, 2. + 1. * I, 3. - 0.25 * I, 1. + 0. * I, 1. + 0. * I, 2. + 0. * I, 9. - 0.75 * I, 3. + 0. * I, 3. + 0. * I, 6. + 0. * I, 15. - 1.25 * I, 5. + 0. * I, 5. + 0. * I, 10. + 0. * I; |
| 133 | 0.025 - 0.3 * I, 3.25 - 2.75 * I, 6. + 0.5 * I, 12. + 1. * I, 0. - 0.1 * I, 1. - 1. * I, 2. + 0. * I, 4. + 0. * I, 0. - 0.1 * I, 1. - 1. * I, 2. + 0. * I, 4. + 0. * I, 0. - 0.2 * I, 2. - 2. * I, 4. + 0. * I, 8. + 0. * I; |
| 134 | 3. + 0.25 * I, 5.75 + 3.5 * I, 9. + 0.75 * I, 12. + 1. * I, 1. + 0. * I, 2. + 1. * I, 3. + 0. * I, 4. + 0. * I, 1. + 0. * I, 2. + 1. * I, 3. + 0. * I, 4. + 0. * I, 2. + 0. * I, 4. + 2. * I, 6. + 0. * I, 8. + 0. * I; |
| 135 | 3.125 - 1.25 * I, 3. + 0.25 * I, 9. + 0.75 * I, 15. + 1.25 * I, 1. - 0.5 * I, 1. + 0. * I, 3. + 0. * I, 5. + 0. * I, 1. - 0.5 * I, 1. + 0. * I, 3. + 0. * I, 5. + 0. * I, 2. - 1. * I, 2. + 0. * I, 6. + 0. * I, 10. + 0. * I; |
| 136 | 9.0625 + 0. * I, 3. + 0.25 * I, 3. + 0.25 * I, 6. + 0.5 * I, 3. - 0.25 * I, 1. + 0. * I, 1. + 0. * I, 2. + 0. * I, 3. - 0.25 * I, 1. + 0. * I, 1. + 0. * I, 2. + 0. * I, 6. - 0.5 * I, 2. + 0. * I, 2. + 0. * I, 4. + 0. * I; |
| 137 | ]; |
| 138 | |
| 139 | let op_matrix = op0 + op1; |
| 140 | |
| 141 | for (x0, x1) in op.matrix().transpose().iter().zip(op_matrix.iter()) { |
| 142 | assert_approx_eq(0., (x0 - x1).abs()); |
| 143 | } |
| 144 | } |
| 145 | |