Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.

Commit 499c068

Browse files
swernliCassandra Granade
andauthored
Fix Exp decomposition to Ising gates (#971)
* Fix Type2 Exp decomposition Corrects the angle convention used when calling the Ising gates as part of the `Exp` decomposition. Fixes Decomposition of `Exp` operation uses incorrect angle convention on IonQ targets #967 * Add decomposition Exp test * Include Exp test in target package tests * Add comment to new test * Update test to check sign consistency Co-authored-by: Cassandra Granade <[email protected]>
1 parent 0eaf0c1 commit 499c068

File tree

9 files changed

+54
-12
lines changed

9 files changed

+54
-12
lines changed

src/Simulation/Simulators.Tests/Circuits/ExpTest.qs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits {
55

66
open Microsoft.Quantum.Intrinsic;
7-
7+
open Microsoft.Quantum.Diagnostics;
8+
open Microsoft.Quantum.Math;
89

910
// At some point, this was causing the simulator to crash.
1011

@@ -26,7 +27,31 @@ namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits {
2627
ResetAll(qubits);
2728
}
2829
}
29-
30+
31+
/// Verify that Exp behaves as expected by using it in two decompositions: SWAP and CNOT.
32+
operation VerifyExpUsingDecompositions() : Unit {
33+
AssertOperationsEqualReferenced(2, (qs => SwapFromExp(qs[0], qs[1])), (qs => SWAP(qs[0], qs[1])));
34+
AssertOperationsEqualReferenced(2, (qs => CnotFromExp(qs[0], qs[1])), (qs => CNOT(qs[0], qs[1])));
35+
}
36+
37+
/// This decomposition only holds if the magnitude of the angle used in the Exp rotation is correct.
38+
operation SwapFromExp(q0 : Qubit, q1 : Qubit) : Unit is Adj {
39+
let qs = [q0, q1];
40+
let theta = PI() / 4.0;
41+
Exp([PauliX, PauliX], theta, qs);
42+
Exp([PauliY, PauliY], theta, qs);
43+
Exp([PauliZ, PauliZ], theta, qs);
44+
}
45+
46+
/// This decomposition only holds if the magnitude of the angle used in Exp is correct and if the
47+
/// sign convention between Rx, Rz, and Exp is consistent.
48+
operation CnotFromExp(q0 : Qubit, q1 : Qubit) : Unit is Adj {
49+
let qs = [q0, q1];
50+
let theta = PI() / 4.0;
51+
Rx(-2.0 * theta, q1);
52+
Rz(-2.0 * theta, q0);
53+
Adjoint Exp([PauliZ, PauliX], theta, qs);
54+
}
3055
}
3156

3257

src/Simulation/Simulators.Tests/QuantumSimulatorTests/VerifyGates.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,20 @@ public void QSimVerifyExpX()
560560
VerifyExp(Pauli.PauliX);
561561
}
562562

563+
[Fact]
564+
public void QSimVerifyExpUsingDecompositions()
565+
{
566+
var simulators = new CommonNativeSimulator[] {
567+
new QuantumSimulator(),
568+
new SparseSimulator()
569+
};
570+
571+
foreach (var sim in simulators)
572+
{
573+
VerifyExpUsingDecompositions.Run(sim).Wait();
574+
}
575+
}
576+
563577
[Fact]
564578
public void QSimVerifyExpFrac()
565579
{

src/Simulation/Simulators.Type1.Tests/Tests.Microsoft.Quantum.Simulators.Type1.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<QSharpCompile Include="..\Simulators.Tests\Circuits\AssertEqual.qs" />
1717
<QSharpCompile Include="..\Simulators.Tests\Circuits\JointMeasureTest.qs" />
1818
<QSharpCompile Include="..\Simulators.Tests\Circuits\VerifyUnitary.qs" />
19+
<QSharpCompile Include="..\Simulators.Tests\Circuits\ExpTest.qs" />
1920
</ItemGroup>
2021

2122
</Project>

src/Simulation/Simulators.Type2.Tests/Tests.Microsoft.Quantum.Simulators.Type2.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<QSharpCompile Include="..\Simulators.Tests\Circuits\AssertEqual.qs" />
1717
<QSharpCompile Include="..\Simulators.Tests\Circuits\JointMeasureTest.qs" />
1818
<QSharpCompile Include="..\Simulators.Tests\Circuits\VerifyUnitary.qs" />
19+
<QSharpCompile Include="..\Simulators.Tests\Circuits\ExpTest.qs" />
1920
</ItemGroup>
2021

2122
</Project>

src/Simulation/Simulators.Type3.Tests/Tests.Microsoft.Quantum.Simulators.Type3.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<QSharpCompile Include="..\Simulators.Tests\Circuits\AssertEqual.qs" />
1717
<QSharpCompile Include="..\Simulators.Tests\Circuits\JointMeasureTest.qs" />
1818
<QSharpCompile Include="..\Simulators.Tests\Circuits\VerifyUnitary.qs" />
19+
<QSharpCompile Include="..\Simulators.Tests\Circuits\ExpTest.qs" />
1920
</ItemGroup>
2021

2122
</Project>

src/Simulation/Simulators/CommonNativeSimulator/IsingXX.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ void IIntrinsicIsingXX.Body(double angle, Qubit target1, Qubit target2)
1515
CheckAngle(angle);
1616
this.CheckQubits(targets);
1717

18-
Exp((uint)targets.Length, paulis, angle * 2.0, targets.GetIds());
18+
Exp((uint)targets.Length, paulis, angle / -2.0, targets.GetIds());
1919
}
2020

2121
void IIntrinsicIsingXX.AdjointBody(double angle, Qubit target1, Qubit target2)
@@ -36,7 +36,7 @@ void IIntrinsicIsingXX.ControlledBody(IQArray<Qubit> controls, double angle, Qub
3636
CheckAngle(angle);
3737
this.CheckQubits(QArray<Qubit>.Add(controls, targets));
3838

39-
MCExp((uint)targets.Length, paulis, angle * 2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
39+
MCExp((uint)targets.Length, paulis, angle / -2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
4040
}
4141
}
4242

src/Simulation/Simulators/CommonNativeSimulator/IsingYY.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ void IIntrinsicIsingYY.Body(double angle, Qubit target1, Qubit target2)
1515
CheckAngle(angle);
1616
this.CheckQubits(targets);
1717

18-
Exp((uint)targets.Length, paulis, angle * 2.0, targets.GetIds());
18+
Exp((uint)targets.Length, paulis, angle / -2.0, targets.GetIds());
1919
}
2020

2121
void IIntrinsicIsingYY.AdjointBody(double angle, Qubit target1, Qubit target2)
@@ -36,7 +36,7 @@ void IIntrinsicIsingYY.ControlledBody(IQArray<Qubit> controls, double angle, Qub
3636
CheckAngle(angle);
3737
this.CheckQubits(QArray<Qubit>.Add(controls, targets));
3838

39-
MCExp((uint)targets.Length, paulis, angle * 2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
39+
MCExp((uint)targets.Length, paulis, angle / -2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
4040
}
4141
}
4242

src/Simulation/Simulators/CommonNativeSimulator/IsingZZ.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ void IIntrinsicIsingZZ.Body(double angle, Qubit target1, Qubit target2)
1515
CheckAngle(angle);
1616
this.CheckQubits(targets);
1717

18-
Exp((uint)targets.Length, paulis, angle * 2.0, targets.GetIds());
18+
Exp((uint)targets.Length, paulis, angle / -2.0, targets.GetIds());
1919
}
2020

2121
void IIntrinsicIsingZZ.AdjointBody(double angle, Qubit target1, Qubit target2)
@@ -36,7 +36,7 @@ void IIntrinsicIsingZZ.ControlledBody(IQArray<Qubit> controls, double angle, Qub
3636
CheckAngle(angle);
3737
this.CheckQubits(QArray<Qubit>.Add(controls, targets));
3838

39-
MCExp((uint)targets.Length, paulis, angle * 2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
39+
MCExp((uint)targets.Length, paulis, angle / -2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds());
4040
}
4141
}
4242

src/Simulation/TargetDefinitions/Decompositions/ExpUtilFromIsing.qs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ namespace Microsoft.Quantum.Intrinsic {
1414
}
1515
apply {
1616
if (paulis[0] == PauliX) {
17-
IsingXX(theta / 2.0, qubits[0], qubits[1]);
17+
IsingXX(-2.0 * theta , qubits[0], qubits[1]);
1818
} elif (paulis[0] == PauliY) {
19-
IsingYY(theta / 2.0, qubits[0], qubits[1]);
19+
IsingYY(-2.0 * theta, qubits[0], qubits[1]);
2020
} elif (paulis[0] == PauliZ) {
21-
IsingZZ(theta / 2.0, qubits[0], qubits[1]);
21+
IsingZZ(-2.0 * theta, qubits[0], qubits[1]);
2222
} else {
2323
fail "Type2 decompositions do not support PauliI as an input to Exp";
2424
}
@@ -35,7 +35,7 @@ namespace Microsoft.Quantum.Intrinsic {
3535
SpreadZ(qubits[1], qubits[2 .. Length(qubits) - 1]);
3636
}
3737
apply {
38-
IsingZZ(theta / 2.0, qubits[0], qubits[1]);
38+
IsingZZ(-2.0 * theta, qubits[0], qubits[1]);
3939
}
4040
}
4141
}

0 commit comments

Comments
 (0)