Skip to content

Commit

Permalink
Merge 0a20cdf into 72c32aa
Browse files Browse the repository at this point in the history
  • Loading branch information
swernli authored Sep 8, 2024
2 parents 72c32aa + 0a20cdf commit d3440cc
Show file tree
Hide file tree
Showing 17 changed files with 624 additions and 147 deletions.
364 changes: 364 additions & 0 deletions compiler/qsc/src/codegen/tests.rs

Large diffs are not rendered by default.

91 changes: 90 additions & 1 deletion compiler/qsc_circuit/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::{
};
use num_bigint::BigUint;
use num_complex::Complex;
use qsc_codegen::remapper::{HardwareId, Remapper};
use qsc_data_structures::index_map::IndexMap;
use qsc_eval::{backend::Backend, val::Value};
use std::{fmt::Write, mem::take, rc::Rc};
Expand Down Expand Up @@ -181,6 +180,10 @@ impl Backend for Builder {
self.remapper.qubit_release(q);
}

fn qubit_swap_id(&mut self, q0: usize, q1: usize) {
self.remapper.swap(q0, q1);
}

fn capture_quantum_state(&mut self) -> (Vec<(BigUint, Complex<f64>)>, usize) {
(Vec::new(), 0)
}
Expand Down Expand Up @@ -370,6 +373,92 @@ impl Builder {
}
}

/// Provides support for qubit id allocation, measurement and
/// reset operations for Base Profile targets.
///
/// Since qubit reuse is disallowed, a mapping is maintained
/// from allocated qubit ids to hardware qubit ids. Each time
/// a qubit is reset, it is remapped to a fresh hardware qubit.
///
/// Note that even though qubit reset & reuse is disallowed,
/// qubit ids are still reused for new allocations.
/// Measurements are tracked and deferred.
#[derive(Default)]
struct Remapper {
next_meas_id: usize,
next_qubit_id: usize,
next_qubit_hardware_id: HardwareId,
qubit_map: IndexMap<usize, HardwareId>,
measurements: Vec<(HardwareId, usize)>,
}

impl Remapper {
fn map(&mut self, qubit: usize) -> HardwareId {
if let Some(mapped) = self.qubit_map.get(qubit) {
*mapped
} else {
let mapped = self.next_qubit_hardware_id;
self.next_qubit_hardware_id.0 += 1;
self.qubit_map.insert(qubit, mapped);
mapped
}
}

fn m(&mut self, q: usize) -> usize {
let mapped_q = self.map(q);
let id = self.get_meas_id();
self.measurements.push((mapped_q, id));
id
}

fn mreset(&mut self, q: usize) -> usize {
let id = self.m(q);
self.reset(q);
id
}

fn reset(&mut self, q: usize) {
self.qubit_map.remove(q);
}

fn qubit_allocate(&mut self) -> usize {
let id = self.next_qubit_id;
self.next_qubit_id += 1;
let _ = self.map(id);
id
}

fn qubit_release(&mut self, _q: usize) {
self.next_qubit_id -= 1;
}

fn swap(&mut self, q0: usize, q1: usize) {
let q0_mapped = self.map(q0);
let q1_mapped = self.map(q1);
self.qubit_map.insert(q0, q1_mapped);
self.qubit_map.insert(q1, q0_mapped);
}

fn measurements(&self) -> impl Iterator<Item = &(HardwareId, usize)> {
self.measurements.iter()
}

#[must_use]
fn num_qubits(&self) -> usize {
self.next_qubit_hardware_id.0
}

#[must_use]
fn get_meas_id(&mut self) -> usize {
let id = self.next_meas_id;
self.next_meas_id += 1;
id
}
}

#[derive(Copy, Clone, Default)]
pub struct HardwareId(pub usize);

#[allow(clippy::unicode_not_nfc)]
static KET_ZERO: &str = "|0〉";

Expand Down
1 change: 0 additions & 1 deletion compiler/qsc_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@

pub mod qir;
pub mod qsharp;
pub mod remapper;
88 changes: 0 additions & 88 deletions compiler/qsc_codegen/src/remapper.rs

This file was deleted.

14 changes: 12 additions & 2 deletions compiler/qsc_eval/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,18 @@ pub trait Backend {
fn qubit_release(&mut self, _q: usize) {
unimplemented!("qubit_release operation");
}
fn qubit_swap_id(&mut self, _q0: usize, _q1: usize) {
unimplemented!("qubit_swap_id operation");
}
fn capture_quantum_state(&mut self) -> (Vec<(BigUint, Complex<f64>)>, usize) {
unimplemented!("capture_quantum_state operation");
}
fn qubit_is_zero(&mut self, _q: usize) -> bool {
unimplemented!("qubit_is_zero operation");
}

fn custom_intrinsic(&mut self, _name: &str, _arg: Value) -> Option<Result<Value, String>> {
None
}

fn set_seed(&mut self, _seed: Option<u64>) {}
}

Expand Down Expand Up @@ -240,6 +241,10 @@ impl Backend for SparseSim {
self.sim.release(q);
}

fn qubit_swap_id(&mut self, q0: usize, q1: usize) {
self.sim.swap_qubit_ids(q0, q1);
}

fn capture_quantum_state(&mut self) -> (Vec<(BigUint, Complex<f64>)>, usize) {
let (state, count) = self.sim.get_state();
// Because the simulator returns the state indices with opposite endianness from the
Expand Down Expand Up @@ -458,6 +463,11 @@ where
self.main.qubit_release(q);
}

fn qubit_swap_id(&mut self, q0: usize, q1: usize) {
self.chained.qubit_swap_id(q0, q1);
self.main.qubit_swap_id(q0, q1);
}

fn capture_quantum_state(
&mut self,
) -> (Vec<(num_bigint::BigUint, num_complex::Complex<f64>)>, usize) {
Expand Down
5 changes: 5 additions & 0 deletions compiler/qsc_eval/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ pub(crate) fn call(
Err(Error::ReleasedQubitNotZero(qubit, arg_span))
}
}
"__quantum__rt__qubit_swap_ids" => {
let [q0, q1] = unwrap_tuple(arg);
sim.qubit_swap_id(q0.unwrap_qubit().0, q1.unwrap_qubit().0);
Ok(Value::unit())
}
"__quantum__qis__ccx__body" => {
three_qubit_gate(|ctl0, ctl1, q| sim.ccx(ctl0, ctl1, q), arg, arg_span)
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/qsc_eval/src/intrinsic/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ impl Backend for CustomSim {
self.sim.qubit_release(q);
}

fn qubit_swap_id(&mut self, q0: usize, q1: usize) {
self.sim.qubit_swap_id(q0, q1);
}

fn capture_quantum_state(
&mut self,
) -> (Vec<(num_bigint::BigUint, num_complex::Complex<f64>)>, usize) {
Expand Down
14 changes: 7 additions & 7 deletions compiler/qsc_eval/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,23 +418,23 @@ fn block_qubit_use_array_invalid_count_expr() {
0,
),
span: Span {
lo: 2064,
hi: 2121,
lo: 2172,
hi: 2229,
},
},
),
[
Frame {
span: Span {
lo: 2064,
hi: 2121,
lo: 2172,
hi: 2229,
},
id: StoreItemId {
package: PackageId(
0,
),
item: LocalItemId(
6,
7,
),
},
caller: PackageId(
Expand Down Expand Up @@ -3724,7 +3724,7 @@ fn controlled_operation_with_duplicate_controls_fails() {
1,
),
item: LocalItemId(
130,
131,
),
},
caller: PackageId(
Expand Down Expand Up @@ -3774,7 +3774,7 @@ fn controlled_operation_with_target_in_controls_fails() {
1,
),
item: LocalItemId(
130,
131,
),
},
caller: PackageId(
Expand Down
Loading

0 comments on commit d3440cc

Please sign in to comment.