Skip to content

Commit 4c1d573

Browse files
committed
Polishing rng management in noise models
1 parent db663bf commit 4c1d573

File tree

15 files changed

+788
-1101
lines changed

15 files changed

+788
-1101
lines changed

crates/pecos-derive/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ proc-macro = true
1010
[dependencies]
1111
syn.workspace = true
1212
quote.workspace = true
13+
14+
[dev-dependencies]
15+
syn = { version = "2", features = ["full"] }

crates/pecos-engines/examples/biased_measurement_example.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
2+
13
use pecos_engines::Engine;
24
use pecos_engines::byte_message::ByteMessage;
35
use pecos_engines::engines::noise::BiasedMeasurementNoise;
@@ -16,12 +18,12 @@ fn main() {
1618
// Create a quantum engine with 1 qubit
1719
let quantum = Box::new(StateVecEngine::new(1));
1820

19-
example1_different_bias_levels(&circ, quantum.clone());
21+
example1_different_bias_levels(&circ, &quantum);
2022
example2_with_seed(&circ);
2123
example3_bell_state();
2224
}
2325

24-
fn example1_different_bias_levels(circ: &ByteMessage, quantum: Box<StateVecEngine>) {
26+
fn example1_different_bias_levels(circ: &ByteMessage, quantum: &StateVecEngine) {
2527
// === EXAMPLE 1: Different bias levels ===
2628
println!("Example 1: Testing different bias levels with 10,000 shots");
2729
println!("{:-^80}", "");
@@ -49,7 +51,7 @@ fn example1_different_bias_levels(circ: &ByteMessage, quantum: Box<StateVecEngin
4951
for (p_flip_0, p_flip_1, desc) in configs {
5052
// Create the biased measurement noise model
5153
let noise = Box::new(BiasedMeasurementNoise::new(p_flip_0, p_flip_1));
52-
let mut system = QuantumSystem::new(noise, quantum.clone());
54+
let mut system = QuantumSystem::new(noise, Box::new(quantum.clone()));
5355

5456
// For deterministic testing, set a fixed seed
5557
system.set_seed(42).expect("Failed to set seed");
@@ -81,8 +83,10 @@ fn example1_different_bias_levels(circ: &ByteMessage, quantum: Box<StateVecEngin
8183
// For a 50/50 input with H gate:
8284
// Expected 0s = 50% * (1-p_flip_0) + 50% * p_flip_1
8385
// Expected 1s = 50% * p_flip_0 + 50% * (1-p_flip_1)
84-
let expected_0 = ((50.0 * (1.0 - p_flip_0) + 50.0 * p_flip_1) as f64).round() as usize;
85-
let expected_1 = ((50.0 * p_flip_0 + 50.0 * (1.0 - p_flip_1)) as f64).round() as usize;
86+
let calc_0: f64 = 50.0 * (1.0 - p_flip_0) + 50.0 * p_flip_1;
87+
let expected_0 = calc_0.round() as usize;
88+
let calc_1: f64 = 50.0 * p_flip_0 + 50.0 * (1.0 - p_flip_1);
89+
let expected_1 = calc_1.round() as usize;
8690

8791
println!(
8892
"{:<30} | {:<10} | {:<10} | {:<10} | {:<10}",
@@ -131,8 +135,10 @@ fn example2_with_seed(circ: &ByteMessage) {
131135
// Calculate expected results for this configuration
132136
let p_flip_0 = 0.4;
133137
let p_flip_1 = 0.1;
134-
let expected_0 = ((50.0 * (1.0 - p_flip_0) + 50.0 * p_flip_1) as f64).round() as usize;
135-
let expected_1 = ((50.0 * p_flip_0 + 50.0 * (1.0 - p_flip_1)) as f64).round() as usize;
138+
let calc_0: f64 = 50.0 * (1.0 - p_flip_0) + 50.0 * p_flip_1;
139+
let expected_0 = calc_0.round() as usize;
140+
let calc_1: f64 = 50.0 * p_flip_0 + 50.0 * (1.0 - p_flip_1);
141+
let expected_1 = calc_1.round() as usize;
136142

137143
println!("Builder pattern with p_flip_0 = 0.4, p_flip_1 = 0.1");
138144
println!(" Expected results: 0: {expected_0}%, 1: {expected_1}%");

crates/pecos-engines/examples/run_noisy_circ.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use pecos_engines::byte_message::ByteMessage;
22
use pecos_engines::engines::quantum::StateVecEngine;
3-
use pecos_engines::{Engine, GeneralDepolarizingNoise};
3+
use pecos_engines::{DepolarizingNoise, Engine};
44
use pecos_engines::{EngineSystem, QuantumSystem};
55

66
fn main() {
@@ -12,7 +12,7 @@ fn main() {
1212
.build();
1313

1414
let quantum = Box::new(StateVecEngine::new(2));
15-
let noise = Box::new(GeneralDepolarizingNoise::new(0.1, 0.1, 0.1, 0.1));
15+
let noise = Box::new(DepolarizingNoise::new(0.1, 0.1, 0.1, 0.1));
1616

1717
let mut system = QuantumSystem::new(noise, quantum);
1818

crates/pecos-engines/src/core/shot_results.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,9 @@ impl fmt::Display for ShotResults {
212212

213213
// Print any other keys (except measurement_ keys and result_X keys)
214214
for (key, value) in shot {
215-
if !key.starts_with("measurement_") &&
215+
if !key.starts_with("measurement_") &&
216216
!key.starts_with("result_") && // Skip result_X keys
217-
key != "result" &&
217+
key != "result" &&
218218
!key.starts_with('q')
219219
{
220220
if first {

crates/pecos-engines/src/engines/hybrid/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl HybridEngineBuilder {
137137
/// The builder for method chaining
138138
#[must_use]
139139
pub fn with_depolarizing_noise(mut self, probability: f64) -> Self {
140-
self.noise_model = Some(Box::new(DepolarizingNoise::new_with_options(probability)));
140+
self.noise_model = Some(Box::new(DepolarizingNoise::new_uniform(probability)));
141141
self.quantum_system = None; // Reset quantum_system as it's now invalid
142142
self
143143
}

crates/pecos-engines/src/engines/monte_carlo/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ impl MonteCarloEngineBuilder {
237237
/// The builder for method chaining
238238
#[must_use]
239239
pub fn with_depolarizing_noise(self, probability: f64) -> Self {
240-
self.with_noise_model(Box::new(DepolarizingNoise::new_with_options(probability)))
240+
self.with_noise_model(Box::new(DepolarizingNoise::new_uniform(probability)))
241241
}
242242

243243
/// Set the quantum system

crates/pecos-engines/src/engines/monte_carlo/engine.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,12 +423,12 @@ impl MonteCarloEngine {
423423
// If a seed is provided, create a noise model with the seed
424424
let noise_seed = derive_seed(s, "noise_model");
425425
DepolarizingNoiseBuilder::new()
426-
.with_probability(p)
426+
.with_uniform_probability(p)
427427
.with_seed(noise_seed)
428428
.build()
429429
} else {
430430
// Otherwise, create a noise model without a specific seed
431-
Box::new(crate::engines::noise::DepolarizingNoise::new(p))
431+
Box::new(crate::engines::noise::DepolarizingNoise::new_uniform(p))
432432
};
433433

434434
// Create a quantum engine with the same number of qubits as the classical engine

crates/pecos-engines/src/engines/noise.rs

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1+
//! Quantum noise models for realistic quantum computation simulation
2+
//!
3+
//! This module provides various noise models that can be used to simulate
4+
//! realistic quantum computation with errors. Each noise model implements
5+
//! the `NoiseModel` trait and can be used with the quantum engines.
6+
17
pub mod biased_measurement;
28
pub mod depolarizing;
3-
pub mod general_depolarizing;
49
pub mod pass_through;
510
pub mod utils;
611

712
pub use biased_measurement::BiasedMeasurementNoise;
813
pub use depolarizing::DepolarizingNoise;
9-
pub use general_depolarizing::GeneralDepolarizingNoise;
1014
pub use pass_through::PassThroughNoise;
1115
pub use utils::{NoiseRng, NoiseUtils, ProbabilityValidator};
1216

@@ -33,26 +37,8 @@ pub trait NoiseModel:
3337
+ Send
3438
+ Sync
3539
+ Any
40+
+ RngManageable<Rng = ChaCha8Rng>
3641
{
37-
/// Set a specific seed for the random number generator
38-
///
39-
/// This method allows for deterministic behavior by setting a specific seed
40-
/// for the random number generator used by the noise model.
41-
///
42-
/// # Arguments
43-
/// * `seed` - Seed value for the random number generator
44-
///
45-
/// # Returns
46-
/// Result indicating success or failure
47-
///
48-
/// # Errors
49-
/// Returns a `QueueError` if setting the seed fails
50-
fn set_seed(&mut self, seed: u64) -> Result<(), QueueError> {
51-
// Default implementation for noise models that don't use randomness
52-
let _ = seed;
53-
Ok(())
54-
}
55-
5642
/// Returns a reference to self as Any
5743
///
5844
/// This allows for type-checking and downcasting without requiring
@@ -136,12 +122,10 @@ impl RngManageable for BaseNoiseModel {
136122
}
137123

138124
fn rng(&self) -> &Self::Rng {
139-
// Delegate to the NoiseRng implementation, which will panic
140125
self.rng.rng()
141126
}
142127

143128
fn rng_mut(&mut self) -> &mut Self::Rng {
144-
// Delegate to the NoiseRng implementation, which will panic
145129
self.rng.rng_mut()
146130
}
147131
}
@@ -188,7 +172,6 @@ mod tests {
188172
use super::*;
189173
use crate::byte_message::ByteMessageBuilder;
190174
use crate::engines::noise::biased_measurement::BiasedMeasurementNoise;
191-
use crate::engines::noise::depolarizing::DepolarizingNoise;
192175

193176
#[test]
194177
fn test_noise_model_biased_measurement() {
@@ -239,7 +222,7 @@ mod tests {
239222
#[test]
240223
fn test_noise_model_depolarizing() {
241224
// Create a depolarizing noise model
242-
let mut noise_model = DepolarizingNoise::new(0.1);
225+
let mut noise_model = DepolarizingNoise::new_uniform(0.1);
243226

244227
// Create a quantum operation message
245228
let mut builder = ByteMessageBuilder::new();

0 commit comments

Comments
 (0)