diff --git a/Standard/src/Canon/Combinators/SinglyControlled.qs b/Standard/src/Canon/Combinators/SinglyControlled.qs new file mode 100644 index 00000000000..29dc8c2d789 --- /dev/null +++ b/Standard/src/Canon/Combinators/SinglyControlled.qs @@ -0,0 +1,60 @@ +// 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 (ctrl, originalInput) => Controlled op([ctrl], originalInput); + } + + /// # 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 (ctrl, originalInput) => Controlled op([ctrl], originalInput); + } + +} diff --git a/Standard/tests/Canon/Combinators/SinglyControlled.qs b/Standard/tests/Canon/Combinators/SinglyControlled.qs new file mode 100644 index 00000000000..a3649328b66 --- /dev/null +++ b/Standard/tests/Canon/Combinators/SinglyControlled.qs @@ -0,0 +1,36 @@ +// 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 TestSinglyControlledWithSimulation() : 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"); + } + } + } + } + + @Test("QuantumSimulator") + operation TestSinglyControlledWithEquivalenceCheck() : Unit { + AssertOperationsEqualReferenced(2, + qs => SinglyControlled(H)(qs[0], qs[1]), + qs => Controlled H([qs[0]], qs[1]) + ); + } +}