From 551acb8c6c7e6246b1a98db17488144e2709ec8b Mon Sep 17 00:00:00 2001 From: Mariia Mykhailova Date: Tue, 3 Dec 2019 10:04:10 -0800 Subject: [PATCH 01/11] Clarify the restriction on the number of bits for IntAsBoolArray (#171) * Clarify the restriction on the number of bits for IntAsBoolArray This should fix #166 by providing a more specific error message. * Update Standard/src/Convert/Convert.qs Co-Authored-By: Chris Granade * Allow to have bits = 0 Looks like our tests assume that number = 0 with bits = 0 is a valid scenario; updating the change to account for that --- Standard/src/Convert/Convert.qs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Standard/src/Convert/Convert.qs b/Standard/src/Convert/Convert.qs index b69b24bd51d..85a89b88367 100644 --- a/Standard/src/Convert/Convert.qs +++ b/Standard/src/Convert/Convert.qs @@ -76,8 +76,10 @@ namespace Microsoft.Quantum.Convert { /// An array of boolean values representing `number`. /// /// # Remarks - /// The input `number` must be at most $2^{\texttt{bits}} - 1$. + /// The input `bits` must be between 0 and 63. + /// The input `number` must be between 0 and $2^{\texttt{bits}} - 1$. function IntAsBoolArray(number : Int, bits : Int) : Bool[] { + Fact(bits >= 0 and bits <= 63, $"`bits` must be between 0 and 63 {2^bits}"); EqualityFactB(number >= 0 and number < 2 ^ bits, true, $"`number` must be between 0 and 2^`bits` - 1"); mutable outputBits = new Bool[bits]; mutable tempInt = number; From d746df20ce7e3673b4c4e7fb66a0e6baa447d5a6 Mon Sep 17 00:00:00 2001 From: bettinaheim <34236215+bettinaheim@users.noreply.github.com> Date: Thu, 12 Dec 2019 20:27:22 -0800 Subject: [PATCH 02/11] Package updates (#188) --- Chemistry/src/DataModel/DataModel.csproj | 8 ++++---- Chemistry/src/Jupyter/Jupyter.csproj | 8 ++++---- Chemistry/src/Runtime/Runtime.csproj | 2 +- Chemistry/tests/ChemistryTests/QSharpTests.csproj | 13 ++++++++----- Chemistry/tests/DataModelTests/CSharpTests.csproj | 15 +++++++++------ Chemistry/tests/JupyterTests/JupyterTests.csproj | 9 ++++++--- Chemistry/tests/SamplesTests/SamplesTests.csproj | 15 +++++++++------ .../SerializationTests/SerializationTests.csproj | 11 +++++++---- Chemistry/tests/SystemTests/SystemTests.csproj | 13 ++++++++----- Numerics/src/Numerics.csproj | 4 ++-- Numerics/tests/NumericsTests.csproj | 13 ++++++++----- Standard/src/Standard.csproj | 7 ++----- Standard/tests/Standard.Tests.csproj | 10 +++++----- 13 files changed, 73 insertions(+), 55 deletions(-) diff --git a/Chemistry/src/DataModel/DataModel.csproj b/Chemistry/src/DataModel/DataModel.csproj index 14086f84be6..6c787137998 100644 --- a/Chemistry/src/DataModel/DataModel.csproj +++ b/Chemistry/src/DataModel/DataModel.csproj @@ -35,9 +35,9 @@ - - - + + + @@ -53,6 +53,6 @@ - + diff --git a/Chemistry/src/Jupyter/Jupyter.csproj b/Chemistry/src/Jupyter/Jupyter.csproj index 57c676d8836..da3e74cc8e6 100644 --- a/Chemistry/src/Jupyter/Jupyter.csproj +++ b/Chemistry/src/Jupyter/Jupyter.csproj @@ -26,9 +26,9 @@ - - - + + + @@ -38,6 +38,6 @@ - + diff --git a/Chemistry/src/Runtime/Runtime.csproj b/Chemistry/src/Runtime/Runtime.csproj index 442a13d14c9..2dfbcf8f9c0 100644 --- a/Chemistry/src/Runtime/Runtime.csproj +++ b/Chemistry/src/Runtime/Runtime.csproj @@ -15,7 +15,7 @@ - + diff --git a/Chemistry/tests/ChemistryTests/QSharpTests.csproj b/Chemistry/tests/ChemistryTests/QSharpTests.csproj index 66e2888e2c0..573b654a2b9 100644 --- a/Chemistry/tests/ChemistryTests/QSharpTests.csproj +++ b/Chemistry/tests/ChemistryTests/QSharpTests.csproj @@ -10,11 +10,14 @@ - - - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Chemistry/tests/DataModelTests/CSharpTests.csproj b/Chemistry/tests/DataModelTests/CSharpTests.csproj index 9c3df4a3cce..f8af284a8e0 100644 --- a/Chemistry/tests/DataModelTests/CSharpTests.csproj +++ b/Chemistry/tests/DataModelTests/CSharpTests.csproj @@ -23,12 +23,15 @@ - - - - - - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Chemistry/tests/JupyterTests/JupyterTests.csproj b/Chemistry/tests/JupyterTests/JupyterTests.csproj index 4b322d832da..bb21b47bf52 100644 --- a/Chemistry/tests/JupyterTests/JupyterTests.csproj +++ b/Chemistry/tests/JupyterTests/JupyterTests.csproj @@ -17,10 +17,13 @@ - + - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Chemistry/tests/SamplesTests/SamplesTests.csproj b/Chemistry/tests/SamplesTests/SamplesTests.csproj index af9581bbb83..cdbfc4688ae 100644 --- a/Chemistry/tests/SamplesTests/SamplesTests.csproj +++ b/Chemistry/tests/SamplesTests/SamplesTests.csproj @@ -17,12 +17,15 @@ - - - - - - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Chemistry/tests/SerializationTests/SerializationTests.csproj b/Chemistry/tests/SerializationTests/SerializationTests.csproj index daab1c45c20..ff8ea481ff9 100644 --- a/Chemistry/tests/SerializationTests/SerializationTests.csproj +++ b/Chemistry/tests/SerializationTests/SerializationTests.csproj @@ -16,10 +16,13 @@ - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Chemistry/tests/SystemTests/SystemTests.csproj b/Chemistry/tests/SystemTests/SystemTests.csproj index 0da8e8b4d71..f5970bf9457 100644 --- a/Chemistry/tests/SystemTests/SystemTests.csproj +++ b/Chemistry/tests/SystemTests/SystemTests.csproj @@ -17,11 +17,14 @@ - - - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Numerics/src/Numerics.csproj b/Numerics/src/Numerics.csproj index fe72ffe01c3..53c33d5ee9c 100644 --- a/Numerics/src/Numerics.csproj +++ b/Numerics/src/Numerics.csproj @@ -30,10 +30,10 @@ - + - + diff --git a/Numerics/tests/NumericsTests.csproj b/Numerics/tests/NumericsTests.csproj index 3f1f62f3317..e8c9b86e785 100644 --- a/Numerics/tests/NumericsTests.csproj +++ b/Numerics/tests/NumericsTests.csproj @@ -15,11 +15,14 @@ - - - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index f32f4c1fdf1..5a44aad43cb 100644 --- a/Standard/src/Standard.csproj +++ b/Standard/src/Standard.csproj @@ -30,10 +30,7 @@ - - - - - + + diff --git a/Standard/tests/Standard.Tests.csproj b/Standard/tests/Standard.Tests.csproj index 771ff3c378a..0be3d1c80a1 100644 --- a/Standard/tests/Standard.Tests.csproj +++ b/Standard/tests/Standard.Tests.csproj @@ -20,11 +20,11 @@ - - - - - + + + + + From 6c9561ac8143b5b2b1790b2525c2a8071afc90ff Mon Sep 17 00:00:00 2001 From: Mathias Soeken Date: Thu, 19 Dec 2019 02:47:55 +0100 Subject: [PATCH 03/11] Quantum AND gates (a.k.a. CCNOT with constant target) (#186) * Two AND gate implementations. * Added test case. * Formatting. * Code formatting. * Update Standard/src/Canon/And.qs Co-Authored-By: Chris Granade * Assertion for 0-target. * Added DOI to references. * Named application for CCNOTop. * Rename operations. * Add Test attribute. * Add links to arXiv. * Rename operations. * Better assertion for 0-target. * Fix bug in LowDepthAnd. * Docs. * Doc string convention. * Controlled variant for `ApplyAnd`. * Controlled AndLowDepth. * Adjoint Controlled LowDepthAnd. * References. * Simplify code. * Apply suggestions from code review Co-Authored-By: Chris Granade * Integrate comment. --- Standard/src/Canon/And.qs | 367 ++++++++++++++++++ .../Canon/Combinators/ApplyMultiControlled.qs | 6 +- Standard/tests/ANDTests.qs | 73 ++++ 3 files changed, 443 insertions(+), 3 deletions(-) create mode 100644 Standard/src/Canon/And.qs create mode 100644 Standard/tests/ANDTests.qs diff --git a/Standard/src/Canon/And.qs b/Standard/src/Canon/And.qs new file mode 100644 index 00000000000..c1c3eec25d2 --- /dev/null +++ b/Standard/src/Canon/And.qs @@ -0,0 +1,367 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Canon { + open Microsoft.Quantum.Arrays; + open Microsoft.Quantum.Convert; + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Math; + open Microsoft.Quantum.Measurement; + + /// # Summary + /// Inverts a given target qubit if and only if both control qubits are in the 1 state, + /// using measurement to perform the adjoint operation. + /// + /// # Description + /// Inverts `target` if and only if both controls are 1, but assumes that + /// `target` is in state 0. The operation has T-count 4, T-depth 2 and + /// requires no helper qubit, and may therefore be preferable to a CCNOT + /// operation, if `target` is known to be 0. The adjoint of this operation + /// is measurement based and requires no T gates. + /// + /// The controlled application of this operation requires no helper qubit, + /// `2^c` `Rz` gates and is not optimized for depth, where `c` is the number + /// of overall control qubits including the two controls from the `ApplyAnd` + /// operation. The adjoint controlled application requires `2^c - 1` `Rz` + /// gates (with an angle twice the size of the non-adjoint operation), no + /// helper qubit and is not optimized for depth. + /// + /// # Input + /// ## control1 + /// First control qubit + /// ## control2 + /// Second control qubit + /// ## target + /// Target auxillary qubit; must be in state 0 + /// + /// # References + /// - Cody Jones: "Novel constructions for the fault-tolerant Toffoli gate", + /// Phys. Rev. A 87, 022328, 2013 + /// [arXiv:1212.5069](https://arxiv.org/abs/1212.5069) + /// doi:10.1103/PhysRevA.87.022328 + /// - Craig Gidney: "Halving the cost of quantum addition", Quantum 2, page + /// 74, 2018 + /// [arXiv:1709.06648](https://arxiv.org/abs/1709.06648) + /// doi:10.1103/PhysRevA.85.044302 + /// - Mathias Soeken: "Quantum Oracle Circuits and the Christmas Tree Pattern", + /// [Blog article from Decemer 19, 2019](https://msoeken.github.io/blog_qac.html) + /// (note: explains the multiple controlled construction) + operation ApplyAnd(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit { + body (...) { + AssertAllZero([target]); + H(target); + T(target); + CNOT(control1, target); + CNOT(control2, target); + within { + CNOT(target, control1); + CNOT(target, control2); + } + apply { + Adjoint T(control1); + Adjoint T(control2); + T(target); + } + HY(target); + } + adjoint (...) { + H(target); + AssertProb([PauliZ], [target], One, 0.5, "Probability of the measurement must be 0.5", 1e-10); + if (IsResultOne(MResetZ(target))) { + CZ(control1, control2); + } + } + controlled (controls, ...) { + _ApplyMultipleControlledAnd(controls + [control1, control2], target); + } + adjoint controlled (controls, ...) { + Adjoint _ApplyMultipleControlledAnd(controls + [control1, control2], target); + } + } + + /// # Summary + /// Inverts a given target qubit if and only if both control qubits are in + /// the 1 state, with T-depth 1, using measurement to perform the adjoint + /// operation. + /// + /// # Description + /// Inverts `target` if and only if both controls are 1, but assumes that + /// `target` is in state 0. The operation has T-count 4, T-depth 1 and + /// requires one helper qubit, and may therefore be preferable to a CCNOT + /// operation, if `target` is known to be 0. The adjoint of this operation + /// is measurement based and requires no T gates, and no helper qubit. + /// + /// # Input + /// ## control1 + /// First control qubit + /// ## control2 + /// Second control qubit + /// ## target + /// Target auxillary qubit; must be in state 0 + /// + /// # References + /// - Cody Jones: "Novel constructions for the fault-tolerant Toffoli gate", + /// Phys. Rev. A 87, 022328, 2013 + /// [arXiv:1212.5069](https://arxiv.org/abs/1212.5069) + /// doi:10.1103/PhysRevA.87.022328 + /// - Peter Selinger: "Quantum circuits of T-depth one", + /// Phys. Rev. A 87, 042302, 2013 + /// [arXiv:1210.0974](https://arxiv.org/abs/1210.0974) + /// doi:10.1103/PhysRevA.87.042302 + operation ApplyLowDepthAnd(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit { + body (...) { + using (helper = Qubit()) { + AssertAllZero([target]); + H(target); + within { + CNOT(target, control1); + CNOT(control1, helper); + CNOT(control2, helper); + CNOT(target, control2); + } + apply { + Adjoint T(control1); + Adjoint T(control2); + T(target); + T(helper); + } + HY(target); + } + } + adjoint (...) { + Adjoint ApplyAnd(control1, control2, target); + } + controlled (controls, ...) { + _ApplyMultipleControlledLowDepthAnd(controls + [control1, control2], target); + } + adjoint controlled (controls, ...) { + Adjoint _ApplyMultipleControlledLowDepthAnd(controls + [control1, control2], target); + } + } + + /// # Summary + /// Creates Gray code sequences + /// + /// # Input + /// ## n + /// Number of bits + /// + /// # Output + /// Array of tuples. First value in tuple is value in GrayCode sequence + /// Second value in tuple is position to change in current value to get + /// next one. + /// + /// # Example + /// ```Q# + /// _GrayCode(2); // [(0, 0),(1, 1),(3, 0),(2, 1)] + /// ``` + function _GrayCode(n : Int) : (Int, Int)[] { + let N = 1 <<< n; + + mutable res = new (Int, Int)[N]; + mutable j = 0; + mutable current = IntAsBoolArray(0, n); + + for (i in 0..N - 1) { + if (i % 2 == 0) { + set j = 0; + } else { + let e = Zip(current, RangeAsIntArray(0..N - 1)); + set j = Snd(Head(Filtered(Fst, e))) + 1; + } + + set j = MaxI(0, Min([j, n - 1])); + set res w/= i <- (BoolArrayAsInt(current), j); + if (j < n) { + set current w/= j <- not current[j]; + } + } + + return res; + } + + /// # Summary + /// Computes the Hamming weight of an integer, i.e., the number of 1s in its + /// binary expansion. + /// + /// # Input + /// ## number + /// Number to compute Hamming weight + /// # Output + /// Hamming weight of the number + function _HammingWeightI(number : Int) : Int { + mutable cnt = number; + set cnt = (cnt &&& 0x5555555555555555) + ((cnt >>> 1) &&& 0x5555555555555555); + set cnt = (cnt &&& 0x3333333333333333) + ((cnt >>> 2) &&& 0x3333333333333333); + set cnt = (cnt &&& 0x0f0f0f0f0f0f0f0f) + ((cnt >>> 4) &&& 0x0f0f0f0f0f0f0f0f); + set cnt = (cnt &&& 0x00ff00ff00ff00ff) + ((cnt >>> 8) &&& 0x00ff00ff00ff00ff); + set cnt = (cnt &&& 0x0000ffff0000ffff) + ((cnt >>> 16) &&& 0x0000ffff0000ffff); + set cnt = (cnt &&& 0x00000000ffffffff) + ((cnt >>> 32) &&& 0x00000000ffffffff); + return cnt; + } + + /// # Summary + /// Returns 1, if `index` has an odd number of 1s and -1, if `index` has an + /// even number of 1s. + /// + /// # Description + /// Value corresponds to the sign of the coefficient of the Rademacher-Walsh + /// spectrum of the n-variable AND function for a given assignment that + /// decides the angle of the rotation. + /// + /// # Input + /// ## index + /// Input assignment as integer (from 0 to 2^n - 1) + function _Angle(index : Int) : Int { + return _HammingWeightI(index) % 2 == 1 ? 1 | -1; + } + + /// # Summary + /// Implements a multiple-controlled Toffoli gate, assuming that target + /// qubit is initialized 0. The adjoint operation assumes that the target + /// qubit will be released to 0. + /// + /// # Input + /// ## controls + /// Control qubits + /// ## target + /// Target qubit + operation _ApplyMultipleControlledAnd(controls : Qubit[], target : Qubit) : Unit { + body (...) { + let vars = Length(controls); + + AssertAllZero([target]); + + H(target); + + let code = _GrayCode(vars); + for (j in 0..Length(code) - 1) { + let (offset, ctrl) = code[j]; + RFrac(PauliZ, _Angle(offset), vars + 1, target); + CNOT(controls[ctrl], target); + } + + HY(target); + } + adjoint (...) { + let vars = Length(controls); + + H(target); + AssertProb([PauliZ], [target], One, 0.5, "Probability of the measurement must be 0.5", 1e-10); + if (IsResultOne(MResetZ(target))) { + for (i in 0..vars - 1) { + let start = 1 <<< i; + let code = _GrayCode(i); + for (j in 0..Length(code) - 1) { + let (offset, ctrl) = code[j]; + RFrac(PauliZ, -_Angle(start + offset), vars, controls[i]); + if (i != 0) { + CNOT(controls[ctrl], controls[i]); + } + } + } + } + } + } + + /// # Summary + /// Arrange control, target, and helper qubits according to an index + /// + /// # Description + /// Returns a Qubit array with target at index 0, and control i at index + /// 2^i. The helper qubits are inserted to all other positions in the + /// array. + function _ArrangeQubits(controls : Qubit[], target : Qubit, helper : Qubit[]) : Qubit[] { + let numControls = Length(controls); + mutable qs = new Qubit[2^numControls] w/ 0 <- target; + mutable cntC = 0; + mutable cntH = 0; + for (i in 1..2^numControls - 1) { + if (i == (i &&& -i)) { + set qs w/= i <- controls[cntC]; + set cntC += 1; + } else { + set qs w/= i <- helper[cntH]; + set cntH += 1; + } + } + return qs; + } + + /// # Summary + /// Implements a multiple-controlled Toffoli gate, assuming that target + /// qubit is initialized 0. The adjoint operation assumes that the target + /// qubit will be released to 0. Requires a Rz depth of 1, while the number + /// of helper qubits are exponential in the number of qubits. + /// + /// # Input + /// ## controls + /// Control qubits + /// ## target + /// Target qubit + operation _ApplyMultipleControlledLowDepthAnd(controls : Qubit[], target : Qubit) : Unit { + body (...) { + let vars = Length(controls); + using (helper = Qubit[2^vars - vars - 1]) { + let qs = _ArrangeQubits(controls, target, helper); + + AssertAllZero([target]); + H(target); + + within { + // initialize helper lines with control lines based on LSB + for (i in 3..2^vars - 1) { + let lsb = i &&& -i; + if (i != lsb) { // i is power of 2 + CNOT(qs[lsb], qs[i]); + } + } + // target to control + ApplyToEachA(CNOT(target, _), controls); + // copy remainder (without LSB) + for (i in 3..2^vars - 1) { + let lsb = i &&& -i; + if (i != lsb) { + CNOT(qs[i - lsb], qs[i]); + } + } + } apply { + for (i in IndexRange(qs)) { + RFrac(PauliZ, _Angle(i), vars + 1, qs[i]); + } + } + + HY(target); + } + } + adjoint (...) { + let vars = Length(controls); + + H(target); + AssertProb([PauliZ], [target], One, 0.5, "Probability of the measurement must be 0.5", 1e-10); + if (IsResultOne(MResetZ(target))) { + using (helper = Qubit[2^vars - vars - 1]) { + let qs = _ArrangeQubits(controls, target, helper); + within { + // this is a bit easier than in the compute part, since + // the target qubit does not have to be copied over to + // the control lines. Therefore, the two LSB CNOT parts + // can be merged into a single loop. + for (i in 3..2^vars - 1) { + let lsb = i &&& -i; + if (i != lsb) { + CNOT(qs[lsb], qs[i]); + CNOT(qs[i - lsb], qs[i]); + } + } + } apply { + for (i in 1..2^vars - 1) { + RFrac(PauliZ, -_Angle(i), vars, qs[i]); + } + } + } + } + } + } +} diff --git a/Standard/src/Canon/Combinators/ApplyMultiControlled.qs b/Standard/src/Canon/Combinators/ApplyMultiControlled.qs index 89bddccafab..ab207594dff 100644 --- a/Standard/src/Canon/Combinators/ApplyMultiControlled.qs +++ b/Standard/src/Canon/Combinators/ApplyMultiControlled.qs @@ -11,7 +11,7 @@ namespace Microsoft.Quantum.Canon { /// # Summary /// The signature type of CCNOT gate. - newtype CCNOTop = ((Qubit, Qubit, Qubit) => Unit is Adj); + newtype CCNOTop = (Apply : ((Qubit, Qubit, Qubit) => Unit is Adj)); /// # Summary @@ -170,10 +170,10 @@ namespace Microsoft.Quantum.Canon { operation AndLadder (ccnot : CCNOTop, controls : Qubit[], targets : Qubit[]) : Unit is Adj { EqualityFactI(Length(controls), Length(targets) + 1, $"Length(controls) must be equal to Length(target) + 1"); Fact(Length(controls) >= 2, $"The operation is not defined for less than 2 controls"); - ccnot!(controls[0], controls[1], targets[0]); + ccnot::Apply(controls[0], controls[1], targets[0]); for (k in 1 .. Length(targets) - 1) { - ccnot!(controls[k + 1], targets[k - 1], targets[k]); + ccnot::Apply(controls[k + 1], targets[k - 1], targets[k]); } } diff --git a/Standard/tests/ANDTests.qs b/Standard/tests/ANDTests.qs new file mode 100644 index 00000000000..4cefc1304f3 --- /dev/null +++ b/Standard/tests/ANDTests.qs @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +namespace Microsoft.Quantum.Tests { + open Microsoft.Quantum.Arrays; + open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Convert; + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Logical; + open Microsoft.Quantum.Measurement; + + operation AndTestHelper(polarity1 : Bool, polarity2 : Bool, gate : CCNOTop) : Unit { + using ((control1, control2, target, output) = (Qubit(), Qubit(), Qubit(), Qubit())) { + within { + ApplyPauliFromBitString(PauliX, true, [polarity1, polarity2], [control1, control2]); + gate::Apply(control1, control2, target); + } + apply { + CNOT(target, output); + } + let expected = BoolAsResult(polarity1 and polarity2); + if (MResetZ(output) != expected) { + fail $"Expected output register to be {expected}"; + } + AssertAllZero([control1, control2, target]); + } + } + + operation ControlledAndTestHelper(polarities : Bool[], gate : ((Qubit, Qubit, Qubit) => Unit is Adj+Ctl)) : Unit { + let numControls = Length(polarities); + using ((controls, target, output) = (Qubit[numControls], Qubit(), Qubit())) { + within { + ApplyPauliFromBitString(PauliX, true, polarities, controls); + Controlled gate(controls[0..numControls - 3], (controls[numControls - 2], controls[numControls - 1], target)); + } + apply { + CNOT(target, output); + } + let expected = BoolAsResult(All(EqualB(true, _), polarities)); + if (MResetZ(output) != expected) { + fail $"Expected output register to be {expected}"; + } + AssertAllZero(controls + [target]); + } + } + + @Test("QuantumSimulator") + operation ApplyAndTest() : Unit { + for (p1 in [false, true]) { + for (p2 in [false, true]) { + for (op in [ApplyAnd, ApplyLowDepthAnd]) { + AndTestHelper(p1, p2, CCNOTop(op)); + } + } + } + } + + @Test("QuantumSimulator") + operation ControlledApplyAndTest() : Unit { + for (numControls in 3..5) { + for (assignment in 0..2^numControls - 1) { + ControlledAndTestHelper(IntAsBoolArray(assignment, numControls), ApplyAnd); + } + } + for (numControls in 3..4) { + for (assignment in 0..2^numControls - 1) { + ControlledAndTestHelper(IntAsBoolArray(assignment, numControls), ApplyLowDepthAnd); + } + } + } +} + + From a01973adf9f67d80153acdc90cae80ed748c8288 Mon Sep 17 00:00:00 2001 From: numpde <21158052+numpde@users.noreply.github.com> Date: Tue, 31 Dec 2019 01:59:42 +0100 Subject: [PATCH 04/11] Removed comment ref to IncrementByIntegerPhaseLE (#189) There appears to be no function IncrementByIntegerPhaseLE, and I guess it is covered by ApplyLEOperationOnPhaseLE. Co-authored-by: Chris Granade --- Standard/src/Arithmetic/Increment.qs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Standard/src/Arithmetic/Increment.qs b/Standard/src/Arithmetic/Increment.qs index f6dd2ae2ec6..53066a5b388 100644 --- a/Standard/src/Arithmetic/Increment.qs +++ b/Standard/src/Arithmetic/Increment.qs @@ -70,9 +70,6 @@ namespace Microsoft.Quantum.Arithmetic { /// encoding. /// ## increment /// The integer by which the `target` is incremented by. - /// - /// # See Also - /// - IncrementByIntegerPhaseLE operation IncrementByInteger(increment : Int, target : LittleEndian) : Unit is Adj + Ctl { ApplyPhaseLEOperationOnLECA(IncrementPhaseByInteger(increment, _), target); } From 39358f70b72f6c7695708ceb7fcfd76f97166581 Mon Sep 17 00:00:00 2001 From: Chris Granade Date: Thu, 2 Jan 2020 12:23:36 -0800 Subject: [PATCH 05/11] New Hadamard and SWAP test operations. (#196) * First work on Hadamard and SWAP test operations. * (c) header and typo fix. * Fixed typo with placement of phase shift. * Put public operations above private. * Added tests for new operations. * Added API documentation comments. * Newline at end of file. --- .../Characterization/Distinguishability.qs | 234 ++++++++++++++++++ .../DistinguishabilityTests.qs | 60 +++++ 2 files changed, 294 insertions(+) create mode 100644 Standard/src/Characterization/Distinguishability.qs create mode 100644 Standard/tests/Characterization/DistinguishabilityTests.qs diff --git a/Standard/src/Characterization/Distinguishability.qs b/Standard/src/Characterization/Distinguishability.qs new file mode 100644 index 00000000000..483cdbed803 --- /dev/null +++ b/Standard/src/Characterization/Distinguishability.qs @@ -0,0 +1,234 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Characterization { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Arrays; + + /// # Summary + /// Given two operations which each prepare copies of a state, estimates + /// the real part of the overlap between the states prepared by each + /// operation. + /// + /// # Input + /// ## commonPreparation + /// An operation that prepares a fixed input state. + /// ## preparation1 + /// The first of the two state preparation operations to be compared. + /// ## preparation2 + /// The second of the two state preparation operations to be compared. + /// ## nQubits + /// The number of qubits on which `commonPreparation`, `preparation1`, and + /// `preparation2` all act. + /// ## nMeasurements + /// The number of measurements to use in estimating the overlap. + /// + /// # Remarks + /// This operation uses the Hadamard test to find the real part of + /// $$ + /// \begin{align} + /// \braket{\psi | V^{\dagger} U | \psi} + /// \end{align} + /// $$ + /// where $\ket{\psi}$ is the state prepared by `commonPreparation`, + /// $U$ is the unitary representation of the action of `preparation1`, + /// and where $V$ corresponds to `preparation2`. + /// + /// # References + /// - Aharonov *et al.* [quant-ph/0511096](https://arxiv.org/abs/quant-ph/0511096). + /// + /// # See Also + /// - Microsoft.Quantum.Characterization.EstimateImagOverlapBetweenStates + /// - Microsoft.Quantum.Characterization.EstimateOverlapBetweenStates + operation EstimateRealOverlapBetweenStates( + commonPreparation : (Qubit[] => Unit is Adj), + preparation1 : (Qubit[] => Unit is Adj + Ctl), + preparation2 : (Qubit[] => Unit is Adj + Ctl), + nQubits : Int, nMeasurements : Int + ) + : Double { + return 2.0 * EstimateFrequencyA( + _ApplyHadamardTestOnSingleRegister(false, commonPreparation, preparation1, preparation2, _), + _HeadMeasurement(nQubits + 1), + nQubits + 1, nMeasurements + ) - 1.0; + } + + /// # Summary + /// Given two operations which each prepare copies of a state, estimates + /// the imaginary part of the overlap between the states prepared by each + /// operation. + /// + /// # Input + /// ## commonPreparation + /// An operation that prepares a fixed input state. + /// ## preparation1 + /// The first of the two state preparation operations to be compared. + /// ## preparation2 + /// The second of the two state preparation operations to be compared. + /// ## nQubits + /// The number of qubits on which `commonPreparation`, `preparation1`, and + /// `preparation2` all act. + /// ## nMeasurements + /// The number of measurements to use in estimating the overlap. + /// + /// # Remarks + /// This operation uses the Hadamard test to find the imaginary part of + /// $$ + /// \begin{align} + /// \braket{\psi | V^{\dagger} U | \psi} + /// \end{align} + /// $$ + /// where $\ket{\psi}$ is the state prepared by `commonPreparation`, + /// $U$ is the unitary representation of the action of `preparation1`, + /// and where $V$ corresponds to `preparation2`. + /// + /// # References + /// - Aharonov *et al.* [quant-ph/0511096](https://arxiv.org/abs/quant-ph/0511096). + /// + /// # See Also + /// - Microsoft.Quantum.Characterization.EstimateRealOverlapBetweenStates + /// - Microsoft.Quantum.Characterization.EstimateOverlapBetweenStates + operation EstimateImagOverlapBetweenStates( + commonPreparation : (Qubit[] => Unit is Adj), + preparation1 : (Qubit[] => Unit is Adj + Ctl), + preparation2 : (Qubit[] => Unit is Adj + Ctl), + nQubits : Int, nMeasurements : Int + ) + : Double { + return 2.0 * EstimateFrequencyA( + _ApplyHadamardTestOnSingleRegister(true, commonPreparation, preparation1, preparation2, _), + _HeadMeasurement(nQubits + 1), + nQubits + 1, nMeasurements + ) - 1.0; + } + + + /// # Summary + /// Given two operations which each prepare copies of a state, estimates + /// the squared overlap between the states prepared by each + /// operation. + /// + /// # Input + /// ## preparation1 + /// The first of the two state preparation operations to be compared. + /// ## preparation2 + /// The second of the two state preparation operations to be compared. + /// ## nQubits + /// The number of qubits on which `commonPreparation`, `preparation1`, and + /// `preparation2` all act. + /// ## nMeasurements + /// The number of measurements to use in estimating the overlap. + /// + /// # Remarks + /// This operation uses the SWAP test to find + /// $$ + /// \begin{align} + /// \left| \braket{00\cdots 0 | V^{\dagger} U | 00\cdots 0} \right|^2 + /// \end{align} + /// $$ + /// where $U$ is the unitary representation of the action of `preparation1`, + /// and where $V$ corresponds to `preparation2`. + /// + /// # See Also + /// - Microsoft.Quantum.Characterization.EstimateRealOverlapBetweenStates + /// - Microsoft.Quantum.Characterization.EstimateImagOverlapBetweenStates + operation EstimateOverlapBetweenStates( + preparation1 : (Qubit[] => Unit is Adj), + preparation2 : (Qubit[] => Unit is Adj), + nQubits : Int, nMeasurements : Int + ) + : Double { + let nTotalQubits = 2 * nQubits + 1; + return 2.0 * EstimateFrequencyA( + _ApplySwapTestOnSingleRegister(preparation1, preparation2, _), + _HeadMeasurement(nTotalQubits), + nTotalQubits, nMeasurements + ) - 1.0; + } + + + operation _ApplyHadamardTest( + phaseShift : Bool, + commonPreparation : (Qubit[] => Unit is Adj), + preparation1 : (Qubit[] => Unit is Adj + Ctl), + preparation2 : (Qubit[] => Unit is Adj + Ctl), + control : Qubit, + target : Qubit[] + ) + : Unit is Adj + { + within { + H(control); + } apply { + commonPreparation(target); + Controlled preparation1([control], target); + within { X(control); } + apply { Controlled preparation2([control], target); } + + (phaseShift ? S | I)(control); + } + } + + operation _ApplyHadamardTestOnSingleRegister( + phaseShift : Bool, + commonPreparation : (Qubit[] => Unit is Adj), + preparation1 : (Qubit[] => Unit is Adj + Ctl), + preparation2 : (Qubit[] => Unit is Adj + Ctl), + register : Qubit[] + ) + : Unit is Adj + { + let control = Head(register); + let target = Rest(register); + _ApplyHadamardTest( + phaseShift, + commonPreparation, + preparation1, preparation2, + control, target + ); + } + + + operation _ApplySwapTest( + preparation1 : (Qubit[] => Unit is Adj), + preparation2 : (Qubit[] => Unit is Adj), + control : Qubit, + target1 : Qubit[], + target2 : Qubit[] + ) + : Unit is Adj { + within { + H(control); + } apply { + preparation1(target1); + preparation2(target2); + ApplyToEachCA(Controlled SWAP([control], _), Zip(target1, target2)); + } + } + + operation _ApplySwapTestOnSingleRegister( + preparation1 : (Qubit[] => Unit is Adj), + preparation2 : (Qubit[] => Unit is Adj), + register : Qubit[] + ) + : Unit is Adj { + let control = Head(register); + let targets = Rest(register); + _ApplySwapTest( + preparation1, preparation2, + control, + targets[...Length(targets) / 2 - 1], + targets[Length(targets) / 2...] + ); + } + + function _HeadMeasurement(nQubits : Int) : (Qubit[] => Result) { + return Measure( + ConstantArray(nQubits, PauliI) w/ 0 <- PauliZ, + _ + ); + } + +} diff --git a/Standard/tests/Characterization/DistinguishabilityTests.qs b/Standard/tests/Characterization/DistinguishabilityTests.qs new file mode 100644 index 00000000000..f9f04bb853d --- /dev/null +++ b/Standard/tests/Characterization/DistinguishabilityTests.qs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Tests { + open Microsoft.Quantum.Math; + open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Characterization; + open Microsoft.Quantum.Diagnostics; + + @Test("QuantumSimulator") + operation CheckOverlapBetweenPlusAndOne() : Unit { + let prep1 = ApplyToEachCA(H, _); + let prep2 = ApplyToEachCA(X, _); + + EqualityWithinToleranceFact( + EstimateRealOverlapBetweenStates( + NoOp, prep1, prep2, 1, 1000000 + ), + 1.0 / Sqrt(2.0), + 0.02 + ); + EqualityWithinToleranceFact( + EstimateImagOverlapBetweenStates( + NoOp, prep1, prep2, 1, 1000000 + ), + 0.0, + 0.02 + ); + EqualityWithinToleranceFact( + 0.5, + EstimateOverlapBetweenStates( + prep1, prep2, 1, 1000000 + ), + 0.02 + ); + } + + @Test("QuantumSimulator") + operation CheckOverlapWithCommonPreparation() : Unit { + let common = ApplyToEachCA(H, _); + let prep1 = ApplyToEachCA(S, _); + let prep2 = ApplyToEachCA(Z, _); + + EqualityWithinToleranceFact( + EstimateRealOverlapBetweenStates( + common, prep1, prep2, 1, 1000000 + ), + 0.5, + 0.02 + ); + EqualityWithinToleranceFact( + EstimateImagOverlapBetweenStates( + common, prep1, prep2, 1, 1000000 + ), + 0.5, + 0.02 + ); + } +} From f1bd9d272de16382adb5d1356afe5e5d801cef52 Mon Sep 17 00:00:00 2001 From: Chris Granade Date: Thu, 2 Jan 2020 13:38:14 -0800 Subject: [PATCH 06/11] Refactor AA namespace to use Q# style guide (#197) * Began simplifying AA interface. * Expose traditional AA as new public operation. * Removed rest of "AmpAmp" prefix. * Resolve deprecation warning. --- .../AmplitudeAmplification.qs | 389 ++++++++---------- .../CommonOracles.qs | 19 +- .../src/AmplitudeAmplification/Convert.qs | 47 +++ .../src/AmplitudeAmplification/Deprecated.qs | 112 +++++ .../StandardAlgorithms.qs | 78 ++++ Standard/src/AmplitudeAmplification/Types.qs | 9 +- Standard/src/Oracles/Convert.qs | 71 ++-- Standard/src/Oracles/Types.qs | 14 +- .../src/Preparation/UniformSuperposition.qs | 12 +- 9 files changed, 456 insertions(+), 295 deletions(-) rename Standard/src/{Oracles => AmplitudeAmplification}/CommonOracles.qs (69%) create mode 100644 Standard/src/AmplitudeAmplification/Convert.qs create mode 100644 Standard/src/AmplitudeAmplification/Deprecated.qs create mode 100644 Standard/src/AmplitudeAmplification/StandardAlgorithms.qs diff --git a/Standard/src/AmplitudeAmplification/AmplitudeAmplification.qs b/Standard/src/AmplitudeAmplification/AmplitudeAmplification.qs index f6564b569ce..dde60e11be4 100644 --- a/Standard/src/AmplitudeAmplification/AmplitudeAmplification.qs +++ b/Standard/src/AmplitudeAmplification/AmplitudeAmplification.qs @@ -2,161 +2,44 @@ // Licensed under the MIT License. namespace Microsoft.Quantum.AmplitudeAmplification { + open Microsoft.Quantum.Arrays; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Convert; open Microsoft.Quantum.Math; open Microsoft.Quantum.Canon; open Microsoft.Quantum.Oracles; - /// # Summary - /// Converts phases specified as single-qubit rotations to phases - /// specified as partial reflections. - /// - /// # Input - /// ## rotPhases - /// Array of single-qubit rotations to be converted to partial - /// reflections. - /// - /// # Output - /// An operation that implements phases specified as partial reflections. - /// - /// # References - /// We use the convention in - /// - [ *G.H. Low, I. L. Chuang* ](https://arxiv.org/abs/1707.05391) - /// for relating single-qubit rotation phases to reflection operator phases. - function AmpAmpRotationToReflectionPhases (rotPhases : RotationPhases) : ReflectionPhases - { - let nPhasesRot = Length(rotPhases!); - let nPhasesRef = (nPhasesRot + 1) / 2; - - if (nPhasesRot % 2 == 0) - { - fail $"Number of rotations must be odd."; - } - - mutable phasesTarget = new Double[nPhasesRef]; - mutable phasesStart = new Double[nPhasesRef]; - set phasesTarget w/= 0 <- ((rotPhases!)[0] - (rotPhases!)[1]) - PI(); - set phasesStart w/= 0 <- -(rotPhases!)[0] + 0.5 * PI(); - - for (idxPhases in 1 .. nPhasesRef - 2) - { - set phasesTarget w/= idxPhases <- ((rotPhases!)[2 * idxPhases] - (rotPhases!)[2 * idxPhases + 1]) - PI(); - set phasesStart w/= idxPhases <- ((rotPhases!)[2 * idxPhases - 1] - (rotPhases!)[2 * idxPhases]) + PI(); - } - - set phasesTarget w/= nPhasesRef - 1 <- (rotPhases!)[2 * nPhasesRef - 2] - 0.5 * PI(); - set phasesStart w/= nPhasesRef - 1 <- ((rotPhases!)[2 * nPhasesRef - 3] - (rotPhases!)[2 * nPhasesRef - 2]) + PI(); - return ReflectionPhases(phasesStart, phasesTarget); - } - - - /// # Summary - /// Computes partial reflection phases for standard amplitude - /// amplification. - /// - /// # Input - /// ## nIterations - /// Number of amplitude amplification iterations to generate partial - /// reflection phases for. - /// - /// # Output - /// An operation that implements phases specified as partial reflections - /// - /// # Remarks - /// All phases are $\pi$, except for the first reflection about the start - /// state and the last reflection about the target state, which are $0$. - function AmpAmpPhasesStandard (nIterations : Int) : ReflectionPhases - { - mutable phasesTarget = new Double[nIterations + 1]; - mutable phasesStart = new Double[nIterations + 1]; - - for (idxPhases in 0 .. nIterations) - { - set phasesTarget w/= idxPhases <- PI(); - set phasesStart w/= idxPhases <- PI(); - } - - set phasesTarget w/= nIterations <- 0.0; - set phasesStart w/= 0 <- 0.0; - return ReflectionPhases(phasesStart, phasesTarget); - } - - - // We use the phases in "Fixed-Point Amplitude Amplification with an - // Optimal Number of Queires" [YoderLowChuang2014] - // See also "Methodology of composite quantum gates" [LowYoderChuang2016] - // for phases in the `RotationPhases` format - - /// # Summary - /// Computes partial reflection phases for fixed-point amplitude - /// amplification. - /// - /// # Input - /// ## nQueries - /// Number of queries to the state preparation oracle. Must be an odd - /// integer. - /// ## successMin - /// Target minimum success probability. - /// - /// # Output - /// Array of phases that can be used in fixed-point amplitude amplification - /// quantum algorithm implementation. - /// - /// # References - /// We use the phases in "Fixed-Point Amplitude Amplification with - /// an Optimal Number of Queries" - /// - [YoderLowChuang2014](https://arxiv.org/abs/1409.3305) - /// See also "Methodology of composite quantum gates" - /// - [LowYoderChuang2016](https://arxiv.org/abs/1603.03996) - /// for phases in the `RotationPhases` format. - function AmpAmpPhasesFixedPoint (nQueries : Int, successMin : Double) : ReflectionPhases - { - mutable phasesRot = new Double[nQueries]; - let nQueriesDouble = IntAsDouble(nQueries); - set phasesRot w/= 0 <- 0.0; - let beta = Cosh((1.0 / nQueriesDouble) * ArcCosh(Sqrt(successMin))); - - for (idxPhases in 1 .. nQueries - 1) - { - set phasesRot w/= idxPhases <- phasesRot[idxPhases - 1] + 2.0 * ArcTan(Tan((((2.0 * 1.0) * IntAsDouble(idxPhases)) * PI()) / nQueriesDouble) * Sqrt(1.0 - beta * beta)); - } - - return AmpAmpRotationToReflectionPhases(RotationPhases(phasesRot)); - } - - /// # Summary /// Oblivious amplitude amplification by specifying partial reflections. /// /// # Input /// ## phases /// Phases of partial reflections - /// ## ancillaReflection - /// Reflection operator about start state of ancilla register + /// ## startStateReflection + /// Reflection operator about start state of auxiliary register /// ## targetStateReflection - /// Reflection operator about target state of ancilla register + /// Reflection operator about target state of auxiliary register /// ## signalOracle /// Unitary oracle $O$ of type `ObliviousOracle` that acts jointly on the - /// ancilla and system registers. - /// ## ancillaRegister - /// Ancilla register + /// auxiliary and system registers. + /// ## auxiliaryRegister + /// Auxiliary register /// ## systemRegister /// System register /// /// # Remarks - /// Given a particular ancilla start state $\ket{\text{start}}\_a$, a - /// particular ancilla target state $\ket{\text{target}}\_a$, and any + /// Given a particular auxiliary start state $\ket{\text{start}}\_a$, a + /// particular auxiliary target state $\ket{\text{target}}\_a$, and any /// system state $\ket{\psi}\_s$, suppose that /// \begin{align} /// O\ket{\text{start}}\_a\ket{\psi}\_s= \lambda\ket{\text{target}}\_a U \ket{\psi}\_s + \sqrt{1-|\lambda|^2}\ket{\text{target}^\perp}\_a\cdots /// \end{align} /// for some unitary $U$. /// By a sequence of reflections about the start and target states on the - /// ancilla register interleaved by applications of `signalOracle` and its + /// auxiliary register interleaved by applications of `signalOracle` and its /// adjoint, the success probability of applying U may be altered. /// - /// In most cases, `ancillaRegister` is initialized in the state $\ket{\text{start}}\_a$. + /// In most cases, `auxiliaryRegister` is initialized in the state $\ket{\text{start}}\_a$. /// /// # References /// See @@ -165,69 +48,67 @@ namespace Microsoft.Quantum.AmplitudeAmplification { /// See /// - [ *G.H. Low, I.L. Chuang* ](https://arxiv.org/abs/1610.06546) /// for a generalization to partial reflections. - operation AmpAmpObliviousByReflectionPhasesImpl (phases : ReflectionPhases, ancillaReflection : ReflectionOracle, targetStateReflection : ReflectionOracle, signalOracle : ObliviousOracle, ancillaRegister : Qubit[], systemRegister : Qubit[]) : Unit - { - body (...) - { - let (phasesAncilla, phasesTarget) = phases!; - let nphases = 2 * Length(phasesTarget); - - //FailOn(nphases != Length(phasesAncilla), "Phase array lengths not equal.") - if (phasesAncilla[0] != 0.0) - { - ancillaReflection!(phasesAncilla[0], ancillaRegister); + operation ApplyObliviousAmplitudeAmplification( + phases : ReflectionPhases, + startStateReflection : ReflectionOracle, + targetStateReflection : ReflectionOracle, + signalOracle : ObliviousOracle, + auxiliaryRegister : Qubit[], + systemRegister : Qubit[] + ) + : Unit is Adj + Ctl { + for ((startPhase, targetPhase) in Zip(phases!)) { + if (startPhase != 0.0) { + startStateReflection::ApplyReflection( + startPhase, auxiliaryRegister + ); } - - for (idxPhases in 1 .. nphases - 1) - { - let idxPhaseAncilla = idxPhases / 2; - let idxPhaseTarget = idxPhases / 2; - - if (idxPhases % 2 == 1) - { - signalOracle!(ancillaRegister, systemRegister); - - if (phasesTarget[idxPhaseTarget] != 0.0) - { - targetStateReflection!(phasesTarget[idxPhaseTarget], ancillaRegister); - } - } - else - { - Adjoint signalOracle!(ancillaRegister, systemRegister); - - if (phasesAncilla[idxPhaseAncilla] != 0.0) - { - ancillaReflection!(phasesAncilla[idxPhaseAncilla], ancillaRegister); - } + + within { + signalOracle!(auxiliaryRegister, systemRegister); + } apply { + if (targetPhase != 0.0) { + targetStateReflection!(targetPhase, auxiliaryRegister); } } } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; + // This gives us one extra application of Adjoint signalOracle!, so we + // apply the forward direction at the end. + signalOracle!(auxiliaryRegister, systemRegister); } - - + + + // NB [STYLE]: The name of this operation uses "From" as it is not a type + // conversion function ("As"), but something that constructs + // an operation from given information in a deterministic + // fashion. /// # Summary /// Returns a unitary that implements oblivious amplitude amplification by specifying for partial reflections. - function AmpAmpObliviousByReflectionPhases (phases : ReflectionPhases, ancillaReflection : ReflectionOracle, targetStateReflection : ReflectionOracle, signalOracle : ObliviousOracle) : ((Qubit[], Qubit[]) => Unit is Adj + Ctl) - { - return AmpAmpObliviousByReflectionPhasesImpl(phases, ancillaReflection, targetStateReflection, signalOracle, _, _); + function ObliviousAmplitudeAmplificationFromPartialReflections( + phases : ReflectionPhases, + startStateReflection : ReflectionOracle, + targetStateReflection : ReflectionOracle, + signalOracle : ObliviousOracle + ) + : ((Qubit[], Qubit[]) => Unit is Adj + Ctl) { + return ApplyObliviousAmplitudeAmplification( + phases, startStateReflection, targetStateReflection, signalOracle, + _, _ + ); } - - + + /// # Summary /// Oblivious amplitude amplification by oracles for partial reflections. /// /// # Input /// ## phases /// Phases of partial reflections - /// ## ancillaOracle - /// Unitary oracle $A$ that prepares ancilla start state + /// ## startStateOracle + /// Unitary oracle $A$ that prepares auxiliary start state /// ## signalOracle - /// Unitary oracle $O$ of type `ObliviousOracle` that acts jointly on the ancilla and system register + /// Unitary oracle $O$ of type `ObliviousOracle` that acts jointly on the + /// auxiliary and system register /// ## idxFlagQubit /// Index to single-qubit flag register /// @@ -235,23 +116,65 @@ namespace Microsoft.Quantum.AmplitudeAmplification { /// An operation that implements oblivious amplitude amplification based on partial reflections. /// /// # Remarks - /// This imposes stricter conditions on form of the ancilla start and target states than in `AmpAmpObliviousByReflectionPhases`. - /// It is assumed that $A\ket{0}\_f\ket{0}\_a= \ket{\text{start}}\_{fa}$ prepares the ancilla start state $\ket{\text{start}}\_{fa}$ from the computational basis $\ket{0}\_f\ket{0}$. + /// This imposes stricter conditions on form of the auxiliary start and target states than in `AmpAmpObliviousByReflectionPhases`. + /// It is assumed that $A\ket{0}\_f\ket{0}\_a= \ket{\text{start}}\_{fa}$ prepares the auxiliary start state $\ket{\text{start}}\_{fa}$ from the computational basis $\ket{0}\_f\ket{0}$. /// It is assumed that the target state is marked by $\ket{1}\_f$. /// It is assumed that /// \begin{align} /// O\ket{\text{start}}\_{fa}\ket{\psi}\_s= \lambda\ket{1}\_f\ket{\text{anything}}\_a\ket{\text{target}}\_s U \ket{\psi}\_s + \sqrt{1-|\lambda|^2}\ket{0}\_f\cdots, /// \end{align} /// for some unitary $U$. - function AmpAmpObliviousByOraclePhases (phases : ReflectionPhases, ancillaOracle : DeterministicStateOracle, signalOracle : ObliviousOracle, idxFlagQubit : Int) : ((Qubit[], Qubit[]) => Unit is Adj + Ctl) - { - let ancillaReflection = ReflectionStart(); + function ObliviousAmplitudeAmplificationFromStatePreparation( + phases : ReflectionPhases, + startStateOracle : DeterministicStateOracle, + signalOracle : ObliviousOracle, + idxFlagQubit : Int + ) + : ((Qubit[], Qubit[]) => Unit is Adj + Ctl) { + let startStateReflection = ReflectionStart(); let targetStateReflection = TargetStateReflectionOracle(idxFlagQubit); - let oracleObliviousNew = ObliviousOracleFromDeterministicStateOracle(ancillaOracle, signalOracle); - return AmpAmpObliviousByReflectionPhases(phases, ancillaReflection, targetStateReflection, oracleObliviousNew); + let obliviousSignalOracle = ObliviousOracleFromDeterministicStateOracle( + startStateOracle, signalOracle + ); + return ObliviousAmplitudeAmplificationFromPartialReflections( + phases, startStateReflection, targetStateReflection, obliviousSignalOracle + ); } - - + + /// # Summary + /// Applies amplitude amplification on a given register, using a given set + /// of phases and oracles to reflect about the initial and final states. + /// + /// # Input + /// ## phases + /// A set of phases describing the partial reflections at each step of the + /// amplitude amplification algorithm. See + /// @"microsoft.quantum.amplitudeamplification.standardreflectionphases" + /// for an example. + /// ## startStateReflection + /// An oracle that reflects about the initial state. + /// ## targetStateReflection + /// An oracle that reflects about the desired final state. + /// ## target + /// A register to perform amplitude amplification on. + operation ApplyAmplitudeAmplification( + phases : ReflectionPhases, + startStateReflection : ReflectionOracle, + targetStateReflection : ReflectionOracle, + target : Qubit[] + ) + : Unit is Adj + Ctl { + // Pass empty qubit array using fact that NoOp does nothing. + let systemRegister = new Qubit[0]; + let signalOracle = ObliviousOracle(NoOp<(Qubit[], Qubit[])>); + let op = ObliviousAmplitudeAmplificationFromPartialReflections( + phases, startStateReflection, targetStateReflection, signalOracle + ); + + op(target, systemRegister); + } + + /// # Summary /// Amplitude amplification by partial reflections. /// @@ -271,15 +194,25 @@ namespace Microsoft.Quantum.AmplitudeAmplification { /// # Remarks /// Amplitude amplification is a special case of oblivious amplitude amplification where there are no system qubits and the oblivious oracle is set to identity. /// In most cases, `startQubits` is initialized in the state $\ket{\text{start}}\_1$, which is the $-1$ eigenstate of `startStateReflection`. - function AmpAmpByReflectionsPhases (phases : ReflectionPhases, startStateReflection : ReflectionOracle, targetStateReflection : ReflectionOracle) : (Qubit[] => Unit is Adj + Ctl) - { + function AmplitudeAmplificationFromPartialReflections( + phases : ReflectionPhases, + startStateReflection : ReflectionOracle, + targetStateReflection : ReflectionOracle + ) + : (Qubit[] => Unit is Adj + Ctl) { // Pass empty qubit array using fact that NoOp does nothing. let qubitEmpty = new Qubit[0]; let signalOracle = ObliviousOracle(NoOp<(Qubit[], Qubit[])>); - return (AmpAmpObliviousByReflectionPhases(phases, startStateReflection, targetStateReflection, signalOracle))(_, qubitEmpty); + return (ObliviousAmplitudeAmplificationFromPartialReflections( + phases, startStateReflection, targetStateReflection, signalOracle + ))(_, qubitEmpty); } - - + + + // NB [STYLE]: The name of this operation uses "From" as it is not a type + // conversion function ("As"), but something that constructs + // an operation from given information in a deterministic + // fashion. /// # Summary /// Amplitude amplification by oracles for partial reflections. /// @@ -304,16 +237,22 @@ namespace Microsoft.Quantum.AmplitudeAmplification { /// \begin{align} /// A\ket{0}\_{f}\ket{0}\_s= \lambda\ket{1}\_f\ket{\text{target}}\_s + \sqrt{1-|\lambda|^2}\ket{0}\_f\cdots, /// \end{align} - /// In most cases, `flagQubit` and `ancillaRegister` is initialized in the state $\ket{0}\_{f}\ket{0}\_s$. - function AmpAmpByOraclePhases (phases : ReflectionPhases, stateOracle : StateOracle, idxFlagQubit : Int) : (Qubit[] => Unit is Adj + Ctl) - { - let qubitEmpty = new Qubit[0]; + /// In most cases, `flagQubit` and `auxiliaryRegister` are initialized in the state $\ket{0}\_{f}\ket{0}\_s$. + function AmplitudeAmplificationFromStatePreparation( + phases : ReflectionPhases, + stateOracle : StateOracle, + idxFlagQubit : Int + ) + : (Qubit[] => Unit is Adj + Ctl) { + let systemRegister = new Qubit[0]; let signalOracle = ObliviousOracle(NoOp<(Qubit[], Qubit[])>); - let ancillaOracle = DeterministicStateOracleFromStateOracle(idxFlagQubit, stateOracle); - return (AmpAmpObliviousByOraclePhases(phases, ancillaOracle, signalOracle, idxFlagQubit))(_, qubitEmpty); + let startStateOracle = DeterministicStateOracleFromStateOracle(idxFlagQubit, stateOracle); + return (ObliviousAmplitudeAmplificationFromStatePreparation( + phases, startStateOracle, signalOracle, idxFlagQubit + ))(_, systemRegister); } - - + + /// # Summary /// Standard Amplitude Amplification algorithm /// @@ -340,17 +279,21 @@ namespace Microsoft.Quantum.AmplitudeAmplification { /// \begin{align} /// \operatorname{AmpAmpByOracle}\ket{0}\_{f}\ket{0}\_s= \sin((2n+1)\sin^{-1}(\lambda))\ket{1}\_f\ket{\text{target}}\_s + \cdots\ket{0}\_f /// \end{align} - /// In most cases, `flagQubit` and `ancillaRegister` is initialized in the state $\ket{0}\_f\ket{0}\_a$. + /// In most cases, `flagQubit` and `auxiliaryRegister` is initialized in the state $\ket{0}\_f\ket{0}\_a$. /// /// # References /// - [ *G. Brassard, P. Hoyer, M. Mosca, A. Tapp* ](https://arxiv.org/abs/quant-ph/0005055) - function AmpAmpByOracle (nIterations : Int, stateOracle : StateOracle, idxFlagQubit : Int) : (Qubit[] => Unit is Adj + Ctl) - { - let phases = AmpAmpPhasesStandard(nIterations); - return AmpAmpByOraclePhases(phases, stateOracle, idxFlagQubit); + function StandardAmplitudeAmplification( + nIterations : Int, + stateOracle : StateOracle, + idxFlagQubit : Int + ) + : (Qubit[] => Unit is Adj + Ctl) { + let phases = StandardReflectionPhases(nIterations); + return AmplitudeAmplificationFromStatePreparation(phases, stateOracle, idxFlagQubit); } - - + + /// # Summary /// Fixed-Point Amplitude Amplification algorithm /// @@ -363,56 +306,50 @@ namespace Microsoft.Quantum.AmplitudeAmplification { /// # Remarks /// The startQubits must be in the $\ket{0 \cdots 0}$ state. This operation iterates over a number of queries in powers of $2$ until either a maximal number of queries /// is reached, or the target state is found. - operation AmpAmpRUSByOracle (statePrepOracle : StateOracle, startQubits : Qubit[]) : Unit - { + operation ApplyFixedPointAmplification(statePrepOracle : StateOracle, startQubits : Qubit[]) + : Unit { // Should be a power of 2 let queriesMax = 999; let successMin = 0.99; mutable finished = Zero; mutable exponentMax = 0; mutable exponentCurrent = 0; - + //Complexity: Let \theta = \mathcal{O}(\sqrt{lambda}) // Number of Measurements = O( Log^2(1/\theta) ) // Number of Queries = O(1/\theta) - using (flagQubit = Qubit[1]) - { + using (flagQubit = Qubit[1]) { let qubits = flagQubit + startQubits; let idxFlagQubit = 0; - - repeat - { - if (2 ^ exponentMax > queriesMax) - { + + repeat { + if (2 ^ exponentMax > queriesMax) { fail $"Target state not found. Maximum number of queries exceeded."; } - - repeat - { + + repeat { let queries = 2 ^ exponentCurrent; - let phases = AmpAmpPhasesFixedPoint(queries, successMin); - (AmpAmpByOraclePhases(phases, statePrepOracle, idxFlagQubit))(qubits); + let phases = FixedPointReflectionPhases(queries, successMin); + (AmplitudeAmplificationFromStatePreparation(phases, statePrepOracle, idxFlagQubit))(qubits); set finished = M(flagQubit[0]); set exponentCurrent = exponentCurrent + 1; } until (finished == One or exponentCurrent > exponentMax) - fixup - { + fixup { // flagQubit is already in Zero for fixup to apply ResetAll(startQubits); } - + set exponentCurrent = 0; set exponentMax = exponentMax + 1; } until (finished == One) - fixup - { + fixup { ResetAll(startQubits); } } } - + } diff --git a/Standard/src/Oracles/CommonOracles.qs b/Standard/src/AmplitudeAmplification/CommonOracles.qs similarity index 69% rename from Standard/src/Oracles/CommonOracles.qs rename to Standard/src/AmplitudeAmplification/CommonOracles.qs index ba169bb7ae4..7bd2bc4e6fb 100644 --- a/Standard/src/Oracles/CommonOracles.qs +++ b/Standard/src/AmplitudeAmplification/CommonOracles.qs @@ -20,20 +20,15 @@ namespace Microsoft.Quantum.AmplitudeAmplification { /// # Summary /// Implementation of . - operation TargetStateReflectionOracleImpl (phase : Double, idxFlagQubit : Int, qubits : Qubit[]) : Unit { - body (...) { - R1(phase, qubits[idxFlagQubit]); - } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; + operation _TargetStateReflectionOracle(phase : Double, idxFlagQubit : Int, qubits : Qubit[]) + : Unit is Adj + Ctl { + R1(phase, qubits[idxFlagQubit]); } /// # Summary /// Constructs a `ReflectionOracle` about the target state uniquely marked by the flag qubit. - /// - /// The target state has a single qubit set to 1, and all others 0: $\ket{1}_f$. + /// + /// The target state has a single qubit set to 1, and all others 0: $\ket{1}_f$. /// /// # Input /// ## idxFlagQubit @@ -44,8 +39,8 @@ namespace Microsoft.Quantum.AmplitudeAmplification { /// /// # See Also /// - Microsoft.Quantum.Canon.ReflectionOracle - function TargetStateReflectionOracle (idxFlagQubit : Int) : ReflectionOracle { - return ReflectionOracle(TargetStateReflectionOracleImpl(_, idxFlagQubit, _)); + function TargetStateReflectionOracle(idxFlagQubit : Int) : ReflectionOracle { + return ReflectionOracle(_TargetStateReflectionOracle(_, idxFlagQubit, _)); } } diff --git a/Standard/src/AmplitudeAmplification/Convert.qs b/Standard/src/AmplitudeAmplification/Convert.qs new file mode 100644 index 00000000000..72bb061bbd3 --- /dev/null +++ b/Standard/src/AmplitudeAmplification/Convert.qs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.AmplitudeAmplification { + open Microsoft.Quantum.Math; + + /// # Summary + /// Converts phases specified as single-qubit rotations to phases + /// specified as partial reflections. + /// + /// # Input + /// ## rotPhases + /// Array of single-qubit rotations to be converted to partial + /// reflections. + /// + /// # Output + /// An operation that implements phases specified as partial reflections. + /// + /// # References + /// We use the convention in + /// - [ *G.H. Low, I. L. Chuang* ](https://arxiv.org/abs/1707.05391) + /// for relating single-qubit rotation phases to reflection operator phases. + function RotationPhasesAsReflectionPhases(rotPhases : RotationPhases) + : ReflectionPhases { + let nPhasesRot = Length(rotPhases!); + let nPhasesRef = (nPhasesRot + 1) / 2; + + if (nPhasesRot % 2 == 0) { + fail $"Number of rotations must be odd."; + } + + mutable phasesTarget = new Double[nPhasesRef]; + mutable phasesStart = new Double[nPhasesRef]; + set phasesTarget w/= 0 <- ((rotPhases!)[0] - (rotPhases!)[1]) - PI(); + set phasesStart w/= 0 <- -(rotPhases!)[0] + 0.5 * PI(); + + for (idxPhases in 1 .. nPhasesRef - 2) { + set phasesTarget w/= idxPhases <- ((rotPhases!)[2 * idxPhases] - (rotPhases!)[2 * idxPhases + 1]) - PI(); + set phasesStart w/= idxPhases <- ((rotPhases!)[2 * idxPhases - 1] - (rotPhases!)[2 * idxPhases]) + PI(); + } + + set phasesTarget w/= nPhasesRef - 1 <- (rotPhases!)[2 * nPhasesRef - 2] - 0.5 * PI(); + set phasesStart w/= nPhasesRef - 1 <- ((rotPhases!)[2 * nPhasesRef - 3] - (rotPhases!)[2 * nPhasesRef - 2]) + PI(); + return ReflectionPhases(phasesStart, phasesTarget); + } + +} diff --git a/Standard/src/AmplitudeAmplification/Deprecated.qs b/Standard/src/AmplitudeAmplification/Deprecated.qs new file mode 100644 index 00000000000..6f0f2158ac4 --- /dev/null +++ b/Standard/src/AmplitudeAmplification/Deprecated.qs @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.AmplitudeAmplification { + open Microsoft.Quantum.Oracles; + + + /// # Deprecated + /// Please use + /// @"microsoft.quantum.amplitudeamplification.rotationphasesasreflectionphases". + @Deprecated("Microsoft.Quantum.AmplitudeAmplification.RotationPhasesAsReflectionPhases") + function AmpAmpRotationToReflectionPhases (rotPhases : RotationPhases) + : ReflectionPhases { + return RotationPhasesAsReflectionPhases(rotPhases); + } + + /// # Deprecated + /// Please use + /// @"microsoft.quantum.amplitudeamplification.standardreflectionphases". + @Deprecated("Microsoft.Quantum.AmplitudeAmplification.StandardReflectionPhases") + function AmpAmpPhasesStandard(nIterations : Int) : ReflectionPhases { + return StandardReflectionPhases(nIterations); + } + + /// # Deprecated + /// Please use + /// @"microsoft.quantum.amplitudeamplification.fixedpointreflectionphases". + @Deprecated("Microsoft.Quantum.AmplitudeAmplification.FixedPointReflectionPhases") + function AmpAmpPhasesFixedPoint(nQueries : Int, successMin : Double) : ReflectionPhases { + return FixedPointReflectionPhases(nQueries, successMin); + } + + /// # Deprecated + /// Please use @"microsoft.quantum.amplitudeamplification.obliviousamplitudeamplificationfrompartialreflections". + @Deprecated("Microsoft.Quantum.AmplitudeAmplification.ObliviousAmplitudeAmplificationFromPartialReflections") + function AmpAmpObliviousByReflectionPhases( + phases : ReflectionPhases, + startStateReflection : ReflectionOracle, + targetStateReflection : ReflectionOracle, + signalOracle : ObliviousOracle + ) + : ((Qubit[], Qubit[]) => Unit is Adj + Ctl) { + return ObliviousAmplitudeAmplificationFromPartialReflections( + phases, startStateReflection, targetStateReflection, signalOracle + ); + } + + /// # Deprecated + /// Please use @"microsoft.quantum.amplitudeamplification.obliviousamplitudeamplificationfromstatepreparation". + @Deprecated("Microsoft.Quantum.AmplitudeAmplification.ObliviousAmplitudeAmplificationFromStatePreparation") + function AmpAmpObliviousByOraclePhases( + phases : ReflectionPhases, + startStateOracle : DeterministicStateOracle, + signalOracle : ObliviousOracle, + idxFlagQubit : Int + ) + : ((Qubit[], Qubit[]) => Unit is Adj + Ctl) { + return ObliviousAmplitudeAmplificationFromStatePreparation( + phases, startStateOracle, signalOracle, idxFlagQubit + ); + } + + /// # Deprecated + /// Please use @"microsoft.quantum.amplitudeamplification.amplitudeamplificationfrompartialreflections". + @Deprecated("Microsoft.Quantum.AmplitudeAmplification.AmplitudeAmplificationFromPartialReflections") + function AmpAmpByReflectionPhases( + phases : ReflectionPhases, + startStateReflection : ReflectionOracle, + targetStateReflection : ReflectionOracle + ) + : (Qubit[] => Unit is Adj + Ctl) { + return AmplitudeAmplificationFromPartialReflections( + phases, startStateReflection, targetStateReflection + ); + } + + /// # Deprecated + /// Please use @"microsoft.quantum.amplitudeamplification.amplitudeamplificationfromstatepreparation". + @Deprecated("Microsoft.Quantum.AmplitudeAmplification.AmplitudeAmplificationFromStatePreparation") + function AmpAmpByOraclePhases( + phases : ReflectionPhases, + stateOracle : StateOracle, + idxFlagQubit : Int + ) + : (Qubit[] => Unit is Adj + Ctl) { + return AmplitudeAmplificationFromStatePreparation( + phases, stateOracle, idxFlagQubit + ); + } + + /// # Deprecated + /// Please use @"microsoft.quantum.amplitudeamplification.standardamplitudeamplification". + @Deprecated("Microsoft.Quantum.AmplitudeAmplification.StandardAmplitudeAmplification") + function AmpAmpByOracle( + nIterations : Int, + stateOracle : StateOracle, + idxFlagQubit : Int + ) + : (Qubit[] => Unit is Adj + Ctl) { + return StandardAmplitudeAmplification(nIterations, stateOracle, idxFlagQubit); + } + + + /// # Deprecated + /// Please use @"microsoft.quantum.amplitudeamplification.applyfixedpointamplification". + @Deprecated("Microsoft.Quantum.AmplitudeAmplification.ApplyFixedPointAmplification") + operation AmpAmpRUSByOracle(statePrepOracle : StateOracle, startQubits : Qubit[]) + : Unit { + ApplyFixedPointAmplification(statePrepOracle, startQubits); + } + +} diff --git a/Standard/src/AmplitudeAmplification/StandardAlgorithms.qs b/Standard/src/AmplitudeAmplification/StandardAlgorithms.qs new file mode 100644 index 00000000000..9bedaeee3d8 --- /dev/null +++ b/Standard/src/AmplitudeAmplification/StandardAlgorithms.qs @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.AmplitudeAmplification { + open Microsoft.Quantum.Convert; + open Microsoft.Quantum.Arrays; + open Microsoft.Quantum.Math; + + /// # Summary + /// Computes partial reflection phases for standard amplitude + /// amplification. + /// + /// # Input + /// ## nIterations + /// Number of amplitude amplification iterations to generate partial + /// reflection phases for. + /// + /// # Output + /// An operation that implements phases specified as partial reflections + /// + /// # Remarks + /// All phases are $\pi$, except for the first reflection about the start + /// state and the last reflection about the target state, which are $0$. + function StandardReflectionPhases(nIterations : Int) : ReflectionPhases { + let commonPhases = ConstantArray(nIterations, PI()); + let targetPhases = commonPhases + [0.0]; + let startPhases = [0.0] + commonPhases; + return ReflectionPhases(startPhases, targetPhases); + } + + // We use the phases in "Fixed-Point Amplitude Amplification with an + // Optimal Number of Queires" [YoderLowChuang2014] + // See also "Methodology of composite quantum gates" [LowYoderChuang2016] + // for phases in the `RotationPhases` format + + /// # Summary + /// Computes partial reflection phases for fixed-point amplitude + /// amplification. + /// + /// # Input + /// ## nQueries + /// Number of queries to the state preparation oracle. Must be an odd + /// integer. + /// ## successMin + /// Target minimum success probability. + /// + /// # Output + /// Array of phases that can be used in fixed-point amplitude amplification + /// quantum algorithm implementation. + /// + /// # References + /// We use the phases in "Fixed-Point Amplitude Amplification with + /// an Optimal Number of Queries" + /// - [YoderLowChuang2014](https://arxiv.org/abs/1409.3305) + /// See also "Methodology of composite quantum gates" + /// - [LowYoderChuang2016](https://arxiv.org/abs/1603.03996) + /// for phases in the `RotationPhases` format. + function FixedPointReflectionPhases(nQueries : Int, successMin : Double) + : ReflectionPhases { + let twoPi = 2.0 * PI(); + mutable phasesRot = new Double[nQueries]; + let nQueriesDouble = IntAsDouble(nQueries); + set phasesRot w/= 0 <- 0.0; + let beta = Cosh((1.0 / nQueriesDouble) * ArcCosh(Sqrt(successMin))); + let alpha = Sqrt(1.0 - beta * beta); + + for (idxPhases in 1 .. nQueries - 1) { + set phasesRot w/= idxPhases <- + phasesRot[idxPhases - 1] + + 2.0 * ArcTan( + Tan(twoPi * IntAsDouble(idxPhases) / nQueriesDouble) * alpha + ); + } + + return RotationPhasesAsReflectionPhases(RotationPhases(phasesRot)); + } + +} diff --git a/Standard/src/AmplitudeAmplification/Types.qs b/Standard/src/AmplitudeAmplification/Types.qs index 57f3fa2d007..5addb42ddfa 100644 --- a/Standard/src/AmplitudeAmplification/Types.qs +++ b/Standard/src/AmplitudeAmplification/Types.qs @@ -7,9 +7,14 @@ namespace Microsoft.Quantum.AmplitudeAmplification { /// Phases for a sequence of partial reflections in amplitude amplification. /// /// # Remarks - /// The first parameter is an array of phases for reflection about the start state. The second parameter is an array of phases for reflection about the target state. + /// The first parameter is an array of phases for reflection about the + /// start state. The second parameter is an array of phases for reflection + /// about the target state. /// Both arrays must be of equal length. Note that in many cases, the first phase about the start state and last phase about the target state introduces a global phase shift and may be set to $0$. - newtype ReflectionPhases = (Double[], Double[]); + newtype ReflectionPhases = ( + AboutStart: Double[], + AboutTarget: Double[] + ); /// # Summary /// Phases for a sequence of single-qubit rotations in amplitude amplification. diff --git a/Standard/src/Oracles/Convert.qs b/Standard/src/Oracles/Convert.qs index 0f9650c653a..3b804227e36 100644 --- a/Standard/src/Oracles/Convert.qs +++ b/Standard/src/Oracles/Convert.qs @@ -6,20 +6,13 @@ namespace Microsoft.Quantum.Oracles { /// # Summary /// Implementation of . - operation _ObliviousOracleFromDeterministicStateOracle (ancillaOracle : DeterministicStateOracle, signalOracle : ObliviousOracle, ancillaRegister : Qubit[], systemRegister : Qubit[]) : Unit - { - body (...) - { - ancillaOracle!(ancillaRegister); - signalOracle!(ancillaRegister, systemRegister); - } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; + operation _ObliviousOracleFromDeterministicStateOracle(ancillaOracle : DeterministicStateOracle, signalOracle : ObliviousOracle, ancillaRegister : Qubit[], systemRegister : Qubit[]) + : Unit is Adj + Ctl { + ancillaOracle!(ancillaRegister); + signalOracle!(ancillaRegister, systemRegister); } - - + + /// # Summary /// Combines the oracles `DeterministicStateOracle` and `ObliviousOracle`. /// @@ -35,27 +28,19 @@ namespace Microsoft.Quantum.Oracles { /// # See Also /// - Microsoft.Quantum.Canon.DeterministicStateOracle /// - Microsoft.Quantum.Canon.ObliviousOracle - function ObliviousOracleFromDeterministicStateOracle (ancillaOracle : DeterministicStateOracle, signalOracle : ObliviousOracle) : ObliviousOracle - { + function ObliviousOracleFromDeterministicStateOracle (ancillaOracle : DeterministicStateOracle, signalOracle : ObliviousOracle) : ObliviousOracle { return ObliviousOracle(_ObliviousOracleFromDeterministicStateOracle(ancillaOracle, signalOracle, _, _)); } - - + + /// # Summary /// Implementation of . - operation _DeterministicStateOracleFromStateOracle (idxFlagQubit : Int, stateOracle : StateOracle, startQubits : Qubit[]) : Unit - { - body (...) - { - stateOracle!(idxFlagQubit, startQubits); - } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; + operation _DeterministicStateOracleFromStateOracle (idxFlagQubit : Int, stateOracle : StateOracle, startQubits : Qubit[]) + : Unit is Adj + Ctl { + stateOracle!(idxFlagQubit, startQubits); } - - + + /// # Summary /// Converts an oracle of type `StateOracle` to `DeterministicStateOracle`. /// @@ -79,8 +64,8 @@ namespace Microsoft.Quantum.Oracles { { return DeterministicStateOracle(_DeterministicStateOracleFromStateOracle(idxFlagQubit, stateOracle, _)); } - - + + /// # Summary /// Implementation of . operation _StateOracleFromDeterministicStateOracle (idxFlagQubit : Int, oracleStateDeterministic : DeterministicStateOracle, qubits : Qubit[]) : Unit @@ -89,13 +74,13 @@ namespace Microsoft.Quantum.Oracles { { oracleStateDeterministic!(qubits); } - + adjoint invert; controlled distribute; controlled adjoint distribute; } - - + + /// # Summary /// Converts an oracle of type `DeterministicStateOracle` to `StateOracle`. /// @@ -115,8 +100,8 @@ namespace Microsoft.Quantum.Oracles { { return StateOracle(_StateOracleFromDeterministicStateOracle(_, deterministicStateOracle, _)); } - - + + /// # Summary /// Implementation of . operation ReflectionOracleFromDeterministicStateOracleImpl (phase : Double, oracle : DeterministicStateOracle, systemRegister : Qubit[]) : Unit @@ -125,20 +110,20 @@ namespace Microsoft.Quantum.Oracles { { ApplyWithCA(Adjoint oracle!, RAll0(phase, _), systemRegister); } - + adjoint invert; controlled distribute; controlled adjoint distribute; } - - + + /// # Summary /// Constructs reflection about a given state from an oracle. - /// - /// Given the oracle $O$ of type + /// + /// Given the oracle $O$ of type /// , - /// the result of this function is a reflection around the state $\ket{\psi}$ - /// where $O\ket{0} = \ket{\psi}$. + /// the result of this function is a reflection around the state $\ket{\psi}$ + /// where $O\ket{0} = \ket{\psi}$. /// /// # Input /// ## oracle diff --git a/Standard/src/Oracles/Types.qs b/Standard/src/Oracles/Types.qs index a3c395ffd95..0350cd20125 100644 --- a/Standard/src/Oracles/Types.qs +++ b/Standard/src/Oracles/Types.qs @@ -14,7 +14,9 @@ namespace Microsoft.Quantum.Oracles { /// This oracle $O = \boldone - (1 - e^{i \phi}) \ket{\psi}\bra{\psi}$ /// performs a partial reflection by a phase $\phi$ about a single pure state /// $\ket{\psi}$. - newtype ReflectionOracle = ((Double, Qubit[]) => Unit is Adj + Ctl); + newtype ReflectionOracle = ( + ApplyReflection: ((Double, Qubit[]) => Unit is Adj + Ctl) + ); // This oracle O|s>_a|ψ>_s = λ |t>_a U |ψ>_s + ... acts on the ancilla state |s>_a to implement the unitary U on any system state |ψ>_s with amplitude λ in the |t>_a basis. @@ -28,7 +30,7 @@ namespace Microsoft.Quantum.Oracles { /// # Remarks /// This oracle defined by /// $$ - ///O\ket{s}\_a\ket{\psi}\_s= \lambda\ket{t}\_a U \ket{\psi}\_s + \sqrt{1-|\lambda|^2}\ket{t^\perp}\_a\cdots + /// O\ket{s}\_a\ket{\psi}\_s= \lambda\ket{t}\_a U \ket{\psi}\_s + \sqrt{1-|\lambda|^2}\ket{t^\perp}\_a\cdots /// $$ /// acts on the ancilla state $\ket{s}\_a$ to implement the unitary $U$ on any system state $\ket{\psi}\_s$ with amplitude $\lambda$ in the basis flagged by $\ket{t}\_a$. /// The first parameter is the qubit register of $\ket{s}\_a$. The second parameter is the qubit register of $\ket{\psi}\_s$. @@ -64,15 +66,15 @@ namespace Microsoft.Quantum.Oracles { /// # Summary /// Represents a discrete-time oracle. - /// - /// This is an oracle that implements $U^m$ for a fixed operation $U$ + /// + /// This is an oracle that implements $U^m$ for a fixed operation $U$ /// and a non-negative integer $m$. newtype DiscreteOracle = ((Int, Qubit[]) => Unit is Adj + Ctl); /// # Summary /// Represents a continuous-time oracle. - /// - /// This is an oracle that implements + /// + /// This is an oracle that implements /// $U(\delta t) : \ket{\psi(t)} \mapsto \ket{\psi(t + \delta t)}$ /// for all times $t$, where $U$ is a fixed operation, and where /// $\delta t$ is a non-negative real number. diff --git a/Standard/src/Preparation/UniformSuperposition.qs b/Standard/src/Preparation/UniformSuperposition.qs index 6cd27f4fdb8..177c43dcef9 100644 --- a/Standard/src/Preparation/UniformSuperposition.qs +++ b/Standard/src/Preparation/UniformSuperposition.qs @@ -9,12 +9,12 @@ namespace Microsoft.Quantum.Preparation { open Microsoft.Quantum.AmplitudeAmplification; open Microsoft.Quantum.Oracles; open Microsoft.Quantum.Math; - + /// # Summary - /// Creates a uniform superposition over states that encode 0 through `nIndices`. - /// + /// Creates a uniform superposition over states that encode 0 through `nIndices`. + /// /// That is, this unitary $U$ creates a uniform superposition over all number states - /// $0$ to $M-1$, given an input state $\ket{0\cdots 0}$. In other words, + /// $0$ to $M-1$, given an input state $\ket{0\cdots 0}$. In other words, /// $$ /// \begin{align} /// U\ket{0}=\frac{1}{\sqrt{M}}\sum_{j=0}^{M-1}\ket{j}. @@ -57,7 +57,7 @@ namespace Microsoft.Quantum.Preparation { let qubits = flagQubit + targetQubits; let stateOracle = StateOracle(PrepareUniformSuperposition_(nIndices, nQubits, _, _)); - (AmpAmpByOracle(1, stateOracle, 0))(qubits); + (StandardAmplitudeAmplification(1, stateOracle, 0))(qubits); ApplyToEachCA(X, flagQubit); } @@ -88,5 +88,5 @@ namespace Microsoft.Quantum.Preparation { controlled auto; adjoint controlled auto; } - + } From 1e645cc7ed251fbe1b2e9cb33d9181d17f508cc1 Mon Sep 17 00:00:00 2001 From: bettinaheim <34236215+bettinaheim@users.noreply.github.com> Date: Fri, 3 Jan 2020 22:28:16 -0800 Subject: [PATCH 07/11] Switching to using the new Sdk (#194) --- Build/props/tests.props | 17 +++++++++++ Build/steps.yml | 4 +-- Chemistry/src/DataModel/DataModel.csproj | 1 - Chemistry/src/Jupyter/Jupyter.csproj | 2 -- Chemistry/src/Runtime/Runtime.csproj | 16 +++++----- .../tests/ChemistryTests/QSharpTests.csproj | 27 +++++------------ .../UnitaryCoupledClusterTests.qs | 2 +- .../tests/DataModelTests/CSharpTests.csproj | 10 +++---- .../tests/SamplesTests/SamplesTests.csproj | 10 +++---- .../tests/SystemTests/SystemTests.csproj | 30 +++++++------------ Numerics/src/Numerics.csproj | 13 ++++---- Numerics/tests/NumericsTests.csproj | 24 ++++----------- Standard/src/Standard.csproj | 13 ++++---- Standard/tests/Standard.Tests.csproj | 25 +++++----------- updateQDKVersion.sh | 7 ++++- 15 files changed, 84 insertions(+), 117 deletions(-) create mode 100644 Build/props/tests.props diff --git a/Build/props/tests.props b/Build/props/tests.props new file mode 100644 index 00000000000..3a231bc74cc --- /dev/null +++ b/Build/props/tests.props @@ -0,0 +1,17 @@ + + + + + false + + + + + + + + + + + + diff --git a/Build/steps.yml b/Build/steps.yml index 2c03754cc15..3f76297789e 100644 --- a/Build/steps.yml +++ b/Build/steps.yml @@ -1,10 +1,10 @@ steps: - task: UseDotNet@2 - displayName: 'Use .NET Core SDK 3.0.100' + displayName: 'Use .NET Core SDK 3.1.100' inputs: packageType: sdk - version: '3.0.100' + version: '3.1.100' - powershell: ./build.ps1 diff --git a/Chemistry/src/DataModel/DataModel.csproj b/Chemistry/src/DataModel/DataModel.csproj index 6c787137998..35bc8eb6b02 100644 --- a/Chemistry/src/DataModel/DataModel.csproj +++ b/Chemistry/src/DataModel/DataModel.csproj @@ -35,7 +35,6 @@ - diff --git a/Chemistry/src/Jupyter/Jupyter.csproj b/Chemistry/src/Jupyter/Jupyter.csproj index da3e74cc8e6..8b0a2728c89 100644 --- a/Chemistry/src/Jupyter/Jupyter.csproj +++ b/Chemistry/src/Jupyter/Jupyter.csproj @@ -26,8 +26,6 @@ - - diff --git a/Chemistry/src/Runtime/Runtime.csproj b/Chemistry/src/Runtime/Runtime.csproj index 2dfbcf8f9c0..48eedf31a98 100644 --- a/Chemistry/src/Runtime/Runtime.csproj +++ b/Chemistry/src/Runtime/Runtime.csproj @@ -1,13 +1,10 @@ - + + netstandard2.1 Microsoft.Quantum.Chemistry.Runtime - bin\$(BuildConfiguration)\$(PlatformTarget)\$(AssemblyName).xml - x64 - - - - True + true + false @@ -15,11 +12,12 @@ - + - + + diff --git a/Chemistry/tests/ChemistryTests/QSharpTests.csproj b/Chemistry/tests/ChemistryTests/QSharpTests.csproj index 573b654a2b9..343d8467fd8 100644 --- a/Chemistry/tests/ChemistryTests/QSharpTests.csproj +++ b/Chemistry/tests/ChemistryTests/QSharpTests.csproj @@ -1,28 +1,15 @@ - + + + + netcoreapp3.0 - x64 - false + false - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + + diff --git a/Chemistry/tests/ChemistryTests/UnitaryCoupledClusterTests.qs b/Chemistry/tests/ChemistryTests/UnitaryCoupledClusterTests.qs index 753ed7b85d8..b9bcc85c262 100644 --- a/Chemistry/tests/ChemistryTests/UnitaryCoupledClusterTests.qs +++ b/Chemistry/tests/ChemistryTests/UnitaryCoupledClusterTests.qs @@ -79,7 +79,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { function _DoublesToComplexPolar(input: Double[]) : ComplexPolar[]{ mutable arr = new ComplexPolar[Length(input)]; for(idx in 0..Length(input)-1){ - set arr w/= idx <- ComplexToComplexPolar(Complex((input[idx],0.))); + set arr w/= idx <- ComplexAsComplexPolar(Complex((input[idx],0.))); } return arr; } diff --git a/Chemistry/tests/DataModelTests/CSharpTests.csproj b/Chemistry/tests/DataModelTests/CSharpTests.csproj index f8af284a8e0..75148d7d6e3 100644 --- a/Chemistry/tests/DataModelTests/CSharpTests.csproj +++ b/Chemistry/tests/DataModelTests/CSharpTests.csproj @@ -18,14 +18,8 @@ - - - - - - @@ -44,6 +38,10 @@ + + + + diff --git a/Chemistry/tests/SamplesTests/SamplesTests.csproj b/Chemistry/tests/SamplesTests/SamplesTests.csproj index cdbfc4688ae..97269f13845 100644 --- a/Chemistry/tests/SamplesTests/SamplesTests.csproj +++ b/Chemistry/tests/SamplesTests/SamplesTests.csproj @@ -12,14 +12,8 @@ - - - - - - @@ -38,6 +32,10 @@ + + + + PreserveNewest diff --git a/Chemistry/tests/SystemTests/SystemTests.csproj b/Chemistry/tests/SystemTests/SystemTests.csproj index f5970bf9457..dea64485fc9 100644 --- a/Chemistry/tests/SystemTests/SystemTests.csproj +++ b/Chemistry/tests/SystemTests/SystemTests.csproj @@ -1,9 +1,10 @@ - + + + netcoreapp3.0 - x64 - false + false @@ -11,23 +12,7 @@ PreserveNewest - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + PreserveNewest @@ -43,6 +28,10 @@ + + + + @@ -50,3 +39,4 @@ + diff --git a/Numerics/src/Numerics.csproj b/Numerics/src/Numerics.csproj index 53c33d5ee9c..5ab73d11b8c 100644 --- a/Numerics/src/Numerics.csproj +++ b/Numerics/src/Numerics.csproj @@ -1,8 +1,10 @@ - + + netstandard2.1 Microsoft.Quantum.Numerics - x64 + true + false @@ -30,10 +32,9 @@ - - - - + + + diff --git a/Numerics/tests/NumericsTests.csproj b/Numerics/tests/NumericsTests.csproj index e8c9b86e785..815adfdd7e6 100644 --- a/Numerics/tests/NumericsTests.csproj +++ b/Numerics/tests/NumericsTests.csproj @@ -1,28 +1,14 @@ - - - netcoreapp3.0 - x64 - false - latest - + + + - 0162 + netcoreapp3.0 + false - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index 5a44aad43cb..c755fa64823 100644 --- a/Standard/src/Standard.csproj +++ b/Standard/src/Standard.csproj @@ -1,14 +1,14 @@ - + + netstandard2.1 Microsoft.Quantum.Standard - x64 + true + false + 1591 - 0162 - 1591 - True Microsoft Microsoft's Quantum standard libraries. © Microsoft Corporation. All rights reserved. @@ -30,7 +30,8 @@ - + + diff --git a/Standard/tests/Standard.Tests.csproj b/Standard/tests/Standard.Tests.csproj index 0be3d1c80a1..616a30db2d4 100644 --- a/Standard/tests/Standard.Tests.csproj +++ b/Standard/tests/Standard.Tests.csproj @@ -1,30 +1,19 @@ - + + + + netcoreapp3.0 - x64 - false - latest Microsoft.Quantum.Standard.Tests - - - - 0162 + false - - + + - - - - - - - - diff --git a/updateQDKVersion.sh b/updateQDKVersion.sh index 9f6b10b1eb2..425337a6cb6 100644 --- a/updateQDKVersion.sh +++ b/updateQDKVersion.sh @@ -15,7 +15,7 @@ else fi : ${ver:="$NUGET_VERSION"} -: ${pkgs:="Microsoft.Quantum.Development.Kit;Microsoft.Quantum.IQSharp.Core;Microsoft.Quantum.Simulators;Microsoft.Quantum.Compiler;Microsoft.Quantum.Canon;Microsoft.Quantum.Xunit;Microsoft.Quantum.Chemistry;Microsoft.Quantum.Research"} +: ${pkgs:="Microsoft.Quantum.CsharpGeneration;Microsoft.Quantum.Runtime.Core;Microsoft.Quantum.QSharp.Core;Microsoft.Quantum.Development.Kit;Microsoft.Quantum.IQSharp.Core;Microsoft.Quantum.Simulators;Microsoft.Quantum.Compiler;Microsoft.Quantum.Xunit;Microsoft.Quantum.Chemistry;Microsoft.Quantum.Research"} for pkg in `echo $pkgs | tr ";" "\n"`; do @@ -23,8 +23,13 @@ for pkg in `echo $pkgs | tr ";" "\n"`; do grep --include=\packages.config -lri -e "package *id=\"$pkg\" *version=" * | xargs sed -i $backup "s/package *id=\"$pkg\" *version=\"\([^\"]*\)\"/package id=\"$pkg\" version=\"$ver\"/i" grep --include=\*proj -lri -e "PackageReference *Include=\"$pkg\" *Version=" * | xargs sed -i $backup "s/PackageReference *Include=\"$pkg\" *Version=\"\([^\"]*\)\"/PackageReference Include=\"$pkg\" Version=\"$ver\"/i" + grep --include=*props -lri -e "PackageReference *Include=\"$pkg\" *Version=" * | xargs sed -i $backup "s/PackageReference *Include=\"$pkg\" *Version=\"\([^\"]*\)\"/PackageReference Include=\"$pkg\" Version=\"$ver\"/i" done +# Update the version number of the Quantum Sdk: +grep --include=*proj -lri -e "Sdk=\"Microsoft.Quantum.Sdk\/" * | xargs sed -i $backup "s/Sdk=\"Microsoft.Quantum.Sdk\/\([^\"]*\)\"/Sdk=\"Microsoft.Quantum.Sdk\/$ver\"/i" +grep --include=*Template.xml -lri -e "Sdk=\"Microsoft.Quantum.Sdk\/" * | xargs sed -i $backup "s/Sdk=\"Microsoft.Quantum.Sdk\/\([^\"]*\)\"/Sdk=\"Microsoft.Quantum.Sdk\/$ver\"/i" + echo done! echo From f2bb6111058b6b90f954acc79d453edf88ddbe32 Mon Sep 17 00:00:00 2001 From: numpde <21158052+numpde@users.noreply.github.com> Date: Tue, 7 Jan 2020 01:44:57 +0100 Subject: [PATCH 08/11] Minor doc fixes (#190) * Minor doc fixes * Minor doc cleanup There are probably still some unstated assumptions on the algorithms. * Add "# Description" for MultiplyByModularInteger ...because there is inline math. Co-Authored-By: Chris Granade * "unitary operation" instead of "unitary operator" Co-Authored-By: Chris Granade * Add "# Description", remove refs in "# Summary" Co-authored-by: Chris Granade --- Standard/src/Arithmetic/Modular.qs | 68 ++++++++++++++++++------------ 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/Standard/src/Arithmetic/Modular.qs b/Standard/src/Arithmetic/Modular.qs index a2650934558..2f9bea6c89d 100644 --- a/Standard/src/Arithmetic/Modular.qs +++ b/Standard/src/Arithmetic/Modular.qs @@ -11,28 +11,31 @@ namespace Microsoft.Quantum.Arithmetic { /// # Summary /// Performs a modular increment of a qubit register by an integer constant. /// - /// Let us denote `increment` by a, `modulus` by N and integer encoded in `target` by y + /// # Description + /// Let us denote `increment` by $a$, `modulus` by $N$ and integer encoded in `target` by $y$. /// Then the operation performs the following transformation: /// \begin{align} - /// \ket{y} \mapsto \ket{y + 1 \operatorname{mod} N} + /// \ket{y} \mapsto \ket{(y + a) \operatorname{mod} N} /// \end{align} /// Integers are encoded in little-endian format. /// /// # Input /// ## increment - /// Integer increment a to be added to y. + /// Integer increment $a$ to be added to $y$. /// ## modulus - /// Integer N that mods y + a. + /// Integer $N$ that mods $y + a$. /// ## target - /// Integer y in `LittleEndian` format that `increment` a is added to. + /// Integer $y$ in `LittleEndian` format that `increment` $a$ is added to. /// /// # See Also - /// - IncrementPhaseByModularInteger + /// - Microsoft.Quantum.Arithmetic.IncrementPhaseByModularInteger /// /// # Remarks - /// Assumes that the value of target is less than N. Note that + /// Assumes that the initial value of target is less than $N$ + /// and that the increment $a$ is less than $N$. + /// Note that /// implements - /// the same operation, but in the `PhaseLittleEndian` basis. + /// the same operation in the `PhaseLittleEndian` basis. operation IncrementByModularInteger(increment : Int, modulus : Int, target : LittleEndian) : Unit { body (...) { let inner = IncrementPhaseByModularInteger(increment, modulus, _); @@ -50,17 +53,20 @@ namespace Microsoft.Quantum.Arithmetic { /// # Summary /// Performs a modular increment of a qubit register by an integer constant. /// - /// Let us denote `increment` by a, `modulus` by N and integer encoded in `target` by y + /// # Description + /// Let us denote `increment` by $a$, `modulus` by $N$ and integer encoded in `target` by $y$. /// Then the operation performs the following transformation: - /// |y⟩ ↦ |y+a (mod N)⟩ - /// Integers are encoded in little-endian format in QFT basis + /// \begin{align} + /// \ket{y} \mapsto \ket{(y + a) \operatorname{mod} N} + /// \end{align} + /// Integers are encoded in little-endian format in QFT basis. /// /// # See Also - /// - Microsoft.Quantum.Canon.ModularIncrementLE + /// - Microsoft.Quantum.Arithmetic.IncrementByModularInteger /// /// # Remarks /// Assumes that `target` has the highest bit set to 0. - /// Also assumes that the value of target is less than N. + /// Also assumes that the value of target is less than $N$. /// /// For the circuit diagram and explanation see Figure 5 on [Page 5 /// of arXiv:quant-ph/0205095v3](https://arxiv.org/pdf/quant-ph/0205095v3.pdf#page=5). @@ -113,10 +119,11 @@ namespace Microsoft.Quantum.Arithmetic { /// # Summary /// Performs a modular multiply-and-add by integer constants on a qubit register. /// + /// # Description /// Implements the map /// $$ /// \begin{align} - /// \ket{x} \ket{b} \mapsto \ket{x} \ket{b + a \cdot x \operatorname{mod} N} + /// \ket{x} \ket{b} \mapsto \ket{x} \ket{(b + a \cdot x) \operatorname{mod} N} /// \end{align} /// $$ /// for a given modulus $N$, constant multiplier $a$, and summand $y$. @@ -133,6 +140,9 @@ namespace Microsoft.Quantum.Arithmetic { /// A quantum register representing an unsigned integer to use as the target /// for this operation. /// + /// # See Also + /// - Microsoft.Quantum.Arithmetic.MultiplyAndAddPhaseByModularInteger + /// /// # Remarks /// - For the circuit diagram and explanation see Figure 6 on [Page 7 /// of arXiv:quant-ph/0205095v3](https://arxiv.org/pdf/quant-ph/0205095v3.pdf#page=7) @@ -153,15 +163,15 @@ namespace Microsoft.Quantum.Arithmetic { } /// # Summary - /// The same as ModularAddProductLE, but assumes that summand encodes - /// integers in QFT basis - /// - /// # See Also - /// - Microsoft.Quantum.Canon.ModularAddProductLE + /// The same as MultiplyAndAddByModularInteger, but assumes that the summand encodes + /// integers in QFT basis. /// /// # Remarks /// Assumes that `phaseSummand` has the highest bit set to 0. - /// Also assumes that the value of `phaseSummand` is less than N. + /// Also assumes that the value of `phaseSummand` is less than $N$. + /// + /// # See Also + /// - Microsoft.Quantum.Arithmetic.MultiplyAndAddByModularInteger operation MultiplyAndAddPhaseByModularInteger(constMultiplier : Int, modulus : Int, multiplier : LittleEndian, phaseSummand : PhaseLittleEndian) : Unit is Adj + Ctl { EqualityFactB(modulus <= 2 ^ (Length(phaseSummand!) - 1), true, $"`multiplier` must be big enough to fit integers modulo `modulus`" + $"with highest bit set to 0"); EqualityFactB(constMultiplier >= 0 and constMultiplier < modulus, true, $"`constMultiplier` must be between 0 and `modulus`-1"); @@ -183,19 +193,25 @@ namespace Microsoft.Quantum.Arithmetic { /// # Summary /// Performs modular multiplication by an integer constant on a qubit register. /// - /// Let us denote modulus by N and constMultiplier by a - /// then this operation implements a unitary defined by the following map on + /// # Description + /// Let us denote `modulus` by $N$ and `constMultiplier` by $a$. + /// Then this operation implements a unitary operation defined by the following map on the /// computational basis: - /// |y⟩ ↦ |a⋅y (mod N) ⟩, for all y between 0 and N - 1 + /// $$ + /// \begin{align} + /// \ket{y} \mapsto \ket{(a \cdot y) \operatorname{mod} N} + /// \end{align} + /// $$ + /// for all $y$ between $0$ and $N - 1$. /// /// # Input /// ## constMultiplier /// Constant by which multiplier is being multiplied. Must be co-prime to modulus. /// ## modulus - /// The multiplication operation is performed modulo `modulus` + /// The multiplication operation is performed modulo `modulus`. /// ## multiplier /// The number being multiplied by a constant. - /// This is an array of qubits representing integer in little-endian bit order. + /// This is an array of qubits encoding an integer in little-endian format. /// /// # Remarks /// - For the circuit diagram and explanation see Figure 7 on [Page 8 @@ -204,7 +220,7 @@ namespace Microsoft.Quantum.Arithmetic { /// [arXiv:quant-ph/0205095v3](https://arxiv.org/pdf/quant-ph/0205095v3.pdf) operation MultiplyByModularInteger(constMultiplier : Int, modulus : Int, multiplier : LittleEndian) : Unit is Adj + Ctl { // Check the preconditions using Microsoft.Quantum.Canon.EqualityFactB - EqualityFactB(constMultiplier >= 0 and constMultiplier < modulus, true, $"`constMultiplier` must be between 0 and `modulus`"); + EqualityFactB(0 <= constMultiplier and constMultiplier < modulus, true, $"`constMultiplier` must be between 0 and `modulus`"); EqualityFactB(modulus <= 2 ^ Length(multiplier!), true, $"`multiplier` must be big enough to fit integers modulo `modulus`"); EqualityFactB(IsCoprimeI(constMultiplier, modulus), true, $"`constMultiplier` and `modulus` must be co-prime"); From 866f2905cc94959e5f9791c289bf887bd1f92b34 Mon Sep 17 00:00:00 2001 From: Andres Paz Date: Wed, 8 Jan 2020 23:15:16 -0800 Subject: [PATCH 09/11] Build pipeline tweaks (#202) --- Chemistry/Common/267DevDivSNKey2048.snk | Bin 288 -> 0 bytes Chemistry/Common/DelaySign.cs | 2 +- Standard/Common/267DevDivSNKey2048.snk | Bin 288 -> 0 bytes Standard/Common/DelaySign.cs | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 Chemistry/Common/267DevDivSNKey2048.snk delete mode 100644 Standard/Common/267DevDivSNKey2048.snk diff --git a/Chemistry/Common/267DevDivSNKey2048.snk b/Chemistry/Common/267DevDivSNKey2048.snk deleted file mode 100644 index 7a1fffb890a43a90273251a13141c1b92d5b2672..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 288 zcmV+*0pI=rBme*mfB*m#0RR970ssI2Bme+XQ$aBR2mk;90097DGnudPj`5axxzmR}d}v>#e4lBjR&}2Era&fE7}!jUWnTqBY9YFX4_ zm5IimTdxd3d8Bg@*(FuY0BX#OSy}SEZV=;O!$mit(q`I#g@t8<$X$Wje?Gt-*;Y(g z**$SQ&=)L@BcTrhIk*g#uy;1~*svm0Do%7I8ec;wBr%IMIi;Y7_~kt>6JMO9e><|_ z3jYf5gp~yQeCj{(lH85p?X6_Sj{W0IR?`BlRsC*&^8(fH&Fbk>WsNjaRvTY7#X|4f m-JghsIMZ~_@dm8-**Zi;!^b??5%5axxzmR}d}v>#e4lBjR&}2Era&fE7}!jUWnTqBY9YFX4_ zm5IimTdxd3d8Bg@*(FuY0BX#OSy}SEZV=;O!$mit(q`I#g@t8<$X$Wje?Gt-*;Y(g z**$SQ&=)L@BcTrhIk*g#uy;1~*svm0Do%7I8ec;wBr%IMIi;Y7_~kt>6JMO9e><|_ z3jYf5gp~yQeCj{(lH85p?X6_Sj{W0IR?`BlRsC*&^8(fH&Fbk>WsNjaRvTY7#X|4f m-JghsIMZ~_@dm8-**Zi;!^b??5%5 Date: Wed, 15 Jan 2020 12:14:02 -0800 Subject: [PATCH 10/11] Code quality improvements (#203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Improve code quality with experimental linter. * Fixed a couple mistakes in previous cleanup. * More fixes to resolve linting issues. * Remove extraneous comment. * Applied feedback from #198. * Applying more documentation fixes suggested by linter. * Fix to deprecation stub. * Whitespace fix noted by @ScottCarda-MS. * Fixed minor mistake introduced with previous code quality fix. * Incorporated more feedback from @ScottCarda-MS. * Update Standard/src/Arrays/Map.qs Co-Authored-By: Alan Geller * Update Standard/src/Canon/Combinators/ApplyIf.qs Co-Authored-By: Alan Geller * Update Standard/src/Canon/Combinators/ApplyIf.qs Co-Authored-By: Alan Geller * Update Standard/src/Canon/Combinators/ApplyIf.qs Co-Authored-By: Alan Geller * Update Standard/src/Arithmetic/Integer.qs Co-Authored-By: Alan Geller * Update Standard/src/Arithmetic/Integer.qs Co-Authored-By: Alan Geller * Update Standard/src/Canon/Combinators/ApplyIf.qs Co-Authored-By: Alan Geller * Update Standard/src/Arithmetic/Integer.qs Co-Authored-By: Alan Geller * Update Standard/src/Arithmetic/Integer.qs Co-Authored-By: Alan Geller * Update Standard/src/Arithmetic/Integer.qs Co-Authored-By: Alan Geller * Update Standard/src/Arithmetic/Integer.qs Co-Authored-By: Alan Geller * Addressing feedback, lots of indentation fixes. * Deprecate the stack data structure. * Slight improvements to phase est operations. * Add missing characteristics to CNOTChainTarget. * CCNOTChainTarget → ApplyCNOTChainWithTarget * Workaround for kata oracle counting. Co-authored-by: Alan Geller --- .../StandardAlgorithms.qs | 5 - Standard/src/Arithmetic/ApplyDual.qs | 132 ++++--- Standard/src/Arithmetic/Arithmetic.qs | 46 +-- Standard/src/Arithmetic/Asserts.qs | 7 +- Standard/src/Arithmetic/Comparators.qs | 16 +- Standard/src/Arithmetic/Deprecated.qs | 17 +- Standard/src/Arithmetic/Integer.qs | 373 ++++++++---------- Standard/src/Arithmetic/Modular.qs | 65 +-- Standard/src/Arrays/Arrays.qs | 4 +- Standard/src/Arrays/Map.qs | 5 +- Standard/src/Canon/And.qs | 4 +- Standard/src/Canon/Combinators/ApplyIf.qs | 16 +- .../Canon/Combinators/ApplyMultiControlled.qs | 33 +- Standard/src/Canon/Combinators/Bind.qs | 158 +++----- Standard/src/Canon/Combinators/Compose.qs | 27 +- Standard/src/Canon/Combinators/Curry.qs | 111 +++--- .../src/Canon/Combinators/OperationPow.qs | 115 +++--- Standard/src/Canon/Combinators/With.qs | 2 +- Standard/src/Canon/CommonGates.qs | 8 +- Standard/src/Canon/DataStructures/Stack.qs | 124 ++---- Standard/src/Canon/Deprecated.qs | 19 + Standard/src/Canon/Enumeration/Trotter.qs | 41 +- .../Canon/IterateThroughCartesianProduct.qs | 109 +++-- Standard/src/Canon/Parity.qs | 60 ++- Standard/src/Characterization/Deprecated.qs | 16 + .../Characterization/Distinguishability.qs | 8 +- .../PhaseEstimation/Iterative.qs | 86 ++-- .../PhaseEstimation/Robust.qs | 8 +- .../src/Characterization/ProcessTomography.qs | 16 - Standard/src/Convert/Deprecated.qs | 2 +- Standard/src/ErrorCorrection/BitFlipCode.qs | 40 +- Standard/src/ErrorCorrection/KnillDistill.qs | 123 +++--- Standard/src/Measurement/Registers.qs | 17 + Standard/src/Oracles/Convert.qs | 40 +- Standard/src/Simulation/BlockEncoding.qs | 152 ++++--- .../QubitizationPauliEvolutionSet.qs | 65 ++- Standard/tests/IntegerTests.qs | 36 +- 37 files changed, 985 insertions(+), 1121 deletions(-) create mode 100644 Standard/src/Characterization/Deprecated.qs diff --git a/Standard/src/AmplitudeAmplification/StandardAlgorithms.qs b/Standard/src/AmplitudeAmplification/StandardAlgorithms.qs index 9bedaeee3d8..6df9d1d5a4f 100644 --- a/Standard/src/AmplitudeAmplification/StandardAlgorithms.qs +++ b/Standard/src/AmplitudeAmplification/StandardAlgorithms.qs @@ -28,11 +28,6 @@ namespace Microsoft.Quantum.AmplitudeAmplification { return ReflectionPhases(startPhases, targetPhases); } - // We use the phases in "Fixed-Point Amplitude Amplification with an - // Optimal Number of Queires" [YoderLowChuang2014] - // See also "Methodology of composite quantum gates" [LowYoderChuang2016] - // for phases in the `RotationPhases` format - /// # Summary /// Computes partial reflection phases for fixed-point amplitude /// amplification. diff --git a/Standard/src/Arithmetic/ApplyDual.qs b/Standard/src/Arithmetic/ApplyDual.qs index 5f7433d0cbe..cf2cd277131 100644 --- a/Standard/src/Arithmetic/ApplyDual.qs +++ b/Standard/src/Arithmetic/ApplyDual.qs @@ -47,11 +47,11 @@ namespace Microsoft.Quantum.Arithmetic { op(phaseLE); Adjoint QFTLE(target); } - + adjoint invert; } - - + + /// # See Also /// - @"microsoft.quantum.canon.applyphaseleoperationonle" operation ApplyPhaseLEOperationOnLEC (op : (PhaseLittleEndian => Unit is Ctl), target : LittleEndian) : Unit @@ -63,7 +63,7 @@ namespace Microsoft.Quantum.Arithmetic { op(phaseLE); Adjoint QFTLE(target); } - + controlled (controls, ...) { QFTLE(target); @@ -72,8 +72,8 @@ namespace Microsoft.Quantum.Arithmetic { Adjoint QFTLE(target); } } - - + + /// # See Also /// - @"microsoft.quantum.canon.applyphaseleoperationonle" operation ApplyPhaseLEOperationOnLECA (op : (PhaseLittleEndian => Unit is Adj + Ctl), target : LittleEndian) : Unit @@ -85,9 +85,9 @@ namespace Microsoft.Quantum.Arithmetic { op(phaseLE); Adjoint QFTLE(target); } - + adjoint invert; - + controlled (controls, ...) { QFTLE(target); @@ -95,11 +95,11 @@ namespace Microsoft.Quantum.Arithmetic { Controlled op(controls, phaseLE); Adjoint QFTLE(target); } - + controlled adjoint invert; } - - + + /// # Summary /// Applies an operation that takes a /// register as input @@ -118,56 +118,94 @@ namespace Microsoft.Quantum.Arithmetic { /// /// # See Also /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLEA - /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLEA + /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLEC /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLECA operation ApplyLEOperationOnPhaseLE (op : (LittleEndian => Unit), target : PhaseLittleEndian) : Unit { let targetLE = LittleEndian(target!); ApplyWith(Adjoint QFTLE, op, targetLE); } - - + + + + /// # Summary + /// Applies an operation that takes a + /// register as input + /// on a target register of type . + /// + /// # Input + /// ## op + /// The operation to be applied. + /// ## target + /// The register to which the operation is applied. + /// + /// # Remarks + /// The register is transformed to `LittleEndian` by the use of + /// and is then returned to + /// its original representation after application of `op`. + /// /// # See Also /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLE - operation ApplyLEOperationOnPhaseLEA (op : (LittleEndian => Unit is Adj), target : PhaseLittleEndian) : Unit - { - body (...) - { - let targetLE = LittleEndian(target!); - ApplyWithA(Adjoint QFTLE, op, targetLE); - } - - adjoint invert; + /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLEC + /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLECA + operation ApplyLEOperationOnPhaseLEA (op : (LittleEndian => Unit is Adj), target : PhaseLittleEndian) + : Unit is Adj { + let targetLE = LittleEndian(target!); + ApplyWithA(Adjoint QFTLE, op, targetLE); } - - + + + /// # Summary + /// Applies an operation that takes a + /// register as input + /// on a target register of type . + /// + /// # Input + /// ## op + /// The operation to be applied. + /// ## target + /// The register to which the operation is applied. + /// + /// # Remarks + /// The register is transformed to `LittleEndian` by the use of + /// and is then returned to + /// its original representation after application of `op`. + /// /// # See Also /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLE - operation ApplyLEOperationOnPhaseLEC (op : (LittleEndian => Unit is Ctl), target : PhaseLittleEndian) : Unit - { - body (...) - { - let targetLE = LittleEndian(target!); - ApplyWithC(Adjoint QFTLE, op, targetLE); - } - - controlled distribute; + /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLEA + /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLECA + operation ApplyLEOperationOnPhaseLEC (op : (LittleEndian => Unit is Ctl), target : PhaseLittleEndian) + : Unit is Ctl { + let targetLE = LittleEndian(target!); + ApplyWithC(Adjoint QFTLE, op, targetLE); } - - + + + /// # Summary + /// Applies an operation that takes a + /// register as input + /// on a target register of type . + /// + /// # Input + /// ## op + /// The operation to be applied. + /// ## target + /// The register to which the operation is applied. + /// + /// # Remarks + /// The register is transformed to `LittleEndian` by the use of + /// and is then returned to + /// its original representation after application of `op`. + /// /// # See Also /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLE - operation ApplyLEOperationOnPhaseLECA (op : (LittleEndian => Unit is Adj + Ctl), target : PhaseLittleEndian) : Unit - { - body (...) - { - let targetLE = LittleEndian(target!); - ApplyWithCA(Adjoint QFTLE, op, targetLE); - } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; + /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLEA + /// - Microsoft.Quantum.Canon.ApplyLEOperationonPhaseLEC + operation ApplyLEOperationOnPhaseLECA(op : (LittleEndian => Unit is Adj + Ctl), target : PhaseLittleEndian) + : Unit is Adj + Ctl { + let targetLE = LittleEndian(target!); + ApplyWithCA(Adjoint QFTLE, op, targetLE); } } diff --git a/Standard/src/Arithmetic/Arithmetic.qs b/Standard/src/Arithmetic/Arithmetic.qs index 1e159d11862..189d0e79ce3 100644 --- a/Standard/src/Arithmetic/Arithmetic.qs +++ b/Standard/src/Arithmetic/Arithmetic.qs @@ -8,7 +8,12 @@ namespace Microsoft.Quantum.Arithmetic { open Microsoft.Quantum.Arrays; /// # Summary - /// Applies `X` operations to qubits in a little-endian register based on 1 bits in an integer. + /// Applies a bitwise-XOR operation between a classical integer and an + /// integer represented by a register of qubits. + /// + /// # Description + /// Applies `X` operations to qubits in a little-endian register based on + /// 1 bits in an integer. /// /// Let us denote `value` by a and let y be an unsigned integer encoded in `target`, /// then `InPlaceXorLE` performs an operation given by the following map: @@ -19,21 +24,20 @@ namespace Microsoft.Quantum.Arithmetic { /// An integer which is assumed to be non-negative. /// ## target /// A quantum register which is used to store `value` in little-endian encoding. - operation ApplyXorInPlace(value : Int, target : LittleEndian) : Unit { - body (...) { - ApplyToEachCA( - CControlledCA(X), - Zip(IntAsBoolArray(value, Length(target!)), target!) - ); - } - - adjoint auto; - controlled auto; - controlled adjoint auto; + operation ApplyXorInPlace(value : Int, target : LittleEndian) + : Unit is Adj + Ctl { + ApplyToEachCA( + CControlledCA(X), + Zip(IntAsBoolArray(value, Length(target!)), target!) + ); } /// # Summary - /// This computes the Majority function in-place on 3 qubits. + /// Applies the three-qubit majority operation in-place on a register of + /// qubits. + /// + /// # Description + /// This operation computes the majority function in-place on 3 qubits. /// /// If we denote output qubit as $z$ and input qubits as $x$ and $y$, /// the operation performs the following transformation: @@ -45,17 +49,13 @@ namespace Microsoft.Quantum.Arithmetic { /// and stored in this qubit. /// ## input /// Second and third input qubits. - operation InPlaceMajority(output: Qubit, input: Qubit[]) : Unit { - body (...) { - if (Length(input) == 2) { - MAJ(input[0], input[1], output); - } else { - fail $"The in-place majority operation on {Length(input)} is qubits not yet implemented."; - } + operation ApplyMajorityInPlace(output: Qubit, input: Qubit[]) + : Unit is Adj + Ctl { + if (Length(input) == 2) { + MAJ(input[0], input[1], output); + } else { + fail $"The in-place majority operation on {Length(input)} is qubits not yet implemented."; } - adjoint auto; - controlled auto; - adjoint controlled auto; } /// # Summary diff --git a/Standard/src/Arithmetic/Asserts.qs b/Standard/src/Arithmetic/Asserts.qs index 41cf8e722b6..3d9201c2486 100644 --- a/Standard/src/Arithmetic/Asserts.qs +++ b/Standard/src/Arithmetic/Asserts.qs @@ -9,9 +9,10 @@ namespace Microsoft.Quantum.Arithmetic { open Microsoft.Quantum.Diagnostics; /// # Summary - /// Asserts that the probability of a specific state of a quantum register has the - /// expected value. - /// + /// Asserts that the probability of a specific state of a quantum register has the + /// expected value. + /// + /// # Description /// Given an $n$-qubit quantum state $\ket{\psi}=\sum^{2^n-1}_{j=0}\alpha_j \ket{j}$, /// asserts that the probability $|\alpha_j|^2$ of the state $\ket{j}$ indexed by $j$ /// has the expected value. diff --git a/Standard/src/Arithmetic/Comparators.qs b/Standard/src/Arithmetic/Comparators.qs index 3f1d5d3cc10..c6898baa6f6 100644 --- a/Standard/src/Arithmetic/Comparators.qs +++ b/Standard/src/Arithmetic/Comparators.qs @@ -7,16 +7,20 @@ namespace Microsoft.Quantum.Arithmetic { open Microsoft.Quantum.Arrays; /// # Summary - /// This unitary tests if two integers `x` and `y` stored in equal-size qubit registers - /// satisfy `x > y`. If true, 1 is XORed into an output - /// qubit. Otherwise, 0 is XORed into an output qubit. + /// This operation tests if an integer represented by a register of qubits + /// is greater than another integer, applying an XOR of the result onto an + /// output qubit. /// - /// In other words, this unitary $U$ satisfies: + /// # Description + /// Given two integers `x` and `y` stored in equal-size qubit registers, + /// this operation checks if they satisfy `x > y`. If true, 1 is + /// XORed into an output qubit. Otherwise, 0 is XORed into an output qubit. + /// In other words, this operation can be represented by the unitary /// $$ /// \begin{align} - /// U\ket{x}\ket{y}\ket{z}=\ket{x}\ket{y}\ket{z\oplus (x>y)}. + /// U\ket{x}\ket{y}\ket{z} = \ket{x}\ket{y}\ket{z\oplus (x>y)}. /// \end{align} - /// $$. + /// $$ /// /// # Input /// ## x diff --git a/Standard/src/Arithmetic/Deprecated.qs b/Standard/src/Arithmetic/Deprecated.qs index b7d27b407b1..5de14dbe09c 100644 --- a/Standard/src/Arithmetic/Deprecated.qs +++ b/Standard/src/Arithmetic/Deprecated.qs @@ -46,7 +46,7 @@ namespace Microsoft.Quantum.Canon { operation ApplyReversedOpBigEndianA(op : (BigEndian => Unit is Adj), register : LittleEndian) : Unit is Adj { ApplyReversedOpBEA(op, register); } - + /// # Deprecated /// Please use @"Microsoft.Quantum.Arithmetic.ApplyReversedOpBEC". @Deprecated("Microsoft.Quantum.Arithmetic.ApplyReversedOpBEC") @@ -193,4 +193,19 @@ namespace Microsoft.Quantum.Canon { CopyMostSignificantBit(from, target); } + /// # Deprecated + /// Please use @"microsoft.quantum.canon.applycnotchain". + @Deprecated("Microsoft.Quantum.Canon.ApplyCNOTChain") + operation CascadeCNOT (register : Qubit[]) : Unit is Adj + Ctl { + Microsoft.Quantum.Canon.ApplyCNOTChain(register); + } + + /// # Deprecated + /// Please use @"microsoft.quantum.arithmetic.applymajorityinplace". + @Deprecated("Microsoft.Quantum.Arithmetic.ApplyMajorityInPlace") + operation InPlaceMajority(output: Qubit, input: Qubit[]) + : Unit is Adj + Ctl { + ApplyMajorityInPlace(output, input); + } + } diff --git a/Standard/src/Arithmetic/Integer.qs b/Standard/src/Arithmetic/Integer.qs index 89ef34fd08a..07c9d9a306a 100644 --- a/Standard/src/Arithmetic/Integer.qs +++ b/Standard/src/Arithmetic/Integer.qs @@ -23,7 +23,8 @@ namespace Microsoft.Quantum.Arithmetic { /// `summand1` and `summand2`. /// ## carryOut /// Carry-out qubit, will be xored with the higher bit of the sum. - operation Carry (carryIn: Qubit, summand1: Qubit, summand2: Qubit, carryOut: Qubit) : Unit is Adj + Ctl { + operation Carry(carryIn: Qubit, summand1: Qubit, summand2: Qubit, carryOut: Qubit) + : Unit is Adj + Ctl { CCNOT (summand1, summand2, carryOut); CNOT (summand1, summand2); CCNOT (carryIn, summand2, carryOut); @@ -46,43 +47,14 @@ namespace Microsoft.Quantum.Arithmetic { /// /// # Remarks /// In contrast to the `Carry` operation, this does not compute the carry-out bit. - operation Sum (carryIn: Qubit, summand1: Qubit, summand2: Qubit) : Unit - { - body (...) { - CNOT (summand1, summand2); - CNOT (carryIn, summand2); - } - adjoint auto; - controlled auto; - adjoint controlled auto; - } - - /// # Summary - /// Implements a cascade of CNOT gates on neighboring qubits in a given qubit - /// register, starting from the qubit at position 0 as control to the qubit at - /// position 1 as the target, then from the qubit at position 1 as the control to - /// the qubit at position 2 as the target, etc., ending with the qubit in position - /// `Length(register)-1` as the target. - /// - /// # Input - /// ## register - /// Qubit register. - operation CascadeCNOT (register : Qubit[]) : Unit - { - body (...) { - let nQubits = Length(register); - - for ( idx in 0..(nQubits-2) ) { - CNOT(register[idx], register[idx+1]); - } - } - adjoint auto; - controlled auto; - adjoint controlled auto; + operation Sum(carryIn: Qubit, summand1: Qubit, summand2: Qubit) + : Unit is Adj + Ctl { + CNOT(summand1, summand2); + CNOT(carryIn, summand2); } /// # Summary - /// Implements a cascade of CCNOT gates controlled on corresponding bits of two + /// Implements a cascade of CCNOT gates controlled on corresponding bits of two /// qubit registers, acting on the next qubit of one of the registers. /// Starting from the qubits at position 0 in both registers as controls, CCNOT is /// applied to the qubit at position 1 of the target register, then controlled by @@ -92,42 +64,37 @@ namespace Microsoft.Quantum.Arithmetic { /// # Input /// ## register /// Qubit register, only used for controls. - /// ## target + /// ## targets /// Qubit register, used for controls and as target. /// /// # Remarks /// The target qubit register must have one qubit more than the other register. - operation CascadeCCNOT (register : Qubit[], targets : Qubit[]) : Unit - { - body (...) { - let nQubits = Length(targets); + operation CascadeCCNOT(register : Qubit[], targets : Qubit[]) + : Unit is Adj + Ctl { + let nQubits = Length(targets); - EqualityFactB( - nQubits == Length(register)+1, true, - "Target register must have one more qubit." ); + EqualityFactB( + nQubits == Length(register)+1, true, + "Target register must have one more qubit." ); - for ( idx in 0..(nQubits-2) ) { - CCNOT(register[idx], targets[idx], targets[idx+1]); - } + for ( idx in 0..(nQubits-2) ) { + CCNOT(register[idx], targets[idx], targets[idx+1]); } - adjoint auto; - controlled auto; - adjoint controlled auto; } /// # Summary - /// Reversible, in-place ripple-carry addition of two integers. + /// Reversible, in-place ripple-carry addition of two integers. /// Given two $n$-bit integers encoded in LittleEndian registers `xs` and `ys`, - /// and a qubit carry, the operation computes the sum of the two integers - /// where the $n$ least significant bits of the result are held in `ys` and - /// the carry out bit is xored to the qubit `carry`. + /// and a qubit carry, the operation computes the sum of the two integers + /// where the $n$ least significant bits of the result are held in `ys` and + /// the carry out bit is xored to the qubit `carry`. /// /// # Input /// ## xs /// LittleEndian qubit register encoding the first integer summand. /// ## ys - /// LittleEndian qubit register encoding the second integer summand, is + /// LittleEndian qubit register encoding the second integer summand, is /// modified to hold the $n$ least significant bits of the sum. /// ## carry /// Carry qubit, is xored with the most significant bit of the sum. @@ -135,17 +102,16 @@ namespace Microsoft.Quantum.Arithmetic { /// # References /// - Thomas G. Draper: "Addition on a Quantum Computer", 2000. /// https://arxiv.org/abs/quant-ph/0008033 - /// - /// # Remarks - /// The specified controlled operation makes use of symmetry and mutual + /// + /// # Remarks + /// The specified controlled operation makes use of symmetry and mutual /// cancellation of operations to improve on the default implementation /// that adds a control to every operation. - operation RippleCarryAdderD (xs : LittleEndian, ys : LittleEndian, carry : Qubit) : Unit - { + operation RippleCarryAdderD(xs : LittleEndian, ys : LittleEndian, carry : Qubit) + : Unit is Adj + Ctl { body (...) { - (Controlled RippleCarryAdderD) (new Qubit[0], (xs, ys, carry)); + Controlled RippleCarryAdderD(new Qubit[0], (xs, ys, carry)); } - adjoint auto; controlled ( controls, ... ) { let nQubits = Length(xs!); @@ -167,15 +133,14 @@ namespace Microsoft.Quantum.Arithmetic { } } } - adjoint controlled auto; } - + /// # Summary - /// Reversible, in-place ripple-carry operation that is used in the - /// integer addition operation RippleCarryAdderCDKM below. + /// Reversible, in-place ripple-carry operation that is used in the + /// integer addition operation RippleCarryAdderCDKM below. /// Given two qubit registers `xs` and `ys` of the same length, the operation /// applies a ripple carry sequence of CNOT and CCNOT gates with qubits - /// in `xs` and `ys` as the controls and qubits in `xs` as the targets. + /// in `xs` and `ys` as the controls and qubits in `xs` as the targets. /// /// # Input /// ## xs @@ -186,7 +151,7 @@ namespace Microsoft.Quantum.Arithmetic { /// The ancilla qubit used in RippleCarryAdderCDKM passed to this operation. /// /// # References - /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David + /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David /// Petrie Moulton: "A new quantum ripple-carry addition circuit", 2004. /// https://arxiv.org/abs/quant-ph/0410184v1 operation _RippleCDKM (xs : LittleEndian, ys : LittleEndian, ancilla : Qubit) : Unit @@ -217,8 +182,8 @@ namespace Microsoft.Quantum.Arithmetic { } /// # Summary - /// The core operation in the RippleCarryAdderCDKM, used with the above - /// _RippleCDKM operation, i.e. conjugated with this operation to obtain + /// The core operation in the RippleCarryAdderCDKM, used with the above + /// _RippleCDKM operation, i.e. conjugated with this operation to obtain /// the inner operation of the RippleCarryAdderCDKM. This operation computes /// the carry out qubit and applies a sequence of NOT gates on part of the input `ys`. /// @@ -233,7 +198,7 @@ namespace Microsoft.Quantum.Arithmetic { /// Carry out qubit in the RippleCarryAdderCDKM operation. /// /// # References - /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David + /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David /// Petrie Moulton: "A new quantum ripple-carry addition circuit", 2004. /// https://arxiv.org/abs/quant-ph/0410184v1 operation _CarryOutCoreCDKM (xs : LittleEndian, ys : LittleEndian, @@ -258,8 +223,8 @@ namespace Microsoft.Quantum.Arithmetic { } /// # Summary - /// Outer operation in the RippleCarryAdderCDKM for use with _InnerCDKM in ApplyWithCA to - /// construct RippleCarryAdderCDKM. + /// Outer operation in the RippleCarryAdderCDKM for use with _InnerCDKM in ApplyWithCA to + /// construct RippleCarryAdderCDKM. /// /// # Input /// ## xs @@ -270,7 +235,7 @@ namespace Microsoft.Quantum.Arithmetic { /// The ancilla qubit used in RippleCarryAdderCDKM. /// /// # References - /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David + /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David /// Petrie Moulton: "A new quantum ripple-carry addition circuit", 2004. /// https://arxiv.org/abs/quant-ph/0410184v1 operation _OuterCDKM (xs : LittleEndian, ys : LittleEndian, ancilla : Qubit) : Unit @@ -292,8 +257,8 @@ namespace Microsoft.Quantum.Arithmetic { } /// # Summary - /// Inner operation in the RippleCarryAdderCDKM for use with _OuterCDKM in ApplyWithCA to - /// construct RippleCarryAdderCDKM. + /// Inner operation in the RippleCarryAdderCDKM for use with _OuterCDKM in ApplyWithCA to + /// construct RippleCarryAdderCDKM. /// /// # Input /// ## xs @@ -306,102 +271,95 @@ namespace Microsoft.Quantum.Arithmetic { /// The ancilla qubit used in RippleCarryAdderCDKM. /// /// # References - /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David + /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David /// Petrie Moulton: "A new quantum ripple-carry addition circuit", 2004. /// https://arxiv.org/abs/quant-ph/0410184v1 - operation _InnerCDKM (xs : LittleEndian, ys : LittleEndian, carry : Qubit, - ancilla : Qubit) : Unit - { - body (...) { - let nQubits = Length(xs!); - - EqualityFactB( - nQubits == Length(ys!), true, - "Input registers must have the same number of qubits." ); - - ApplyWithCA(_RippleCDKM, - _CarryOutCoreCDKM(_, _, _, carry), (xs, ys, ancilla)); - ApplyToEachCA (X, Most(Rest(ys!))); // X on ys[1..(nQubits-2)] - } - adjoint auto; - controlled auto; - adjoint controlled auto; + operation _InnerCDKM(xs : LittleEndian, ys : LittleEndian, carry : Qubit, + ancilla : Qubit) + : Unit is Adj + Ctl { + let nQubits = Length(xs!); + + EqualityFactI( + nQubits, Length(ys!), + "Input registers must have the same number of qubits." + ); + + ApplyWithCA(_RippleCDKM, + _CarryOutCoreCDKM(_, _, _, carry), (xs, ys, ancilla)); + ApplyToEachCA (X, Most(Rest(ys!))); // X on ys[1..(nQubits-2)] } /// # Summary - /// Reversible, in-place ripple-carry addition of two integers. + /// Reversible, in-place ripple-carry addition of two integers. + /// + /// # Description /// Given two $n$-bit integers encoded in LittleEndian registers `xs` and `ys`, - /// and a qubit carry, the operation computes the sum of the two integers - /// where the $n$ least significant bits of the result are held in `ys` and - /// the carry out bit is xored to the qubit `carry`. + /// and a qubit carry, the operation computes the sum of the two integers + /// where the $n$ least significant bits of the result are held in `ys` and + /// the carry out bit is xored to the qubit `carry`. /// /// # Input /// ## xs /// LittleEndian qubit register encoding the first integer summand. /// ## ys - /// LittleEndian qubit register encoding the second integer summand, is + /// LittleEndian qubit register encoding the second integer summand, is /// modified to hold the n least significant bits of the sum. /// ## carry /// Carry qubit, is xored with the most significant bit of the sum. /// /// # References - /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David + /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David /// Petrie Moulton: "A new quantum ripple-carry addition circuit", 2004. /// https://arxiv.org/abs/quant-ph/0410184v1 /// - /// # Remarks - /// This operation has the same functionality as RippleCarryAdderD, but + /// # Remarks + /// This operation has the same functionality as RippleCarryAdderD, but /// only uses one ancilla qubit instead of $n$. - operation RippleCarryAdderCDKM (xs : LittleEndian, ys : LittleEndian, carry : Qubit) : Unit - { - body (...) { - let nQubits = Length(xs!); + operation RippleCarryAdderCDKM (xs : LittleEndian, ys : LittleEndian, carry : Qubit) + : Unit is Adj + Ctl { + let nQubits = Length(xs!); - EqualityFactB( - nQubits == Length(ys!), true, - "Input registers must have the same number of qubits." ); + EqualityFactI( + nQubits, Length(ys!), + "Input registers must have the same number of qubits." + ); - using ( ancilla = Qubit() ) { - ApplyWithCA(_OuterCDKM, _InnerCDKM(_, _, carry, _), (xs, ys, ancilla)); - CNOT (xs![0], ys![0]); - } + using ( ancilla = Qubit() ) { + ApplyWithCA(_OuterCDKM, _InnerCDKM(_, _, carry, _), (xs, ys, ancilla)); + CNOT(xs![0], ys![0]); } - adjoint auto; - controlled auto; - adjoint controlled auto; } /// # Summary - /// Implements the inner addition function for the operation + /// Implements the inner addition function for the operation /// RippleCarryAdderTTK. This is the inner operation that is conjugated /// with the outer operation to construct the full adder. /// /// # Input /// ## xs - /// LittleEndian qubit register encoding the first integer summand + /// LittleEndian qubit register encoding the first integer summand /// input to RippleCarryAdderTTK. /// ## ys - /// LittleEndian qubit register encoding the second integer summand + /// LittleEndian qubit register encoding the second integer summand /// input to RippleCarryAdderTTK. /// ## carry /// Carry qubit, is xored with the most significant bit of the sum. /// /// # References - /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum + /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum /// Addition Circuits and Unbounded Fan-Out", Quantum Information and /// Computation, Vol. 10, 2010. - /// https://arxiv.org/abs/0910.2530 + /// https://arxiv.org/abs/0910.2530 /// /// # Remarks - /// The specified controlled operation makes use of symmetry and mutual + /// The specified controlled operation makes use of symmetry and mutual /// cancellation of operations to improve on the default implementation /// that adds a control to every operation. - operation _InnerAddTTK (xs : LittleEndian, ys : LittleEndian, carry : Qubit) : Unit - { + operation _InnerAddTTK (xs : LittleEndian, ys : LittleEndian, carry : Qubit) + : Unit is Adj + Ctl { body (...) { (Controlled _InnerAddTTK) (new Qubit[0], (xs, ys, carry)); } - adjoint auto; controlled ( controls, ... ) { let nQubits = Length(xs!); @@ -418,7 +376,6 @@ namespace Microsoft.Quantum.Arithmetic { CCNOT (xs![idx-1], ys![idx-1], xs![idx]); } } - adjoint controlled auto; } /// # Summary @@ -427,111 +384,101 @@ namespace Microsoft.Quantum.Arithmetic { /// /// # Input /// ## xs - /// LittleEndian qubit register encoding the first integer summand + /// LittleEndian qubit register encoding the first integer summand /// input to RippleCarryAdderTTK. /// ## ys - /// LittleEndian qubit register encoding the second integer summand + /// LittleEndian qubit register encoding the second integer summand /// input to RippleCarryAdderTTK. /// /// # References - /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum + /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum /// Addition Circuits and Unbounded Fan-Out", Quantum Information and /// Computation, Vol. 10, 2010. - /// https://arxiv.org/abs/0910.2530 - operation _OuterTTK (xs : LittleEndian, ys : LittleEndian) : Unit - { - body (...) { - let nQubits = Length(xs!); + /// https://arxiv.org/abs/0910.2530 + operation _OuterTTK (xs : LittleEndian, ys : LittleEndian) + : Unit is Adj + Ctl { + let nQubits = Length(xs!); - EqualityFactB( - nQubits == Length(ys!), true, - "Input registers must have the same number of qubits." ); + EqualityFactB( + nQubits == Length(ys!), true, + "Input registers must have the same number of qubits." ); - ApplyToEachCA(CNOT, Zip(Rest(xs!), Rest(ys!))); - (Adjoint CascadeCNOT) (Rest(xs!)); - } - adjoint auto; - controlled auto; - adjoint controlled auto; + ApplyToEachCA(CNOT, Zip(Rest(xs!), Rest(ys!))); + (Adjoint CascadeCNOT) (Rest(xs!)); } /// # Summary - /// Reversible, in-place ripple-carry addition of two integers. + /// Reversible, in-place ripple-carry addition of two integers. /// Given two $n$-bit integers encoded in LittleEndian registers `xs` and `ys`, - /// and a qubit carry, the operation computes the sum of the two integers - /// where the $n$ least significant bits of the result are held in `ys` and - /// the carry out bit is xored to the qubit `carry`. + /// and a qubit carry, the operation computes the sum of the two integers + /// where the $n$ least significant bits of the result are held in `ys` and + /// the carry out bit is xored to the qubit `carry`. /// /// # Input /// ## xs /// LittleEndian qubit register encoding the first integer summand. /// ## ys - /// LittleEndian qubit register encoding the second integer summand, is + /// LittleEndian qubit register encoding the second integer summand, is /// modified to hold the $n$ least significant bits of the sum. /// ## carry /// Carry qubit, is xored with the most significant bit of the sum. /// /// # References - /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum + /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum /// Addition Circuits and Unbounded Fan-Out", Quantum Information and /// Computation, Vol. 10, 2010. - /// https://arxiv.org/abs/0910.2530 + /// https://arxiv.org/abs/0910.2530 /// - /// # Remarks + /// # Remarks /// This operation has the same functionality as RippleCarryAdderD and, /// RippleCarryAdderCDKM but does not use any ancilla qubits. - operation RippleCarryAdderTTK (xs : LittleEndian, ys : LittleEndian, carry : Qubit) : Unit - { - body (...) { - let nQubits = Length(xs!); - - EqualityFactB( - nQubits == Length(ys!), true, - "Input registers must have the same number of qubits." ); - - if (nQubits > 1) { - CNOT(xs![nQubits-1], carry); - ApplyWithCA(_OuterTTK, _InnerAddTTK(_, _, carry), (xs, ys)); - } - else { - CCNOT(xs![0], ys![0], carry); - } - CNOT(xs![0], ys![0]); + operation RippleCarryAdderTTK (xs : LittleEndian, ys : LittleEndian, carry : Qubit) + : Unit is Adj + Ctl { + let nQubits = Length(xs!); + + EqualityFactI( + nQubits, Length(ys!), + "Input registers must have the same number of qubits." + ); + + if (nQubits > 1) { + CNOT(xs![nQubits-1], carry); + ApplyWithCA(_OuterTTK, _InnerAddTTK(_, _, carry), (xs, ys)); } - adjoint auto; - controlled auto; - adjoint controlled auto; + else { + CCNOT(xs![0], ys![0], carry); + } + CNOT(xs![0], ys![0]); } /// # Summary - /// Implements the inner addition function for the operation + /// Implements the inner addition function for the operation /// RippleCarryAdderNoCarryTTK. This is the inner operation that is conjugated /// with the outer operation to construct the full adder. /// /// # Input /// ## xs - /// LittleEndian qubit register encoding the first integer summand + /// LittleEndian qubit register encoding the first integer summand /// input to RippleCarryAdderNoCarryTTK. /// ## ys - /// LittleEndian qubit register encoding the second integer summand + /// LittleEndian qubit register encoding the second integer summand /// input to RippleCarryAdderNoCarryTTK. /// /// # References - /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum + /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum /// Addition Circuits and Unbounded Fan-Out", Quantum Information and /// Computation, Vol. 10, 2010. - /// https://arxiv.org/abs/0910.2530 + /// https://arxiv.org/abs/0910.2530 /// /// # Remarks - /// The specified controlled operation makes use of symmetry and mutual + /// The specified controlled operation makes use of symmetry and mutual /// cancellation of operations to improve on the default implementation /// that adds a control to every operation. - operation _InnerAddNoCarryTTK (xs : LittleEndian, ys : LittleEndian) : Unit - { + operation _InnerAddNoCarryTTK (xs : LittleEndian, ys : LittleEndian) + : Unit is Adj + Ctl { body (...) { (Controlled _InnerAddNoCarryTTK) (new Qubit[0], (xs, ys)); } - adjoint auto; controlled ( controls, ... ) { let nQubits = Length(xs!); @@ -547,55 +494,56 @@ namespace Microsoft.Quantum.Arithmetic { CCNOT (xs![idx-1], ys![idx-1], xs![idx]); } } - adjoint controlled auto; } /// # Summary - /// Reversible, in-place ripple-carry addition of two integers without carry out. + /// Reversible, in-place ripple-carry addition of two integers without carry out. + /// + /// # Description /// Given two $n$-bit integers encoded in LittleEndian registers `xs` and `ys`, /// the operation computes the sum of the two integers modulo $2^n$, - /// where $n$ is the bit size of the inputs `xs` and `ys`. It does not compute - /// the carry out bit. + /// where $n$ is the bit size of the inputs `xs` and `ys`. It does not compute + /// the carry out bit. /// /// # Input /// ## xs /// LittleEndian qubit register encoding the first integer summand. /// ## ys - /// LittleEndian qubit register encoding the second integer summand, is + /// LittleEndian qubit register encoding the second integer summand, is /// modified to hold the $n$ least significant bits of the sum. /// /// # References - /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum + /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum /// Addition Circuits and Unbounded Fan-Out", Quantum Information and /// Computation, Vol. 10, 2010. - /// https://arxiv.org/abs/0910.2530 + /// https://arxiv.org/abs/0910.2530 /// - /// # Remarks + /// # Remarks /// This operation has the same functionality as RippleCarryAdderTTK but does /// not return the carry bit. - operation RippleCarryAdderNoCarryTTK (xs : LittleEndian, ys : LittleEndian) : Unit - { - body (...) { - let nQubits = Length(xs!); + operation RippleCarryAdderNoCarryTTK (xs : LittleEndian, ys : LittleEndian) + : Unit is Adj + Ctl { + let nQubits = Length(xs!); - EqualityFactB( - nQubits == Length(ys!), true, - "Input registers must have the same number of qubits." ); + EqualityFactB( + nQubits == Length(ys!), true, + "Input registers must have the same number of qubits." ); - if (nQubits > 1) { - ApplyWithCA(_OuterTTK, _InnerAddNoCarryTTK, (xs, ys)); - } - CNOT (xs![0], ys![0]); + if (nQubits > 1) { + ApplyWithCA(_OuterTTK, _InnerAddNoCarryTTK, (xs, ys)); } - adjoint auto; - controlled auto; - adjoint controlled auto; + CNOT (xs![0], ys![0]); } /// # Summary + /// Applies a greater-than comparison between two integers encoded into + /// qubit registers, flipping a target qubit based on the result of the + /// comparison. + /// + /// # Description /// Carries out a strictly greater than comparison of two integers $x$ and $y$, encoded - /// in qubit registers xs and ys. If $x > y$, then the result qubit will be flipped, - /// otherwise retain its state. + /// in qubit registers xs and ys. If $x > y$, then the result qubit will be flipped, + /// otherwise the result qubit will retain its state. /// /// # Input /// ## xs @@ -604,9 +552,9 @@ namespace Microsoft.Quantum.Arithmetic { /// LittleEndian qubit register encoding the second integer $y$. /// ## result /// Single qubit that will be flipped if $x > y$. - /// + /// /// # References - /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David + /// - Steven A. Cuccaro, Thomas G. Draper, Samuel A. Kutin, David /// Petrie Moulton: "A new quantum ripple-carry addition circuit", 2004. /// https://arxiv.org/abs/quant-ph/0410184v1 /// @@ -615,19 +563,19 @@ namespace Microsoft.Quantum.Arithmetic { /// https://arxiv.org/abs/1611.07995 /// /// # Remarks - /// Uses the trick that $x-y = (x'+y)'$, where ' denotes the one's complement. - operation GreaterThan (xs : LittleEndian, ys : LittleEndian, result : Qubit) : Unit - { + /// Uses the trick that $x - y = (x'+y)'$, where ' denotes the one's complement. + operation GreaterThan(xs : LittleEndian, ys : LittleEndian, result : Qubit) + : Unit is Adj + Ctl { body (...) { (Controlled GreaterThan) (new Qubit[0], (xs, ys, result)); } - adjoint auto; controlled (controls, ...) { let nQubits = Length(xs!); - EqualityFactB( - nQubits == Length(ys!), true, - "Input registers must have the same number of qubits." ); + EqualityFactI( + nQubits, Length(ys!), + "Input registers must have the same number of qubits." + ); if (nQubits == 1) { X(ys![0]); @@ -647,7 +595,6 @@ namespace Microsoft.Quantum.Arithmetic { ApplyToEachCA(X, ys!); } } - adjoint controlled auto; } } diff --git a/Standard/src/Arithmetic/Modular.qs b/Standard/src/Arithmetic/Modular.qs index 2f9bea6c89d..d0aa04e4171 100644 --- a/Standard/src/Arithmetic/Modular.qs +++ b/Standard/src/Arithmetic/Modular.qs @@ -36,18 +36,13 @@ namespace Microsoft.Quantum.Arithmetic { /// Note that /// implements /// the same operation in the `PhaseLittleEndian` basis. - operation IncrementByModularInteger(increment : Int, modulus : Int, target : LittleEndian) : Unit { - body (...) { - let inner = IncrementPhaseByModularInteger(increment, modulus, _); + operation IncrementByModularInteger(increment : Int, modulus : Int, target : LittleEndian) + : Unit is Adj + Ctl { + let inner = IncrementPhaseByModularInteger(increment, modulus, _); - using (extraZeroBit = Qubit()) { - ApplyPhaseLEOperationOnLECA(inner, LittleEndian(target! + [extraZeroBit])); - } + using (extraZeroBit = Qubit()) { + ApplyPhaseLEOperationOnLECA(inner, LittleEndian(target! + [extraZeroBit])); } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; } /// # Summary @@ -61,6 +56,14 @@ namespace Microsoft.Quantum.Arithmetic { /// \end{align} /// Integers are encoded in little-endian format in QFT basis. /// + /// # Input + /// ## increment + /// Integer increment $a$ to be added to $y$. + /// ## modulus + /// Integer $N$ that mods $y + a$. + /// ## target + /// Integer $y$ in phase-encoded little-endian format that `increment` $a$ is added to. + /// /// # See Also /// - Microsoft.Quantum.Arithmetic.IncrementByModularInteger /// @@ -70,11 +73,11 @@ namespace Microsoft.Quantum.Arithmetic { /// /// For the circuit diagram and explanation see Figure 5 on [Page 5 /// of arXiv:quant-ph/0205095v3](https://arxiv.org/pdf/quant-ph/0205095v3.pdf#page=5). - operation IncrementPhaseByModularInteger(increment : Int, modulus : Int, target : PhaseLittleEndian) : Unit { + operation IncrementPhaseByModularInteger(increment : Int, modulus : Int, target : PhaseLittleEndian) + : Unit is Adj + Ctl { body (...) { Controlled IncrementPhaseByModularInteger(new Qubit[0], (increment, modulus, target)); } - adjoint auto; controlled (controls, ...) { Fact(modulus <= 2 ^ (Length(target!) - 1), $"`multiplier` must be big enough to fit integers modulo `modulus`" + $"with highest bit set to 0"); @@ -112,8 +115,6 @@ namespace Microsoft.Quantum.Arithmetic { Controlled IncrementPhaseByInteger(controls, (increment, target)); } } - - controlled adjoint auto; } /// # Summary @@ -148,33 +149,41 @@ namespace Microsoft.Quantum.Arithmetic { /// of arXiv:quant-ph/0205095v3](https://arxiv.org/pdf/quant-ph/0205095v3.pdf#page=7) /// - This operation corresponds to CMULT(a)MOD(N) in /// [arXiv:quant-ph/0205095v3](https://arxiv.org/pdf/quant-ph/0205095v3.pdf) - operation MultiplyAndAddByModularInteger(constMultiplier : Int, modulus : Int, multiplier : LittleEndian, summand : LittleEndian) : Unit { - body (...) { - let inner = MultiplyAndAddPhaseByModularInteger(constMultiplier, modulus, multiplier, _); + operation MultiplyAndAddByModularInteger(constMultiplier : Int, modulus : Int, multiplier : LittleEndian, summand : LittleEndian) + : Unit is Adj + Ctl { + let inner = MultiplyAndAddPhaseByModularInteger(constMultiplier, modulus, multiplier, _); - using (extraZeroBit = Qubit()) { - ApplyPhaseLEOperationOnLECA(inner, LittleEndian(summand! + [extraZeroBit])); - } + using (extraZeroBit = Qubit()) { + ApplyPhaseLEOperationOnLECA(inner, LittleEndian(summand! + [extraZeroBit])); } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; } /// # Summary /// The same as MultiplyAndAddByModularInteger, but assumes that the summand encodes /// integers in QFT basis. /// + /// # Input + /// ## constantMultiplier + /// An integer $a$ to be added to each basis state label. + /// ## modulus + /// The modulus $N$ which addition and multiplication is taken with respect to. + /// ## multiplier + /// A quantum register representing an unsigned integer whose value is to + /// be added to each basis state label of `summand`. + /// ## phaseSummand + /// A quantum register representing an unsigned integer to use as the target + /// for this operation. + /// /// # Remarks /// Assumes that `phaseSummand` has the highest bit set to 0. /// Also assumes that the value of `phaseSummand` is less than $N$. /// /// # See Also /// - Microsoft.Quantum.Arithmetic.MultiplyAndAddByModularInteger - operation MultiplyAndAddPhaseByModularInteger(constMultiplier : Int, modulus : Int, multiplier : LittleEndian, phaseSummand : PhaseLittleEndian) : Unit is Adj + Ctl { - EqualityFactB(modulus <= 2 ^ (Length(phaseSummand!) - 1), true, $"`multiplier` must be big enough to fit integers modulo `modulus`" + $"with highest bit set to 0"); - EqualityFactB(constMultiplier >= 0 and constMultiplier < modulus, true, $"`constMultiplier` must be between 0 and `modulus`-1"); + operation MultiplyAndAddPhaseByModularInteger(constMultiplier : Int, modulus : Int, multiplier : LittleEndian, phaseSummand : PhaseLittleEndian) + : Unit is Adj + Ctl { + Fact(modulus <= 2 ^ (Length(phaseSummand!) - 1), $"`multiplier` must be big enough to fit integers modulo `modulus`" + $"with highest bit set to 0"); + Fact(constMultiplier >= 0 and constMultiplier < modulus, $"`constMultiplier` must be between 0 and `modulus`-1"); if (_EnableExtraAssertsForArithmetic()) { // assert that the highest bit is zero, by switching to computational basis @@ -184,7 +193,7 @@ namespace Microsoft.Quantum.Arithmetic { AssertPhaseLessThan(modulus, phaseSummand); } - for (i in 0 .. Length(multiplier!) - 1) { + for (i in IndexRange(multiplier!)) { let summand = (ExpModI(2, i, modulus) * constMultiplier) % modulus; Controlled IncrementPhaseByModularInteger([(multiplier!)[i]], (summand, modulus, phaseSummand)); } diff --git a/Standard/src/Arrays/Arrays.qs b/Standard/src/Arrays/Arrays.qs index 740b4f195b4..c252056149f 100644 --- a/Standard/src/Arrays/Arrays.qs +++ b/Standard/src/Arrays/Arrays.qs @@ -63,7 +63,7 @@ namespace Microsoft.Quantum.Arrays { return array[0 .. Length(array) - 2]; } - function LookupImpl<'T> (array : 'T[], index : Int) : 'T { + function _Lookup<'T> (array : 'T[], index : Int) : 'T { return array[index]; } @@ -90,7 +90,7 @@ namespace Microsoft.Quantum.Arrays { /// where functions are used to avoid the need to record an entire array /// in memory. function LookupFunction<'T> (array : 'T[]) : (Int -> 'T) { - return LookupImpl(array, _); + return _Lookup(array, _); } /// # Summary diff --git a/Standard/src/Arrays/Map.qs b/Standard/src/Arrays/Map.qs index 4e28ccea7ad..e6e28337d0e 100644 --- a/Standard/src/Arrays/Map.qs +++ b/Standard/src/Arrays/Map.qs @@ -103,8 +103,8 @@ namespace Microsoft.Quantum.Arrays { /// The result type of the `action` operation. /// /// # Input - /// ## mapper - /// A function from `'T` to `'U` that is used to map elements. + /// ## action + /// An operation from `'T` to `'U` that is applied to each element. /// ## array /// An array of elements over `'T`. /// @@ -122,4 +122,3 @@ namespace Microsoft.Quantum.Arrays { } - diff --git a/Standard/src/Canon/And.qs b/Standard/src/Canon/And.qs index c1c3eec25d2..dc786cca0e7 100644 --- a/Standard/src/Canon/And.qs +++ b/Standard/src/Canon/And.qs @@ -220,7 +220,7 @@ namespace Microsoft.Quantum.Canon { /// # Summary /// Implements a multiple-controlled Toffoli gate, assuming that target /// qubit is initialized 0. The adjoint operation assumes that the target - /// qubit will be released to 0. + /// qubit will be reset to 0. /// /// # Input /// ## controls @@ -292,7 +292,7 @@ namespace Microsoft.Quantum.Canon { /// # Summary /// Implements a multiple-controlled Toffoli gate, assuming that target /// qubit is initialized 0. The adjoint operation assumes that the target - /// qubit will be released to 0. Requires a Rz depth of 1, while the number + /// qubit will be reset to 0. Requires a Rz depth of 1, while the number /// of helper qubits are exponential in the number of qubits. /// /// # Input diff --git a/Standard/src/Canon/Combinators/ApplyIf.qs b/Standard/src/Canon/Combinators/ApplyIf.qs index 93662de16d4..69dfc6c4c9b 100644 --- a/Standard/src/Canon/Combinators/ApplyIf.qs +++ b/Standard/src/Canon/Combinators/ApplyIf.qs @@ -593,8 +593,8 @@ namespace Microsoft.Quantum.Canon { /// when `bit` is `false`. /// /// # Input - /// ## result - /// The measurement result used to determine if `trueOp` or `falseOp` is + /// ## bit + /// The boolean value used to determine whether `trueOp` or `falseOp` is /// applied. /// ## trueOp /// The operation to be applied when `bit` is `true`. @@ -635,8 +635,8 @@ namespace Microsoft.Quantum.Canon { /// when `bit` is `false`. /// /// # Input - /// ## result - /// The measurement result used to determine if `trueOp` or `falseOp` is + /// ## bit + /// The boolean value used to determine whether `trueOp` or `falseOp` is /// applied. /// ## trueOp /// The controllable operation to be applied when `bit` is `true`. @@ -677,8 +677,8 @@ namespace Microsoft.Quantum.Canon { /// when `bit` is `false`. /// /// # Input - /// ## result - /// The measurement result used to determine if `trueOp` or `falseOp` is + /// ## bit + /// The boolean value used to determine whether `trueOp` or `falseOp` is /// applied. /// ## trueOp /// The adjointable operation to be applied when `bit` is `true`. @@ -719,8 +719,8 @@ namespace Microsoft.Quantum.Canon { /// when `bit` is `false`. /// /// # Input - /// ## result - /// The measurement result used to determine if `trueOp` or `falseOp` is + /// ## bit + /// The boolean value used to determine whether `trueOp` or `falseOp` is /// applied. /// ## trueOp /// The unitary operation to be applied when `bit` is `true`. diff --git a/Standard/src/Canon/Combinators/ApplyMultiControlled.qs b/Standard/src/Canon/Combinators/ApplyMultiControlled.qs index ab207594dff..3a66a084c76 100644 --- a/Standard/src/Canon/Combinators/ApplyMultiControlled.qs +++ b/Standard/src/Canon/Combinators/ApplyMultiControlled.qs @@ -4,16 +4,16 @@ namespace Microsoft.Quantum.Canon { open Microsoft.Quantum.Diagnostics; open Microsoft.Quantum.Arrays; - + /////////////////////////////////////////////////////////////////////////////////////////////// // Combinators for constructing multiply controlled versions of operations /////////////////////////////////////////////////////////////////////////////////////////////// - + /// # Summary /// The signature type of CCNOT gate. newtype CCNOTop = (Apply : ((Qubit, Qubit, Qubit) => Unit is Adj)); - - + + /// # Summary /// Applies a multiply controlled version of a singly controlled /// operation. @@ -50,7 +50,7 @@ namespace Microsoft.Quantum.Canon { body (...) { EqualityFactB(Length(controls) >= 1, true, $"Length of controls must be at least 1"); - + if (Length(controls) == 1) { singlyControlledOp(controls + targets); @@ -65,14 +65,14 @@ namespace Microsoft.Quantum.Canon { } } } - + controlled (extraControls, ...) { ApplyMultiControlledC(singlyControlledOp, ccnot, extraControls + controls, targets); } } - - + + /// # Summary /// Applies a multiply controlled version of a singly controlled /// operation. @@ -119,21 +119,22 @@ namespace Microsoft.Quantum.Canon { } } } - + adjoint invert; - + controlled (extraControls, ...) { ApplyMultiControlledCA(singlyControlledOp, ccnot, extraControls + controls, targets); } - + controlled adjoint invert; } - - + /// # Summary - /// Performs a controlled 'AND ladder' on the target qubits. - /// - /// This applies a unitary given by the following map on computational basis vectors: + /// Performs a controlled "AND ladder" on a register of target qubits. + /// + /// # Description + /// This operation applies a transformation described by the following + /// mapping of the computational basis, /// $$ /// \begin{align} /// \ket{x\_1, \dots, x\_n} \ket{y\_1, \dots, y\_{n - 1}} \mapsto diff --git a/Standard/src/Canon/Combinators/Bind.qs b/Standard/src/Canon/Combinators/Bind.qs index 5d295731230..6bcae71b3ff 100644 --- a/Standard/src/Canon/Combinators/Bind.qs +++ b/Standard/src/Canon/Combinators/Bind.qs @@ -6,16 +6,12 @@ namespace Microsoft.Quantum.Canon { /// # See Also /// - Microsoft.Quantum.Canon.Bound - operation BindImpl<'T> (operations : ('T => Unit)[], target : 'T) : Unit - { - for (idxOperation in IndexRange(operations)) - { - let op = operations[idxOperation]; + operation _Bound<'T> (operations : ('T => Unit)[], target : 'T) : Unit { + for (op in operations) { op(target); } } - - + /// # Summary /// Given an array of operations acting on a single input, /// produces a new operation that @@ -40,8 +36,8 @@ namespace Microsoft.Quantum.Canon { /// let bound = Bound([U, V]); /// bound(x); /// ``` - /// and - /// ```qsharp + /// and + /// ```qsharp /// U(x); V(x); /// ``` /// @@ -49,37 +45,21 @@ namespace Microsoft.Quantum.Canon { /// - Microsoft.Quantum.Canon.BoundC /// - Microsoft.Quantum.Canon.BoundA /// - Microsoft.Quantum.Canon.BoundCA - function Bound<'T> (operations : ('T => Unit)[]) : ('T => Unit) - { - return BindImpl(operations, _); + function Bound<'T> (operations : ('T => Unit)[]) : ('T => Unit) { + return _Bound(operations, _); } - - + + /// # See Also /// - Microsoft.Quantum.Canon.BoundA - operation BindAImpl<'T> (operations : ('T => Unit is Adj)[], target : 'T) : Unit - { - body (...) - { - for (idxOperation in IndexRange(operations)) - { - let op = operations[idxOperation]; - op(target); - } - } - - adjoint (...) { - // TODO: replace with an implementation based on Reversed : 'T[] -> 'T[] - // and AdjointAll : ('T => () is Adj)[] -> ('T => () is Adj). - for (idxOperation in Length(operations) - 1 .. -1 .. 0) - { - let op = Adjoint operations[idxOperation]; - op(target); - } + operation _BoundA<'T> (operations : ('T => Unit is Adj)[], target : 'T) + : Unit is Adj { + for (op in operations) { + op(target); } } - - + + /// # Summary /// Given an array of operations acting on a single input, /// produces a new operation that @@ -105,43 +85,29 @@ namespace Microsoft.Quantum.Canon { /// let bound = BoundA([U, V]); /// bound(x); /// ``` - /// and - /// ```qsharp + /// and + /// ```qsharp /// U(x); V(x); /// ``` /// /// # See Also /// - Microsoft.Quantum.Canon.Bound - function BoundA<'T> (operations : ('T => Unit is Adj)[]) : ('T => Unit is Adj) - { - return BindAImpl(operations, _); + function BoundA<'T> (operations : ('T => Unit is Adj)[]) + : ('T => Unit is Adj) { + return _BoundA(operations, _); } - - + + /// # See Also /// - Microsoft.Quantum.Canon.BoundC - operation BindCImpl<'T> (operations : ('T => Unit is Ctl)[], target : 'T) : Unit - { - body (...) - { - for (idxOperation in IndexRange(operations)) - { - let op = operations[idxOperation]; - op(target); - } - } - - controlled (controls, ...) - { - for (idxOperation in IndexRange(operations)) - { - let op = Controlled operations[idxOperation]; - op(controls, target); - } + operation _BoundC<'T> (operations : ('T => Unit is Ctl)[], target : 'T) + : Unit is Ctl { + for (op in operations) { + op(target); } } - - + + /// # Summary /// Given an array of operations acting on a single input, /// produces a new operation that @@ -167,61 +133,28 @@ namespace Microsoft.Quantum.Canon { /// let bound = BoundC([U, V]); /// bound(x); /// ``` - /// and - /// ```qsharp + /// and + /// ```qsharp /// U(x); V(x); /// ``` /// /// # See Also /// - Microsoft.Quantum.Canon.Bound - function BoundC<'T> (operations : ('T => Unit is Ctl)[]) : ('T => Unit is Ctl) - { - return BindCImpl(operations, _); + function BoundC<'T> (operations : ('T => Unit is Ctl)[]) : ('T => Unit is Ctl) { + return _BoundC(operations, _); } - - + + /// # See Also /// - Microsoft.Quantum.Canon.BoundCA - operation BindCAImpl<'T> (operations : ('T => Unit is Adj + Ctl)[], target : 'T) : Unit - { - body (...) - { - for (idxOperation in IndexRange(operations)) - { - let op = operations[idxOperation]; - op(target); - } - } - - adjoint (...) - { - for (idxOperation in Length(operations) - 1 .. -1 .. 0) - { - let op = Adjoint operations[idxOperation]; - op(target); - } - } - - controlled (controls, ...) - { - for (idxOperation in IndexRange(operations)) - { - let op = Controlled operations[idxOperation]; - op(controls, target); - } - } - - controlled adjoint (controls, ...) - { - for (idxOperation in Length(operations) - 1 .. -1 .. 0) - { - let op = Controlled (Adjoint operations[idxOperation]); - op(controls, target); - } + operation _BoundCA<'T> (operations : ('T => Unit is Adj + Ctl)[], target : 'T) + : Unit is Adj + Ctl { + for (op in operations) { + op(target); } } - - + + /// # Summary /// Given an array of operations acting on a single input, /// produces a new operation that @@ -248,18 +181,17 @@ namespace Microsoft.Quantum.Canon { /// let bound = BoundCA([U, V]); /// bound(x); /// ``` - /// and - /// ```qsharp + /// and + /// ```qsharp /// U(x); V(x); /// ``` /// /// # See Also /// - Microsoft.Quantum.Canon.Bound - function BoundCA<'T> (operations : ('T => Unit is Adj + Ctl)[]) : ('T => Unit is Adj + Ctl) - { - return BindCAImpl(operations, _); + function BoundCA<'T> (operations : ('T => Unit is Adj + Ctl)[]) : ('T => Unit is Adj + Ctl) { + return _BoundCA(operations, _); } - + } diff --git a/Standard/src/Canon/Combinators/Compose.qs b/Standard/src/Canon/Combinators/Compose.qs index 89d2ce40e94..95a0c5ee4f6 100644 --- a/Standard/src/Canon/Combinators/Compose.qs +++ b/Standard/src/Canon/Combinators/Compose.qs @@ -1,19 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -namespace Microsoft.Quantum.Canon -{ - - function ComposeImpl<'T, 'U, 'V> (outer : ('U -> 'V), inner : ('T -> 'U), target : 'T) : 'V - { +namespace Microsoft.Quantum.Canon { + + function _Compose<'T, 'U, 'V> (outer : ('U -> 'V), inner : ('T -> 'U), target : 'T) : 'V { return outer(inner(target)); } - - + /// # Summary - /// Generates the composition of two functions. - /// - /// That is, given two functions $f$ and $g$, returns a new function representing + /// Returns the composition of two functions. + /// + /// # Description + /// Given two functions $f$ and $g$, returns a new function representing /// $f \circ g$. /// /// # Input @@ -33,11 +31,8 @@ namespace Microsoft.Quantum.Canon /// of the second function to be applied. /// ## 'V /// The output type of the second function to be applied. - function Compose<'T, 'U, 'V> (outer : ('U -> 'V), inner : ('T -> 'U)) : ('T -> 'V) - { - return ComposeImpl(outer, inner, _); + function Compose<'T, 'U, 'V> (outer : ('U -> 'V), inner : ('T -> 'U)) : ('T -> 'V) { + return _Compose(outer, inner, _); } - -} - +} diff --git a/Standard/src/Canon/Combinators/Curry.qs b/Standard/src/Canon/Combinators/Curry.qs index 18d365c72f6..d04f3e48c29 100644 --- a/Standard/src/Canon/Combinators/Curry.qs +++ b/Standard/src/Canon/Combinators/Curry.qs @@ -3,15 +3,14 @@ namespace Microsoft.Quantum.Canon { - function CurryOpImpl<'T, 'U> (op : (('T, 'U) => Unit), arg1 : 'T) : ('U => Unit) - { + function _CurriedOp<'T, 'U> (op : (('T, 'U) => Unit), arg1 : 'T) : ('U => Unit) { return op(arg1, _); } - - + + /// # Summary - /// Returns a curried version of an operation on two inputs. - /// + /// Returns a curried version of an operation on two inputs. + /// /// That is, given an operation with two inputs, this function applies Curry's isomorphism /// $f(x, y) \equiv f(x)(y)$ to return an operation of one input which /// returns an operation of one input. @@ -40,19 +39,16 @@ namespace Microsoft.Quantum.Canon { /// let partial = curried(x); /// partial(y); /// ``` - function CurriedOp<'T, 'U> (op : (('T, 'U) => Unit)) : ('T -> ('U => Unit)) - { - return CurryOpImpl(op, _); + function CurriedOp<'T, 'U> (op : (('T, 'U) => Unit)) : ('T -> ('U => Unit)) { + return _CurriedOp(op, _); } - - - operation UncurryOpImpl<'T, 'U> (curriedOp : ('T -> ('U => Unit)), first : 'T, second : 'U) : Unit - { + + operation _UncurryOp<'T, 'U> (curriedOp : ('T -> ('U => Unit)), first : 'T, second : 'U) : Unit { let innerOp = curriedOp(first); innerOp(second); } - - + + /// # Summary /// Given a function which returns operations, /// returns a new operation which takes both inputs @@ -77,22 +73,17 @@ namespace Microsoft.Quantum.Canon { /// - @"microsoft.quantum.canon.uncurryopca" function UncurriedOp<'T, 'U> (curriedOp : ('T -> ('U => Unit))) : (('T, 'U) => Unit) { - return UncurryOpImpl(curriedOp, _, _); + return _UncurryOp(curriedOp, _, _); } - - - operation UncurryOpCImpl<'T, 'U> (curriedOp : ('T -> ('U => Unit is Ctl)), first : 'T, second : 'U) : Unit - { - body (...) - { - let innerOp = curriedOp(first); - innerOp(second); - } - - controlled distribute; + + + operation _UncurriedOpC<'T, 'U>(curriedOp : ('T -> ('U => Unit is Ctl)), first : 'T, second : 'U) + : Unit is Ctl { + let innerOp = curriedOp(first); + innerOp(second); } - - + + /// # Summary /// Given a function which returns operations, /// returns a new operation which takes both inputs @@ -115,24 +106,19 @@ namespace Microsoft.Quantum.Canon { /// /// # See Also /// - @"microsoft.quantum.canon.uncurryop" - function UncurriedOpC<'T, 'U> (curriedOp : ('T -> ('U => Unit is Ctl))) : (('T, 'U) => Unit is Ctl) - { - return UncurryOpCImpl(curriedOp, _, _); + function UncurriedOpC<'T, 'U> (curriedOp : ('T -> ('U => Unit is Ctl))) + : (('T, 'U) => Unit is Ctl) { + return _UncurriedOpC(curriedOp, _, _); } - - - operation UncurryOpAImpl<'T, 'U> (curriedOp : ('T -> ('U => Unit is Adj)), first : 'T, second : 'U) : Unit - { - body (...) - { - let innerOp = curriedOp(first); - innerOp(second); - } - - adjoint invert; + + + operation _UncurriedOpA<'T, 'U> (curriedOp : ('T -> ('U => Unit is Adj)), first : 'T, second : 'U) + : Unit is Adj { + let innerOp = curriedOp(first); + innerOp(second); } - - + + /// # Summary /// Given a function which returns operations, /// returns a new operation which takes both inputs @@ -155,26 +141,18 @@ namespace Microsoft.Quantum.Canon { /// /// # See Also /// - @"microsoft.quantum.canon.uncurryop" - function UncurriedOpA<'T, 'U> (curriedOp : ('T -> ('U => Unit is Adj))) : (('T, 'U) => Unit is Adj) - { - return UncurryOpAImpl(curriedOp, _, _); + function UncurriedOpA<'T, 'U> (curriedOp : ('T -> ('U => Unit is Adj))) : (('T, 'U) => Unit is Adj) { + return _UncurriedOpA(curriedOp, _, _); } - - - operation UncurryOpCAImpl<'T, 'U> (curriedOp : ('T -> ('U => Unit is Ctl + Adj)), first : 'T, second : 'U) : Unit - { - body (...) - { - let innerOp = curriedOp(first); - innerOp(second); - } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; + + + operation _UncurriedOpCA<'T, 'U> (curriedOp : ('T -> ('U => Unit is Ctl + Adj)), first : 'T, second : 'U) + : Unit is Adj + Ctl { + let innerOp = curriedOp(first); + innerOp(second); } - - + + /// # Summary /// Given a function which returns operations, /// returns a new operation which takes both inputs @@ -197,11 +175,10 @@ namespace Microsoft.Quantum.Canon { /// /// # See Also /// - @"microsoft.quantum.canon.uncurryop" - function UncurriedOpCA<'T, 'U> (curriedOp : ('T -> ('U => Unit is Ctl + Adj))) : (('T, 'U) => Unit is Ctl + Adj) - { - return UncurryOpCAImpl(curriedOp, _, _); + function UncurriedOpCA<'T, 'U> (curriedOp : ('T -> ('U => Unit is Ctl + Adj))) : (('T, 'U) => Unit is Ctl + Adj) { + return _UncurriedOpCA(curriedOp, _, _); } - + } diff --git a/Standard/src/Canon/Combinators/OperationPow.qs b/Standard/src/Canon/Combinators/OperationPow.qs index fbd8c8a0b14..657b0c7f085 100644 --- a/Standard/src/Canon/Combinators/OperationPow.qs +++ b/Standard/src/Canon/Combinators/OperationPow.qs @@ -1,51 +1,48 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -namespace Microsoft.Quantum.Canon -{ - - operation OperationPowImpl<'T> (oracle : ('T => Unit), power : Int, target : 'T) : Unit { - for (idxApplication in 0 .. power - 1) - { - oracle(target); +namespace Microsoft.Quantum.Canon { + + operation _OperationPow<'T> (op : ('T => Unit), power : Int, target : 'T) + : Unit { + for (idxApplication in 0 .. power - 1) { + op(target); } } - - - operation OperationPowImplC<'T> (oracle : ('T => Unit is Ctl), power : Int, target : 'T) : Unit is Ctl { - for (idxApplication in 0 .. power - 1) - { - oracle(target); + + + operation _OperationPowC<'T> (op : ('T => Unit is Ctl), power : Int, target : 'T) + : Unit is Ctl { + for (idxApplication in 0 .. power - 1) { + op(target); } } - - - operation OperationPowImplA<'T> (oracle : ('T => Unit is Adj), power : Int, target : 'T) : Unit is Adj - { - for (idxApplication in 0 .. power - 1) - { - oracle(target); + + + operation _OperationPowA<'T> (op : ('T => Unit is Adj), power : Int, target : 'T) + : Unit is Adj { + for (idxApplication in 0 .. power - 1) { + op(target); } } - - - operation OperationPowImplCA<'T> (oracle : ('T => Unit is Adj + Ctl), power : Int, target : 'T) : Unit is Adj + Ctl - { - for (idxApplication in 0 .. power - 1) - { - oracle(target); + + + operation _OperationPowCA<'T> (op : ('T => Unit is Adj + Ctl), power : Int, target : 'T) + : Unit is Adj + Ctl { + for (idxApplication in 0 .. power - 1) { + op(target); } } - - + + /// # Summary - /// Raises an operation to a power. - /// + /// Raises an operation to a power. + /// /// That is, given an operation representing a gate $U$, returns a new operation /// $U^m$ for a power $m$. /// /// # Input - /// ## oracle + /// ## op /// An operation $U$ representing the gate to be repeated. /// ## power /// The number of times that $U$ is to be repeated. @@ -61,21 +58,20 @@ namespace Microsoft.Quantum.Canon /// - @"microsoft.quantum.canon.operationpowc" /// - @"microsoft.quantum.canon.operationpowa" /// - @"microsoft.quantum.canon.operationpowca" - function OperationPow<'T> (oracle : ('T => Unit), power : Int) : ('T => Unit) - { - return OperationPowImpl(oracle, power, _); + function OperationPow<'T> (op : ('T => Unit), power : Int) : ('T => Unit) { + return _OperationPow(op, power, _); } - - + + /// # Summary - /// Raises an operation to a power. + /// Raises an operation to a power. /// The modifier `C` indicates that the operation is controllable. - /// + /// /// That is, given an operation representing a gate $U$, returns a new operation /// $U^m$ for a power $m$. /// /// # Input - /// ## oracle + /// ## op /// An operation $U$ representing the gate to be repeated. /// ## power /// The number of times that $U$ is to be repeated. @@ -89,21 +85,20 @@ namespace Microsoft.Quantum.Canon /// /// # See Also /// - @"microsoft.quantum.canon.operationpow" - function OperationPowC<'T> (oracle : ('T => Unit is Ctl), power : Int) : ('T => Unit is Ctl) - { - return OperationPowImplC(oracle, power, _); + function OperationPowC<'T> (op : ('T => Unit is Ctl), power : Int) : ('T => Unit is Ctl) { + return _OperationPowC(op, power, _); } - - + + /// # Summary - /// Raises an operation to a power. + /// Raises an operation to a power. /// The modifier `A` indicates that the operation is adjointable. - /// + /// /// That is, given an operation representing a gate $U$, returns a new operation /// $U^m$ for a power $m$. /// /// # Input - /// ## oracle + /// ## op /// An operation $U$ representing the gate to be repeated. /// ## power /// The number of times that $U$ is to be repeated. @@ -117,21 +112,20 @@ namespace Microsoft.Quantum.Canon /// /// # See Also /// - @"microsoft.quantum.canon.operationpow" - function OperationPowA<'T> (oracle : ('T => Unit is Adj), power : Int) : ('T => Unit is Adj) - { - return OperationPowImplA(oracle, power, _); + function OperationPowA<'T> (op : ('T => Unit is Adj), power : Int) : ('T => Unit is Adj) { + return _OperationPowA(op, power, _); } - - + + /// # Summary - /// Raises an operation to a power. + /// Raises an operation to a power. /// The modifier `A` indicates that the operation is controllable and adjointable. - /// + /// /// That is, given an operation representing a gate $U$, returns a new operation /// $U^m$ for a power $m$. /// /// # Input - /// ## oracle + /// ## op /// An operation $U$ representing the gate to be repeated. /// ## power /// The number of times that $U$ is to be repeated. @@ -145,11 +139,8 @@ namespace Microsoft.Quantum.Canon /// /// # See Also /// - @"microsoft.quantum.canon.operationpow" - function OperationPowCA<'T> (oracle : ('T => Unit is Ctl + Adj), power : Int) : ('T => Unit is Ctl + Adj) - { - return OperationPowImplCA(oracle, power, _); + function OperationPowCA<'T> (op : ('T => Unit is Ctl + Adj), power : Int) : ('T => Unit is Ctl + Adj) { + return _OperationPowCA(op, power, _); } - -} - +} diff --git a/Standard/src/Canon/Combinators/With.qs b/Standard/src/Canon/Combinators/With.qs index a01f482f428..08908862352 100644 --- a/Standard/src/Canon/Combinators/With.qs +++ b/Standard/src/Canon/Combinators/With.qs @@ -153,7 +153,7 @@ namespace Microsoft.Quantum.Canon { return ApplyWithA(outerOperation, innerOperation, _); } - // # Summary + /// # Summary /// Given two operations, applies one as conjugated with the other. /// /// # Description diff --git a/Standard/src/Canon/CommonGates.qs b/Standard/src/Canon/CommonGates.qs index fafc2dcd31f..4d5feb63975 100644 --- a/Standard/src/Canon/CommonGates.qs +++ b/Standard/src/Canon/CommonGates.qs @@ -219,14 +219,12 @@ namespace Microsoft.Quantum.Canon { /// \end{align} /// /// # Input - /// ## qubit + /// ## target /// Qubit to which the gate should be applied. /// /// # See Also - operation HY (target : Qubit) : Unit - { - body (...) - { + operation HY (target : Qubit) : Unit { + body (...) { H(target); S(target); } diff --git a/Standard/src/Canon/DataStructures/Stack.qs b/Standard/src/Canon/DataStructures/Stack.qs index 8e690dfa631..d7c703ce582 100644 --- a/Standard/src/Canon/DataStructures/Stack.qs +++ b/Standard/src/Canon/DataStructures/Stack.qs @@ -3,90 +3,45 @@ namespace Microsoft.Quantum.Canon { - - /// # Summary - /// A last-in-first-out stack of `Result` variables. - /// The stack consists of an integer capacity, a stack pointer and a `Result` array. + @Deprecated("") newtype ResultStack = (Int, Int, Result[]); - - - /// # Summary - /// Retrieves the capacity of a . - /// - /// # Input - /// ## stack - /// The stack whose capacity is to be determined. - /// - /// # Output - /// The number of elements fitting into the stack. - function StackCapacity (stack : ResultStack) : Int - { + + + @Deprecated("") + function StackCapacity (stack : ResultStack) : Int { let (size, pos, data) = stack!; return size; } - - - /// # Summary - /// Retrieves the number of elements stored in a - /// . - /// - /// # Input - /// ## stack - /// The stack whose length is to be determined. - /// - /// # Output - /// The number of elements on the stack. - function StackLength (stack : ResultStack) : Int - { + + + @Deprecated("") + function StackLength (stack : ResultStack) : Int { let (size, pos, data) = stack!; return pos; } - - - /// # Summary - /// Removes the topmost element from a . - /// - /// # Input - /// ## stack - /// The stack to be popped. - /// - /// # Output - /// The `stack` with the top element removed. The new stack has the same capacity as - /// the old one, but its length is reduced by one. - function StackPop (stack : ResultStack) : ResultStack - { + + @Deprecated("") + function StackPop (stack : ResultStack) : ResultStack { let (size, pos, data) = stack!; - + if (pos == 0) { fail $"Cannot pop an empty stack."; } - + return ResultStack(size, pos - 1, data); } - - - /// # Summary - /// Pushes a new element onto a . - /// - /// # Input - /// ## stack - /// The stack to be grown. - /// ## datum - /// The `Result` value to be pushed onto `stack`. - /// - /// # Output - /// The `stack` with `datum` added as its new top element. The new stack's length is - /// increased by one. - function StackPush (stack : ResultStack, datum : Result) : ResultStack - { + + + @Deprecated("") + function StackPush (stack : ResultStack, datum : Result) : ResultStack { let (size, pos, data) = stack!; - + if (pos == size) { fail $"Stack is full."; } - + // FIXME: implies an O(n) copy! // This could be fixed by using a native C# operation to // wrap ImmutableStack. @@ -95,44 +50,25 @@ namespace Microsoft.Quantum.Canon set newData w/= pos <- datum; return ResultStack(size, pos + 1, newData); } - - - /// # Summary - /// Retrieves the topmost element of a . - /// - /// # Input - /// ## stack - /// The stack to be inspected. - /// - /// # Output - /// The value stored at the top of `stack`. - function StackPeek (stack : ResultStack) : Result - { + + + @Deprecated("") + function StackPeek (stack : ResultStack) : Result { let (size, pos, data) = stack!; - + if (pos == 0) { fail $"Cannot peek at an empty stack."; } - + return data[pos - 1]; } - - - /// # Summary - /// Creates a new empty with given capacity. - /// - /// # Input - /// ## size - /// The capacity of the new stack. - /// - /// # Output - /// A new `ResultStack` that has capacity `size` and length 0. - function StackNew (size : Int) : ResultStack - { + + @Deprecated("") + function StackNew (size : Int) : ResultStack { return ResultStack(size, 0, new Result[size]); } - + } diff --git a/Standard/src/Canon/Deprecated.qs b/Standard/src/Canon/Deprecated.qs index 65602fd4116..b2a357aa7ab 100644 --- a/Standard/src/Canon/Deprecated.qs +++ b/Standard/src/Canon/Deprecated.qs @@ -3,6 +3,7 @@ namespace Microsoft.Quantum.Canon { open Microsoft.Quantum.Arithmetic; + open Microsoft.Quantum.Logical; /// # Deprecated /// This operation has been removed. @@ -18,4 +19,22 @@ namespace Microsoft.Quantum.Canon { ApplyQuantumFourierTransform(qs); } + /// # Deprecated + /// Please use @"microsoft.quantum.logical.xor". + @Deprecated("Microsoft.Quantum.Logical.Xor") + function XOR(bit1 : Bool, bit2 : Bool) : Bool { + return Xor(bit1, bit2); + } + + @Deprecated("Microsoft.Quantum.Canon.ApplyCNOTChain") + operation CNOTChain(qubits : Qubit[]) : Unit is Adj + Ctl { + ApplyCNOTChain(qubits); + } + + @Deprecated("Microsoft.Quantum.Canon.ApplyCNOTChainWithTarget") + operation CNOTChainTarget(qubits : Qubit[], targetQubit : Qubit) + : Unit is Adj + Ctl { + ApplyCNOTChainWithTarget(qubits, targetQubit); + } + } diff --git a/Standard/src/Canon/Enumeration/Trotter.qs b/Standard/src/Canon/Enumeration/Trotter.qs index b8229e14ff7..dcdf635afea 100644 --- a/Standard/src/Canon/Enumeration/Trotter.qs +++ b/Standard/src/Canon/Enumeration/Trotter.qs @@ -108,30 +108,21 @@ namespace Microsoft.Quantum.Canon { /// Multiplier on size of each step of the simulation. /// ## target /// A quantum register on which the operations act. - operation _TrotterArbitraryImplCA<'T> (order:Int, (nSteps : Int, op : ((Int, Double, 'T) => Unit is Adj + Ctl)), stepSize : Double, target : 'T) : Unit - { - body (...) - { - if(order > 2){ - let stepSizeOuter = _TrotterStepSize(order); - let stepSizeInner = 1.0 - 4.0 * stepSizeOuter; - _TrotterArbitraryImplCA(order -2, (nSteps, op), stepSizeOuter * stepSize, target); - _TrotterArbitraryImplCA(order -2, (nSteps, op), stepSizeOuter * stepSize, target); - _TrotterArbitraryImplCA(order -2, (nSteps, op), stepSizeInner * stepSize, target); - _TrotterArbitraryImplCA(order -2, (nSteps, op), stepSizeOuter * stepSize, target); - _TrotterArbitraryImplCA(order -2, (nSteps, op), stepSizeOuter * stepSize, target); - } - elif(order == 2){ - _Trotter2ImplCA((nSteps, op), stepSize, target); - } - else{ - _Trotter1ImplCA((nSteps, op), stepSize, target); - } + operation _TrotterArbitraryImplCA<'T> (order:Int, (nSteps : Int, op : ((Int, Double, 'T) => Unit is Adj + Ctl)), stepSize : Double, target : 'T) + : Unit is Adj + Ctl { + if (order > 2) { + let stepSizeOuter = _TrotterStepSize(order); + let stepSizeInner = 1.0 - 4.0 * stepSizeOuter; + _TrotterArbitraryImplCA(order -2, (nSteps, op), stepSizeOuter * stepSize, target); + _TrotterArbitraryImplCA(order -2, (nSteps, op), stepSizeOuter * stepSize, target); + _TrotterArbitraryImplCA(order -2, (nSteps, op), stepSizeInner * stepSize, target); + _TrotterArbitraryImplCA(order -2, (nSteps, op), stepSizeOuter * stepSize, target); + _TrotterArbitraryImplCA(order -2, (nSteps, op), stepSizeOuter * stepSize, target); + } elif (order == 2) { + _Trotter2ImplCA((nSteps, op), stepSize, target); + } else { + _Trotter1ImplCA((nSteps, op), stepSize, target); } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; } /// # Summary @@ -152,9 +143,9 @@ namespace Microsoft.Quantum.Canon { /// `Qubit[]` or `Qubit`. /// /// # Input - /// ### nSteps + /// ## nSteps /// The number of operations to be decomposed into time steps. - /// ### op + /// ## op /// An operation which accepts an index input (type `Int`) and a time /// input (type `Double`) for decomposition. /// ## trotterOrder diff --git a/Standard/src/Canon/IterateThroughCartesianProduct.qs b/Standard/src/Canon/IterateThroughCartesianProduct.qs index 4773ad77e0d..7966b0027c0 100644 --- a/Standard/src/Canon/IterateThroughCartesianProduct.qs +++ b/Standard/src/Canon/IterateThroughCartesianProduct.qs @@ -3,54 +3,105 @@ namespace Microsoft.Quantum.Canon { open Microsoft.Quantum.Arrays; - + /// # Summary - /// Iterates a variable, say `arr`, through a Cartesian product - /// [ 0, bounds[0]-1 ] × [ 0, bounds[1]-1 ] × [ 0, bounds[Length(bounds)-1]-1 ] - /// and calls op(arr) for every element of the Cartesian product - operation IterateThroughCartesianProduct (bounds : Int[], op : (Int[] => Unit)) : Unit - { + /// Applies an operation for each index in the Cartesian product of several + /// ranges. + /// + /// # Description + /// Iteratively applies an operation for each element of the Cartesian product + /// of `0..(bounds[0] - 1)`, `0..(bounds[1] - 1)`, ..., `0..(bounds[Length(bounds) - 1] - 1)` + /// + /// # Input + /// ## bounds + /// An array specifying the ranges to be iterated over, with each range + /// being specified as an integer length. + /// ## op + /// An operation to be called for each element of the given Cartesian product. + /// + /// # Example + /// Given an operation `op`, the following two snippets are equivalent: + /// ```Q# + /// IterateThroughCartesianProduct([3, 4, 5], op); + /// ``` + /// ```Q# + /// op([0, 0, 0]); + /// op([1, 0, 0]); + /// op([2, 0, 0]); + /// op([0, 1, 0]); + /// // ... + /// op([0, 3, 0]); + /// op([0, 0, 1]); + /// // + /// op([2, 3, 4]); + /// ``` + /// + /// # See Also + /// - Microsoft.Quantum.Canon.IterateThroughCartesianPower + operation IterateThroughCartesianProduct(bounds : Int[], op : (Int[] => Unit)) : Unit { mutable arr = new Int[Length(bounds)]; mutable finished = false; - - repeat - { - if (not finished) - { + + repeat { + if (not finished) { op(arr); } } until (finished) - fixup - { + fixup { //computes the next element in the Cartesian product set arr w/= 0 <- arr[0] + 1; - - for (i in 0 .. Length(arr) - 2) - { - if (arr[i] == bounds[i]) - { + + for (i in 0 .. Length(arr) - 2) { + if (arr[i] == bounds[i]) { set arr w/= i + 1 <- arr[i + 1] + 1; set arr w/= i <- 0; } } - - if (arr[Length(arr) - 1] == bounds[Length(arr) - 1]) - { + + if (arr[Length(arr) - 1] == bounds[Length(arr) - 1]) { set finished = true; } } } - - + + /// # Summary - /// Iterates a variable, say arr, through Cartesian product - /// [ 0, bound - 1 ] × [ 0, bound - 1 ] × [ 0, bound - 1 ] - /// and calls op(arr) for every element of the Cartesian product + /// Applies an operation for each index in the Cartesian power of an + /// integer range. + /// + /// # Description + /// Iteratively applies an operation for each element of a Cartesian power + /// of the range `0..(bound - 1)`. + /// + /// # Input + /// ## power + /// The Cartesian power to which the range `0..(bound - 1)` should be + /// raised. + /// ## bound + /// A specification of the range to be iterated over, given as the length + /// of the range. + /// ## op + /// An operation to be called for each element of the given Cartesian power. + /// + /// # Example + /// Given an operation `op`, the following two snippets are equivalent: + /// ```Q# + /// IterateThroughCartesianPower(2, 3, op); + /// ``` + /// ```Q# + /// op([0, 0]); + /// op([1, 0]); + /// op([2, 0]); + /// op([0, 1]); + /// // .. + /// op([2, 2]); + /// ``` + /// + /// # See Also + /// - Microsoft.Quantum.Canon.IterateThroughCartesianProduct operation IterateThroughCartesianPower (power : Int, bound : Int, op : (Int[] => Unit)) : Unit { IterateThroughCartesianProduct(ConstantArray(power, bound), op); } - -} - +} diff --git a/Standard/src/Canon/Parity.qs b/Standard/src/Canon/Parity.qs index 46f96714d1d..041b8ff5756 100644 --- a/Standard/src/Canon/Parity.qs +++ b/Standard/src/Canon/Parity.qs @@ -3,32 +3,33 @@ namespace Microsoft.Quantum.Canon { open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Arrays; /// # Summary - /// Computes the parity of an array of qubits in-place. - /// - /// It follows the pattern - /// $\ket{q_0} \ket{q_0 \oplus q_1} \ket{q_0 \oplus q_1 \oplus q_2} \cdots$. + /// Computes the parity of a register of qubits in-place. + /// + /// # Description + /// This operation transforms the state of its input as + /// $$ + /// \begin{align} + /// \ket{q_0} \ket{q_1} \cdots \ket{q_{n - 1}} & \mapsto + /// \ket{q_0} \ket{q_0 \oplus q_1} \ket{q_0 \oplus q_1 \oplus q_2} \cdots + /// \ket{q_0 \oplus \cdots \oplus q_{n - 1}}. + /// \end{align} + /// $$ /// /// # Input /// ## qubits - /// Array of qubits on which parity is computed - /// and stored. - operation CNOTChain(qubits: Qubit[]) : Unit { - body (...) { - for (idxQubit in 0..Length(qubits) - 2){ - CNOT(qubits[idxQubit], qubits[idxQubit + 1]); - } - } - adjoint auto; - controlled auto; - adjoint controlled auto; + /// Array of qubits whose parity is to be computed and stored. + operation ApplyCNOTChain(qubits : Qubit[]) : Unit is Adj + Ctl { + ApplyToEachCA(CNOT, Zip(Most(qubits), Rest(qubits))); } /// # Summary /// Computes the parity of an array of qubits into a target qubit. - /// - /// If the array is initially in the state + /// + /// # Description + /// If the array is initially in the state /// $\ket{q_0} \ket{q_1} \cdots \ket{q_{\text{target}}}$, /// the final state is given by /// $\ket{q_0} \ket{q_1 \oplus q_0} \cdots \ket{q_{n - 1} \oplus \cdots \oplus q_0 \oplus q_{\text{target}}}$. @@ -42,26 +43,15 @@ namespace Microsoft.Quantum.Canon { /// # Remarks /// The following are equivalent: /// ```qsharp - /// CNOTChainTarget(Most(qs), Last(qs)); + /// ApplyCNOTChainWithTarget(Most(qs), Last(qs)); /// ``` - /// and - /// ```qsharp - /// CNOTChain(qs); + /// and + /// ```qsharp + /// ApplyCNOTChain(qs); /// ``` - operation CNOTChainTarget(qubits: Qubit[], targetQubit: Qubit) : Unit { - body (...) { - let allQubits = qubits + [targetQubit]; - CNOTChain(allQubits); - } - adjoint auto; - controlled auto; - adjoint controlled auto; - } - - /// # Summary - /// This computes the exclusive-OR of two bits. - function XOR(bit1: Bool, bit2: Bool) : Bool { - return (bit1 or bit2) and (not bit1 or not bit2); + operation ApplyCNOTChainWithTarget(qubits : Qubit[], targetQubit : Qubit) + : Unit is Adj + Ctl { + ApplyCNOTChain(qubits + [targetQubit]); } } diff --git a/Standard/src/Characterization/Deprecated.qs b/Standard/src/Characterization/Deprecated.qs new file mode 100644 index 00000000000..2fec53af203 --- /dev/null +++ b/Standard/src/Characterization/Deprecated.qs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Characterization { + open Microsoft.Quantum.Measurement as Meas; + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Arrays; + + /// # Deprecated + /// Please use @"microsoft.quantum.measurement.measureAllZ". + @Deprecated("Microsoft.Quantum.Measurement.MeasureAllZ") + operation MeasureAllZ(register : Qubit[]) : Result { + return Measure(ConstantArray(Length(register), PauliZ), register); + } + +} diff --git a/Standard/src/Characterization/Distinguishability.qs b/Standard/src/Characterization/Distinguishability.qs index 483cdbed803..b4b98d74b4d 100644 --- a/Standard/src/Characterization/Distinguishability.qs +++ b/Standard/src/Characterization/Distinguishability.qs @@ -164,8 +164,12 @@ namespace Microsoft.Quantum.Characterization { } apply { commonPreparation(target); Controlled preparation1([control], target); - within { X(control); } - apply { Controlled preparation2([control], target); } + within { + X(control); + } + apply { + Controlled preparation2([control], target); + } (phaseShift ? S | I)(control); } diff --git a/Standard/src/Characterization/PhaseEstimation/Iterative.qs b/Standard/src/Characterization/PhaseEstimation/Iterative.qs index 48823f2952b..06844cec11b 100644 --- a/Standard/src/Characterization/PhaseEstimation/Iterative.qs +++ b/Standard/src/Characterization/PhaseEstimation/Iterative.qs @@ -18,17 +18,17 @@ namespace Microsoft.Quantum.Characterization { // let DiscreteOracle = OracleToDiscrete(U); // DiscretePhaseEstimationIteration(oracle, pow, theta, targetState, control); // let datum = M(control); - + // This design then enables providing more efficient implementations of U^m // to be provided by the user for specific U, while providing a sensible // "default" for operations which cannot be fast-forwarded by taking advantage // of their definitions. - + // Finally, we also ensure that quantum arguments are placed last to follow // standard conventions for partial application. In particular, this allows for // the discrete and continuous phase estimation iterations to be used in // an allocate-op-measure pattern; we may soon want to abstract that away. - + /// # Summary /// Performs a single iteration of an iterative (classically-controlled) phase /// estimation algorithm using integer powers of a unitary oracle. @@ -46,32 +46,34 @@ namespace Microsoft.Quantum.Characterization { /// acting on the target state. /// ## targetState /// Register of state acted upon by the given unitary oracle. - operation DiscretePhaseEstimationIteration (oracle : DiscreteOracle, power : Int, theta : Double, targetState : Qubit[], controlQubit : Qubit) : Unit - { + /// ## controlQubit + /// An auxillary qubit used to control the application of the given oracle. + operation DiscretePhaseEstimationIteration( + oracle : DiscreteOracle, + power : Int, + theta : Double, + targetState : Qubit[], + controlQubit : Qubit + ) + : Unit is Adj + Ctl { // NB: We accept the control qubit as input so that we can allow for this operation // to subject to the adjoint and control modifiers (that is, such that we do not need // a return statement, but rather *act* on the given qubits). - body (...) - { - // Find the actual inversion angle by rescaling with the power of the - // oracle. - let inversionAngle = -theta * IntAsDouble(power); - - // Prepare the control qubit. + // Find the actual inversion angle by rescaling with the power of the + // oracle. + let inversionAngle = -theta * IntAsDouble(power); + + // Prepare the control qubit, using the within/apply block to + // return the control qubit to the appropriate measurement basis. + within { H(controlQubit); + } apply { Rz(inversionAngle, controlQubit); Controlled oracle!([controlQubit], (power, targetState)); - - // Return the control qubit to the appropriate measurement basis. - H(controlQubit); } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; } - - + + /// # Summary /// Performs a single iteration of an iterative (classically-controlled) phase /// estimation algorithm using arbitrary real powers of a unitary oracle. @@ -89,40 +91,26 @@ namespace Microsoft.Quantum.Characterization { /// acting on the target state. /// ## targetState /// Register of state acted upon by the given unitary oracle. - operation ContinuousPhaseEstimationIteration (oracle : ContinuousOracle, time : Double, theta : Double, targetState : Qubit[], controlQubit : Qubit) : Unit + operation ContinuousPhaseEstimationIteration( + oracle : ContinuousOracle, + time : Double, + theta : Double, + targetState : Qubit[], + controlQubit : Qubit + ) : Unit is Adj + Ctl { - body (...) - { - let inversionAngle = -(theta * time); - - // Prepare the control qubit. + let inversionAngle = -(theta * time); + + // Prepare the control qubit, using the within/apply block to + // return the control qubit to the appropriate measurement basis. + within { H(controlQubit); + } apply { Rz(inversionAngle, controlQubit); Controlled oracle!([controlQubit], (time, targetState)); - - // Return the control qubit to the appropriate measurement basis. - H(controlQubit); } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; } - - - operation PrepAndMeasurePhaseEstImpl (wInv : Double, t : Double, op : ((Double, Double, Qubit) => Unit)) : Result - { - mutable datum = Zero; - - using (register = Qubit[1]) - { - op(t, wInv, register[0]); - set datum = MResetZ(register[0]); - } - - return datum; - } - + } diff --git a/Standard/src/Characterization/PhaseEstimation/Robust.qs b/Standard/src/Characterization/PhaseEstimation/Robust.qs index 9739c6cc3af..cdb11021ceb 100644 --- a/Standard/src/Characterization/PhaseEstimation/Robust.qs +++ b/Standard/src/Characterization/PhaseEstimation/Robust.qs @@ -59,9 +59,9 @@ namespace Microsoft.Quantum.Characterization { if (result == Zero) { if (idxExperiment == 0) { - set pZero = pZero + 1.0; + set pZero += 1.0; } elif (idxExperiment == 1) { - set pPlus = pPlus + 1.0; + set pPlus += 1.0; } } @@ -76,10 +76,10 @@ namespace Microsoft.Quantum.Characterization { Reset(controlQubit); } - + return thetaEst; } - + } diff --git a/Standard/src/Characterization/ProcessTomography.qs b/Standard/src/Characterization/ProcessTomography.qs index 739de791934..dc027054c0f 100644 --- a/Standard/src/Characterization/ProcessTomography.qs +++ b/Standard/src/Characterization/ProcessTomography.qs @@ -8,22 +8,6 @@ namespace Microsoft.Quantum.Characterization { open Microsoft.Quantum.Preparation; open Microsoft.Quantum.Arrays; - /// # Summary - /// Jointly measures a register of qubits in the Pauli Z basis. - /// - /// In other words, measures the operation $Z \otimes Z \otimes \cdots \otimes Z$ on - /// a given register. - /// - /// # Input - /// ## register - /// The register to be measured. - /// - /// # Output - /// The result of measuring $Z \otimes Z \otimes \cdots \otimes Z$. - operation MeasureAllZ (register : Qubit[]) : Result { - return Measure(ConstantArray(Length(register), PauliZ), register); - } - /// # Summary /// Measures the identity operator on a register /// of qubits. diff --git a/Standard/src/Convert/Deprecated.qs b/Standard/src/Convert/Deprecated.qs index 56ff2280951..e1b7f3ed0e2 100644 --- a/Standard/src/Convert/Deprecated.qs +++ b/Standard/src/Convert/Deprecated.qs @@ -6,8 +6,8 @@ namespace Microsoft.Quantum.Canon { /// # Deprecated /// This function has been removed. + @Deprecated("") function AsQubitArray (arr : Qubit[]) : Qubit[] { - // TODO: add call to _Removed. return arr; } diff --git a/Standard/src/ErrorCorrection/BitFlipCode.qs b/Standard/src/ErrorCorrection/BitFlipCode.qs index 4fb8d11d905..83b778b6adb 100644 --- a/Standard/src/ErrorCorrection/BitFlipCode.qs +++ b/Standard/src/ErrorCorrection/BitFlipCode.qs @@ -17,23 +17,17 @@ namespace Microsoft.Quantum.ErrorCorrection { /// /// # References /// - doi:10.1103/PhysRevA.85.044302 - operation BFEncoderImpl (coherentRecovery : Bool, data : Qubit[], scratch : Qubit[]) : Unit - { - body (...) - { - if (coherentRecovery) - { - Controlled X(scratch, data[0]); - } - - Controlled X(data, scratch[0]); - Controlled X(data, scratch[1]); + operation _BFEncoder(coherentRecovery : Bool, data : Qubit[], scratch : Qubit[]) + : Unit is Adj { + if (coherentRecovery) { + Controlled X(scratch, data[0]); } - - adjoint invert; + + Controlled X(data, scratch[0]); + Controlled X(data, scratch[1]); } - - + + /// # Summary /// Encodes into the [3, 1, 3] / ⟦3, 1, 1⟧ bit-flip code. /// @@ -50,14 +44,14 @@ namespace Microsoft.Quantum.ErrorCorrection { /// /// # See Also /// - LogicalRegister - operation EncodeIntoBitFlipCode(physRegister : Qubit[], auxQubits : Qubit[]) : LogicalRegister - { - BFEncoderImpl(false, physRegister, auxQubits); + operation EncodeIntoBitFlipCode(physRegister : Qubit[], auxQubits : Qubit[]) + : LogicalRegister { + _BFEncoder(false, physRegister, auxQubits); let logicalRegister = LogicalRegister(physRegister + auxQubits); return logicalRegister; } - - + + /// # Summary /// Decodes from the [3, 1, 3] / ⟦3, 1, 1⟧ bit-flip code. /// @@ -72,11 +66,11 @@ namespace Microsoft.Quantum.ErrorCorrection { /// # See Also /// - LogicalRegister /// - EncodeIntoBitFlipCode - operation DecodeFromBitFlipCode(logicalRegister : LogicalRegister) : (Qubit[], Qubit[]) - { + operation DecodeFromBitFlipCode(logicalRegister : LogicalRegister) + : (Qubit[], Qubit[]) { let physRegister = [(logicalRegister!)[0]]; let auxQubits = (logicalRegister!)[1 .. 2]; - Adjoint BFEncoderImpl(false, physRegister, auxQubits); + Adjoint _BFEncoder(false, physRegister, auxQubits); return (physRegister, auxQubits); } diff --git a/Standard/src/ErrorCorrection/KnillDistill.qs b/Standard/src/ErrorCorrection/KnillDistill.qs index 86345d10738..cbc07cb4fe0 100644 --- a/Standard/src/ErrorCorrection/KnillDistill.qs +++ b/Standard/src/ErrorCorrection/KnillDistill.qs @@ -6,10 +6,9 @@ namespace Microsoft.Quantum.ErrorCorrection { open Microsoft.Quantum.Canon; open Microsoft.Quantum.Measurement; - /// # Summary /// Syndrome measurement and the inverse of embedding. - /// + /// /// $X$- and $Z$-stabilizers are not treated equally, /// which is due to the particular choice of the encoding circuit. /// This asymmetry leads to a different syndrome extraction routine. @@ -24,71 +23,68 @@ namespace Microsoft.Quantum.ErrorCorrection { /// would have caused the measured syndrome. /// /// # Remarks - /// + /// /// > [!WARNING] /// > This routine is tailored /// > to a particular encoding circuit for Steane's 7 qubit code; /// > if the encoding circuit is modified then the syndrome outcome /// > might have to be interpreted differently. - /// - operation _ExtractLogicalQubitFromSteaneCode (code : LogicalRegister) : (Qubit, Int, Int) - { + /// + operation _ExtractLogicalQubitFromSteaneCode (code : LogicalRegister) + : (Qubit, Int, Int) { Adjoint SteaneCodeEncoderImpl((code!)[0 .. 0], (code!)[1 .. 6]); let x0 = M((code!)[6]); let x1 = M((code!)[1]); let x2 = M((code!)[3]); mutable xsyn = 0; - - if (x0 == One) - { + + if (x0 == One) { set xsyn = xsyn ^^^ 1; } - - if (x1 == One) - { + + if (x1 == One) { set xsyn = xsyn ^^^ 2; } - - if (x2 == One) - { + + if (x2 == One) { set xsyn = xsyn ^^^ 4; } - - set xsyn = xsyn - 1; - + + set xsyn -= 1; + // xsyn contains the qubit index (0..6) at which a single Z-error would // produce the given syndrome. let z0 = M((code!)[5]); let z1 = M((code!)[2]); let z2 = M((code!)[4]); mutable zsyn = 0; - - if (z0 == One) - { + + if (z0 == One) { set zsyn = zsyn ^^^ 1; } - - if (z1 == One) - { + + if (z1 == One) { set zsyn = zsyn ^^^ 2; } - - if (z2 == One) - { + + if (z2 == One) { set zsyn = zsyn ^^^ 5; } - - set zsyn = zsyn - 1; - + + set zsyn -= 1; + // zsyn contains the qubit index (0..6) at which a single X-error would // produce the given syndrome. return ((code!)[0], xsyn, zsyn); } - - + + /// # Summary + /// Rotates a single qubit by π/4 about the Y-axis. + /// + /// # Description /// Performs a π/4 rotation about `Y`. - /// + /// /// The rotation is performed by consuming a magic /// state; that is, a copy of the state /// $$ @@ -122,19 +118,19 @@ namespace Microsoft.Quantum.ErrorCorrection { /// This operation supports the `Adjoint` functor, in which /// case the same magic state is consumed, but the effect /// on the data qubit is a $-\pi/4$ $Y$-rotation. - operation InjectPi4YRotation (data : Qubit, magic : Qubit) : Unit - { - body (...) - { + operation InjectPi4YRotation (data : Qubit, magic : Qubit) + : Unit is Adj { + body (...) { Adjoint S(data); CNOT(magic, data); S(data); let r = MResetY(magic); - - if (r == One) - { - // The following five gates is equal to Ry( Pi()/2.0, data) - // up to global phase. + + if (r == One) { + // The following five operations are equivalant to + // Ry( Pi()/2.0, data), up to global phase. + // Since this operation does not support Controlled, we need + // not worry about global phases. S(data); H(data); Adjoint S(data); @@ -142,16 +138,14 @@ namespace Microsoft.Quantum.ErrorCorrection { Adjoint S(data); } } - - adjoint (...) - { + + adjoint (...) { Adjoint S(data); CNOT(magic, data); S(data); let r = MResetY(magic); - - if (r == Zero) - { + + if (r == Zero) { S(data); H(data); S(data); @@ -160,11 +154,12 @@ namespace Microsoft.Quantum.ErrorCorrection { } } } - - + + /// # Summary /// Implements the Knill magic state distillation algorithm. - /// + /// + /// # Description /// Given 15 approximate copies of a magic state /// $$ /// \begin{align} @@ -195,39 +190,35 @@ namespace Microsoft.Quantum.ErrorCorrection { /// /// # References /// - [Knill](https://arxiv.org/abs/quant-ph/0402171) - operation KnillDistill (roughMagic : Qubit[]) : Bool - { + operation KnillDistill (roughMagic : Qubit[]) : Bool { mutable accept = false; - - using (scratch = Qubit[8]) - { + + using (scratch = Qubit[8]) { let anc = scratch[7]; let code = scratch[0 .. 6]; InjectPi4YRotation(code[0], roughMagic[14]); SteaneCodeEncoderImpl(code[0 .. 0], code[1 .. 6]); - - for (idx in 0 .. 6) - { + + for (idx in 0 .. 6) { Adjoint InjectPi4YRotation(code[idx], roughMagic[idx]); CNOT(code[idx], anc); InjectPi4YRotation(code[idx], roughMagic[idx + 7]); } - + let (logicalQubit, xsyn, zsyn) = _ExtractLogicalQubitFromSteaneCode(LogicalRegister(code)); let m = M(anc); - - if ((xsyn == -1 and zsyn == -1) and m == Zero) - { + + if ((xsyn == -1 and zsyn == -1) and m == Zero) { SWAP(logicalQubit, roughMagic[0]); set accept = true; } - + ResetAll(scratch); } - + return accept; } - + } diff --git a/Standard/src/Measurement/Registers.qs b/Standard/src/Measurement/Registers.qs index e3b3e515af9..f5052180bf9 100644 --- a/Standard/src/Measurement/Registers.qs +++ b/Standard/src/Measurement/Registers.qs @@ -72,4 +72,21 @@ namespace Microsoft.Quantum.Measurement { return ForEach(M, targets); } + /// # Summary + /// Jointly measures a register of qubits in the Pauli Z basis. + /// + /// # Description + /// Measures a register of qubits in the $Z \otimes Z \otimes \cdots \otimes Z$ + /// basis, representing the parity of the entire register. + /// + /// # Input + /// ## register + /// The register to be measured. + /// + /// # Output + /// The result of measuring $Z \otimes Z \otimes \cdots \otimes Z$. + operation MeasureAllZ (register : Qubit[]) : Result { + return Measure(ConstantArray(Length(register), PauliZ), register); + } + } diff --git a/Standard/src/Oracles/Convert.qs b/Standard/src/Oracles/Convert.qs index 3b804227e36..25484cba36a 100644 --- a/Standard/src/Oracles/Convert.qs +++ b/Standard/src/Oracles/Convert.qs @@ -104,40 +104,34 @@ namespace Microsoft.Quantum.Oracles { /// # Summary /// Implementation of . - operation ReflectionOracleFromDeterministicStateOracleImpl (phase : Double, oracle : DeterministicStateOracle, systemRegister : Qubit[]) : Unit - { - body (...) - { - ApplyWithCA(Adjoint oracle!, RAll0(phase, _), systemRegister); - } - - adjoint invert; - controlled distribute; - controlled adjoint distribute; + operation _ReflectionOracleFromDeterministicStateOracle(phase : Double, oracle : DeterministicStateOracle, systemRegister : Qubit[]) + : Unit is Adj + Ctl { + ApplyWithCA(Adjoint oracle!, RAll0(phase, _), systemRegister); } - /// # Summary /// Constructs reflection about a given state from an oracle. /// - /// Given the oracle $O$ of type - /// , - /// the result of this function is a reflection around the state $\ket{\psi}$ - /// where $O\ket{0} = \ket{\psi}$. + /// # Description + /// Given a determinstic state preparation oracle represented by a unitary + /// matrix $O$, + /// the result of this function is an oracle that applies a reflection + /// around the state $\ket{\psi}$ prepared by the oracle $O$; that is, + /// the state $\ket{\psi}$ such that $O\ket{0} = \ket{\psi}$. /// /// # Input /// ## oracle - /// Oracle of type "DeterministicStateOracle" + /// An oracle that prepares copies of the state $\ket{\psi}$. /// /// # Output - /// A `ReflectionOracle` that reflects about the state $\ket{\psi}$. + /// An oracle that reflects about the state $\ket{\psi}$. /// /// # See Also - /// - DeterministicStateOracle - /// - ReflectionOracle - function ReflectionOracleFromDeterministicStateOracle (oracle : DeterministicStateOracle) : ReflectionOracle - { - return ReflectionOracle(ReflectionOracleFromDeterministicStateOracleImpl(_, oracle, _)); + /// - Microsoft.Quantum.Oracles.DeterministicStateOracle + /// - Microsoft.Quantum.Oracles.ReflectionOracle + function ReflectionOracleFromDeterministicStateOracle(oracle : DeterministicStateOracle) + : ReflectionOracle { + return ReflectionOracle(_ReflectionOracleFromDeterministicStateOracle(_, oracle, _)); } /// # Summary @@ -155,7 +149,7 @@ namespace Microsoft.Quantum.Oracles { /// ## Example /// `OracleToDiscrete(U)(3, target)` is equivalent to `U(target)` repeated three times. function OracleToDiscrete (blackBoxOracle : (Qubit[] => Unit is Adj + Ctl)) : DiscreteOracle { - return DiscreteOracle(OperationPowImplCA(blackBoxOracle, _, _)); + return DiscreteOracle(_OperationPowCA(blackBoxOracle, _, _)); } } diff --git a/Standard/src/Simulation/BlockEncoding.qs b/Standard/src/Simulation/BlockEncoding.qs index 25059c970bd..3eec6b4feb7 100644 --- a/Standard/src/Simulation/BlockEncoding.qs +++ b/Standard/src/Simulation/BlockEncoding.qs @@ -14,10 +14,10 @@ namespace Microsoft.Quantum.Simulation { // block-encoding. /// # Summary - /// Represents a unitary where an arbitrary operator of + /// Represents a unitary where an arbitrary operator of /// interest is encoded in the top-left block. - /// - /// That is, a `BlockEncoding` is a unitary $U$ where an arbitrary operator $H$ of + /// + /// That is, a `BlockEncoding` is a unitary $U$ where an arbitrary operator $H$ of /// interest that acts on the system register `s` is encoded in the top- /// left block corresponding to auxiliary state $\ket{0}_a$. That is, /// @@ -58,10 +58,10 @@ namespace Microsoft.Quantum.Simulation { newtype BlockEncodingReflection = BlockEncoding; /// # Summary - /// Represents a `BlockEncoding` that is controlled by a clock register. - /// - /// That is, a `TimeDependentBlockEncoding` is a unitary $U$ controlled by a state - /// $\ket{k}_d$ in clock register `d` such that an arbitrary operator $H_k$ of + /// Represents a `BlockEncoding` that is controlled by a clock register. + /// + /// That is, a `TimeDependentBlockEncoding` is a unitary $U$ controlled by a state + /// $\ket{k}_d$ in clock register `d` such that an arbitrary operator $H_k$ of /// interest that acts on the system register `s` is encoded in the top- /// left block corresponding to auxiliary state $\ket{0}_a$. That is, /// @@ -86,11 +86,11 @@ namespace Microsoft.Quantum.Simulation { newtype TimeDependentBlockEncoding = ((Qubit[], Qubit[], Qubit[]) => Unit is Adj + Ctl); /// # Summary - /// Converts a `BlockEncoding` into an equivalent `BLockEncodingReflection`. - /// + /// Converts a `BlockEncoding` into an equivalent `BLockEncodingReflection`. + /// /// That is, given a `BlockEncoding` unitary $U$ that encodes some /// operator $H$ of interest, converts it into a `BlockEncodingReflection` $U'$ that - /// encodes the same operator, but also satisfies $U'^\dagger = U'$. + /// encodes the same operator, but also satisfies $U'^\dagger = U'$. /// This increases the size of the auxiliary register of $U$ by one qubit. /// /// # Input @@ -102,7 +102,7 @@ namespace Microsoft.Quantum.Simulation { /// encodes $H$, and satisfies $U'^\dagger = U'$. /// /// # Remarks - /// This increases the size of the auxiliary register of $U$ by one qubit. + /// This increases the size of the auxiliary register of $U$ by one qubit. /// /// # References /// - Hamiltonian Simulation by Qubitization @@ -112,32 +112,29 @@ namespace Microsoft.Quantum.Simulation { /// # See Also /// - Microsoft.Quantum.Canon.BlockEncoding /// - Microsoft.Quantum.Canon.BlockEncodingReflection - function BlockEncodingToReflection(blockEncoding: BlockEncoding) : BlockEncodingReflection - { - return BlockEncodingReflection(BlockEncoding(BlockEncodingToReflection_(blockEncoding, _, _))); + function BlockEncodingToReflection(blockEncoding: BlockEncoding) + : BlockEncodingReflection { + return BlockEncodingReflection(BlockEncoding(_BlockEncodingToReflection(blockEncoding, _, _))); } - + /// # Summary /// Implementation of `BlockEncodingToReflection`. - operation BlockEncodingToReflection_(blockEncoding: BlockEncoding, auxiliary: Qubit[], system: Qubit[]) : Unit { - body (...) { - let prep = auxiliary[0]; - let blockEncodingAncilla = Rest(auxiliary); - let op1 = Controlled blockEncoding!(_, (blockEncodingAncilla, system)); - let op0 = ApplyToEachCA(H,_); - ApplyWithCA(op0, ApplyWithCA(op1, ApplyToEachCA(X,_), _), [prep]); - } - adjoint auto; - controlled auto; - adjoint controlled auto; + operation _BlockEncodingToReflection(blockEncoding: BlockEncoding, auxiliary: Qubit[], system: Qubit[]) + : Unit is Adj + Ctl { + let prep = auxiliary[0]; + let blockEncodingAux = Rest(auxiliary); + let op1 = Controlled blockEncoding!(_, (blockEncodingAux, system)); + let op0 = ApplyToEachCA(H,_); + ApplyWithCA(op0, ApplyWithCA(op1, ApplyToEachCA(X,_), _), [prep]); } /// # Summary - /// Converts a `BlockEncodingReflection` into a quantum walk. - /// - /// That is, given a `BlockEncodingReflection` unitary $U$ - /// that encodes some operator $H$ of interest, converts it into a quantum walk - /// $W$ containing the spectrum of $\pm e^{\pm i\sin^{-1}(H)}$. + /// Converts a block-encoding reflection into a quantum walk. + /// + /// # Description + /// Given a `BlockEncodingReflection` represented by a unitary $U$ + /// that encodes some operator $H$ of interest, converts it into a quantum + /// walk $W$ containing the spectrum of $\pm e^{\pm i\sin^{-1}(H)}$. /// /// # Input /// ## blockEncodingReflection @@ -156,27 +153,28 @@ namespace Microsoft.Quantum.Simulation { /// # See Also /// - Microsoft.Quantum.Canon.BlockEncoding /// - Microsoft.Quantum.Canon.BlockEncodingReflection - function QuantumWalkByQubitization(blockEncoding: BlockEncodingReflection) : ((Qubit[], Qubit[]) => Unit is Adj + Ctl) { - return QuantumWalkByQubitization_(blockEncoding, _, _); + function QuantumWalkByQubitization(blockEncoding: BlockEncodingReflection) + : ((Qubit[], Qubit[]) => Unit is Adj + Ctl) { + return _QuantumWalkByQubitization(blockEncoding, _, _); } /// # Summary /// Implementation of `Qubitization`. - operation QuantumWalkByQubitization_(blockEncoding: BlockEncodingReflection, auxiliary: Qubit[], system: Qubit[]) : Unit { - body (...){ - Exp([PauliI], -0.5 * PI(), [system[0]]); - RAll0(PI(), auxiliary); - // NB: We unwrap twice here, since BlockEncodingReflection wraps BlockEncoding. - blockEncoding!!(auxiliary, system); - } - adjoint auto; - controlled auto; - adjoint controlled auto; + operation _QuantumWalkByQubitization( + blockEncoding : BlockEncodingReflection, + auxiliary : Qubit[], + system : Qubit[] + ) + : Unit is Adj + Ctl { + Exp([PauliI], -0.5 * PI(), [Head(system)]); + RAll0(PI(), auxiliary); + // NB: We unwrap twice here, since BlockEncodingReflection wraps BlockEncoding. + blockEncoding!!(auxiliary, system); } /// # Summary - /// Encodes an operator of interest into a `BlockEncoding`. - /// + /// Encodes an operator of interest into a `BlockEncoding`. + /// /// This constructs a `BlockEncoding` unitary $U=P\cdot V\cdot P^\dagger$ that encodes some /// operator $H=\sum_{j}|\alpha_j|U_j$ of interest that is a linear combination of /// unitaries. Typically, $P$ is a state preparation unitary such that @@ -194,38 +192,35 @@ namespace Microsoft.Quantum.Simulation { /// encodes $H$, and satisfies $U^\dagger = U$. /// /// # Remarks - /// This `BlockEncoding` implementation gives it the properties of a + /// This `BlockEncoding` implementation gives it the properties of a /// `BlockEncodingReflection`. /// /// # See Also /// - Microsoft.Quantum.Canon.BlockEncoding /// - Microsoft.Quantum.Canon.BlockEncodingReflection function BlockEncodingByLCU<'T,'S>( - statePreparation: ('T => Unit is Adj + Ctl), - selector: (('T, 'S) => Unit is Adj + Ctl)) - : (('T, 'S) => Unit is Adj + Ctl) { - return BlockEncodingByLCU_(statePreparation, selector, _, _); - } + statePreparation: ('T => Unit is Adj + Ctl), + selector: (('T, 'S) => Unit is Adj + Ctl) + ) + : (('T, 'S) => Unit is Adj + Ctl) { + return _BlockEncodingByLCU(statePreparation, selector, _, _); + } /// # Summary /// Implementation of `BlockEncodingByLCU`. - operation BlockEncodingByLCU_<'T,'S>( - statePreparation: ('T => Unit is Adj + Ctl), + operation _BlockEncodingByLCU<'T,'S>( + statePreparation: ('T => Unit is Adj + Ctl), selector: (('T, 'S) => Unit is Adj + Ctl), - auxiliary: 'T, - system: 'S) - : Unit { - body (...){ - ApplyWithCA(statePreparation, selector(_, system), auxiliary); - } - adjoint auto; - controlled auto; - adjoint controlled auto; + auxiliary: 'T, + system: 'S + ) + : Unit is Adj + Ctl { + ApplyWithCA(statePreparation, selector(_, system), auxiliary); } /// # Summary - /// Encodes an operator of interest into a `BlockEncodingReflection`. - /// + /// Encodes an operator of interest into a `BlockEncodingReflection`. + /// /// This constructs a `BlockEncodingReflection` unitary $U=P\cdot V\cdot P^\dagger$ that encodes some /// operator $H=\sum_{j}|\alpha_j|U_j$ of interest that is a linear combination of /// unitaries. Typically, $P$ is a state preparation unitary such that @@ -243,33 +238,30 @@ namespace Microsoft.Quantum.Simulation { /// encodes $H$, and satisfies $U'^{-1} = U$. /// /// # Remarks - /// This `BlockEncoding` implementation gives it the properties of a + /// This `BlockEncoding` implementation gives it the properties of a /// `BlockEncodingReflection`. /// /// # See Also /// - Microsoft.Quantum.Canon.BlockEncoding /// - Microsoft.Quantum.Canon.BlockEncodingReflection function BlockEncodingReflectionByLCU( - statePreparation: (Qubit[] => Unit is Adj + Ctl), - selector: ((Qubit[], Qubit[]) => Unit is Adj + Ctl) - ) : BlockEncodingReflection { + statePreparation : (Qubit[] => Unit is Adj + Ctl), + selector : ((Qubit[], Qubit[]) => Unit is Adj + Ctl) + ) + : BlockEncodingReflection { return BlockEncodingToReflection(BlockEncoding(BlockEncodingByLCU(statePreparation, selector))); } /// # Summary /// Conversion of ((LittleEndian, Qubit[]) => () is Adj + Ctl) to BlockEncoding - operation BlockEncodingFromBEandQubit_( - op: ((LittleEndian, Qubit[]) => Unit is Adj + Ctl), - auxiliary: Qubit[], - system: Qubit[]) : Unit - { - body (...) { - op(LittleEndian(auxiliary), system); - } - adjoint auto; - controlled auto; - adjoint controlled auto; + operation _BlockEncodingFromBEandQubit( + op: ((LittleEndian, Qubit[]) => Unit is Adj + Ctl), + auxiliary: Qubit[], + system: Qubit[] + ) + : Unit is Adj + Ctl { + op(LittleEndian(auxiliary), system); } - + } diff --git a/Standard/src/Simulation/QubitizationPauliEvolutionSet.qs b/Standard/src/Simulation/QubitizationPauliEvolutionSet.qs index a133fe1c0ef..9f554dbe83a 100644 --- a/Standard/src/Simulation/QubitizationPauliEvolutionSet.qs +++ b/Standard/src/Simulation/QubitizationPauliEvolutionSet.qs @@ -41,9 +41,9 @@ namespace Microsoft.Quantum.Simulation { } /// # Summary - /// Creates a block-encoding unitary for a Hamiltonian. - /// - /// The Hamiltonian $H=\sum_{j}\alpha_j P_j$ is described by a + /// Creates a block-encoding unitary for a Hamiltonian. + /// + /// The Hamiltonian $H=\sum_{j}\alpha_j P_j$ is described by a /// sum of Pauli terms $P_j$, each with real coefficient $\alpha_j$. /// /// # Input @@ -54,25 +54,24 @@ namespace Microsoft.Quantum.Simulation { /// ## First parameter /// The one-norm of coefficients $\alpha=\sum_{j}|\alpha_j|$. /// ## Second parameter - /// A `BlockEncodingReflection` unitary $U$ of the Hamiltonian $H$. As this unitary + /// A `BlockEncodingReflection` unitary $U$ of the Hamiltonian $H$. As this unitary /// satisfies $U^2 = I$, it is also a reflection. /// /// # Remarks /// This is obtained by preparing and unpreparing the state $\sum_{j}\sqrt{\alpha_j/\alpha}\ket{j}$, - /// and constructing a multiply-controlled unitary + /// and constructing a multiply-controlled unitary /// and /// . function PauliBlockEncoding(generatorSystem: GeneratorSystem) : (Double, BlockEncodingReflection) { let statePrepUnitary = StatePreparationPositiveCoefficients; - let multiplexer = MultiplexerFromGenerator; - return PauliBlockEncodingImpl(generatorSystem, statePrepUnitary, multiplexer); - + let multiplexer = MultiplexerFromGenerator; + return _PauliBlockEncoding(generatorSystem, statePrepUnitary, multiplexer); } /// # Summary - /// Creates a block-encoding unitary for a Hamiltonian. - /// - /// The Hamiltonian $H=\sum_{j}\alpha_j P_j$ is described by a + /// Creates a block-encoding unitary for a Hamiltonian. + /// + /// The Hamiltonian $H=\sum_{j}\alpha_j P_j$ is described by a /// sum of Pauli terms $P_j$, each with real coefficient $\alpha_j$. /// /// # Input @@ -89,7 +88,7 @@ namespace Microsoft.Quantum.Simulation { /// ## First parameter /// The one-norm of coefficients $\alpha=\sum_{j}|\alpha_j|$. /// ## Second parameter - /// A `BlockEncodingReflection` unitary $U$ of the Hamiltonian $U$. As this unitary + /// A `BlockEncodingReflection` unitary $U$ of the Hamiltonian $U$. As this unitary /// satisfies $U^2 = I$, it is also a reflection. /// /// # Remarks @@ -97,18 +96,18 @@ namespace Microsoft.Quantum.Simulation { /// and construct a multiply-controlled unitary are /// and /// . - function PauliBlockEncodingImpl( + function _PauliBlockEncoding( generatorSystem: GeneratorSystem, - statePrepUnitary: (Double[] -> (LittleEndian => Unit is Adj + Ctl)), + statePrepUnitary: (Double[] -> (LittleEndian => Unit is Adj + Ctl)), multiplexer: ((Int, (Int -> (Qubit[] => Unit is Adj + Ctl))) -> ((LittleEndian, Qubit[]) => Unit is Adj + Ctl))) : (Double, BlockEncodingReflection) { let (nTerms, intToGenIdx) = generatorSystem!; - let op = IdxToCoeff_(_, intToGenIdx, PauliCoefficientFromGenIdx); + let op = _IdxToCoeff(_, intToGenIdx, PauliCoefficientFromGenIdx); let coefficients = Mapped(op, RangeAsIntArray(0..nTerms-1)); let oneNorm = PowD(PNorm(2.0, coefficients),2.0); - let unitaryGenerator = (nTerms, IdxToUnitary_(_, intToGenIdx, PauliLCUUnitary_)); + let unitaryGenerator = (nTerms, _IdxToUnitary(_, intToGenIdx, _PauliLCUUnitary)); let statePreparation = statePrepUnitary(coefficients); - let selector = multiplexer(unitaryGenerator); - let blockEncoding = BlockEncodingReflection(BlockEncoding(BlockEncodingFromBEandQubit_(BlockEncodingByLCU(statePreparation, selector),_,_))); + let selector = multiplexer(unitaryGenerator); + let blockEncoding = BlockEncodingReflection(BlockEncoding(_BlockEncodingFromBEandQubit(BlockEncodingByLCU(statePreparation, selector),_,_))); return (oneNorm, blockEncoding); } @@ -116,7 +115,7 @@ namespace Microsoft.Quantum.Simulation { /// Used in implementation of `PauliBlockEncoding` /// # See Also /// - Microsoft.Quantum.Canon.PauliBlockEncoding - function IdxToCoeff_(idx: Int, genFun: (Int -> GeneratorIndex), genIdxToCoeff: (GeneratorIndex -> Double)) : Double { + function _IdxToCoeff(idx: Int, genFun: (Int -> GeneratorIndex), genIdxToCoeff: (GeneratorIndex -> Double)) : Double { return Sqrt(AbsD(genIdxToCoeff(genFun(idx)))); } @@ -124,7 +123,7 @@ namespace Microsoft.Quantum.Simulation { /// Used in implementation of `PauliBlockEncoding` /// # See Also /// - Microsoft.Quantum.Canon.PauliBlockEncoding - function IdxToUnitary_(idx: Int, genFun: (Int -> GeneratorIndex), genIdxToUnitary: (GeneratorIndex -> (Qubit[] => Unit is Adj + Ctl))) : (Qubit[] => Unit is Adj + Ctl) { + function _IdxToUnitary(idx: Int, genFun: (Int -> GeneratorIndex), genIdxToUnitary: (GeneratorIndex -> (Qubit[] => Unit is Adj + Ctl))) : (Qubit[] => Unit is Adj + Ctl) { return genIdxToUnitary(genFun(idx)); } @@ -133,30 +132,26 @@ namespace Microsoft.Quantum.Simulation { /// Used in implementation of `PauliBlockEncoding` /// # See Also /// - Microsoft.Quantum.Canon.PauliBlockEncoding - function PauliLCUUnitary_(generatorIndex: GeneratorIndex) : (Qubit[] => Unit is Adj + Ctl) { - return ApplyPauliLCUUnitary_(generatorIndex,_); + function _PauliLCUUnitary(generatorIndex: GeneratorIndex) : (Qubit[] => Unit is Adj + Ctl) { + return _ApplyPauliLCUUnitary(generatorIndex,_); } /// # Summary /// Used in implementation of `PauliBlockEncoding` /// # See Also /// - Microsoft.Quantum.Canon.PauliBlockEncoding - operation ApplyPauliLCUUnitary_(generatorIndex: GeneratorIndex, qubits: Qubit[]) : Unit { - body (...) { - let ((idxPaulis, coeff), idxQubits) = generatorIndex!; - let pauliString = IntsToPaulis(idxPaulis); - let pauliQubits = Subarray(idxQubits, qubits); + operation _ApplyPauliLCUUnitary(generatorIndex: GeneratorIndex, qubits: Qubit[]) + : Unit is Adj + Ctl { + let ((idxPaulis, coeff), idxQubits) = generatorIndex!; + let pauliString = IntsToPaulis(idxPaulis); + let pauliQubits = Subarray(idxQubits, qubits); - ApplyPauli(pauliString, pauliQubits); + ApplyPauli(pauliString, pauliQubits); - if (coeff[0] < 0.0) { - // -1 phase - Exp([PauliI], PI(), [pauliQubits[0]]); - } + if (coeff[0] < 0.0) { + // -1 phase + Exp([PauliI], PI(), [Head(pauliQubits)]); } - adjoint auto; - controlled auto; - adjoint controlled auto; } } diff --git a/Standard/tests/IntegerTests.qs b/Standard/tests/IntegerTests.qs index a8605f38db2..403e6c02970 100644 --- a/Standard/tests/IntegerTests.qs +++ b/Standard/tests/IntegerTests.qs @@ -18,12 +18,12 @@ namespace Microsoft.Quantum.Arithmetic { let summand1LE = LittleEndian(register[0 .. numberOfQubits - 1]); let summand2LE = LittleEndian(register[numberOfQubits .. 2*numberOfQubits - 1]); let carry = register[2*numberOfQubits]; - + ApplyXorInPlace(summand1, summand1LE); ApplyXorInPlace(summand2, summand2LE); IntegerAdder(summand1LE, summand2LE, carry); - + let sum = summand1 + summand2; let expected = ModulusI(sum, 2^numberOfQubits); set actual1 = MeasureInteger(summand1LE); @@ -35,7 +35,7 @@ namespace Microsoft.Quantum.Arithmetic { if (measured_carry == One) {set actual_carry = 1;} else {set actual_carry = 0;} EqualityFactI(expected_carry, actual_carry, $"Expected {expected_carry}, got {actual_carry}"); - for (numberOfControls in 1..2) { + for (numberOfControls in 1..2) { using (controls = Qubit[numberOfControls]) { ApplyXorInPlace(summand1, summand1LE); ApplyXorInPlace(summand2, summand2LE); @@ -66,7 +66,7 @@ namespace Microsoft.Quantum.Arithmetic { } } } - + operation IntegerAdderExhaustiveTestHelper (IntegerAdder : ( (LittleEndian, LittleEndian, Qubit) => Unit is Ctl), numberOfQubits : Int) : Unit { for( summand1 in 0 .. 2^numberOfQubits - 1 ) { for( summand2 in 0 .. 2^numberOfQubits - 1 ) { @@ -90,26 +90,26 @@ namespace Microsoft.Quantum.Arithmetic { operation RippleCarryAdderDTestReversible () : Unit { let numberOfQubits = 20; - let summand1 = 823709; - let summand2 = 88487; + let summand1 = 823709; + let summand2 = 88487; IntegerAdderTestHelper(RippleCarryAdderD, summand1, summand2, numberOfQubits); } operation RippleCarryAdderCDKMExhaustiveTest () : Unit { let numberOfQubits = 4; - IntegerAdderExhaustiveTestHelper (RippleCarryAdderCDKM, numberOfQubits); + IntegerAdderExhaustiveTestHelper (RippleCarryAdderCDKM, numberOfQubits); } operation RippleCarryAdderCDKMTestReversible () : Unit { let numberOfQubits = 20; - let summand1 = 823709; - let summand2 = 88487; + let summand1 = 823709; + let summand2 = 88487; IntegerAdderTestHelper(RippleCarryAdderCDKM, summand1, summand2, numberOfQubits); } operation RippleCarryAdderCDKMExhaustiveTestReversible () : Unit { for (numberOfQubits in 3..6) { - IntegerAdderExhaustiveTestHelper (RippleCarryAdderCDKM, numberOfQubits); + IntegerAdderExhaustiveTestHelper (RippleCarryAdderCDKM, numberOfQubits); } } @@ -131,12 +131,12 @@ namespace Microsoft.Quantum.Arithmetic { mutable actual2 = 0; let summand1LE = LittleEndian(register[0 .. numberOfQubits - 1]); let summand2LE = LittleEndian(register[numberOfQubits .. 2*numberOfQubits - 1]); - + ApplyXorInPlace(summand1, summand1LE); ApplyXorInPlace(summand2, summand2LE); IntegerAdder(summand1LE, summand2LE); - + let sum = summand1 + summand2; let expected = ModulusI(sum, 2^numberOfQubits); set actual1 = MeasureInteger(summand1LE); @@ -145,7 +145,7 @@ namespace Microsoft.Quantum.Arithmetic { EqualityFactI(expected, actual2, $"Expected {expected}, got {actual2}"); let expected_carry = (sum / 2^numberOfQubits); - for (numberOfControls in 1..2) { + for (numberOfControls in 1..2) { using (controls = Qubit[numberOfControls]) { ApplyXorInPlace(summand1, summand1LE); ApplyXorInPlace(summand2, summand2LE); @@ -180,8 +180,8 @@ namespace Microsoft.Quantum.Arithmetic { operation RippleCarryAdderNoCarryTTKTestReversible () : Unit { let numberOfQubits = 10; - let summand1 = 1021; - let summand2 = 973; + let summand1 = 1021; + let summand2 = 973; IntegerAdderNoCarryTestHelper(RippleCarryAdderNoCarryTTK, summand1, summand2, numberOfQubits); } @@ -206,13 +206,13 @@ namespace Microsoft.Quantum.Arithmetic { let integer1LE = LittleEndian(register[0 .. numberOfQubits - 1]); let integer2LE = LittleEndian(register[numberOfQubits .. 2*numberOfQubits - 1]); let result = register[2*numberOfQubits]; - + ApplyXorInPlace(integer1, integer1LE); ApplyXorInPlace(integer2, integer2LE); GreaterThan(integer1LE, integer2LE, result); - if (integer1 > integer2) {set gt = One;} + if (integer1 > integer2) {set gt = One;} set actual1 = MeasureInteger(integer1LE); EqualityFactI(integer1, actual1, $"Expected {integer1}, got {actual1}"); set actual2 = MeasureInteger(integer2LE); @@ -221,7 +221,7 @@ namespace Microsoft.Quantum.Arithmetic { EqualityFactB((gt == actualr), true, $"Expected {gt}, got {actualr}"); Reset(result); - for (numberOfControls in 1..2) { + for (numberOfControls in 1..2) { using (controls = Qubit[numberOfControls]) { ApplyXorInPlace(integer1, integer1LE); ApplyXorInPlace(integer2, integer2LE); From a23e3eafb20365e1cef00a499e73fe3df9281541 Mon Sep 17 00:00:00 2001 From: Guang Hao Low Date: Wed, 15 Jan 2020 13:05:52 -0800 Subject: [PATCH 11/11] Fix high-order Trotter bug (#178) Co-authored-by: Chris Granade --- Standard/src/Canon/Enumeration/Trotter.qs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Standard/src/Canon/Enumeration/Trotter.qs b/Standard/src/Canon/Enumeration/Trotter.qs index dcdf635afea..036896b769e 100644 --- a/Standard/src/Canon/Enumeration/Trotter.qs +++ b/Standard/src/Canon/Enumeration/Trotter.qs @@ -129,7 +129,7 @@ namespace Microsoft.Quantum.Canon { /// Computes Trotter step size in recursive implementation of /// Trotter simulation algorithm. function _TrotterStepSize (order: Int) : Double { - return 1.0 / (4.0 - PowD(4.0, 1.0 / (2.0 * IntAsDouble(order) - 1.0))); + return 1.0 / (4.0 - PowD(4.0, 1.0 / (IntAsDouble(order) - 1.0))); }