Skip to content

Commit

Permalink
Merge pull request #19 from qsharp-community/noise
Browse files Browse the repository at this point in the history
added support for QASM generation options
  • Loading branch information
filipw authored Dec 11, 2024
2 parents 0957ecc + 5ef4459 commit 7856007
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"operation Main() : (Result, Result) {{\n",
" {qsharp_expression}\n",
"}}\"\"\"\n",
" qasm_code = qasm2(code_to_run)\n",
" generation_options = QasmGenerationOptions(include_qelib=False, reset_behavior=QasmResetBehavior.IGNORED)\n",
" qasm_code = qasm2(code_to_run, generation_options)\n",
"\n",
" req = {\n",
" 'script': qasm_code,\n",
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use crate::sim::QsError;
use crate::sim::QubitState;
use crate::sim::ExecutionOptions;
use crate::sim::PauliDistribution;
use crate::qasm::QasmGenerationOptions;
use crate::qasm::QasmResetBehavior;

pub mod circuit;
pub mod sim;
Expand Down
54 changes: 46 additions & 8 deletions src/qasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,40 @@ pub(crate) struct Qasm2Backend {
qubits: HashSet<usize>,
next_qubit_id: usize,
cbit_counter: usize,
generation_options: QasmGenerationOptions,
}

pub struct QasmGenerationOptions {
pub include_qelib: bool,
pub reset_behavior: QasmResetBehavior,
}

pub enum QasmResetBehavior {
Supported,
Ignored,
Error,
}

impl Qasm2Backend {
pub fn new() -> Self {
pub fn new(generation_options: QasmGenerationOptions) -> Self {
Qasm2Backend {
code: Vec::new(),
qubits: HashSet::new(),
next_qubit_id: 0,
cbit_counter: 0,
errors: Vec::new(),
generation_options
}
}

pub fn get_qasm(&self, include_qelib: bool) -> Result<String, Vec<String>> {
pub fn get_qasm(&self) -> Result<String, Vec<String>> {
if !self.errors.is_empty() {
return Err(self.errors.clone());
}

let mut qasm = String::new();
qasm.push_str("OPENQASM 2.0;\n");
if include_qelib {
if self.generation_options.include_qelib {
qasm.push_str("include \"qelib1.inc\";\n");
}
let n_qubits = self.next_qubit_id;
Expand Down Expand Up @@ -128,13 +141,38 @@ impl Backend for Qasm2Backend {
false
}

fn mresetz(&mut self, _q: usize) -> Self::ResultType {
self.errors.push("Reset not supported in QASM 2.0".to_string());
false
fn mresetz(&mut self, q: usize) -> Self::ResultType {
match self.generation_options.reset_behavior {
QasmResetBehavior::Supported => {
let c = self.cbit_counter;
self.cbit_counter += 1;
self.code.push(format!("measure q[{}] -> c[{}];", q, c));
self.code.push(format!("reset q[{}];", q));
false
}
QasmResetBehavior::Ignored => {
let c = self.cbit_counter;
self.cbit_counter += 1;
self.code.push(format!("measure q[{}] -> c[{}];", q, c));
false
}
QasmResetBehavior::Error => {
self.errors.push("Reset is not supported".to_string());
false
}
}
}

fn reset(&mut self, _q: usize) {
self.errors.push("Reset not supported in QASM 2.0".to_string());
fn reset(&mut self, q: usize) {
match self.generation_options.reset_behavior {
QasmResetBehavior::Supported => {
self.code.push(format!("reset q[{}];", q));
}
QasmResetBehavior::Ignored => {}
QasmResetBehavior::Error => {
self.errors.push("Reset is not supported".to_string());
}
}
}

fn rxx(&mut self, theta: f64, q0: usize, q1: usize) {
Expand Down
15 changes: 13 additions & 2 deletions src/qsharp-bridge.udl
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ namespace qsharp_bridge {
string qir([ByRef]string expression);

[Throws=QsError]
string qasm2([ByRef]string source);
string qasm2([ByRef]string source, QasmGenerationOptions generation_options);

[Throws=QsError]
string qasm2_expression([ByRef]string expression);
string qasm2_expression([ByRef]string expression, QasmGenerationOptions generation_options);

[Throws=QsError]
string estimate([ByRef]string source, string? job_params);
Expand All @@ -25,6 +25,17 @@ namespace qsharp_bridge {
string estimate_expression([ByRef]string expression, string? job_params);
};

dictionary QasmGenerationOptions {
boolean include_qelib;
QasmResetBehavior reset_behavior;
};

enum QasmResetBehavior {
"Supported",
"Ignored",
"Error"
};

dictionary PauliDistribution {
f64 x;
f64 y;
Expand Down
14 changes: 7 additions & 7 deletions src/sim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use qsc::interpret::output;
use qsc::{format_state_id, LanguageFeatures, PackageType, PauliNoise, SourceMap, SparseSim, TargetCapabilityFlags};

use crate::circuit::Circuit;
use crate::qasm::Qasm2Backend;
use crate::qasm::{Qasm2Backend, QasmGenerationOptions};

pub struct ExecutionOptions {
pub shots: u32,
Expand Down Expand Up @@ -120,27 +120,27 @@ pub fn estimate_expression(expression: &str, job_params: Option<String>) -> Resu
return Ok(result);
}

pub fn qasm2(source: &str) -> Result<String, QsError> {
pub fn qasm2(source: &str, generation_options: QasmGenerationOptions) -> Result<String, QsError> {
let mut stdout = vec![];
let mut out = GenericReceiver::new(&mut stdout);
let mut backend = Qasm2Backend::new();
let mut backend = Qasm2Backend::new(generation_options);

let mut interpreter = create_interpreter(Some(source), PackageType::Exe, TargetCapabilityFlags::empty())?;
let _ = interpreter.eval_entry_with_sim(&mut backend, &mut out)?;

let qasm = backend.get_qasm(false).map_err(|errors| QsError::ErrorMessage { error_text: errors.join(", ") })?;
let qasm = backend.get_qasm().map_err(|errors| QsError::ErrorMessage { error_text: errors.join(", ") })?;
Ok(qasm)
}

pub fn qasm2_expression(expression: &str) -> Result<String, QsError> {
pub fn qasm2_expression(expression: &str, generation_options: QasmGenerationOptions) -> Result<String, QsError> {
let mut stdout = vec![];
let mut out = GenericReceiver::new(&mut stdout);
let mut backend = Qasm2Backend::new();
let mut backend = Qasm2Backend::new(generation_options);

let mut interpreter = create_interpreter(None, PackageType::Lib, TargetCapabilityFlags::empty())?;
let _ = interpreter.run_with_sim(&mut backend, &mut out, Some(expression))?;

let qasm = backend.get_qasm(false).map_err(|errors| QsError::ErrorMessage { error_text: errors.join(", ") })?;
let qasm = backend.get_qasm().map_err(|errors| QsError::ErrorMessage { error_text: errors.join(", ") })?;
Ok(qasm)
}

Expand Down
36 changes: 33 additions & 3 deletions tests/tests_qasm.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,35 @@
use qsharp_bridge::sim::{qasm2, qasm2_expression};
use qsharp_bridge::{qasm::{QasmGenerationOptions, QasmResetBehavior}, sim::{qasm2, qasm2_expression}};

#[test]
fn test_qasm_entanglement() {
let source = std::fs::read_to_string("tests/assets/entanglement.qs").unwrap();
let generation_options = QasmGenerationOptions {
include_qelib: true,
reset_behavior: QasmResetBehavior::Supported,
};
let result = qasm2(&source, generation_options).unwrap();
let expected = r####"OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0], q[1];
measure q[0] -> c[0];
reset q[0];
measure q[1] -> c[1];
reset q[1];
"####;
assert_eq!(result, expected);
}

#[test]
fn test_qasm_entanglement_no_reset() {
let source = std::fs::read_to_string("tests/assets/entanglement_noreset.qs").unwrap();
let result = qasm2(&source).unwrap();
let generation_options = QasmGenerationOptions {
include_qelib: false,
reset_behavior: QasmResetBehavior::Ignored,
};
let result = qasm2(&source, generation_options).unwrap();
let expected = r####"OPENQASM 2.0;
qreg q[2];
creg c[2];
Expand All @@ -17,7 +43,11 @@ measure q[1] -> c[1];

#[test]
fn test_qasm_expression() {
let result = qasm2_expression("{ operation Foo() : Result { use q = Qubit(); let r = M(q); r }; Foo() }").unwrap();
let generation_options = QasmGenerationOptions {
include_qelib: false,
reset_behavior: QasmResetBehavior::Ignored,
};
let result = qasm2_expression("{ operation Foo() : Result { use q = Qubit(); let r = M(q); r }; Foo() }", generation_options).unwrap();
let expected = r####"OPENQASM 2.0;
qreg q[1];
creg c[1];
Expand Down

0 comments on commit 7856007

Please sign in to comment.