microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
minestarks/copilot

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

compiler/qsc_eval/src/backend/noise_tests.rs

204lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::{
5 backend::{Backend, SparseSim},
6 noise::PauliNoise,
7 state::{fmt_complex, format_state_id},
8};
9use expect_test::{expect, Expect};
10use num_bigint::BigUint;
11use num_complex::Complex;
12use std::fmt::Write;
13
14#[test]
15fn pauli_noise() {
16 let noise = PauliNoise::from_probabilities(0.0, 0.0, 0.0);
17 assert!(
18 noise
19 .expect("noiseless Pauli noise should be constructable.")
20 .is_noiseless(),
21 "Expected noiseless noise."
22 );
23 let noise = PauliNoise::from_probabilities(1e-5, 0.0, 0.0);
24 assert!(
25 !noise
26 .expect("bit flip noise with probability 1e-5 should be constructable.")
27 .is_noiseless(),
28 "Expected noise to be noisy."
29 );
30 let noise = PauliNoise::from_probabilities(1.0, 0.0, 0.0);
31 assert!(
32 !noise
33 .expect("bit flip noise with probability 1 should be constructable.")
34 .is_noiseless(),
35 "Expected noise to be noisy."
36 );
37 let noise = PauliNoise::from_probabilities(0.01, 0.01, 0.01)
38 .expect("depolarizing noise with probability 0.01 should be constructable..");
39 assert!(!noise.is_noiseless(), "Expected noise to be noisy.");
40 assert!(
41 0.0 <= noise.distribution[0]
42 && noise.distribution[0] <= noise.distribution[1]
43 && noise.distribution[1] <= noise.distribution[2]
44 && noise.distribution[2] <= 1.1,
45 "Expected non-decreasing noise distribution."
46 );
47 let _ = PauliNoise::from_probabilities(-1e-10, 0.1, 0.1)
48 .expect_err("pauli noise with probabilities -1e-10, 0.1, 0.1 should result in error.");
49 let _ = PauliNoise::from_probabilities(1.0 + -1e-10, 0.1, 0.1)
50 .expect_err("pauli noise with probabilities 1.0+1e-10, 0.1, 0.1 should result in error.");
51 let _ = PauliNoise::from_probabilities(0.3, 0.4, 0.5)
52 .expect_err("pauli noise with probabilities 0.3, 0.4, 0.5 should result in error.");
53}
54
55#[test]
56fn noisy_simulator() {
57 let sim = SparseSim::new();
58 assert!(sim.is_noiseless(), "Expected noiseless simulator.");
59
60 let noise = PauliNoise::from_probabilities(0.0, 0.0, 0.0)
61 .expect("noiseless Pauli noise should be constructable.");
62 let sim = SparseSim::new_with_noise(&noise);
63 assert!(sim.is_noiseless(), "Expected noiseless simulator.");
64
65 let noise = PauliNoise::from_probabilities(1e-10, 0.0, 0.0)
66 .expect("1e-10, 0.0, 0.0 Pauli noise should be constructable.");
67 let sim = SparseSim::new_with_noise(&noise);
68 assert!(!sim.is_noiseless(), "Expected noisy simulator.");
69
70 let noise = PauliNoise::from_probabilities(0.0, 0.0, 1e-10)
71 .expect("0.0, 0.0, 1e-10 Pauli noise should be constructable.");
72 let sim = SparseSim::new_with_noise(&noise);
73 assert!(!sim.is_noiseless(), "Expected noisy simulator.");
74}
75
76#[test]
77fn noiseless_gate() {
78 let noise = PauliNoise::from_probabilities(0.0, 0.0, 0.0)
79 .expect("noiseless Pauli noise should be constructable.");
80 let mut sim = SparseSim::new_with_noise(&noise);
81 let q = sim.qubit_allocate();
82 for _ in 0..100 {
83 sim.x(q);
84 let res1 = sim.m(q);
85 assert!(res1, "Expected True without noise.");
86 sim.x(q);
87 let res2 = sim.m(q);
88 assert!(!res2, "Expected False without noise.");
89 }
90 assert!(
91 sim.qubit_release(q),
92 "Expected correct qubit state on release."
93 );
94}
95
96#[test]
97fn bitflip_measurement() {
98 let noise = PauliNoise::from_probabilities(1.0, 0.0, 0.0)
99 .expect("bit flip noise with probability 100% should be constructable.");
100 let mut sim = SparseSim::new_with_noise(&noise);
101 assert!(!sim.is_noiseless(), "Expected noisy simulator.");
102 let q = sim.qubit_allocate(); // Allocation is noiseless even with noise.
103 for _ in 0..100 {
104 let res1 = sim.m(q); // Always applies X before measuring
105 assert!(res1, "Expected True for 100% bit flip noise.");
106 let res2 = sim.m(q); // Always applies X before measuring
107 assert!(!res2, "Expected False for 100% bit flip noise.");
108 }
109 assert!(
110 sim.qubit_release(q),
111 "Expected correct qubit state on release."
112 );
113}
114
115#[test]
116fn noisy_measurement() {
117 let noise = PauliNoise::from_probabilities(0.3, 0.0, 0.0)
118 .expect("bit flip noise with probability 100% should be constructable.");
119 let mut sim = SparseSim::new_with_noise(&noise);
120 assert!(!sim.is_noiseless(), "Expected noisy simulator.");
121 sim.set_seed(Some(0));
122 let mut true_count = 0;
123 for _ in 0..1000 {
124 let q = sim.qubit_allocate(); // Allocation is noiseless even with noise.
125 // sim.m sometimes applies X before measuring
126 if sim.m(q) {
127 true_count += 1;
128 };
129 sim.qubit_release(q);
130 }
131 assert!(
132 true_count > 200 && true_count < 400,
133 "Expected about 30% bit flip noise."
134 );
135}
136
137pub fn state_to_string(input: &(Vec<(BigUint, Complex<f64>)>, usize)) -> String {
138 input
139 .0
140 .iter()
141 .fold(String::new(), |mut output, (id, state)| {
142 let _ = write!(
143 output,
144 "{}: {} ",
145 format_state_id(id, input.1),
146 fmt_complex(state)
147 );
148 output
149 })
150 .to_string()
151}
152
153fn check_state(sim: &mut SparseSim, expected: &Expect) {
154 let state = sim.capture_quantum_state();
155 expected.assert_eq(&state_to_string(&state));
156}
157
158#[test]
159fn noisy_via_x() {
160 let noise = PauliNoise::from_probabilities(1.0, 0.0, 0.0)
161 .expect("bit flip noise with probability 100% should be constructable.");
162 let mut sim = SparseSim::new_with_noise(&noise);
163 assert!(!sim.is_noiseless(), "Expected noisy simulator.");
164 let q = sim.qubit_allocate(); // Allocation is noiseless even with noise.
165 check_state(&mut sim, &expect!["|0⟩: 1.0000+0.0000𝑖 "]);
166 sim.x(q); // Followed by X. So, no op.
167 check_state(&mut sim, &expect!["|0⟩: 1.0000+0.0000𝑖 "]);
168 sim.y(q); // Followed by X.
169 check_state(&mut sim, &expect!["|0⟩: 0.0000+1.0000𝑖 "]);
170 sim.z(q); // Followed by X.
171 check_state(&mut sim, &expect!["|1⟩: 0.0000+1.0000𝑖 "]);
172}
173
174#[test]
175fn noisy_via_y() {
176 let noise = PauliNoise::from_probabilities(0.0, 1.0, 0.0)
177 .expect("0.0, 1.0, 0.0 Pauli noise should be constructable.");
178 let mut sim = SparseSim::new_with_noise(&noise);
179 assert!(!sim.is_noiseless(), "Expected noisy simulator.");
180 let q = sim.qubit_allocate(); // Allocation is noiseless even with noise.
181 check_state(&mut sim, &expect!["|0⟩: 1.0000+0.0000𝑖 "]);
182 sim.x(q); // Followed by Y.
183 check_state(&mut sim, &expect!["|0⟩: 0.0000−1.0000𝑖 "]);
184 sim.y(q); // Followed by Y. So, no op.
185 check_state(&mut sim, &expect!["|0⟩: 0.0000−1.0000𝑖 "]);
186 sim.z(q); // Followed by Y.
187 check_state(&mut sim, &expect!["|1⟩: 1.0000+0.0000𝑖 "]);
188}
189
190#[test]
191fn noisy_via_z() {
192 let noise = PauliNoise::from_probabilities(0.0, 0.0, 1.0)
193 .expect("phase flip noise with probability 100% should be constructable.");
194 let mut sim = SparseSim::new_with_noise(&noise);
195 assert!(!sim.is_noiseless(), "Expected noisy simulator.");
196 let q = sim.qubit_allocate(); // Allocation is noiseless even with noise.
197 check_state(&mut sim, &expect!["|0⟩: 1.0000+0.0000𝑖 "]);
198 sim.x(q); // Followed by Z.
199 check_state(&mut sim, &expect!["|1⟩: −1.0000+0.0000𝑖 "]);
200 sim.y(q); // Followed by Z.
201 check_state(&mut sim, &expect!["|0⟩: 0.0000+1.0000𝑖 "]);
202 sim.z(q); // Followed by Z. So, no op.
203 check_state(&mut sim, &expect!["|0⟩: 0.0000+1.0000𝑖 "]);
204}
205