diff --git a/src/Simulation/TargetDefinitions/Decompositions/Utils.qs b/src/Simulation/TargetDefinitions/Decompositions/Utils.qs index 09fe6fcfd2b..f19fbe615e7 100644 --- a/src/Simulation/TargetDefinitions/Decompositions/Utils.qs +++ b/src/Simulation/TargetDefinitions/Decompositions/Utils.qs @@ -6,12 +6,12 @@ namespace Microsoft.Quantum.Intrinsic { internal operation SpreadZ (from : Qubit, to : Qubit[]) : Unit is Adj { if (Length(to) > 0) { - CNOT(to[0], from); if (Length(to) > 1) { let half = Length(to) / 2; SpreadZ(to[0], to[half + 1 .. Length(to) - 1]); SpreadZ(from, to[1 .. half]); } + CNOT(to[0], from); } } diff --git a/src/Simulation/TargetDefinitions/Tests/DecompositionTests.qs b/src/Simulation/TargetDefinitions/Tests/DecompositionTests.qs index 33f5421edac..c9d013c6a82 100644 --- a/src/Simulation/TargetDefinitions/Tests/DecompositionTests.qs +++ b/src/Simulation/TargetDefinitions/Tests/DecompositionTests.qs @@ -106,6 +106,16 @@ namespace DecompositionTests { VerifyUnitaryAndFunctors2(SWAP, Reference.SWAP); } + @Test("SparseSimulator") + operation VerifyExp() : Unit { + // Use an angle that doesn't have any symmetries as a stand-in for broader validation. + let angle = PI() / 7.0; + VerifyUnitaryAndFunctors(q => Exp([PauliZ], angle, [q]), q => Reference.Exp([PauliZ], angle, [q])); + VerifyUnitaryAndFunctors2((q0, q1) => Exp([PauliZ, size = 2], angle, [q0, q1]), (q0, q1) => Reference.Exp([PauliZ, size = 2], angle, [q0, q1])); + VerifyUnitaryAndFunctors3((q0, q1, q2) => Exp([PauliZ, size = 3], angle, [q0, q1, q2]), (q0, q1, q2) => Reference.Exp([PauliZ, size = 3], angle, [q0, q1, q2])); + VerifyUnitaryAndFunctors4((q0, q1, q2, q3) => Exp([PauliZ, size = 4], angle, [q0, q1, q2, q3]), (q0, q1, q2, q3) => Reference.Exp([PauliZ, size = 4], angle, [q0, q1, q2, q3])); + } + internal operation VerifyUnitaryAndFunctors(unitary : Qubit => Unit is Adj + Ctl, reference : Qubit => Unit is Adj + Ctl) : Unit { VerifyUnitary(unitary, reference, 8); VerifyUnitary(Adjoint unitary, Adjoint reference, 8); @@ -127,6 +137,13 @@ namespace DecompositionTests { VerifyUnitary4((q0, q1, q2, q3) => Controlled Adjoint unitary([q0], (q1, q2, q3)), (q0, q1, q2, q3) => Controlled Adjoint reference([q0], (q1, q2, q3)), 7); } + internal operation VerifyUnitaryAndFunctors4(unitary : (Qubit, Qubit, Qubit, Qubit) => Unit is Adj + Ctl, reference : (Qubit, Qubit, Qubit, Qubit) => Unit is Adj + Ctl) : Unit { + VerifyUnitary4(unitary, reference, 8); + VerifyUnitary4(Adjoint unitary, Adjoint reference, 8); + VerifyUnitary5((q0, q1, q2, q3, q4) => Controlled unitary([q0], (q1, q2, q3, q4)), (q0, q1, q2, q3, q4) => Controlled reference([q0], (q1, q2, q3, q4)), 7); + VerifyUnitary5((q0, q1, q2, q3, q4) => Controlled Adjoint unitary([q0], (q1, q2, q3, q4)), (q0, q1, q2, q3, q4) => Controlled Adjoint reference([q0], (q1, q2, q3, q4)), 7); + } + internal operation VerifyUnitary(unitary : Qubit => Unit is Adj + Ctl, reference : Qubit => Unit is Adj + Ctl, limit : Int) : Unit { // Verify equality up to 8 controls. Reference.AssertOperationsEqualReferenced(1, qs => unitary(qs[0]), @@ -170,4 +187,15 @@ namespace DecompositionTests { qs => Controlled reference(qs[4..(numControls + 3)], (qs[0], qs[1], qs[2], qs[3]))); } } + + internal operation VerifyUnitary5(unitary : (Qubit, Qubit, Qubit, Qubit, Qubit) => Unit is Adj + Ctl, reference : (Qubit, Qubit, Qubit, Qubit, Qubit) => Unit is Adj + Ctl, limit : Int) : Unit { + // Verify equality up to 8 controls. + Reference.AssertOperationsEqualReferenced(5, qs => unitary(qs[0], qs[1], qs[2], qs[3], qs[4]), + qs => reference(qs[0], qs[1], qs[2], qs[3], qs[4])); + + for numControls in 0..limit { + Reference.AssertOperationsEqualReferenced(5 + numControls, qs => Controlled unitary(qs[5..(numControls + 4)], (qs[0], qs[1], qs[2], qs[3], qs[4])), + qs => Controlled reference(qs[5..(numControls + 4)], (qs[0], qs[1], qs[2], qs[3], qs[4]))); + } + } } diff --git a/src/Simulation/TargetDefinitions/Tests/Reference.qs b/src/Simulation/TargetDefinitions/Tests/Reference.qs index 4821abf6e59..12c0a9a8d2b 100644 --- a/src/Simulation/TargetDefinitions/Tests/Reference.qs +++ b/src/Simulation/TargetDefinitions/Tests/Reference.qs @@ -38,6 +38,10 @@ namespace Reference { body intrinsic; } + operation Exp (paulis : Pauli[], theta : Double, qubits : Qubit[]) : Unit is Adj + Ctl { + body intrinsic; + } + operation Reset(qubit : Qubit) : Unit { body intrinsic; } diff --git a/src/Simulation/TargetDefinitions/Tests/Tests.TargetDefinitions.csproj b/src/Simulation/TargetDefinitions/Tests/Tests.TargetDefinitions.csproj index 0c9f042f7f3..43998ca0837 100644 --- a/src/Simulation/TargetDefinitions/Tests/Tests.TargetDefinitions.csproj +++ b/src/Simulation/TargetDefinitions/Tests/Tests.TargetDefinitions.csproj @@ -36,6 +36,8 @@ + +