Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 64 additions & 26 deletions source/compiler/qsc/src/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use qsc_data_structures::{
};
use qsc_eval::{
Env, ErrorBehavior, State, VariableInfo,
backend::{Backend, SparseSim, TracingBackend},
backend::{Backend, CliffordSim, SparseSim, TracingBackend},
output::Receiver,
};
pub use qsc_eval::{
Expand Down Expand Up @@ -122,6 +122,13 @@ pub enum Error {
PartialEvaluation(#[from] WithSource<qsc_partial_eval::Error>),
}

#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
pub enum SimType {
#[default]
Sparse,
Clifford(usize),
}

/// A Q# interpreter.
pub struct Interpreter {
/// The incremental Q# compiler.
Expand Down Expand Up @@ -844,30 +851,47 @@ impl Interpreter {
qubit_loss: Option<f64>,
noise_config: Option<NoiseConfig<f64, f64>>,
seed: Option<u64>,
sim_type: SimType,
) -> InterpretResult {
let qubit_loss = if noise_config.is_none() {
qubit_loss
} else {
None
};
let mut sim = match noise {
Some(noise) => SparseSim::new_with_noise(&noise),
None => match noise_config {
Some(config) => SparseSim::new_with_noise_config(config.into()),
None => SparseSim::new(),
},
};
if let Some(loss) = qubit_loss {
sim.set_loss(loss);
}
if seed.is_some() {
sim.set_seed(seed);

match sim_type {
SimType::Sparse => {
let mut sim = match noise {
Some(noise) => SparseSim::new_with_noise(&noise),
None => match noise_config {
Some(config) => SparseSim::new_with_noise_config(config.into()),
None => SparseSim::new(),
},
};
if let Some(loss) = qubit_loss {
sim.set_loss(loss);
}
if seed.is_some() {
sim.set_seed(seed);
}
self.invoke_with_sim(&mut sim, receiver, callable, args, seed)
}
SimType::Clifford(num_qubits) => {
let mut sim = match noise_config {
Some(config) => CliffordSim::new_with_noise_config(num_qubits, config.into()),
None => CliffordSim::new(num_qubits),
};
if seed.is_some() {
sim.set_seed(seed);
}
self.invoke_with_sim(&mut sim, receiver, callable, args, seed)
}
}
self.invoke_with_sim(&mut sim, receiver, callable, args, seed)
}

/// Runs the given entry expression on a new instance of the environment and simulator,
/// but using the current compilation.
#[allow(clippy::too_many_arguments)]
pub fn run(
&mut self,
receiver: &mut impl Receiver,
Expand All @@ -876,28 +900,42 @@ impl Interpreter {
qubit_loss: Option<f64>,
noise_config: Option<NoiseConfig<f64, f64>>,
seed: Option<u64>,
sim_type: SimType,
) -> InterpretResult {
let qubit_loss = if noise_config.is_none() {
qubit_loss
} else {
None
};
let mut sim = match noise {
Some(noise) => SparseSim::new_with_noise(&noise),
None => match noise_config {
Some(config) => SparseSim::new_with_noise_config(config.into()),
None => SparseSim::new(),
},
};
if let Some(loss) = qubit_loss {
sim.set_loss(loss);
match sim_type {
SimType::Sparse => {
let mut sim = match noise {
Some(noise) => SparseSim::new_with_noise(&noise),
None => match noise_config {
Some(config) => SparseSim::new_with_noise_config(config.into()),
None => SparseSim::new(),
},
};
if let Some(loss) = qubit_loss {
sim.set_loss(loss);
}
self.run_with_sim(&mut sim, receiver, expr, seed)
}
SimType::Clifford(num_qubits) => {
let mut sim = match noise_config {
Some(config) => CliffordSim::new_with_noise_config(num_qubits, config.into()),
None => CliffordSim::new(num_qubits),
};
self.run_with_sim(&mut sim, receiver, expr, seed)
}
}
self.run_with_sim(&mut sim, receiver, expr, seed)
}

/// Gets the current quantum state of the simulator.
pub fn get_quantum_state(&mut self) -> (Vec<(BigUint, Complex<f64>)>, usize) {
self.sim.capture_quantum_state()
self.sim
.capture_quantum_state()
.expect("interpreter should use infallible sparse sim by default")
}

/// Get the current circuit representation of the program.
Expand Down Expand Up @@ -1641,7 +1679,7 @@ impl Debugger {
}

pub fn capture_quantum_state(&mut self) -> (Vec<(BigUint, Complex<f64>)>, usize) {
self.interpreter.sim.capture_quantum_state()
self.interpreter.get_quantum_state()
}

pub fn circuit(&self) -> Circuit {
Expand Down
10 changes: 9 additions & 1 deletion source/compiler/qsc/src/interpret/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,15 @@ mod given_interpreter {
fn run(interpreter: &mut Interpreter, expr: &str) -> (InterpretResult, String) {
let mut cursor = Cursor::new(Vec::<u8>::new());
let mut receiver = CursorReceiver::new(&mut cursor);
let res = interpreter.run(&mut receiver, Some(expr), None, None, None, None);
let res = interpreter.run(
&mut receiver,
Some(expr),
None,
None,
None,
None,
Default::default(),
);
(res, receiver.dump())
}

Expand Down
2 changes: 1 addition & 1 deletion source/compiler/qsc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub mod line_column {
}

pub use qsc_eval::{
backend::{Backend, SparseSim},
backend::{Backend, CliffordSim, SparseSim},
noise::PauliNoise,
state::{
fmt_basis_state_label, fmt_complex, format_state_id, get_matrix_latex, get_phase,
Expand Down
Loading
Loading