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