From de7099c793c918d707363aa7e419bf21ebad4c29 Mon Sep 17 00:00:00 2001 From: "Stefan J. Wernli" Date: Thu, 20 Aug 2020 12:45:07 -0700 Subject: [PATCH] Create QsharpCore targeting package This change splits all the intrinsics and decompositions defined in QsharpCore out into their own files to allow them to be individually combined into a target definition package. Q# should include decompositions to alternate quantum gate sets #249 --- src/Simulation/QsharpCore/Intrinsic.qs | 661 ------------------ .../Microsoft.Quantum.QSharp.Core.csproj | 2 + src/Simulation/QsharpCore/Reset.qs | 127 ---- .../Arrays/Enumeration.qs | 4 - .../Canon/NoOp.qs | 0 .../Diagnostics/AssertAllZero.qs | 0 .../Diagnostics/AssertQubit.qs | 12 +- .../Diagnostics/Dump.qs | 0 .../Diagnostics/UnitTests.qs | 0 .../QuantumTestSuite/AssertProbMultiQubit.qs | 43 +- .../QuantumTestSuite/AssertQubitUnitary.qs | 2 +- .../QuantumTestSuite/AssertUnitary.qs | 2 +- .../QuantumTestSuite/JointOneQubitTests.qs | 2 +- .../AssertOperationsEqualInPlace.qs | 20 +- .../AssertOperationsEqualReferenced.qs | 6 +- .../TargetDefinitions/Decompositions/CCNOT.qs | 27 + .../TargetDefinitions/Decompositions/CNOT.qs | 38 + .../Decompositions/ExpFrac.qs | 35 + .../TargetDefinitions/Decompositions/M.qs | 33 + .../Decompositions/MResetX.qs | 38 + .../Decompositions/MResetY.qs | 43 ++ .../Decompositions/MResetZ.qs | 35 + .../TargetDefinitions/Decompositions/R1.qs | 30 + .../Decompositions/R1Frac.qs | 40 ++ .../TargetDefinitions/Decompositions/RFrac.qs | 45 ++ .../TargetDefinitions/Decompositions/Reset.qs | 17 + .../Decompositions/ResetAll.qs | 17 + .../TargetDefinitions/Decompositions/Rx.qs | 37 + .../TargetDefinitions/Decompositions/Ry.qs | 37 + .../TargetDefinitions/Decompositions/Rz.qs | 37 + .../TargetDefinitions/Decompositions/SWAP.qs | 42 ++ .../Decompositions/SetToBasisState.qs | 25 + .../TargetDefinitions/Intrinsic/Exp.qs | 27 + .../TargetDefinitions/Intrinsic/H.qs | 25 + .../TargetDefinitions/Intrinsic/I.qs | 15 + .../TargetDefinitions/Intrinsic/Measure.qs | 43 ++ .../TargetDefinitions/Intrinsic/R.qs | 30 + .../TargetDefinitions/Intrinsic/S.qs | 23 + .../TargetDefinitions/Intrinsic/T.qs | 23 + .../TargetDefinitions/Intrinsic/X.qs | 24 + .../TargetDefinitions/Intrinsic/Y.qs | 24 + .../TargetDefinitions/Intrinsic/Z.qs | 24 + .../TargetPackages/QsharpCore.Package.props | 39 ++ 43 files changed, 935 insertions(+), 819 deletions(-) delete mode 100644 src/Simulation/QsharpCore/Intrinsic.qs delete mode 100644 src/Simulation/QsharpCore/Reset.qs rename src/Simulation/{QsharpCore => QsharpFoundation}/Arrays/Enumeration.qs (91%) rename src/Simulation/{QsharpCore => QsharpFoundation}/Canon/NoOp.qs (100%) rename src/Simulation/{QsharpCore => QsharpFoundation}/Diagnostics/AssertAllZero.qs (100%) rename src/Simulation/{QsharpCore => QsharpFoundation}/Diagnostics/AssertQubit.qs (87%) rename src/Simulation/{QsharpCore => QsharpFoundation}/Diagnostics/Dump.qs (100%) rename src/Simulation/{QsharpCore => QsharpFoundation}/Diagnostics/UnitTests.qs (100%) rename src/Simulation/{QsharpCore/Diagnostics => TargetDefinitions/Decompositions}/AssertOperationsEqualInPlace.qs (88%) rename src/Simulation/{QsharpCore/Diagnostics => TargetDefinitions/Decompositions}/AssertOperationsEqualReferenced.qs (93%) create mode 100644 src/Simulation/TargetDefinitions/Decompositions/CCNOT.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/CNOT.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/ExpFrac.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/M.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/MResetX.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/MResetY.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/MResetZ.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/R1.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/R1Frac.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/RFrac.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/Reset.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/ResetAll.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/Rx.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/Ry.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/Rz.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/SWAP.qs create mode 100644 src/Simulation/TargetDefinitions/Decompositions/SetToBasisState.qs create mode 100644 src/Simulation/TargetDefinitions/Intrinsic/Exp.qs create mode 100644 src/Simulation/TargetDefinitions/Intrinsic/H.qs create mode 100644 src/Simulation/TargetDefinitions/Intrinsic/I.qs create mode 100644 src/Simulation/TargetDefinitions/Intrinsic/Measure.qs create mode 100644 src/Simulation/TargetDefinitions/Intrinsic/R.qs create mode 100644 src/Simulation/TargetDefinitions/Intrinsic/S.qs create mode 100644 src/Simulation/TargetDefinitions/Intrinsic/T.qs create mode 100644 src/Simulation/TargetDefinitions/Intrinsic/X.qs create mode 100644 src/Simulation/TargetDefinitions/Intrinsic/Y.qs create mode 100644 src/Simulation/TargetDefinitions/Intrinsic/Z.qs create mode 100644 src/Simulation/TargetDefinitions/TargetPackages/QsharpCore.Package.props diff --git a/src/Simulation/QsharpCore/Intrinsic.qs b/src/Simulation/QsharpCore/Intrinsic.qs deleted file mode 100644 index b546a5e7d1f..00000000000 --- a/src/Simulation/QsharpCore/Intrinsic.qs +++ /dev/null @@ -1,661 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Microsoft.Quantum.Intrinsic { - open Microsoft.Quantum.Math; - open Microsoft.Quantum.Convert; - - //------------------------------------------------- - // Clifford and related operations - //------------------------------------------------- - - /// # Summary - /// Performs the identity operation (no-op) on a single qubit. - /// - /// # Remarks - /// This is a no-op. It is provided for completeness and because - /// sometimes it is useful to call the identity in an algorithm or to pass it as a parameter. - operation I (target : Qubit) : Unit - is Adj + Ctl { - body (...) { } - adjoint self; - } - - - /// # Summary - /// Applies the Pauli $X$ gate. - /// - /// \begin{align} - /// \sigma_x \mathrel{:=} - /// \begin{bmatrix} - /// 0 & 1 \\\\ - /// 1 & 0 - /// \end{bmatrix}. - /// \end{align} - /// - /// # Input - /// ## qubit - /// Qubit to which the gate should be applied. - operation X (qubit : Qubit) : Unit - is Adj + Ctl { - body intrinsic; - adjoint self; - } - - /// # Summary - /// Applies the Pauli $Y$ gate. - /// - /// \begin{align} - /// \sigma_y \mathrel{:=} - /// \begin{bmatrix} - /// 0 & -i \\\\ - /// i & 0 - /// \end{bmatrix}. - /// \end{align} - /// - /// # Input - /// ## qubit - /// Qubit to which the gate should be applied. - operation Y (qubit : Qubit) : Unit - is Adj + Ctl { - body intrinsic; - adjoint self; - } - - - /// # Summary - /// Applies the Pauli $Z$ gate. - /// - /// \begin{align} - /// \sigma_z \mathrel{:=} - /// \begin{bmatrix} - /// 1 & 0 \\\\ - /// 0 & -1 - /// \end{bmatrix}. - /// \end{align} - /// - /// # Input - /// ## qubit - /// Qubit to which the gate should be applied. - operation Z (qubit : Qubit) : Unit - is Adj + Ctl { - body intrinsic; - adjoint self; - } - - - /// # Summary - /// Applies the Hadamard transformation to a single qubit. - /// - /// \begin{align} - /// H \mathrel{:=} - /// \frac{1}{\sqrt{2}} - /// \begin{bmatrix} - /// 1 & 1 \\\\ - /// 1 & -1 - /// \end{bmatrix}. - /// \end{align} - /// - /// # Input - /// ## qubit - /// Qubit to which the gate should be applied. - operation H (qubit : Qubit) : Unit - is Adj + Ctl { - body intrinsic; - adjoint self; - } - - - /// # Summary - /// Applies the S gate to a single qubit. - /// - /// # Description - /// This operation can be simulated by the unitary matrix - /// \begin{align} - /// S \mathrel{:=} - /// \begin{bmatrix} - /// 1 & 0 \\\\ - /// 0 & i - /// \end{bmatrix}. - /// \end{align} - /// - /// # Input - /// ## qubit - /// Qubit to which the gate should be applied. - operation S(qubit : Qubit) : Unit - is Adj + Ctl { - body intrinsic; - } - - - /// # Summary - /// Applies the T gate to a single qubit. - /// - /// # Description - /// This operation can be simulated by the unitary matrix - /// \begin{align} - /// T \mathrel{:=} - /// \begin{bmatrix} - /// 1 & 0 \\\\ - /// 0 & e^{i \pi / 4} - /// \end{bmatrix}. - /// \end{align} - /// - /// # Input - /// ## qubit - /// Qubit to which the gate should be applied. - operation T(qubit : Qubit) : Unit - is Adj + Ctl { - body intrinsic; - } - - - /// # Summary - /// Applies the controlled-NOT (CNOT) gate to a pair of qubits. - /// - /// \begin{align} - /// \operatorname{CNOT} \mathrel{:=} - /// \begin{bmatrix} - /// 1 & 0 & 0 & 0 \\\\ - /// 0 & 1 & 0 & 0 \\\\ - /// 0 & 0 & 0 & 1 \\\\ - /// 0 & 0 & 1 & 0 - /// \end{bmatrix}, - /// \end{align} - /// - /// where rows and columns are ordered as in the quantum concepts guide. - /// - /// # Input - /// ## control - /// Control qubit for the CNOT gate. - /// ## target - /// Target qubit for the CNOT gate. - /// - /// # Remarks - /// Equivalent to: - /// ```qsharp - /// Controlled X([control], target); - /// ``` - operation CNOT (control : Qubit, target : Qubit) : Unit - is Adj + Ctl { - - body (...) { - Controlled X([control], target); - } - - adjoint self; - } - - - /// # Summary - /// Applies the doubly controlled–NOT (CCNOT) gate to three qubits. - /// - /// # Input - /// ## control1 - /// First control qubit for the CCNOT gate. - /// ## control2 - /// Second control qubit for the CCNOT gate. - /// ## target - /// Target qubit for the CCNOT gate. - /// - /// # Remarks - /// Equivalent to: - /// ```qsharp - /// Controlled X([control1, control2], target); - /// ``` - operation CCNOT (control1 : Qubit, control2 : Qubit, target : Qubit) : Unit - is Adj + Ctl { - body (...) { - Controlled X([control1, control2], target); - } - - adjoint self; - } - - - /// # Summary - /// Applies the SWAP gate to a pair of qubits. - /// - /// \begin{align} - /// \operatorname{SWAP} \mathrel{:=} - /// \begin{bmatrix} - /// 1 & 0 & 0 & 0 \\\\ - /// 0 & 0 & 1 & 0 \\\\ - /// 0 & 1 & 0 & 0 \\\\ - /// 0 & 0 & 0 & 1 - /// \end{bmatrix}, - /// \end{align} - /// - /// where rows and columns are ordered as in the quantum concepts guide. - /// - /// # Input - /// ## qubit1 - /// First qubit to be swapped. - /// ## qubit2 - /// Second qubit to be swapped. - /// - /// # Remarks - /// Equivalent to: - /// ```qsharp - /// CNOT(qubit1, qubit2); - /// CNOT(qubit2, qubit1); - /// CNOT(qubit1, qubit2); - /// ``` - operation SWAP (qubit1 : Qubit, qubit2 : Qubit) : Unit - is Adj + Ctl { - body (...) - { - CNOT(qubit1, qubit2); - CNOT(qubit2, qubit1); - CNOT(qubit1, qubit2); - } - - adjoint self; - } - - //------------------------------------------------- - // Rotations - //------------------------------------------------- - - /// # Summary - /// Applies a rotation about the given Pauli axis. - /// - /// \begin{align} - /// R_{\mu}(\theta) \mathrel{:=} - /// e^{-i \theta \sigma_{\mu} / 2}, - /// \end{align} - /// where $\mu \in \{I, X, Y, Z\}$. - /// - /// # Input - /// ## pauli - /// Pauli operator ($\mu$) to be exponentiated to form the rotation. - /// ## theta - /// Angle about which the qubit is to be rotated. - /// ## qubit - /// Qubit to which the gate should be applied. - /// - /// # Remarks - /// When called with `pauli = PauliI`, this operation applies - /// a *global phase*. This phase can be significant - /// when used with the `Controlled` functor. - operation R (pauli : Pauli, theta : Double, qubit : Qubit) : Unit - is Adj + Ctl { - body intrinsic; - } - - - /// # Summary - /// Applies a rotation about the given Pauli axis by an angle specified - /// as a dyadic fraction. - /// - /// \begin{align} - /// R_{\mu}(n, k) \mathrel{:=} - /// e^{i \pi n \sigma_{\mu} / 2^k}, - /// \end{align} - /// where $\mu \in \{I, X, Y, Z\}$. - /// - /// > [!WARNING] - /// > This operation uses the **opposite** sign convention from - /// > @"microsoft.quantum.intrinsic.r". - /// - /// # Input - /// ## pauli - /// Pauli operator to be exponentiated to form the rotation. - /// ## numerator - /// Numerator in the dyadic fraction representation of the angle - /// by which the qubit is to be rotated. - /// ## power - /// Power of two specifying the denominator of the angle by which - /// the qubit is to be rotated. - /// ## qubit - /// Qubit to which the gate should be applied. - /// - /// # Remarks - /// Equivalent to: - /// ```qsharp - /// // PI() is a Q# function that returns an approximation of π. - /// R(pauli, -PI() * IntAsDouble(numerator) / IntAsDouble(2 ^ (power - 1)), qubit); - /// ``` - operation RFrac (pauli : Pauli, numerator : Int, power : Int, qubit : Qubit) : Unit - is Adj + Ctl { - - let angle = ((-2.0 * PI()) * IntAsDouble(numerator)) / IntAsDouble(2 ^ power); - R(pauli, angle, qubit); - } - - - /// # Summary - /// Applies a rotation about the $x$-axis by a given angle. - /// - /// \begin{align} - /// R_x(\theta) \mathrel{:=} - /// e^{-i \theta \sigma_x / 2} = - /// \begin{bmatrix} - /// \cos \frac{\theta}{2} & -i\sin \frac{\theta}{2} \\\\ - /// -i\sin \frac{\theta}{2} & \cos \frac{\theta}{2} - /// \end{bmatrix}. - /// \end{align} - /// - /// # Input - /// ## theta - /// Angle about which the qubit is to be rotated. - /// ## qubit - /// Qubit to which the gate should be applied. - /// - /// # Remarks - /// Equivalent to: - /// ```qsharp - /// R(PauliX, theta, qubit); - /// ``` - operation Rx (theta : Double, qubit : Qubit) : Unit - is Adj + Ctl { - body (...) - { - R(PauliX, theta, qubit); - } - - adjoint (...) - { - R(PauliX, -theta, qubit); - } - } - - - /// # Summary - /// Applies a rotation about the $y$-axis by a given angle. - /// - /// \begin{align} - /// R_y(\theta) \mathrel{:=} - /// e^{-i \theta \sigma_y / 2} = - /// \begin{bmatrix} - /// \cos \frac{\theta}{2} & -\sin \frac{\theta}{2} \\\\ - /// \sin \frac{\theta}{2} & \cos \frac{\theta}{2} - /// \end{bmatrix}. - /// \end{align} - /// - /// # Input - /// ## theta - /// Angle about which the qubit is to be rotated. - /// ## qubit - /// Qubit to which the gate should be applied. - /// - /// # Remarks - /// Equivalent to: - /// ```qsharp - /// R(PauliY, theta, qubit); - /// ``` - operation Ry (theta : Double, qubit : Qubit) : Unit - is Adj + Ctl { - body (...) - { - R(PauliY, theta, qubit); - } - - adjoint (...) - { - R(PauliY, -theta, qubit); - } - } - - - /// # Summary - /// Applies a rotation about the $z$-axis by a given angle. - /// - /// \begin{align} - /// R_z(\theta) \mathrel{:=} - /// e^{-i \theta \sigma_z / 2} = - /// \begin{bmatrix} - /// e^{-i \theta / 2} & 0 \\\\ - /// 0 & e^{i \theta / 2} - /// \end{bmatrix}. - /// \end{align} - /// - /// # Input - /// ## theta - /// Angle about which the qubit is to be rotated. - /// ## qubit - /// Qubit to which the gate should be applied. - /// - /// # Remarks - /// Equivalent to: - /// ```qsharp - /// R(PauliZ, theta, qubit); - /// ``` - operation Rz (theta : Double, qubit : Qubit) : Unit - is Adj + Ctl { - body (...) - { - R(PauliZ, theta, qubit); - } - - adjoint (...) - { - R(PauliZ, -theta, qubit); - } - } - - - /// # Summary - /// Applies a rotation about the $\ket{1}$ state by a given angle. - /// - /// \begin{align} - /// R_1(\theta) \mathrel{:=} - /// \operatorname{diag}(1, e^{i\theta}). - /// \end{align} - /// - /// # Input - /// ## theta - /// Angle about which the qubit is to be rotated. - /// ## qubit - /// Qubit to which the gate should be applied. - /// - /// # Remarks - /// Equivalent to: - /// ```qsharp - /// R(PauliZ, theta, qubit); - /// R(PauliI, -theta, qubit); - /// ``` - operation R1 (theta : Double, qubit : Qubit) : Unit - is Adj + Ctl { - - R(PauliZ, theta, qubit); - R(PauliI, -theta, qubit); - } - - - /// # Summary - /// Applies a rotation about the $\ket{1}$ state by an angle specified - /// as a dyadic fraction. - /// - /// \begin{align} - /// R_1(n, k) \mathrel{:=} - /// \operatorname{diag}(1, e^{i \pi k / 2^n}). - /// \end{align} - /// - /// > [!WARNING] - /// > This operation uses the **opposite** sign convention from - /// > @"microsoft.quantum.intrinsic.r", and does not include the - /// > factor of $1/ 2$ included by @"microsoft.quantum.intrinsic.r1". - /// - /// # Input - /// ## numerator - /// Numerator in the dyadic fraction representation of the angle - /// by which the qubit is to be rotated. - /// ## power - /// Power of two specifying the denominator of the angle by which - /// the qubit is to be rotated. - /// ## qubit - /// Qubit to which the gate should be applied. - /// - /// # Remarks - /// Equivalent to: - /// ```qsharp - /// RFrac(PauliZ, -numerator, denominator + 1, qubit); - /// RFrac(PauliI, numerator, denominator + 1, qubit); - /// ``` - operation R1Frac (numerator : Int, power : Int, qubit : Qubit) : Unit - is Adj + Ctl { - - RFrac(PauliZ, -numerator, power + 1, qubit); - RFrac(PauliI, numerator, power + 1, qubit); - } - - - /// # Summary - /// Applies the exponential of a multi-qubit Pauli operator. - /// - /// \begin{align} - /// e^{i \theta [P_0 \otimes P_1 \cdots P_{N-1}]}, - /// \end{align} - /// where $P_i$ is the $i$th element of `paulis`, and where - /// $N = $`Length(paulis)`. - /// - /// # Input - /// ## paulis - /// Array of single-qubit Pauli values indicating the tensor product - /// factors on each qubit. - /// ## theta - /// Angle about the given multi-qubit Pauli operator by which the - /// target register is to be rotated. - /// ## qubits - /// Register to apply the given rotation to. - operation Exp (paulis : Pauli[], theta : Double, qubits : Qubit[]) : Unit - is Adj + Ctl { - body intrinsic; - } - - - /// # Summary - /// Applies the exponential of a multi-qubit Pauli operator - /// with an argument given by a dyadic fraction. - /// - /// \begin{align} - /// e^{i \pi k [P_0 \otimes P_1 \cdots P_{N-1}] / 2^n}, - /// \end{align} - /// where $P_i$ is the $i$th element of `paulis`, and where - /// $N = $`Length(paulis)`. - /// - /// # Input - /// ## paulis - /// Array of single-qubit Pauli values indicating the tensor product - /// factors on each qubit. - /// ## numerator - /// Numerator ($k$) in the dyadic fraction representation of the angle - /// by which the qubit register is to be rotated. - /// ## power - /// Power of two ($n$) specifying the denominator of the angle by which - /// the qubit register is to be rotated. - /// ## qubits - /// Register to apply the given rotation to. - operation ExpFrac (paulis : Pauli[], numerator : Int, power : Int, qubits : Qubit[]) : Unit - is Adj + Ctl { - let angle = (PI() * IntAsDouble(numerator)) / IntAsDouble(2 ^ power); - Exp(paulis, angle, qubits); - } - - - //------------------------------------------------- - // Measurements - //------------------------------------------------- - - /// # Summary - /// Performs a joint measurement of one or more qubits in the - /// specified Pauli bases. - /// - /// The output result is given by the distribution: - /// \begin{align} - /// \Pr(\texttt{Zero} | \ket{\psi}) = - /// \frac12 \braket{ - /// \psi \mid| - /// \left( - /// \boldone + P_0 \otimes P_1 \otimes \cdots \otimes P_{N-1} - /// \right) \mid| - /// \psi - /// }, - /// \end{align} - /// where $P_i$ is the $i$th element of `bases`, and where - /// $N = \texttt{Length}(\texttt{bases})$. - /// That is, measurement returns a `Result` $d$ such that the eigenvalue of the - /// observed measurement effect is $(-1)^d$. - /// - /// # Input - /// ## bases - /// Array of single-qubit Pauli values indicating the tensor product - /// factors on each qubit. - /// ## qubits - /// Register of qubits to be measured. - /// - /// # Output - /// `Zero` if the $+1$ eigenvalue is observed, and `One` if - /// the $-1$ eigenvalue is observed. - /// - /// # Remarks - /// If the basis array and qubit array are different lengths, then the - /// operation will fail. - operation Measure (bases : Pauli[], qubits : Qubit[]) : Result { - body intrinsic; - } - - - /// # Summary - /// Performs a measurement of a single qubit in the - /// Pauli $Z$ basis. - /// - /// The output result is given by - /// the distribution - /// \begin{align} - /// \Pr(\texttt{Zero} | \ket{\psi}) = - /// \braket{\psi | 0} \braket{0 | \psi}. - /// \end{align} - /// - /// # Input - /// ## qubit - /// Qubit to be measured. - /// - /// # Output - /// `Zero` if the $+1$ eigenvalue is observed, and `One` if - /// the $-1$ eigenvalue is observed. - /// - /// # Remarks - /// Equivalent to: - /// ```qsharp - /// Measure([PauliZ], [qubit]); - /// ``` - operation M (qubit : Qubit) : Result { - return Measure([PauliZ], [qubit]); - } - - - /// # Summary - /// Given a single qubit, measures it and ensures it is in the |0⟩ state - /// such that it can be safely released. - /// - /// # Input - /// ## qubit - /// The qubit whose state is to be reset to $\ket{0}$. - operation Reset (target : Qubit) : Unit { - - if (M(target) == One) - { - X(target); - } - } - - - /// # Summary - /// Given an array of qubits, measure them and ensure they are in the |0⟩ state - /// such that they can be safely released. - /// - /// # Input - /// ## qubits - /// An array of qubits whose states are to be reset to $\ket{0}$. - operation ResetAll (qubits : Qubit[]) : Unit { - - for (qubit in qubits) { - Reset(qubit); - } - } - -} - - diff --git a/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj b/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj index 519f0b31367..3b0fe3f8c55 100644 --- a/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj +++ b/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj @@ -3,6 +3,8 @@ + + netstandard2.1 true diff --git a/src/Simulation/QsharpCore/Reset.qs b/src/Simulation/QsharpCore/Reset.qs deleted file mode 100644 index b62e4b114e5..00000000000 --- a/src/Simulation/QsharpCore/Reset.qs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Microsoft.Quantum.Measurement { - open Microsoft.Quantum.Intrinsic; - - internal operation BasisChangeZtoY(target : Qubit) : Unit is Adj + Ctl { - H(target); - S(target); - } - - - /// # Summary - /// Sets a qubit to a given computational basis state by measuring the - /// qubit and applying a bit flip if needed. - /// - /// # Input - /// ## desired - /// The basis state that the qubit should be set to. - /// ## target - /// The qubit whose state is to be set. - /// - /// # Remarks - /// As an invariant of this operation, calling `M(q)` immediately - /// after `SetToBasisState(result, q)` will return `result`. - operation SetToBasisState(desired : Result, target : Qubit) : Unit { - if (desired != M(target)) { - X(target); - } - } - - /// # Summary - /// Measures a single qubit in the Z basis, - /// and resets it to a fixed initial state - /// following the measurement. - /// - /// # Description - /// Performs a single-qubit measurement in the $Z$-basis, - /// and ensures that the qubit is returned to $\ket{0}$ - /// following the measurement. - /// - /// # Input - /// ## target - /// A single qubit to be measured. - /// - /// # Output - /// The result of measuring `target` in the Pauli $Z$ basis. - operation MResetZ (target : Qubit) : Result { - let result = M(target); - - if (result == One) { - // Recall that the +1 eigenspace of a measurement operator corresponds to - // the Result case Zero. Thus, if we see a One case, we must reset the state - // have +1 eigenvalue. - X(target); - } - - return result; - } - - - /// # Summary - /// Measures a single qubit in the X basis, - /// and resets it to a fixed initial state - /// following the measurement. - /// - /// # Description - /// Performs a single-qubit measurement in the $X$-basis, - /// and ensures that the qubit is returned to $\ket{0}$ - /// following the measurement. - /// - /// # Input - /// ## target - /// A single qubit to be measured. - /// - /// # Output - /// The result of measuring `target` in the Pauli $X$ basis. - operation MResetX (target : Qubit) : Result { - let result = Measure([PauliX], [target]); - - // We must return the qubit to the Z basis as well. - H(target); - - if (result == One) { - // Recall that the +1 eigenspace of a measurement operator corresponds to - // the Result case Zero. Thus, if we see a One case, we must reset the state - // have +1 eigenvalue. - X(target); - } - - return result; - } - - - /// # Summary - /// Measures a single qubit in the Y basis, - /// and resets it to a fixed initial state - /// following the measurement. - /// - /// # Description - /// Performs a single-qubit measurement in the $Y$-basis, - /// and ensures that the qubit is returned to $\ket{0}$ - /// following the measurement. - /// - /// # Input - /// ## target - /// A single qubit to be measured. - /// - /// # Output - /// The result of measuring `target` in the Pauli $Y$ basis. - operation MResetY (target : Qubit) : Result { - let result = Measure([PauliY], [target]); - - // We must return the qubit to the Z basis as well. - Adjoint BasisChangeZtoY(target); - - if (result == One) { - // Recall that the +1 eigenspace of a measurement operator corresponds to - // the Result case Zero. Thus, if we see a One case, we must reset the state - // have +1 eigenvalue. - X(target); - } - - return result; - } - -} diff --git a/src/Simulation/QsharpCore/Arrays/Enumeration.qs b/src/Simulation/QsharpFoundation/Arrays/Enumeration.qs similarity index 91% rename from src/Simulation/QsharpCore/Arrays/Enumeration.qs rename to src/Simulation/QsharpFoundation/Arrays/Enumeration.qs index a90383b1ab5..2a4634681a7 100644 --- a/src/Simulation/QsharpCore/Arrays/Enumeration.qs +++ b/src/Simulation/QsharpFoundation/Arrays/Enumeration.qs @@ -2,9 +2,6 @@ // Licensed under the MIT License. namespace Microsoft.Quantum.Arrays { - open Microsoft.Quantum.Intrinsic; - open Microsoft.Quantum.Canon; - /// # Summary /// Given an array, returns a range over the indices of that array, suitable /// for use in a for loop. @@ -29,5 +26,4 @@ namespace Microsoft.Quantum.Arrays { function IndexRange<'TElement>(array : 'TElement[]) : Range { return 0..(Length(array) - 1); } - } diff --git a/src/Simulation/QsharpCore/Canon/NoOp.qs b/src/Simulation/QsharpFoundation/Canon/NoOp.qs similarity index 100% rename from src/Simulation/QsharpCore/Canon/NoOp.qs rename to src/Simulation/QsharpFoundation/Canon/NoOp.qs diff --git a/src/Simulation/QsharpCore/Diagnostics/AssertAllZero.qs b/src/Simulation/QsharpFoundation/Diagnostics/AssertAllZero.qs similarity index 100% rename from src/Simulation/QsharpCore/Diagnostics/AssertAllZero.qs rename to src/Simulation/QsharpFoundation/Diagnostics/AssertAllZero.qs diff --git a/src/Simulation/QsharpCore/Diagnostics/AssertQubit.qs b/src/Simulation/QsharpFoundation/Diagnostics/AssertQubit.qs similarity index 87% rename from src/Simulation/QsharpCore/Diagnostics/AssertQubit.qs rename to src/Simulation/QsharpFoundation/Diagnostics/AssertQubit.qs index 973c07e8f7a..9c74954cd08 100644 --- a/src/Simulation/QsharpCore/Diagnostics/AssertQubit.qs +++ b/src/Simulation/QsharpFoundation/Diagnostics/AssertQubit.qs @@ -22,7 +22,7 @@ namespace Microsoft.Quantum.Diagnostics { /// allows for asserting /// arbitrary qubit states rather than only $Z$ eigenstates. operation AssertQubit (expected : Result, q : Qubit) : Unit { - Assert([PauliZ], [q], expected, $"Qubit in invalid state. Expecting: {expected}"); + AssertMeasurement([PauliZ], [q], expected, $"Qubit in invalid state. Expecting: {expected}"); } /// # Summary @@ -47,7 +47,7 @@ namespace Microsoft.Quantum.Diagnostics { /// allows for asserting /// arbitrary qubit states rather than only $Z$ eigenstates. operation AssertQubitWithinTolerance(expected : Result, q : Qubit, tolerance : Double) : Unit { - AssertProb([PauliZ], [q], expected, 1.0, $"Qubit in invalid state. Expecting: {expected} with tolerance {tolerance}", tolerance); + AssertMeasurementProbability([PauliZ], [q], expected, 1.0, $"Qubit in invalid state. Expecting: {expected} with tolerance {tolerance}", tolerance); } /// # Summary @@ -126,10 +126,10 @@ namespace Microsoft.Quantum.Diagnostics { // Probability of getting outcome One in measuring PauliZ is Tr(M(I-Z)/2) = (mi-mz)/2.0 // similarly, we find the probabilities for measuring PauliX,PauliY let tol = tolerance / 2.0; - AssertProb([PauliX], [register], Zero, (mi + mx) / 2.0, $"Qubit Zero probability on X basis failed", tol); - AssertProb([PauliY], [register], Zero, (mi + my) / 2.0, $"Qubit Zero probability on Y basis failed", tol); - AssertProb([PauliZ], [register], Zero, (mi + mz) / 2.0, $"Qubit Zero probability on Z basis failed", tol); - AssertProb([PauliZ], [register], One, (mi - mz) / 2.0, $"Qubit One probability on Z basis failed", tol); + AssertMeasurementProbability([PauliX], [register], Zero, (mi + mx) / 2.0, $"Qubit Zero probability on X basis failed", tol); + AssertMeasurementProbability([PauliY], [register], Zero, (mi + my) / 2.0, $"Qubit Zero probability on Y basis failed", tol); + AssertMeasurementProbability([PauliZ], [register], Zero, (mi + mz) / 2.0, $"Qubit Zero probability on Z basis failed", tol); + AssertMeasurementProbability([PauliZ], [register], One, (mi - mz) / 2.0, $"Qubit One probability on Z basis failed", tol); } } diff --git a/src/Simulation/QsharpCore/Diagnostics/Dump.qs b/src/Simulation/QsharpFoundation/Diagnostics/Dump.qs similarity index 100% rename from src/Simulation/QsharpCore/Diagnostics/Dump.qs rename to src/Simulation/QsharpFoundation/Diagnostics/Dump.qs diff --git a/src/Simulation/QsharpCore/Diagnostics/UnitTests.qs b/src/Simulation/QsharpFoundation/Diagnostics/UnitTests.qs similarity index 100% rename from src/Simulation/QsharpCore/Diagnostics/UnitTests.qs rename to src/Simulation/QsharpFoundation/Diagnostics/UnitTests.qs diff --git a/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertProbMultiQubit.qs b/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertProbMultiQubit.qs index 49392e3aa0c..61619fdc008 100644 --- a/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertProbMultiQubit.qs +++ b/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertProbMultiQubit.qs @@ -8,6 +8,41 @@ namespace Microsoft.Quantum.Simulation.TestSuite { open Microsoft.Quantum.Simulation.TestSuite.Math; + internal operation flipToBasis (basis : Int[], qubits : Qubit[]) : Unit is Adj + Ctl { + if (Length(qubits) != Length(basis)) + { + fail $"qubits and stateIds must have the same length"; + } + + for (i in 0 .. Length(qubits) - 1) + { + let id = basis[i]; + let qubit = qubits[i]; + + if (id < 0 or id > 3) { + fail $"Invalid basis. Must be between 0 and 3, it was {basis}"; + } + + if (id == 0) + { + I(qubit); + } + elif (id == 1) + { + X(qubit); + } + elif (id == 2) + { + H(qubit); + } + else + { + H(qubit); + S(qubit); + } + } + } + operation AssertProbMultiQubitTest () : Unit { @@ -51,12 +86,12 @@ namespace Microsoft.Quantum.Simulation.TestSuite { } using (qubits = Qubit[l]) { - _flipToBasis(stateId, qubits); + flipToBasis(stateId, qubits); let expectedZeroProbability = 0.5 + 0.5 * ExpectedValueForMultiPauliByStateId(observable, stateId); let expectedOneProbability = 1.0 - expectedZeroProbability; - AssertProb(observable, qubits, Zero, expectedZeroProbability, $"", Accuracy()); - AssertProb(observable, qubits, One, expectedOneProbability, $"", Accuracy()); - Adjoint _flipToBasis(stateId, qubits); + AssertMeasurementProbability(observable, qubits, Zero, expectedZeroProbability, $"", Accuracy()); + AssertMeasurementProbability(observable, qubits, One, expectedOneProbability, $"", Accuracy()); + Adjoint flipToBasis(stateId, qubits); } } diff --git a/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertQubitUnitary.qs b/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertQubitUnitary.qs index 82f4009c77b..642003c7f61 100644 --- a/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertQubitUnitary.qs +++ b/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertQubitUnitary.qs @@ -15,7 +15,7 @@ namespace Microsoft.Quantum.Simulation.TestSuite { for (stateId in 0 .. maxId) { let expectedState = ApplyMatrix(unitaryMatrix, StateIdToVector(stateId)); - _flipToBasis([stateId], [qubit]); + flipToBasis([stateId], [qubit]); unitaryOp(qubit); let alpha = Microsoft.Quantum.Math.Complex((expectedState![0])!); let beta = Microsoft.Quantum.Math.Complex((expectedState![1])!); diff --git a/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertUnitary.qs b/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertUnitary.qs index 22a38acbe2b..e808fdb532c 100644 --- a/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertUnitary.qs +++ b/src/Simulation/Simulators.Tests/QuantumTestSuite/AssertUnitary.qs @@ -10,7 +10,7 @@ namespace Microsoft.Quantum.Simulation.TestSuite { operation AssertUnitaryHelper (stateIds : Int[], unitaryMatrix : RowMajorMatrix, unitaryOp : (Qubit[] => Unit), qubits : Qubit[]) : Unit { let expectedState = ApplyMatrix(unitaryMatrix, StateById(stateIds)); - _flipToBasis(stateIds, qubits); + flipToBasis(stateIds, qubits); unitaryOp(qubits); AssertState(expectedState, qubits); ResetAll(qubits); diff --git a/src/Simulation/Simulators.Tests/QuantumTestSuite/JointOneQubitTests.qs b/src/Simulation/Simulators.Tests/QuantumTestSuite/JointOneQubitTests.qs index 137ea806f31..937b84b7099 100644 --- a/src/Simulation/Simulators.Tests/QuantumTestSuite/JointOneQubitTests.qs +++ b/src/Simulation/Simulators.Tests/QuantumTestSuite/JointOneQubitTests.qs @@ -23,7 +23,7 @@ namespace Microsoft.Quantum.Simulation.TestSuite { } mutable states = new Vector[numQubits]; - _flipToBasis(inputStateId, qubits); + flipToBasis(inputStateId, qubits); for (i in 0 .. numQubits - 1) { let (op, matrix) = operationsToTest[i]!; diff --git a/src/Simulation/QsharpCore/Diagnostics/AssertOperationsEqualInPlace.qs b/src/Simulation/TargetDefinitions/Decompositions/AssertOperationsEqualInPlace.qs similarity index 88% rename from src/Simulation/QsharpCore/Diagnostics/AssertOperationsEqualInPlace.qs rename to src/Simulation/TargetDefinitions/Decompositions/AssertOperationsEqualInPlace.qs index 33bfdd67896..aa1c0cedc93 100644 --- a/src/Simulation/QsharpCore/Diagnostics/AssertOperationsEqualInPlace.qs +++ b/src/Simulation/TargetDefinitions/Decompositions/AssertOperationsEqualInPlace.qs @@ -9,7 +9,7 @@ namespace Microsoft.Quantum.Diagnostics { /// Iterates a variable through a Cartesian product /// [ 0, bounds[0]-1 ] × [ 0, bounds[1]-1 ] × [ 0, bounds[Length(bounds)-1]-1 ] /// and calls op(arr) for every element of the Cartesian product - operation _iterateThroughCartesianPower (length : Int, value : Int, op : (Int[] => Unit)) : Unit { + internal operation iterateThroughCartesianPower (length : Int, value : Int, op : (Int[] => Unit)) : Unit { mutable bounds = new Int[length]; for (i in 0 .. length - 1) @@ -67,9 +67,7 @@ namespace Microsoft.Quantum.Diagnostics { /// ## basis /// Array of single-qubit basis state IDs (0 <= id <= 3), one for each element of /// qubits. - operation _flipToBasis (basis : Int[], qubits : Qubit[]) : Unit - is Adj + Ctl { - + internal operation flipToBasis (basis : Int[], qubits : Qubit[]) : Unit is Adj + Ctl { if (Length(qubits) != Length(basis)) { fail $"qubits and stateIds must have the same length"; @@ -119,15 +117,15 @@ namespace Microsoft.Quantum.Diagnostics { /// Operation on $n$ qubits to be checked. /// ## expectedU /// Reference operation on $n$ qubits that givenU is to be compared against. - operation _assertEqualOnBasisVector (basis : Int[], givenU : (Qubit[] => Unit), expectedU : (Qubit[] => Unit is Adj)) : Unit { + internal operation assertEqualOnBasisVector (basis : Int[], givenU : (Qubit[] => Unit), expectedU : (Qubit[] => Unit is Adj)) : Unit { let tolerance = 1e-5; using (qubits = Qubit[Length(basis)]) { AssertAllZeroWithinTolerance(qubits, tolerance); - _flipToBasis(basis, qubits); + flipToBasis(basis, qubits); givenU(qubits); Adjoint expectedU(qubits); - Adjoint _flipToBasis(basis, qubits); + Adjoint flipToBasis(basis, qubits); AssertAllZeroWithinTolerance(qubits, tolerance); } } @@ -157,8 +155,8 @@ namespace Microsoft.Quantum.Diagnostics { /// described in [ *I. L. Chuang, M. A. Nielsen* ](https://arxiv.org/abs/quant-ph/9610001). operation AssertOperationsEqualInPlace(nQubits : Int, givenU : (Qubit[] => Unit), expectedU : (Qubit[] => Unit is Adj)) : Unit { - let checkOperation = _assertEqualOnBasisVector(_, givenU, expectedU); - _iterateThroughCartesianPower(nQubits, 4, checkOperation); + let checkOperation = assertEqualOnBasisVector(_, givenU, expectedU); + iterateThroughCartesianPower(nQubits, 4, checkOperation); } /// # Summary @@ -177,8 +175,8 @@ namespace Microsoft.Quantum.Diagnostics { /// Reference operation on $n$ qubits that `givenU` is to be compared against. operation AssertOperationsEqualInPlaceCompBasis (nQubits : Int, givenU : (Qubit[] => Unit), expectedU : (Qubit[] => Unit is Adj)) : Unit { - let checkOperation = _assertEqualOnBasisVector(_, givenU, expectedU); - _iterateThroughCartesianPower(nQubits, 2, checkOperation); + let checkOperation = assertEqualOnBasisVector(_, givenU, expectedU); + iterateThroughCartesianPower(nQubits, 2, checkOperation); } } diff --git a/src/Simulation/QsharpCore/Diagnostics/AssertOperationsEqualReferenced.qs b/src/Simulation/TargetDefinitions/Decompositions/AssertOperationsEqualReferenced.qs similarity index 93% rename from src/Simulation/QsharpCore/Diagnostics/AssertOperationsEqualReferenced.qs rename to src/Simulation/TargetDefinitions/Decompositions/AssertOperationsEqualReferenced.qs index d29eecf85db..90399286af2 100644 --- a/src/Simulation/QsharpCore/Diagnostics/AssertOperationsEqualReferenced.qs +++ b/src/Simulation/TargetDefinitions/Decompositions/AssertOperationsEqualReferenced.qs @@ -17,7 +17,7 @@ namespace Microsoft.Quantum.Diagnostics { /// A qubit array in the $\ket{0\cdots 0}$ state /// ## right /// A qubit array in the $\ket{0\cdots 0}$ state - operation _prepareEntangledState (left : Qubit[], right : Qubit[]) : Unit + internal operation prepareEntangledState (left : Qubit[], right : Qubit[]) : Unit is Adj + Ctl { for (idxQubit in 0 .. Length(left) - 1) @@ -56,10 +56,10 @@ namespace Microsoft.Quantum.Diagnostics { operation AssertOperationsEqualReferenced (nQubits : Int, actual : (Qubit[] => Unit), expected : (Qubit[] => Unit is Adj)) : Unit { // Prepare a reference register entangled with the target register. using ((reference, target) = (Qubit[nQubits], Qubit[nQubits])) { - _prepareEntangledState(reference, target); + prepareEntangledState(reference, target); actual(target); Adjoint expected(target); - Adjoint _prepareEntangledState(reference, target); + Adjoint prepareEntangledState(reference, target); AssertAllZero(reference + target); ResetAll(target); ResetAll(reference); diff --git a/src/Simulation/TargetDefinitions/Decompositions/CCNOT.qs b/src/Simulation/TargetDefinitions/Decompositions/CCNOT.qs new file mode 100644 index 00000000000..430ab0e4c9f --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/CCNOT.qs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies the doubly controlled–NOT (CCNOT) gate to three qubits. + /// + /// # Input + /// ## control1 + /// First control qubit for the CCNOT gate. + /// ## control2 + /// Second control qubit for the CCNOT gate. + /// ## target + /// Target qubit for the CCNOT gate. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// Controlled X([control1, control2], target); + /// ``` + operation CCNOT (control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj + Ctl { + body (...) { + Controlled X([control1, control2], target); + } + adjoint self; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/CNOT.qs b/src/Simulation/TargetDefinitions/Decompositions/CNOT.qs new file mode 100644 index 00000000000..f6403a74e5f --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/CNOT.qs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies the controlled-NOT (CNOT) gate to a pair of qubits. + /// + /// # Description + /// \begin{align} + /// \operatorname{CNOT} \mathrel{:=} + /// \begin{bmatrix} + /// 1 & 0 & 0 & 0 \\\\ + /// 0 & 1 & 0 & 0 \\\\ + /// 0 & 0 & 0 & 1 \\\\ + /// 0 & 0 & 1 & 0 + /// \end{bmatrix}, + /// \end{align} + /// + /// where rows and columns are ordered as in the quantum concepts guide. + /// + /// # Input + /// ## control + /// Control qubit for the CNOT gate. + /// ## target + /// Target qubit for the CNOT gate. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// Controlled X([control], target); + /// ``` + operation CNOT (control : Qubit, target : Qubit) : Unit is Adj + Ctl { + body (...) { + Controlled X([control], target); + } + adjoint self; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/ExpFrac.qs b/src/Simulation/TargetDefinitions/Decompositions/ExpFrac.qs new file mode 100644 index 00000000000..e18d4e98e0d --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/ExpFrac.qs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + open Microsoft.Quantum.Math; + open Microsoft.Quantum.Convert; + + /// # Summary + /// Applies the exponential of a multi-qubit Pauli operator + /// with an argument given by a dyadic fraction. + /// + /// # Description + /// \begin{align} + /// e^{i \pi k [P_0 \otimes P_1 \cdots P_{N-1}] / 2^n}, + /// \end{align} + /// where $P_i$ is the $i$th element of `paulis`, and where + /// $N = $`Length(paulis)`. + /// + /// # Input + /// ## paulis + /// Array of single-qubit Pauli values indicating the tensor product + /// factors on each qubit. + /// ## numerator + /// Numerator ($k$) in the dyadic fraction representation of the angle + /// by which the qubit register is to be rotated. + /// ## power + /// Power of two ($n$) specifying the denominator of the angle by which + /// the qubit register is to be rotated. + /// ## qubits + /// Register to apply the given rotation to. + operation ExpFrac (paulis : Pauli[], numerator : Int, power : Int, qubits : Qubit[]) : Unit is Adj + Ctl { + let angle = (PI() * IntAsDouble(numerator)) / IntAsDouble(2 ^ power); + Exp(paulis, angle, qubits); + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/M.qs b/src/Simulation/TargetDefinitions/Decompositions/M.qs new file mode 100644 index 00000000000..c5066f9ee6c --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/M.qs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Performs a measurement of a single qubit in the + /// Pauli $Z$ basis. + /// + /// # Description + /// The output result is given by + /// the distribution + /// \begin{align} + /// \Pr(\texttt{Zero} | \ket{\psi}) = + /// \braket{\psi | 0} \braket{0 | \psi}. + /// \end{align} + /// + /// # Input + /// ## qubit + /// Qubit to be measured. + /// + /// # Output + /// `Zero` if the $+1$ eigenvalue is observed, and `One` if + /// the $-1$ eigenvalue is observed. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// Measure([PauliZ], [qubit]); + /// ``` + operation M (qubit : Qubit) : Result { + return Measure([PauliZ], [qubit]); + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/MResetX.qs b/src/Simulation/TargetDefinitions/Decompositions/MResetX.qs new file mode 100644 index 00000000000..ae845f9b788 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/MResetX.qs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Measurement { + open Microsoft.Quantum.Intrinsic; + + /// # Summary + /// Measures a single qubit in the X basis, + /// and resets it to a fixed initial state + /// following the measurement. + /// + /// # Description + /// Performs a single-qubit measurement in the $X$-basis, + /// and ensures that the qubit is returned to $\ket{0}$ + /// following the measurement. + /// + /// # Input + /// ## target + /// A single qubit to be measured. + /// + /// # Output + /// The result of measuring `target` in the Pauli $X$ basis. + operation MResetX (target : Qubit) : Result { + let result = Measure([PauliX], [target]); + + // We must return the qubit to the Z basis as well. + H(target); + + if (result == One) { + // Recall that the +1 eigenspace of a measurement operator corresponds to + // the Result case Zero. Thus, if we see a One case, we must reset the state + // have +1 eigenvalue. + X(target); + } + + return result; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/MResetY.qs b/src/Simulation/TargetDefinitions/Decompositions/MResetY.qs new file mode 100644 index 00000000000..41271901ab9 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/MResetY.qs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Measurement { + open Microsoft.Quantum.Intrinsic; + + internal operation BasisChangeZtoY(target : Qubit) : Unit is Adj + Ctl { + H(target); + S(target); + } + + /// # Summary + /// Measures a single qubit in the Y basis, + /// and resets it to a fixed initial state + /// following the measurement. + /// + /// # Description + /// Performs a single-qubit measurement in the $Y$-basis, + /// and ensures that the qubit is returned to $\ket{0}$ + /// following the measurement. + /// + /// # Input + /// ## target + /// A single qubit to be measured. + /// + /// # Output + /// The result of measuring `target` in the Pauli $Y$ basis. + operation MResetY (target : Qubit) : Result { + let result = Measure([PauliY], [target]); + + // We must return the qubit to the Z basis as well. + Adjoint BasisChangeZtoY(target); + + if (result == One) { + // Recall that the +1 eigenspace of a measurement operator corresponds to + // the Result case Zero. Thus, if we see a One case, we must reset the state + // have +1 eigenvalue. + X(target); + } + + return result; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/MResetZ.qs b/src/Simulation/TargetDefinitions/Decompositions/MResetZ.qs new file mode 100644 index 00000000000..64c04237af6 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/MResetZ.qs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Measurement { + open Microsoft.Quantum.Intrinsic; + + /// # Summary + /// Measures a single qubit in the Z basis, + /// and resets it to a fixed initial state + /// following the measurement. + /// + /// # Description + /// Performs a single-qubit measurement in the $Z$-basis, + /// and ensures that the qubit is returned to $\ket{0}$ + /// following the measurement. + /// + /// # Input + /// ## target + /// A single qubit to be measured. + /// + /// # Output + /// The result of measuring `target` in the Pauli $Z$ basis. + operation MResetZ (target : Qubit) : Result { + let result = M(target); + + if (result == One) { + // Recall that the +1 eigenspace of a measurement operator corresponds to + // the Result case Zero. Thus, if we see a One case, we must reset the state + // have +1 eigenvalue. + X(target); + } + + return result; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/R1.qs b/src/Simulation/TargetDefinitions/Decompositions/R1.qs new file mode 100644 index 00000000000..06678d7f707 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/R1.qs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies a rotation about the $\ket{1}$ state by a given angle. + /// + /// # Description + /// \begin{align} + /// R_1(\theta) \mathrel{:=} + /// \operatorname{diag}(1, e^{i\theta}). + /// \end{align} + /// + /// # Input + /// ## theta + /// Angle about which the qubit is to be rotated. + /// ## qubit + /// Qubit to which the gate should be applied. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// R(PauliZ, theta, qubit); + /// R(PauliI, -theta, qubit); + /// ``` + operation R1 (theta : Double, qubit : Qubit) : Unit is Adj + Ctl { + R(PauliZ, theta, qubit); + R(PauliI, -theta, qubit); + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/R1Frac.qs b/src/Simulation/TargetDefinitions/Decompositions/R1Frac.qs new file mode 100644 index 00000000000..338f32c8ff1 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/R1Frac.qs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies a rotation about the $\ket{1}$ state by an angle specified + /// as a dyadic fraction. + /// + /// # Description + /// \begin{align} + /// R_1(n, k) \mathrel{:=} + /// \operatorname{diag}(1, e^{i \pi k / 2^n}). + /// \end{align} + /// + /// > [!WARNING] + /// > This operation uses the **opposite** sign convention from + /// > @"microsoft.quantum.intrinsic.r", and does not include the + /// > factor of $1/ 2$ included by @"microsoft.quantum.intrinsic.r1". + /// + /// # Input + /// ## numerator + /// Numerator in the dyadic fraction representation of the angle + /// by which the qubit is to be rotated. + /// ## power + /// Power of two specifying the denominator of the angle by which + /// the qubit is to be rotated. + /// ## qubit + /// Qubit to which the gate should be applied. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// RFrac(PauliZ, -numerator, denominator + 1, qubit); + /// RFrac(PauliI, numerator, denominator + 1, qubit); + /// ``` + operation R1Frac (numerator : Int, power : Int, qubit : Qubit) : Unit is Adj + Ctl { + RFrac(PauliZ, -numerator, power + 1, qubit); + RFrac(PauliI, numerator, power + 1, qubit); + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/RFrac.qs b/src/Simulation/TargetDefinitions/Decompositions/RFrac.qs new file mode 100644 index 00000000000..a0f632c7e03 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/RFrac.qs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + open Microsoft.Quantum.Math; + open Microsoft.Quantum.Convert; + + /// # Summary + /// Applies a rotation about the given Pauli axis by an angle specified + /// as a dyadic fraction. + /// + /// # Description + /// \begin{align} + /// R_{\mu}(n, k) \mathrel{:=} + /// e^{i \pi n \sigma_{\mu} / 2^k}, + /// \end{align} + /// where $\mu \in \{I, X, Y, Z\}$. + /// + /// > [!WARNING] + /// > This operation uses the **opposite** sign convention from + /// > @"microsoft.quantum.intrinsic.r". + /// + /// # Input + /// ## pauli + /// Pauli operator to be exponentiated to form the rotation. + /// ## numerator + /// Numerator in the dyadic fraction representation of the angle + /// by which the qubit is to be rotated. + /// ## power + /// Power of two specifying the denominator of the angle by which + /// the qubit is to be rotated. + /// ## qubit + /// Qubit to which the gate should be applied. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// // PI() is a Q# function that returns an approximation of π. + /// R(pauli, -PI() * IntAsDouble(numerator) / IntAsDouble(2 ^ (power - 1)), qubit); + /// ``` + operation RFrac (pauli : Pauli, numerator : Int, power : Int, qubit : Qubit) : Unit is Adj + Ctl { + let angle = ((-2.0 * PI()) * IntAsDouble(numerator)) / IntAsDouble(2 ^ power); + R(pauli, angle, qubit); + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/Reset.qs b/src/Simulation/TargetDefinitions/Decompositions/Reset.qs new file mode 100644 index 00000000000..a5bb975894d --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/Reset.qs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Given a single qubit, measures it and ensures it is in the |0⟩ state + /// such that it can be safely released. + /// + /// # Input + /// ## qubit + /// The qubit whose state is to be reset to $\ket{0}$. + operation Reset (target : Qubit) : Unit { + if (M(target) == One) { + X(target); + } + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/ResetAll.qs b/src/Simulation/TargetDefinitions/Decompositions/ResetAll.qs new file mode 100644 index 00000000000..cd76adc599e --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/ResetAll.qs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Given an array of qubits, measure them and ensure they are in the |0⟩ state + /// such that they can be safely released. + /// + /// # Input + /// ## qubits + /// An array of qubits whose states are to be reset to $\ket{0}$. + operation ResetAll (qubits : Qubit[]) : Unit { + for (qubit in qubits) { + Reset(qubit); + } + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/Rx.qs b/src/Simulation/TargetDefinitions/Decompositions/Rx.qs new file mode 100644 index 00000000000..d4c999a83b2 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/Rx.qs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies a rotation about the $x$-axis by a given angle. + /// + /// # Description + /// \begin{align} + /// R_x(\theta) \mathrel{:=} + /// e^{-i \theta \sigma_x / 2} = + /// \begin{bmatrix} + /// \cos \frac{\theta}{2} & -i\sin \frac{\theta}{2} \\\\ + /// -i\sin \frac{\theta}{2} & \cos \frac{\theta}{2} + /// \end{bmatrix}. + /// \end{align} + /// + /// # Input + /// ## theta + /// Angle about which the qubit is to be rotated. + /// ## qubit + /// Qubit to which the gate should be applied. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// R(PauliX, theta, qubit); + /// ``` + operation Rx (theta : Double, qubit : Qubit) : Unit is Adj + Ctl { + body (...) { + R(PauliX, theta, qubit); + } + adjoint (...) { + R(PauliX, -theta, qubit); + } + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/Ry.qs b/src/Simulation/TargetDefinitions/Decompositions/Ry.qs new file mode 100644 index 00000000000..e68732523b6 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/Ry.qs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies a rotation about the $y$-axis by a given angle. + /// + /// # Description + /// \begin{align} + /// R_y(\theta) \mathrel{:=} + /// e^{-i \theta \sigma_y / 2} = + /// \begin{bmatrix} + /// \cos \frac{\theta}{2} & -\sin \frac{\theta}{2} \\\\ + /// \sin \frac{\theta}{2} & \cos \frac{\theta}{2} + /// \end{bmatrix}. + /// \end{align} + /// + /// # Input + /// ## theta + /// Angle about which the qubit is to be rotated. + /// ## qubit + /// Qubit to which the gate should be applied. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// R(PauliY, theta, qubit); + /// ``` + operation Ry (theta : Double, qubit : Qubit) : Unit is Adj + Ctl { + body (...) { + R(PauliY, theta, qubit); + } + adjoint (...) { + R(PauliY, -theta, qubit); + } + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/Rz.qs b/src/Simulation/TargetDefinitions/Decompositions/Rz.qs new file mode 100644 index 00000000000..30956ac6640 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/Rz.qs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies a rotation about the $z$-axis by a given angle. + /// + /// # Description + /// \begin{align} + /// R_z(\theta) \mathrel{:=} + /// e^{-i \theta \sigma_z / 2} = + /// \begin{bmatrix} + /// e^{-i \theta / 2} & 0 \\\\ + /// 0 & e^{i \theta / 2} + /// \end{bmatrix}. + /// \end{align} + /// + /// # Input + /// ## theta + /// Angle about which the qubit is to be rotated. + /// ## qubit + /// Qubit to which the gate should be applied. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// R(PauliZ, theta, qubit); + /// ``` + operation Rz (theta : Double, qubit : Qubit) : Unit is Adj + Ctl { + body (...) { + R(PauliZ, theta, qubit); + } + adjoint (...) { + R(PauliZ, -theta, qubit); + } + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/SWAP.qs b/src/Simulation/TargetDefinitions/Decompositions/SWAP.qs new file mode 100644 index 00000000000..19cc13a1634 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/SWAP.qs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies the SWAP gate to a pair of qubits. + /// + /// # Description + /// \begin{align} + /// \operatorname{SWAP} \mathrel{:=} + /// \begin{bmatrix} + /// 1 & 0 & 0 & 0 \\\\ + /// 0 & 0 & 1 & 0 \\\\ + /// 0 & 1 & 0 & 0 \\\\ + /// 0 & 0 & 0 & 1 + /// \end{bmatrix}, + /// \end{align} + /// + /// where rows and columns are ordered as in the quantum concepts guide. + /// + /// # Input + /// ## qubit1 + /// First qubit to be swapped. + /// ## qubit2 + /// Second qubit to be swapped. + /// + /// # Remarks + /// Equivalent to: + /// ```qsharp + /// CNOT(qubit1, qubit2); + /// CNOT(qubit2, qubit1); + /// CNOT(qubit1, qubit2); + /// ``` + operation SWAP (qubit1 : Qubit, qubit2 : Qubit) : Unit is Adj + Ctl { + body (...) { + CNOT(qubit1, qubit2); + CNOT(qubit2, qubit1); + CNOT(qubit1, qubit2); + } + adjoint self; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Decompositions/SetToBasisState.qs b/src/Simulation/TargetDefinitions/Decompositions/SetToBasisState.qs new file mode 100644 index 00000000000..ff7ec846edf --- /dev/null +++ b/src/Simulation/TargetDefinitions/Decompositions/SetToBasisState.qs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Measurement { + open Microsoft.Quantum.Intrinsic; + + /// # Summary + /// Sets a qubit to a given computational basis state by measuring the + /// qubit and applying a bit flip if needed. + /// + /// # Input + /// ## desired + /// The basis state that the qubit should be set to. + /// ## target + /// The qubit whose state is to be set. + /// + /// # Remarks + /// As an invariant of this operation, calling `M(q)` immediately + /// after `SetToBasisState(result, q)` will return `result`. + operation SetToBasisState(desired : Result, target : Qubit) : Unit { + if (desired != M(target)) { + X(target); + } + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Intrinsic/Exp.qs b/src/Simulation/TargetDefinitions/Intrinsic/Exp.qs new file mode 100644 index 00000000000..0d008f67b25 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Intrinsic/Exp.qs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies the exponential of a multi-qubit Pauli operator. + /// + /// # Description + /// \begin{align} + /// e^{i \theta [P_0 \otimes P_1 \cdots P_{N-1}]}, + /// \end{align} + /// where $P_i$ is the $i$th element of `paulis`, and where + /// $N = $`Length(paulis)`. + /// + /// # Input + /// ## paulis + /// Array of single-qubit Pauli values indicating the tensor product + /// factors on each qubit. + /// ## theta + /// Angle about the given multi-qubit Pauli operator by which the + /// target register is to be rotated. + /// ## qubits + /// Register to apply the given rotation to. + operation Exp (paulis : Pauli[], theta : Double, qubits : Qubit[]) : Unit is Adj + Ctl { + body intrinsic; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Intrinsic/H.qs b/src/Simulation/TargetDefinitions/Intrinsic/H.qs new file mode 100644 index 00000000000..25a12838d32 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Intrinsic/H.qs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies the Hadamard transformation to a single qubit. + /// + /// # Description + /// \begin{align} + /// H \mathrel{:=} + /// \frac{1}{\sqrt{2}} + /// \begin{bmatrix} + /// 1 & 1 \\\\ + /// 1 & -1 + /// \end{bmatrix}. + /// \end{align} + /// + /// # Input + /// ## qubit + /// Qubit to which the gate should be applied. + operation H (qubit : Qubit) : Unit is Adj + Ctl { + body intrinsic; + adjoint self; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Intrinsic/I.qs b/src/Simulation/TargetDefinitions/Intrinsic/I.qs new file mode 100644 index 00000000000..57a0a1d3125 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Intrinsic/I.qs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Performs the identity operation (no-op) on a single qubit. + /// + /// # Remarks + /// This is a no-op. It is provided for completeness and because + /// sometimes it is useful to call the identity in an algorithm or to pass it as a parameter. + operation I (target : Qubit) : Unit is Adj + Ctl { + body (...) { } + adjoint self; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Intrinsic/Measure.qs b/src/Simulation/TargetDefinitions/Intrinsic/Measure.qs new file mode 100644 index 00000000000..957726d85da --- /dev/null +++ b/src/Simulation/TargetDefinitions/Intrinsic/Measure.qs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Performs a joint measurement of one or more qubits in the + /// specified Pauli bases. + /// + /// # Description + /// The output result is given by the distribution: + /// \begin{align} + /// \Pr(\texttt{Zero} | \ket{\psi}) = + /// \frac12 \braket{ + /// \psi \mid| + /// \left( + /// \boldone + P_0 \otimes P_1 \otimes \cdots \otimes P_{N-1} + /// \right) \mid| + /// \psi + /// }, + /// \end{align} + /// where $P_i$ is the $i$th element of `bases`, and where + /// $N = \texttt{Length}(\texttt{bases})$. + /// That is, measurement returns a `Result` $d$ such that the eigenvalue of the + /// observed measurement effect is $(-1)^d$. + /// + /// # Input + /// ## bases + /// Array of single-qubit Pauli values indicating the tensor product + /// factors on each qubit. + /// ## qubits + /// Register of qubits to be measured. + /// + /// # Output + /// `Zero` if the $+1$ eigenvalue is observed, and `One` if + /// the $-1$ eigenvalue is observed. + /// + /// # Remarks + /// If the basis array and qubit array are different lengths, then the + /// operation will fail. + operation Measure (bases : Pauli[], qubits : Qubit[]) : Result { + body intrinsic; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Intrinsic/R.qs b/src/Simulation/TargetDefinitions/Intrinsic/R.qs new file mode 100644 index 00000000000..ff64e63631b --- /dev/null +++ b/src/Simulation/TargetDefinitions/Intrinsic/R.qs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies a rotation about the given Pauli axis. + /// + /// # Description + /// \begin{align} + /// R_{\mu}(\theta) \mathrel{:=} + /// e^{-i \theta \sigma_{\mu} / 2}, + /// \end{align} + /// where $\mu \in \{I, X, Y, Z\}$. + /// + /// # Input + /// ## pauli + /// Pauli operator ($\mu$) to be exponentiated to form the rotation. + /// ## theta + /// Angle about which the qubit is to be rotated. + /// ## qubit + /// Qubit to which the gate should be applied. + /// + /// # Remarks + /// When called with `pauli = PauliI`, this operation applies + /// a *global phase*. This phase can be significant + /// when used with the `Controlled` functor. + operation R (pauli : Pauli, theta : Double, qubit : Qubit) : Unit is Adj + Ctl { + body intrinsic; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Intrinsic/S.qs b/src/Simulation/TargetDefinitions/Intrinsic/S.qs new file mode 100644 index 00000000000..e30b637d086 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Intrinsic/S.qs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies the π/4 phase gate to a single qubit. + /// + /// # Description + /// \begin{align} + /// S \mathrel{:=} + /// \begin{bmatrix} + /// 1 & 0 \\\\ + /// 0 & i + /// \end{bmatrix}. + /// \end{align} + /// + /// # Input + /// ## qubit + /// Qubit to which the gate should be applied. + operation S (qubit : Qubit) : Unit is Adj + Ctl { + body intrinsic; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Intrinsic/T.qs b/src/Simulation/TargetDefinitions/Intrinsic/T.qs new file mode 100644 index 00000000000..287ec3087bc --- /dev/null +++ b/src/Simulation/TargetDefinitions/Intrinsic/T.qs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies the π/8 gate to a single qubit. + /// + /// # Description + /// \begin{align} + /// T \mathrel{:=} + /// \begin{bmatrix} + /// 1 & 0 \\\\ + /// 0 & e^{i \pi / 4} + /// \end{bmatrix}. + /// \end{align} + /// + /// # Input + /// ## qubit + /// Qubit to which the gate should be applied. + operation T (qubit : Qubit) : Unit is Adj + Ctl { + body intrinsic; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Intrinsic/X.qs b/src/Simulation/TargetDefinitions/Intrinsic/X.qs new file mode 100644 index 00000000000..522592f537a --- /dev/null +++ b/src/Simulation/TargetDefinitions/Intrinsic/X.qs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies the Pauli $X$ gate. + /// + /// # Description + /// \begin{align} + /// \sigma_x \mathrel{:=} + /// \begin{bmatrix} + /// 0 & 1 \\\\ + /// 1 & 0 + /// \end{bmatrix}. + /// \end{align} + /// + /// # Input + /// ## qubit + /// Qubit to which the gate should be applied. + operation X (qubit : Qubit) : Unit is Adj + Ctl { + body intrinsic; + adjoint self; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Intrinsic/Y.qs b/src/Simulation/TargetDefinitions/Intrinsic/Y.qs new file mode 100644 index 00000000000..91769077adc --- /dev/null +++ b/src/Simulation/TargetDefinitions/Intrinsic/Y.qs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies the Pauli $Y$ gate. + /// + /// # Description + /// \begin{align} + /// \sigma_y \mathrel{:=} + /// \begin{bmatrix} + /// 0 & -i \\\\ + /// i & 0 + /// \end{bmatrix}. + /// \end{align} + /// + /// # Input + /// ## qubit + /// Qubit to which the gate should be applied. + operation Y (qubit : Qubit) : Unit is Adj + Ctl { + body intrinsic; + adjoint self; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/Intrinsic/Z.qs b/src/Simulation/TargetDefinitions/Intrinsic/Z.qs new file mode 100644 index 00000000000..9d505596f15 --- /dev/null +++ b/src/Simulation/TargetDefinitions/Intrinsic/Z.qs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Intrinsic { + /// # Summary + /// Applies the Pauli $Z$ gate. + /// + /// # Description + /// \begin{align} + /// \sigma_z \mathrel{:=} + /// \begin{bmatrix} + /// 1 & 0 \\\\ + /// 0 & -1 + /// \end{bmatrix}. + /// \end{align} + /// + /// # Input + /// ## qubit + /// Qubit to which the gate should be applied. + operation Z (qubit : Qubit) : Unit is Adj + Ctl { + body intrinsic; + adjoint self; + } +} \ No newline at end of file diff --git a/src/Simulation/TargetDefinitions/TargetPackages/QsharpCore.Package.props b/src/Simulation/TargetDefinitions/TargetPackages/QsharpCore.Package.props new file mode 100644 index 00000000000..06d5e3117ea --- /dev/null +++ b/src/Simulation/TargetDefinitions/TargetPackages/QsharpCore.Package.props @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +