From 77df473595a85a9352878c187321f7c58e1111e9 Mon Sep 17 00:00:00 2001 From: Mathias Soeken Date: Wed, 6 Apr 2022 18:52:37 +0200 Subject: [PATCH 1/2] Implements #442. --- .../src/Canon/Combinators/SinglyControlled.qs | 68 +++++++++++++++++++ .../Canon/Combinators/SinglyControlled.qs | 28 ++++++++ 2 files changed, 96 insertions(+) create mode 100644 Standard/src/Canon/Combinators/SinglyControlled.qs create mode 100644 Standard/tests/Canon/Combinators/SinglyControlled.qs diff --git a/Standard/src/Canon/Combinators/SinglyControlled.qs b/Standard/src/Canon/Combinators/SinglyControlled.qs new file mode 100644 index 00000000000..87a0e6d6c2f --- /dev/null +++ b/Standard/src/Canon/Combinators/SinglyControlled.qs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Canon { + + /// # Summary + /// Given a controllable operation, returns a controlled version of that operation + /// accepting exactly one control qubit. + /// + /// # Input + /// ## op + /// The operation to be controlled. + /// + /// # Output + /// A controlled variant of `op` accepting exactly one control qubit. + /// + /// # Example + /// To add the weight (number of "1" bits) of a control register to + /// a target register: + /// ```qsharp + /// ApplyToEachCA( + /// SinglyControlled(IncrementByInteger)(_, (1, target)), + /// controls) + /// ); + /// ``` + /// + /// # See Also + /// - Microsoft.Quantum.Canon.SinglyControlledA + function SinglyControlled<'T>(op : 'T => Unit is Ctl) : (Qubit, 'T) => Unit is Ctl { + return ApplySinglyControlled(op, _, _); + } + + internal operation ApplySinglyControlled<'T>(op : 'T => Unit is Ctl, ctl : Qubit, target : 'T) : Unit is Ctl { + Controlled op([ctl], target); + } + + /// # Summary + /// Given a controllable operation, returns a controlled version of that operation + /// accepting exactly one control qubit. + /// + /// # Input + /// ## op + /// The operation to be controlled. + /// + /// # Output + /// A controlled variant of `op` accepting exactly one control qubit. + /// + /// # Example + /// To add the weight (number of "1" bits) of a control register to + /// a target register: + /// ```qsharp + /// ApplyToEachCA( + /// SinglyControlledA(IncrementByInteger)(_, (1, target)), + /// controls) + /// ); + /// ``` + /// + /// # See Also + /// - Microsoft.Quantum.Canon.SinglyControlled + function SinglyControlledA<'T>(op : 'T => Unit is Adj + Ctl) : (Qubit, 'T) => Unit is Adj + Ctl { + return ApplySinglyControlledA(op, _, _); + } + + internal operation ApplySinglyControlledA<'T>(op : 'T => Unit is Adj + Ctl, ctl : Qubit, target : 'T) : Unit is Adj + Ctl { + Controlled op([ctl], target); + } + +} diff --git a/Standard/tests/Canon/Combinators/SinglyControlled.qs b/Standard/tests/Canon/Combinators/SinglyControlled.qs new file mode 100644 index 00000000000..ea98cdb234c --- /dev/null +++ b/Standard/tests/Canon/Combinators/SinglyControlled.qs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Tests { + open Microsoft.Quantum.Arithmetic; + open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Intrinsic; + + @Test("ToffoliSimulator") + operation TestSinglyControlled() : Unit { + use ctl = Qubit(); + use target = Qubit[3]; + let targetLE = LittleEndian(target); + let value = 5; + + for singlyControlled in [SinglyControlled, SinglyControlledA] { + for enableControl in [false, true] { + within { + ApplyIfA(enableControl, X, ctl); + } apply { + singlyControlled(ApplyXorInPlace(value, _))(ctl, targetLE); + EqualityFactI(MeasureInteger(targetLE), enableControl ? value | 0, "Unexpected measurement result for SinglyControlled"); + } + } + } + } +} From 4cf9e680d97f23326032cfe673eaefbe28c7e1d0 Mon Sep 17 00:00:00 2001 From: Mathias Soeken Date: Wed, 6 Apr 2022 20:51:04 +0200 Subject: [PATCH 2/2] Address reviewer feedback. --- Standard/src/Canon/Combinators/SinglyControlled.qs | 12 ++---------- Standard/tests/Canon/Combinators/SinglyControlled.qs | 10 +++++++++- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Standard/src/Canon/Combinators/SinglyControlled.qs b/Standard/src/Canon/Combinators/SinglyControlled.qs index 87a0e6d6c2f..29dc8c2d789 100644 --- a/Standard/src/Canon/Combinators/SinglyControlled.qs +++ b/Standard/src/Canon/Combinators/SinglyControlled.qs @@ -27,11 +27,7 @@ namespace Microsoft.Quantum.Canon { /// # See Also /// - Microsoft.Quantum.Canon.SinglyControlledA function SinglyControlled<'T>(op : 'T => Unit is Ctl) : (Qubit, 'T) => Unit is Ctl { - return ApplySinglyControlled(op, _, _); - } - - internal operation ApplySinglyControlled<'T>(op : 'T => Unit is Ctl, ctl : Qubit, target : 'T) : Unit is Ctl { - Controlled op([ctl], target); + return (ctrl, originalInput) => Controlled op([ctrl], originalInput); } /// # Summary @@ -58,11 +54,7 @@ namespace Microsoft.Quantum.Canon { /// # See Also /// - Microsoft.Quantum.Canon.SinglyControlled function SinglyControlledA<'T>(op : 'T => Unit is Adj + Ctl) : (Qubit, 'T) => Unit is Adj + Ctl { - return ApplySinglyControlledA(op, _, _); - } - - internal operation ApplySinglyControlledA<'T>(op : 'T => Unit is Adj + Ctl, ctl : Qubit, target : 'T) : Unit is Adj + Ctl { - Controlled op([ctl], target); + return (ctrl, originalInput) => Controlled op([ctrl], originalInput); } } diff --git a/Standard/tests/Canon/Combinators/SinglyControlled.qs b/Standard/tests/Canon/Combinators/SinglyControlled.qs index ea98cdb234c..a3649328b66 100644 --- a/Standard/tests/Canon/Combinators/SinglyControlled.qs +++ b/Standard/tests/Canon/Combinators/SinglyControlled.qs @@ -8,7 +8,7 @@ namespace Microsoft.Quantum.Tests { open Microsoft.Quantum.Intrinsic; @Test("ToffoliSimulator") - operation TestSinglyControlled() : Unit { + operation TestSinglyControlledWithSimulation() : Unit { use ctl = Qubit(); use target = Qubit[3]; let targetLE = LittleEndian(target); @@ -25,4 +25,12 @@ namespace Microsoft.Quantum.Tests { } } } + + @Test("QuantumSimulator") + operation TestSinglyControlledWithEquivalenceCheck() : Unit { + AssertOperationsEqualReferenced(2, + qs => SinglyControlled(H)(qs[0], qs[1]), + qs => Controlled H([qs[0]], qs[1]) + ); + } }