Fix SpreadZ decomposition utility (#1036)

This fixes the operation of `SpreadZ` when running on lists of more than 3 qubits. It adds tests that operate on lists of 1 to 4 qubits.

Fixes #1021 Bug in the internal `SpreadZ` operation (used in `Exp` decomposition)
This commit is contained in:
Stefan J. Wernli 2022-06-14 09:51:42 -07:00 коммит произвёл GitHub
Родитель e58a90cb50
Коммит c037629fe2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 35 добавлений и 1 удалений

Просмотреть файл

@ -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);
}
}

Просмотреть файл

@ -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])));
}
}
}

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -36,6 +36,8 @@
<QSharpCompile Include="..\Decompositions\CX.qs" />
<QSharpCompile Include="..\Decompositions\CYFromCNOT.qs" />
<QSharpCompile Include="..\Decompositions\CZFromSinglyControlled.qs" />
<QsharpCompile Include="..\Decompositions\ExpFromExpUtil.qs" />
<QsharpCompile Include="..\Decompositions\ExpUtil.qs" />
<QsharpCompile Include="..\Decompositions\HFromSinglyControlled.qs" />
<QSharpCompile Include="..\Decompositions\MResetZExplicit.qs" />
<QsharpCompile Include="..\Decompositions\RFromSinglyControlledR1.qs" />