diff --git a/compiler/SUPPORT.md b/compiler/SUPPORT.md index e3ee94c2d6..3f1e8b9bc7 100644 --- a/compiler/SUPPORT.md +++ b/compiler/SUPPORT.md @@ -13,25 +13,6 @@ and are not called out specifically here. ## Unsupported Features -### Conjugate expressions (within-apply) - -```qsharp -within { - Prepare(qs); -} -apply { - Op(qs); -} -``` - -#### Alternative: Explicitly define adjoint preparation - -```qsharp -Prepare(qs); -Op(qs); -Adjoint Prepare(qs); -``` - ### String Interpolation ```qsharp @@ -90,3 +71,4 @@ supported by the evaluator, matching the callables present in the standard libra - Callables as arguments to other callables (ie: `operation ApplyToEach(op : (Qubit => Unit), q : Qubit) : Unit {}`) - Controlled generator (`controlled distribute` and `controlled adjoint distribute`) - Adjoint generator (`adjoint invert` and `controlled adjoint invert`) +- Conjugate expressions (within-apply) diff --git a/compiler/qsc_passes/src/conjugate_invert.rs b/compiler/qsc_passes/src/conjugate_invert.rs new file mode 100644 index 0000000000..7c6d6e7acc --- /dev/null +++ b/compiler/qsc_passes/src/conjugate_invert.rs @@ -0,0 +1,169 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#[cfg(test)] +mod tests; + +use std::{collections::HashSet, mem::take}; + +use miette::Diagnostic; +use qsc_data_structures::span::Span; +use qsc_frontend::compile::CompileUnit; +use qsc_hir::{ + assigner::Assigner, + hir::{Block, Expr, ExprKind, NodeId, Res, Stmt, StmtKind, Ty}, + mut_visit::{self, MutVisitor}, + visit::{self, Visitor}, +}; +use thiserror::Error; + +use crate::{ + invert_block::adj_invert_block, + spec_gen::adj_gen::{self, AdjDistrib}, +}; + +#[derive(Clone, Debug, Diagnostic, Error)] +pub enum Error { + #[diagnostic(transparent)] + #[error(transparent)] + AdjGen(adj_gen::Error), + + #[error("variable cannot be assigned in apply-block since it is used in within-block")] + #[diagnostic(help("updating mutable variables in the apply-block that are used in the within-block can violate logic reversibility"))] + ApplyAssign(#[label] Span), +} + +/// Generates adjoint inverted blocks for within-blocks across all conjugate expressions, +/// eliminating the conjugate expression from the compilation unit. +pub fn invert_conjugate_exprs(unit: &mut CompileUnit) -> Vec { + let mut pass = ConjugateElim { + assigner: &mut unit.assigner, + errors: Vec::new(), + }; + pass.visit_package(&mut unit.package); + + pass.errors +} + +struct ConjugateElim<'a> { + assigner: &'a mut Assigner, + errors: Vec, +} + +impl<'a> MutVisitor for ConjugateElim<'a> { + fn visit_expr(&mut self, expr: &mut Expr) { + mut_visit::walk_expr(self, expr); + + match take(&mut expr.kind) { + ExprKind::Conjugate(within, apply) => { + let mut usage = Usage { + used: HashSet::new(), + }; + usage.visit_block(&within); + let mut assign_check = AssignmentCheck { + used: usage.used, + errors: Vec::new(), + }; + assign_check.visit_block(&apply); + self.errors.extend(assign_check.errors); + + let mut adj_within = within.clone(); + if let Err(invert_errors) = adj_invert_block(self.assigner, &mut adj_within) { + self.errors.extend( + invert_errors + .into_iter() + .map(adj_gen::Error::LogicSep) + .map(Error::AdjGen), + ); + return; + } + let mut distrib = AdjDistrib { errors: Vec::new() }; + distrib.visit_block(&mut adj_within); + self.errors + .extend(distrib.errors.into_iter().map(Error::AdjGen)); + + let new_block = Block { + id: NodeId::default(), + span: Span::default(), + ty: Ty::UNIT, + stmts: vec![ + block_as_stmt(within), + block_as_stmt(apply), + block_as_stmt(adj_within), + ], + }; + *expr = block_as_expr(new_block); + } + kind => expr.kind = kind, + } + } +} + +fn block_as_expr(block: Block) -> Expr { + Expr { + id: NodeId::default(), + span: Span::default(), + ty: Ty::UNIT, + kind: ExprKind::Block(block), + } +} + +fn block_as_stmt(block: Block) -> Stmt { + Stmt { + id: NodeId::default(), + span: Span::default(), + kind: StmtKind::Expr(block_as_expr(block)), + } +} + +struct Usage { + used: HashSet, +} + +impl<'a> Visitor<'a> for Usage { + fn visit_expr(&mut self, expr: &'a Expr) { + match &expr.kind { + ExprKind::Name(Res::Local(id)) => { + self.used.insert(*id); + } + _ => visit::walk_expr(self, expr), + } + } +} + +struct AssignmentCheck { + used: HashSet, + errors: Vec, +} + +impl<'a> Visitor<'a> for AssignmentCheck { + fn visit_expr(&mut self, expr: &'a Expr) { + match &expr.kind { + ExprKind::Assign(lhs, rhs) => { + self.visit_expr(rhs); + self.check_assign(lhs); + } + _ => visit::walk_expr(self, expr), + } + } +} + +impl AssignmentCheck { + fn check_assign(&mut self, expr: &Expr) { + match &expr.kind { + ExprKind::Hole => {} + ExprKind::Paren(expr) => self.check_assign(expr), + ExprKind::Name(Res::Local(id)) => { + if self.used.contains(id) { + self.errors.push(Error::ApplyAssign(expr.span)); + } + } + ExprKind::Tuple(var_tup) => { + for expr in var_tup { + self.check_assign(expr); + } + } + _ => panic!("unexpected expr type in assignment"), + } + } +} diff --git a/compiler/qsc_passes/src/conjugate_invert/tests.rs b/compiler/qsc_passes/src/conjugate_invert/tests.rs new file mode 100644 index 0000000000..a06bf75548 --- /dev/null +++ b/compiler/qsc_passes/src/conjugate_invert/tests.rs @@ -0,0 +1,402 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![allow(clippy::too_many_lines)] + +use expect_test::{expect, Expect}; +use indoc::indoc; +use qsc_frontend::compile::{compile, PackageStore}; + +use crate::conjugate_invert::invert_conjugate_exprs; + +fn check(file: &str, expect: &Expect) { + let store = PackageStore::new(); + let mut unit = compile(&store, [], [file], ""); + assert!( + unit.errors.is_empty(), + "Compilation errors: {:?}", + unit.errors + ); + let errors = invert_conjugate_exprs(&mut unit); + if errors.is_empty() { + expect.assert_eq(&unit.package.to_string()); + } else { + expect.assert_debug_eq(&errors); + } +} + +#[test] +fn conjugate_invert() { + check( + indoc! {" + namespace Test { + operation B(i : Int) : Unit is Adj {} + operation A() : Unit { + within { + B(1); + B(2); + } + apply { + B(3); + B(4); + } + } + } + "}, + &expect![[r#" + Package: + Item 0 [0-218]: + Namespace (Ident 35 [10-14] "Test"): Item 1, Item 2 + Item 1 [21-58]: + Parent: 0 + Callable 0 [21-58] (Operation): + name: Ident 1 [31-32] "B" + input: Pat 2 [32-41] [Type Int]: Paren: + Pat 3 [33-40] [Type Int]: Bind: Ident 4 [33-34] "i" + output: () + functors: Functor Expr 5 [52-55]: Adj + body: Block: Block 6 [56-58]: + Item 2 [63-216]: + Parent: 0 + Callable 7 [63-216] (Operation): + name: Ident 8 [73-74] "A" + input: Pat 9 [74-76] [Type ()]: Unit + output: () + body: Block: Block 10 [84-216] [Type ()]: + Stmt 11 [94-210]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block _id_ [0-0] [Type ()]: + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 13 [101-148] [Type ()]: + Stmt 14 [115-120]: Semi: Expr 15 [115-119] [Type ()]: Call: + Expr 16 [115-116] [Type (Int => () is Adj)]: Name: Item 1 + Expr 17 [116-119] [Type Int]: Paren: Expr 18 [117-118] [Type Int]: Lit: Int(1) + Stmt 19 [133-138]: Semi: Expr 20 [133-137] [Type ()]: Call: + Expr 21 [133-134] [Type (Int => () is Adj)]: Name: Item 1 + Expr 22 [134-137] [Type Int]: Paren: Expr 23 [135-136] [Type Int]: Lit: Int(2) + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 24 [163-210] [Type ()]: + Stmt 25 [177-182]: Semi: Expr 26 [177-181] [Type ()]: Call: + Expr 27 [177-178] [Type (Int => () is Adj)]: Name: Item 1 + Expr 28 [178-181] [Type Int]: Paren: Expr 29 [179-180] [Type Int]: Lit: Int(3) + Stmt 30 [195-200]: Semi: Expr 31 [195-199] [Type ()]: Call: + Expr 32 [195-196] [Type (Int => () is Adj)]: Name: Item 1 + Expr 33 [196-199] [Type Int]: Paren: Expr 34 [197-198] [Type Int]: Lit: Int(4) + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 13 [101-148] [Type ()]: + Stmt 19 [133-138]: Semi: Expr 20 [133-137] [Type ()]: Call: + Expr _id_ [133-134] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 21 [133-134] [Type (Int => () is Adj)]: Name: Item 1 + Expr 22 [134-137] [Type Int]: Paren: Expr 23 [135-136] [Type Int]: Lit: Int(2) + Stmt 14 [115-120]: Semi: Expr 15 [115-119] [Type ()]: Call: + Expr _id_ [115-116] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 16 [115-116] [Type (Int => () is Adj)]: Name: Item 1 + Expr 17 [116-119] [Type Int]: Paren: Expr 18 [117-118] [Type Int]: Lit: Int(1)"#]], + ); +} + +#[test] +fn nested_conjugate_invert() { + check( + indoc! {" + namespace Test { + operation B(i : Int) : Unit is Adj {} + operation A() : Unit { + within { + B(0); + within { + B(1); + B(2); + } + apply { + B(3); + B(4); + } + } + apply { + B(5); + B(6); + } + } + } + "}, + &expect![[r#" + Package: + Item 0 [0-357]: + Namespace (Ident 54 [10-14] "Test"): Item 1, Item 2 + Item 1 [21-58]: + Parent: 0 + Callable 0 [21-58] (Operation): + name: Ident 1 [31-32] "B" + input: Pat 2 [32-41] [Type Int]: Paren: + Pat 3 [33-40] [Type Int]: Bind: Ident 4 [33-34] "i" + output: () + functors: Functor Expr 5 [52-55]: Adj + body: Block: Block 6 [56-58]: + Item 2 [63-355]: + Parent: 0 + Callable 7 [63-355] (Operation): + name: Ident 8 [73-74] "A" + input: Pat 9 [74-76] [Type ()]: Unit + output: () + body: Block: Block 10 [84-355] [Type ()]: + Stmt 11 [94-349]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block _id_ [0-0] [Type ()]: + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 13 [101-287] [Type ()]: + Stmt 14 [115-120]: Semi: Expr 15 [115-119] [Type ()]: Call: + Expr 16 [115-116] [Type (Int => () is Adj)]: Name: Item 1 + Expr 17 [116-119] [Type Int]: Paren: Expr 18 [117-118] [Type Int]: Lit: Int(0) + Stmt 19 [133-277]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block _id_ [0-0] [Type ()]: + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 21 [140-199] [Type ()]: + Stmt 22 [158-163]: Semi: Expr 23 [158-162] [Type ()]: Call: + Expr 24 [158-159] [Type (Int => () is Adj)]: Name: Item 1 + Expr 25 [159-162] [Type Int]: Paren: Expr 26 [160-161] [Type Int]: Lit: Int(1) + Stmt 27 [180-185]: Semi: Expr 28 [180-184] [Type ()]: Call: + Expr 29 [180-181] [Type (Int => () is Adj)]: Name: Item 1 + Expr 30 [181-184] [Type Int]: Paren: Expr 31 [182-183] [Type Int]: Lit: Int(2) + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 32 [218-277] [Type ()]: + Stmt 33 [236-241]: Semi: Expr 34 [236-240] [Type ()]: Call: + Expr 35 [236-237] [Type (Int => () is Adj)]: Name: Item 1 + Expr 36 [237-240] [Type Int]: Paren: Expr 37 [238-239] [Type Int]: Lit: Int(3) + Stmt 38 [258-263]: Semi: Expr 39 [258-262] [Type ()]: Call: + Expr 40 [258-259] [Type (Int => () is Adj)]: Name: Item 1 + Expr 41 [259-262] [Type Int]: Paren: Expr 42 [260-261] [Type Int]: Lit: Int(4) + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 21 [140-199] [Type ()]: + Stmt 27 [180-185]: Semi: Expr 28 [180-184] [Type ()]: Call: + Expr _id_ [180-181] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 29 [180-181] [Type (Int => () is Adj)]: Name: Item 1 + Expr 30 [181-184] [Type Int]: Paren: Expr 31 [182-183] [Type Int]: Lit: Int(2) + Stmt 22 [158-163]: Semi: Expr 23 [158-162] [Type ()]: Call: + Expr _id_ [158-159] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 24 [158-159] [Type (Int => () is Adj)]: Name: Item 1 + Expr 25 [159-162] [Type Int]: Paren: Expr 26 [160-161] [Type Int]: Lit: Int(1) + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 43 [302-349] [Type ()]: + Stmt 44 [316-321]: Semi: Expr 45 [316-320] [Type ()]: Call: + Expr 46 [316-317] [Type (Int => () is Adj)]: Name: Item 1 + Expr 47 [317-320] [Type Int]: Paren: Expr 48 [318-319] [Type Int]: Lit: Int(5) + Stmt 49 [334-339]: Semi: Expr 50 [334-338] [Type ()]: Call: + Expr 51 [334-335] [Type (Int => () is Adj)]: Name: Item 1 + Expr 52 [335-338] [Type Int]: Paren: Expr 53 [336-337] [Type Int]: Lit: Int(6) + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 13 [101-287] [Type ()]: + Stmt 19 [133-277]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block _id_ [0-0] [Type ()]: + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 21 [140-199] [Type ()]: + Stmt 22 [158-163]: Semi: Expr 23 [158-162] [Type ()]: Call: + Expr _id_ [158-159] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr _id_ [158-159] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 24 [158-159] [Type (Int => () is Adj)]: Name: Item 1 + Expr 25 [159-162] [Type Int]: Paren: Expr 26 [160-161] [Type Int]: Lit: Int(1) + Stmt 27 [180-185]: Semi: Expr 28 [180-184] [Type ()]: Call: + Expr _id_ [180-181] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr _id_ [180-181] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 29 [180-181] [Type (Int => () is Adj)]: Name: Item 1 + Expr 30 [181-184] [Type Int]: Paren: Expr 31 [182-183] [Type Int]: Lit: Int(2) + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 32 [218-277] [Type ()]: + Stmt 38 [258-263]: Semi: Expr 39 [258-262] [Type ()]: Call: + Expr _id_ [258-259] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 40 [258-259] [Type (Int => () is Adj)]: Name: Item 1 + Expr 41 [259-262] [Type Int]: Paren: Expr 42 [260-261] [Type Int]: Lit: Int(4) + Stmt 33 [236-241]: Semi: Expr 34 [236-240] [Type ()]: Call: + Expr _id_ [236-237] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 35 [236-237] [Type (Int => () is Adj)]: Name: Item 1 + Expr 36 [237-240] [Type Int]: Paren: Expr 37 [238-239] [Type Int]: Lit: Int(3) + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 21 [140-199] [Type ()]: + Stmt 27 [180-185]: Semi: Expr 28 [180-184] [Type ()]: Call: + Expr _id_ [180-181] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 29 [180-181] [Type (Int => () is Adj)]: Name: Item 1 + Expr 30 [181-184] [Type Int]: Paren: Expr 31 [182-183] [Type Int]: Lit: Int(2) + Stmt 22 [158-163]: Semi: Expr 23 [158-162] [Type ()]: Call: + Expr _id_ [158-159] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 24 [158-159] [Type (Int => () is Adj)]: Name: Item 1 + Expr 25 [159-162] [Type Int]: Paren: Expr 26 [160-161] [Type Int]: Lit: Int(1) + Stmt 14 [115-120]: Semi: Expr 15 [115-119] [Type ()]: Call: + Expr _id_ [115-116] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 16 [115-116] [Type (Int => () is Adj)]: Name: Item 1 + Expr 17 [116-119] [Type Int]: Paren: Expr 18 [117-118] [Type Int]: Lit: Int(0)"#]], + ); +} + +#[test] +fn conjugate_invalid_op_fails() { + check( + indoc! {" + namespace Test { + operation B(i : Int) : Unit {} + operation A() : Unit { + within { + B(1); + B(2); + } + apply { + B(3); + B(4); + } + } + } + "}, + &expect![[r#" + [ + AdjGen( + MissingAdjFunctor( + Span { + lo: 126, + hi: 127, + }, + ), + ), + AdjGen( + MissingAdjFunctor( + Span { + lo: 108, + hi: 109, + }, + ), + ), + ] + "#]], + ); +} + +#[test] +fn conjugate_not_separable_fail() { + check( + indoc! {" + namespace Test { + operation B(i : Int) : Unit is Adj {} + operation A() : Unit { + within { + let x = B(1); + B(2); + } + apply { + B(3); + B(4); + } + } + } + "}, + &expect![[r#" + [ + AdjGen( + LogicSep( + OpCallForbidden( + Span { + lo: 123, + hi: 127, + }, + ), + ), + ), + ] + "#]], + ); +} + +#[test] +fn conjugate_mutable_update_in_apply_fail() { + check( + indoc! {" + namespace Test { + operation B(i : Int) : Unit is Adj {} + operation A() : Unit { + mutable a = 1; + within { + let x = a; + B(2); + } + apply { + set a = 3; + B(4); + } + } + } + "}, + &expect![[r#" + [ + ApplyAssign( + Span { + lo: 209, + hi: 210, + }, + ), + ] + "#]], + ); +} + +#[test] +fn conjugate_mutable_correct_use_succeeds() { + check( + indoc! {" + namespace Test { + operation B(i : Int) : Unit is Adj {} + operation A() : Unit { + mutable a = 1; + within { + let x = a; + B(1); + B(2); + } + apply { + mutable b = a; + set b = 0; + B(3); + B(4); + } + } + } + "}, + &expect![[r#" + Package: + Item 0 [0-314]: + Namespace (Ident 51 [10-14] "Test"): Item 1, Item 2 + Item 1 [21-58]: + Parent: 0 + Callable 0 [21-58] (Operation): + name: Ident 1 [31-32] "B" + input: Pat 2 [32-41] [Type Int]: Paren: + Pat 3 [33-40] [Type Int]: Bind: Ident 4 [33-34] "i" + output: () + functors: Functor Expr 5 [52-55]: Adj + body: Block: Block 6 [56-58]: + Item 2 [63-312]: + Parent: 0 + Callable 7 [63-312] (Operation): + name: Ident 8 [73-74] "A" + input: Pat 9 [74-76] [Type ()]: Unit + output: () + body: Block: Block 10 [84-312] [Type ()]: + Stmt 11 [94-108]: Local (Mutable): + Pat 12 [102-103] [Type Int]: Bind: Ident 13 [102-103] "a" + Expr 14 [106-107] [Type Int]: Lit: Int(1) + Stmt 15 [117-306]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block _id_ [0-0] [Type ()]: + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 17 [124-194] [Type ()]: + Stmt 18 [138-148]: Local (Immutable): + Pat 19 [142-143] [Type Int]: Bind: Ident 20 [142-143] "x" + Expr 21 [146-147] [Type Int]: Name: Local 13 + Stmt 22 [161-166]: Semi: Expr 23 [161-165] [Type ()]: Call: + Expr 24 [161-162] [Type (Int => () is Adj)]: Name: Item 1 + Expr 25 [162-165] [Type Int]: Paren: Expr 26 [163-164] [Type Int]: Lit: Int(1) + Stmt 27 [179-184]: Semi: Expr 28 [179-183] [Type ()]: Call: + Expr 29 [179-180] [Type (Int => () is Adj)]: Name: Item 1 + Expr 30 [180-183] [Type Int]: Paren: Expr 31 [181-182] [Type Int]: Lit: Int(2) + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 32 [209-306] [Type ()]: + Stmt 33 [223-237]: Local (Mutable): + Pat 34 [231-232] [Type Int]: Bind: Ident 35 [231-232] "b" + Expr 36 [235-236] [Type Int]: Name: Local 13 + Stmt 37 [250-260]: Semi: Expr 38 [250-259] [Type ()]: Assign: + Expr 39 [254-255] [Type Int]: Name: Local 35 + Expr 40 [258-259] [Type Int]: Lit: Int(0) + Stmt 41 [273-278]: Semi: Expr 42 [273-277] [Type ()]: Call: + Expr 43 [273-274] [Type (Int => () is Adj)]: Name: Item 1 + Expr 44 [274-277] [Type Int]: Paren: Expr 45 [275-276] [Type Int]: Lit: Int(3) + Stmt 46 [291-296]: Semi: Expr 47 [291-295] [Type ()]: Call: + Expr 48 [291-292] [Type (Int => () is Adj)]: Name: Item 1 + Expr 49 [292-295] [Type Int]: Paren: Expr 50 [293-294] [Type Int]: Lit: Int(4) + Stmt _id_ [0-0]: Expr: Expr _id_ [0-0] [Type ()]: Expr Block: Block 17 [124-194] [Type ()]: + Stmt 18 [138-148]: Local (Immutable): + Pat 19 [142-143] [Type Int]: Bind: Ident 20 [142-143] "x" + Expr 21 [146-147] [Type Int]: Name: Local 13 + Stmt 27 [179-184]: Semi: Expr 28 [179-183] [Type ()]: Call: + Expr _id_ [179-180] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 29 [179-180] [Type (Int => () is Adj)]: Name: Item 1 + Expr 30 [180-183] [Type Int]: Paren: Expr 31 [181-182] [Type Int]: Lit: Int(2) + Stmt 22 [161-166]: Semi: Expr 23 [161-165] [Type ()]: Call: + Expr _id_ [161-162] [Type (Int => () is Adj)]: UnOp (Functor Adj): + Expr 24 [161-162] [Type (Int => () is Adj)]: Name: Item 1 + Expr 25 [162-165] [Type Int]: Paren: Expr 26 [163-164] [Type Int]: Lit: Int(1)"#]], + ); +} diff --git a/compiler/qsc_passes/src/lib.rs b/compiler/qsc_passes/src/lib.rs index fc64c73aeb..55099ad470 100644 --- a/compiler/qsc_passes/src/lib.rs +++ b/compiler/qsc_passes/src/lib.rs @@ -3,6 +3,7 @@ #![warn(clippy::mod_module_files, clippy::pedantic, clippy::unwrap_used)] +pub mod conjugate_invert; pub mod entry_point; mod invert_block; mod logic_sep; @@ -18,6 +19,7 @@ use thiserror::Error; pub enum Error { EntryPoint(entry_point::Error), SpecGen(spec_gen::Error), + ConjInvert(conjugate_invert::Error), } /// Run the default set of passes required for evaluation. @@ -30,5 +32,11 @@ pub fn run_default_passes(unit: &mut CompileUnit) -> Vec { .map(Error::SpecGen), ); + errors.extend( + conjugate_invert::invert_conjugate_exprs(unit) + .into_iter() + .map(Error::ConjInvert), + ); + errors } diff --git a/compiler/qsc_passes/src/spec_gen.rs b/compiler/qsc_passes/src/spec_gen.rs index f43f33ee63..9ef1c261d2 100644 --- a/compiler/qsc_passes/src/spec_gen.rs +++ b/compiler/qsc_passes/src/spec_gen.rs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -mod adj_gen; +pub(crate) mod adj_gen; mod ctl_gen; #[cfg(test)] diff --git a/compiler/qsc_passes/src/spec_gen/adj_gen.rs b/compiler/qsc_passes/src/spec_gen/adj_gen.rs index 5a904ba574..5b5d95cb71 100644 --- a/compiler/qsc_passes/src/spec_gen/adj_gen.rs +++ b/compiler/qsc_passes/src/spec_gen/adj_gen.rs @@ -21,8 +21,8 @@ pub enum Error { LogicSep(logic_sep::Error), } -pub(super) struct AdjDistrib { - pub(super) errors: Vec, +pub(crate) struct AdjDistrib { + pub(crate) errors: Vec, } impl MutVisitor for AdjDistrib { diff --git a/katas/content/single_qubit_gates/global_phase_i/verify.qs b/katas/content/single_qubit_gates/global_phase_i/verify.qs index fcf733c897..f4804bca29 100644 --- a/katas/content/single_qubit_gates/global_phase_i/verify.qs +++ b/katas/content/single_qubit_gates/global_phase_i/verify.qs @@ -17,10 +17,13 @@ namespace Kata { // Explicit scopes are used to make output from DumpMachine calls more useful. { use (ctl, target) = (Qubit(), Qubit()); - H(ctl); - Controlled task([ctl], target); - Adjoint Controlled taskRef([ctl], target); - H(ctl); + within { + H(ctl); + } + apply { + Controlled task([ctl], target); + Adjoint Controlled taskRef([ctl], target); + } set isCorrect = CheckAllZero([ctl, target]); ResetAll([ctl, target]); } diff --git a/katas/content/single_qubit_gates/y_gate/verify.qs b/katas/content/single_qubit_gates/y_gate/verify.qs index 817f55428f..b99003361a 100644 --- a/katas/content/single_qubit_gates/y_gate/verify.qs +++ b/katas/content/single_qubit_gates/y_gate/verify.qs @@ -15,10 +15,13 @@ namespace Kata { // Explicit scopes are used to make output from DumpMachine calls more useful. { use (ctl, target) = (Qubit(), Qubit()); - H(ctl); - Controlled task([ctl], target); - Adjoint Controlled taskRef([ctl], target); - H(ctl); + within { + H(ctl); + } + apply { + Controlled task([ctl], target); + Adjoint Controlled taskRef([ctl], target); + } set isCorrect = CheckAllZero([ctl, target]); ResetAll([ctl, target]); } diff --git a/samples/Teleportation.qs b/samples/Teleportation.qs index b3dee25f52..8cdedbc3e6 100644 --- a/samples/Teleportation.qs +++ b/samples/Teleportation.qs @@ -47,9 +47,9 @@ namespace Microsoft.Quantum.Samples.Teleportation { // Measure the qubits to extract the classical data we need to // decode the message by applying the corrections on // the target qubit accordingly. - if (M(msg) == One) { Z(target); } + if M(msg) == One { Z(target); } // Correction step - if (M(register) == One) { + if M(register) == One { X(target); // Reset register to Zero state before releasing X(register); @@ -78,7 +78,7 @@ namespace Microsoft.Quantum.Samples.Teleportation { use (msg, target) = (Qubit(), Qubit()); // Encode the message we want to send. - if (message) { + if message { X(msg); } @@ -113,23 +113,13 @@ namespace Microsoft.Quantum.Samples.Teleportation { /// # Summary /// Returns true if qubit is |+⟩ (assumes qubit is either |+⟩ or |−⟩) operation MeasureIsPlus(q: Qubit) : Bool { - // BLOCKED ON: within implementation. Measure, MapPauli. - // return (Measure([PauliX], [q]) == Zero); - H(q); - let result = M(q) == Zero; - H(q); - return result; + Measure([PauliX], [q]) == Zero } /// # Summary /// Returns true if qubit is |−⟩ (assumes qubit is either |+> or |−⟩) operation MeasureIsMinus(q: Qubit) : Bool { - // BLOCKED ON: within implementation. Measure, MapPauli. - // return (Measure([PauliX], [q]) == One); - H(q); - let result = M(q) == One; - H(q); - return result; + Measure([PauliX], [q]) == One } /// # Summary @@ -137,7 +127,7 @@ namespace Microsoft.Quantum.Samples.Teleportation { operation PrepareRandomMessage(q: Qubit) : Unit { let choice = DrawRandomInt(0, 1) == 1; - if (choice) { + if choice { Message("Sending |->"); SetToMinus(q); } else { @@ -163,8 +153,8 @@ namespace Microsoft.Quantum.Samples.Teleportation { Teleport(msg, target); // Report message received: - if (MeasureIsPlus(target)) { Message("Received |+>"); } - if (MeasureIsMinus(target)) { Message("Received |->"); } + if MeasureIsPlus(target) { Message("Received |+>"); } + if MeasureIsMinus(target) { Message("Received |->"); } // Reset all of the qubits that we used before releasing // them.