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 ef1a835a77e..5f7d7dba3ea 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 5a480fa6b97..3f77384b03c 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 4eee1e92205..8e8b3c09c51 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 94bfd34ffc9..ef74163503e 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 59db46d6537..20afc319ae5 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 410bb53582c..d60d4de76e0 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 071091e0595..80bc481579a 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/MachineLearning/src/DataModel/DataModel.csproj b/MachineLearning/src/DataModel/DataModel.csproj index 0b9c2b15adb..3aadd057759 100644 --- a/MachineLearning/src/DataModel/DataModel.csproj +++ b/MachineLearning/src/DataModel/DataModel.csproj @@ -5,6 +5,7 @@ x64 Microsoft.Quantum.MachineLearning.DataModel bin\$(BuildConfiguration)\$(PlatformTarget)\$(AssemblyName).xml + true @@ -31,11 +32,6 @@ - - - - - diff --git a/MachineLearning/src/Runtime/Runtime.csproj b/MachineLearning/src/Runtime/Runtime.csproj index c3da71b95ce..60fa28844d9 100644 --- a/MachineLearning/src/Runtime/Runtime.csproj +++ b/MachineLearning/src/Runtime/Runtime.csproj @@ -1,18 +1,16 @@ - + netstandard2.1 x64 Microsoft.Quantum.MachineLearning.Runtime + true + + false - - True - - - - - - diff --git a/MachineLearning/tests/MachineLearningTests.csproj b/MachineLearning/tests/MachineLearningTests.csproj index e8620296bed..d2f2b5afd76 100644 --- a/MachineLearning/tests/MachineLearningTests.csproj +++ b/MachineLearning/tests/MachineLearningTests.csproj @@ -1,23 +1,17 @@ - + + + + netcoreapp3.0 - x64 - false + Microsoft.Quantum.Standard.Tests + false - - - - - - - - - diff --git a/Numerics/src/Numerics.csproj b/Numerics/src/Numerics.csproj index e385cfc0376..d0798426a3d 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 a8ba4731346..62542b6e1e0 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/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/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); } 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"); 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/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/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; } - + } diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index 27ba8c776f0..78df63647d9 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/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); + } + } + } +} + + 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 + ); + } +} diff --git a/Standard/tests/Standard.Tests.csproj b/Standard/tests/Standard.Tests.csproj index dc037e959cf..84d317fdcb2 100644 --- a/Standard/tests/Standard.Tests.csproj +++ b/Standard/tests/Standard.Tests.csproj @@ -1,14 +1,11 @@ - + + + + netcoreapp3.0 - x64 - false - latest Microsoft.Quantum.Standard.Tests - - - - 0162 + false @@ -19,12 +16,4 @@ - - - - - - - - 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