Skip to content
Open
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
62 changes: 60 additions & 2 deletions library/src/tests/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use crate::tests::test_expression_fails;
use crate::tests::{
test_expression_fails, test_expression_fails_with_lib_and_profile_and_sim,
test_expression_with_lib_and_profile_and_sim,
};

use super::test_expression;
use expect_test::expect;
use qsc::interpret::Value;
use qsc::{interpret::Value, target::Profile};

#[test]
fn check_operations_are_equal() {
Expand Down Expand Up @@ -535,6 +538,24 @@ fn check_post_select_collapses_superposition_to_zero() {
);
}

#[test]
fn check_post_select_collapses_superposition_to_zero_on_clifford() {
test_expression_with_lib_and_profile_and_sim(
"{
import Std.Diagnostics.PostSelectZ;
import Std.Diagnostics.CheckZero;
use q = Qubit();
H(q);
PostSelectZ(Zero, q);
// Qubit must be zero on release.
}",
"",
Profile::Unrestricted,
&mut qsc::CliffordSim::new(1),
&Value::unit(),
);
}

#[test]
fn check_post_select_collapses_superposition_to_one() {
test_expression(
Expand All @@ -552,6 +573,24 @@ fn check_post_select_collapses_superposition_to_one() {
);
}

#[test]
fn check_post_select_collapses_superposition_to_one_on_clifford() {
test_expression_with_lib_and_profile_and_sim(
"{
import Std.Diagnostics.PostSelectZ;
import Std.Diagnostics.CheckZero;
use q = Qubit();
H(q);
PostSelectZ(One, q);
X(q); // Resets the qubit back to zero for release.
}",
"",
Profile::Unrestricted,
&mut qsc::CliffordSim::new(1),
&Value::unit(),
);
}

#[test]
fn check_post_select_fails_with_non_existent_state() {
let err = test_expression_fails(
Expand All @@ -567,3 +606,22 @@ fn check_post_select_fails_with_non_existent_state() {
]
.assert_eq(&err);
}

#[test]
fn check_post_select_fails_with_non_existent_state_on_clifford() {
let err = test_expression_fails_with_lib_and_profile_and_sim(
"{
import Std.Diagnostics.PostSelectZ;
import Std.Diagnostics.CheckZero;
use q = Qubit();
PostSelectZ(One, q);
}",
"",
Profile::Unrestricted,
&mut qsc::CliffordSim::new(1),
);
expect![
"intrinsic callable `PostSelectZ` failed: post-selection condition has zero probability"
]
.assert_eq(&err);
}
6 changes: 5 additions & 1 deletion library/std/src/Std/OpenQASM/Intrinsic.qs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export rxx, ryy, rzz;
// that Qiskit wont emit correctly.
export dcx, ecr, r, rzx, cs, csdg, sxdg, csx, rccx, c3sqrtx, c3x, rc3x, xx_minus_yy, xx_plus_yy, ccz;

export mresetz_checked;
export mresetz_checked, postselectz;

export __quantum__qis__barrier__body;

Expand Down Expand Up @@ -647,6 +647,10 @@ operation mresetz_checked(q : Qubit) : Int {
}
}

operation postselectz(r : Result, q : Qubit) : Unit {
Std.Diagnostics.PostSelectZ(r, q);
}

/// The ``BARRIER`` function is used to implement the `barrier` statement in QASM.
/// The `@SimulatableIntrinsic` attribute is used to mark the operation for QIR
/// generation.
Expand Down
13 changes: 9 additions & 4 deletions source/compiler/qsc_eval/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1390,7 +1390,7 @@ impl Backend for CliffordSim {
Err("adjoint T gate is not supported in Clifford simulation".to_string())
}

fn custom_intrinsic(&mut self, name: &str, _arg: Value) -> Option<Result<Value, String>> {
fn custom_intrinsic(&mut self, name: &str, arg: Value) -> Option<Result<Value, String>> {
match name {
"BeginEstimateCaching" => Some(Ok(Value::Bool(true))),
"GlobalPhase"
Expand All @@ -1413,9 +1413,14 @@ impl Backend for CliffordSim {
"Apply" => Some(Err(
"arbitrary unitary application not supported in Clifford simulation".to_string(),
)),
"PostSelectZ" => Some(Err(
"post-selection not supported in Clifford simulation".to_string()
)),
"PostSelectZ" => {
let [result, qubit] = unwrap_tuple(arg);
let id = qubit.unwrap_qubit().deref().0;
let Value::Result(val::Result::Val(val)) = result else {
panic!("first argument to PostSelectZ should be a measurement result");
};
Some(self.sim.post_select_z(val, id).map(|()| Value::unit()))
}
_ => None,
}
}
Expand Down

Large diffs are not rendered by default.

Loading
Loading