diff --git a/src/Simulation/Simulators.Tests/Circuits/ExpTest.qs b/src/Simulation/Simulators.Tests/Circuits/ExpTest.qs
index 430bbd0ccdd..e45a9e70adb 100644
--- a/src/Simulation/Simulators.Tests/Circuits/ExpTest.qs
+++ b/src/Simulation/Simulators.Tests/Circuits/ExpTest.qs
@@ -4,7 +4,8 @@
namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits {
open Microsoft.Quantum.Intrinsic;
-
+ open Microsoft.Quantum.Diagnostics;
+ open Microsoft.Quantum.Math;
// At some point, this was causing the simulator to crash.
@@ -26,7 +27,31 @@ namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits {
ResetAll(qubits);
}
}
-
+
+ /// Verify that Exp behaves as expected by using it in two decompositions: SWAP and CNOT.
+ operation VerifyExpUsingDecompositions() : Unit {
+ AssertOperationsEqualReferenced(2, (qs => SwapFromExp(qs[0], qs[1])), (qs => SWAP(qs[0], qs[1])));
+ AssertOperationsEqualReferenced(2, (qs => CnotFromExp(qs[0], qs[1])), (qs => CNOT(qs[0], qs[1])));
+ }
+
+ /// This decomposition only holds if the magnitude of the angle used in the Exp rotation is correct.
+ operation SwapFromExp(q0 : Qubit, q1 : Qubit) : Unit is Adj {
+ let qs = [q0, q1];
+ let theta = PI() / 4.0;
+ Exp([PauliX, PauliX], theta, qs);
+ Exp([PauliY, PauliY], theta, qs);
+ Exp([PauliZ, PauliZ], theta, qs);
+ }
+
+ /// This decomposition only holds if the magnitude of the angle used in Exp is correct and if the
+ /// sign convention between Rx, Rz, and Exp is consistent.
+ operation CnotFromExp(q0 : Qubit, q1 : Qubit) : Unit is Adj {
+ let qs = [q0, q1];
+ let theta = PI() / 4.0;
+ Rx(-2.0 * theta, q1);
+ Rz(-2.0 * theta, q0);
+ Adjoint Exp([PauliZ, PauliX], theta, qs);
+ }
}
diff --git a/src/Simulation/Simulators.Tests/QuantumSimulatorTests/VerifyGates.cs b/src/Simulation/Simulators.Tests/QuantumSimulatorTests/VerifyGates.cs
index f01ed172cfa..41455c4b9e7 100644
--- a/src/Simulation/Simulators.Tests/QuantumSimulatorTests/VerifyGates.cs
+++ b/src/Simulation/Simulators.Tests/QuantumSimulatorTests/VerifyGates.cs
@@ -560,6 +560,20 @@ public void QSimVerifyExpX()
VerifyExp(Pauli.PauliX);
}
+ [Fact]
+ public void QSimVerifyExpUsingDecompositions()
+ {
+ var simulators = new CommonNativeSimulator[] {
+ new QuantumSimulator(),
+ new SparseSimulator()
+ };
+
+ foreach (var sim in simulators)
+ {
+ VerifyExpUsingDecompositions.Run(sim).Wait();
+ }
+ }
+
[Fact]
public void QSimVerifyExpFrac()
{
diff --git a/src/Simulation/Simulators.Type1.Tests/Tests.Microsoft.Quantum.Simulators.Type1.csproj b/src/Simulation/Simulators.Type1.Tests/Tests.Microsoft.Quantum.Simulators.Type1.csproj
index 197bdb2173d..5f1c4583cf7 100644
--- a/src/Simulation/Simulators.Type1.Tests/Tests.Microsoft.Quantum.Simulators.Type1.csproj
+++ b/src/Simulation/Simulators.Type1.Tests/Tests.Microsoft.Quantum.Simulators.Type1.csproj
@@ -16,6 +16,7 @@
+
diff --git a/src/Simulation/Simulators.Type2.Tests/Tests.Microsoft.Quantum.Simulators.Type2.csproj b/src/Simulation/Simulators.Type2.Tests/Tests.Microsoft.Quantum.Simulators.Type2.csproj
index 18f70718414..4fab0d44a49 100644
--- a/src/Simulation/Simulators.Type2.Tests/Tests.Microsoft.Quantum.Simulators.Type2.csproj
+++ b/src/Simulation/Simulators.Type2.Tests/Tests.Microsoft.Quantum.Simulators.Type2.csproj
@@ -16,6 +16,7 @@
+
diff --git a/src/Simulation/Simulators.Type3.Tests/Tests.Microsoft.Quantum.Simulators.Type3.csproj b/src/Simulation/Simulators.Type3.Tests/Tests.Microsoft.Quantum.Simulators.Type3.csproj
index 0df36c4db25..30416f0148c 100644
--- a/src/Simulation/Simulators.Type3.Tests/Tests.Microsoft.Quantum.Simulators.Type3.csproj
+++ b/src/Simulation/Simulators.Type3.Tests/Tests.Microsoft.Quantum.Simulators.Type3.csproj
@@ -16,6 +16,7 @@
+
diff --git a/src/Simulation/Simulators/CommonNativeSimulator/IsingXX.cs b/src/Simulation/Simulators/CommonNativeSimulator/IsingXX.cs
index 5f114db803a..ee02e94e7cb 100644
--- a/src/Simulation/Simulators/CommonNativeSimulator/IsingXX.cs
+++ b/src/Simulation/Simulators/CommonNativeSimulator/IsingXX.cs
@@ -15,7 +15,7 @@ void IIntrinsicIsingXX.Body(double angle, Qubit target1, Qubit target2)
CheckAngle(angle);
this.CheckQubits(targets);
- Exp((uint)targets.Length, paulis, angle * 2.0, targets.GetIds());
+ Exp((uint)targets.Length, paulis, angle / -2.0, targets.GetIds());
}
void IIntrinsicIsingXX.AdjointBody(double angle, Qubit target1, Qubit target2)
@@ -36,7 +36,7 @@ void IIntrinsicIsingXX.ControlledBody(IQArray controls, double angle, Qub
CheckAngle(angle);
this.CheckQubits(QArray.Add(controls, targets));
- MCExp((uint)targets.Length, paulis, angle * 2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
+ MCExp((uint)targets.Length, paulis, angle / -2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
}
}
diff --git a/src/Simulation/Simulators/CommonNativeSimulator/IsingYY.cs b/src/Simulation/Simulators/CommonNativeSimulator/IsingYY.cs
index 1aa000ec554..377eb1992cf 100644
--- a/src/Simulation/Simulators/CommonNativeSimulator/IsingYY.cs
+++ b/src/Simulation/Simulators/CommonNativeSimulator/IsingYY.cs
@@ -15,7 +15,7 @@ void IIntrinsicIsingYY.Body(double angle, Qubit target1, Qubit target2)
CheckAngle(angle);
this.CheckQubits(targets);
- Exp((uint)targets.Length, paulis, angle * 2.0, targets.GetIds());
+ Exp((uint)targets.Length, paulis, angle / -2.0, targets.GetIds());
}
void IIntrinsicIsingYY.AdjointBody(double angle, Qubit target1, Qubit target2)
@@ -36,7 +36,7 @@ void IIntrinsicIsingYY.ControlledBody(IQArray controls, double angle, Qub
CheckAngle(angle);
this.CheckQubits(QArray.Add(controls, targets));
- MCExp((uint)targets.Length, paulis, angle * 2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
+ MCExp((uint)targets.Length, paulis, angle / -2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
}
}
diff --git a/src/Simulation/Simulators/CommonNativeSimulator/IsingZZ.cs b/src/Simulation/Simulators/CommonNativeSimulator/IsingZZ.cs
index ffdef477228..862792910eb 100644
--- a/src/Simulation/Simulators/CommonNativeSimulator/IsingZZ.cs
+++ b/src/Simulation/Simulators/CommonNativeSimulator/IsingZZ.cs
@@ -15,7 +15,7 @@ void IIntrinsicIsingZZ.Body(double angle, Qubit target1, Qubit target2)
CheckAngle(angle);
this.CheckQubits(targets);
- Exp((uint)targets.Length, paulis, angle * 2.0, targets.GetIds());
+ Exp((uint)targets.Length, paulis, angle / -2.0, targets.GetIds());
}
void IIntrinsicIsingZZ.AdjointBody(double angle, Qubit target1, Qubit target2)
@@ -36,7 +36,7 @@ void IIntrinsicIsingZZ.ControlledBody(IQArray controls, double angle, Qub
CheckAngle(angle);
this.CheckQubits(QArray.Add(controls, targets));
- MCExp((uint)targets.Length, paulis, angle * 2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
+ MCExp((uint)targets.Length, paulis, angle / -2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
}
}
diff --git a/src/Simulation/TargetDefinitions/Decompositions/ExpUtilFromIsing.qs b/src/Simulation/TargetDefinitions/Decompositions/ExpUtilFromIsing.qs
index ebc50d9aca4..0840705a66f 100644
--- a/src/Simulation/TargetDefinitions/Decompositions/ExpUtilFromIsing.qs
+++ b/src/Simulation/TargetDefinitions/Decompositions/ExpUtilFromIsing.qs
@@ -14,11 +14,11 @@ namespace Microsoft.Quantum.Intrinsic {
}
apply {
if (paulis[0] == PauliX) {
- IsingXX(theta / 2.0, qubits[0], qubits[1]);
+ IsingXX(-2.0 * theta , qubits[0], qubits[1]);
} elif (paulis[0] == PauliY) {
- IsingYY(theta / 2.0, qubits[0], qubits[1]);
+ IsingYY(-2.0 * theta, qubits[0], qubits[1]);
} elif (paulis[0] == PauliZ) {
- IsingZZ(theta / 2.0, qubits[0], qubits[1]);
+ IsingZZ(-2.0 * theta, qubits[0], qubits[1]);
} else {
fail "Type2 decompositions do not support PauliI as an input to Exp";
}
@@ -35,7 +35,7 @@ namespace Microsoft.Quantum.Intrinsic {
SpreadZ(qubits[1], qubits[2 .. Length(qubits) - 1]);
}
apply {
- IsingZZ(theta / 2.0, qubits[0], qubits[1]);
+ IsingZZ(-2.0 * theta, qubits[0], qubits[1]);
}
}
}