Skip to content

Commit

Permalink
Add apply_clifford_basis_change_tensor (#1005)
Browse files Browse the repository at this point in the history
* add `apply_clifford_basis_change_tensor`

* Update tailoring.pyi

* update changelog, rewrite method types

* Update tailoring.cpp

* Update characterisation_test.py

* Update pytket/docs/changelog.rst

Co-authored-by: yao-cqc <[email protected]>

* Update tailoring.cpp

* fix changelog formatting

---------

Co-authored-by: yao-cqc <[email protected]>
  • Loading branch information
sjdilkes and yao-cqc authored Sep 6, 2023
1 parent 2255abb commit ea4ffbf
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 7 deletions.
27 changes: 21 additions & 6 deletions pytket/binders/tailoring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,14 @@ namespace py = pybind11;

namespace tket {

QubitPauliString apply_clifford_basis_change(
QubitPauliTensor apply_clifford_basis_change_tensor(
const QubitPauliTensor &in_pauli, const Circuit &circ) {
UnitaryRevTableau tab = circuit_to_unitary_rev_tableau(circ);
QubitPauliTensor new_operator = tab.get_row_product(in_pauli);
return new_operator;
}

QubitPauliString apply_clifford_basis_change_string(
const QubitPauliString &in_pauli, const Circuit &circ) {
UnitaryRevTableau tab = circuit_to_unitary_rev_tableau(circ);
QubitPauliTensor new_operator =
Expand Down Expand Up @@ -163,13 +170,21 @@ PYBIND11_MODULE(tailoring, m) {
py::arg("circuit"), py::arg("samples"))
.def("__repr__", &UniversalFrameRandomisation::to_string);
m.def(
"apply_clifford_basis_change", &apply_clifford_basis_change,
"apply_clifford_basis_change", &apply_clifford_basis_change_string,
"Given Pauli operator P and Clifford circuit C, "
"returns C_dagger.P.C in multiplication order. This ignores any -1 "
"phase that could be introduced.\n\n:param pauli: Pauli "
"operator being transformed. \n:param circuit: "
"Clifford circuit acting on Pauli operator.\n"
":return: :py:class:`QubitPauliString` for new operator",
"phase that could be introduced. "
"\n\n:param pauli: Pauli operator being transformed. "
"\n:param circuit: Clifford circuit acting on Pauli operator. "
"\n:return: :py:class:`QubitPauliString` for new operator",
py::arg("pauli"), py::arg("circuit"));
m.def(
"apply_clifford_basis_change_tensor", &apply_clifford_basis_change_tensor,
"Given Pauli operator P and Clifford circuit C, "
"returns C_dagger.P.C in multiplication order"
"\n\n:param pauli: Pauli operator being transformed."
"\n:param circuit: Clifford circuit acting on Pauli operator. "
"\n:return: :py:class:`QubitPauliTensor` for new operator",
py::arg("pauli"), py::arg("circuit"));
}
} // namespace tket
4 changes: 4 additions & 0 deletions pytket/docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Changelog
Unreleased
----------

Minor new features:

* Add ``apply_clifford_basis_change_tensor``.

Fixes:

* Correct implementation of `symbol_substitution()` for box types that cannot
Expand Down
1 change: 1 addition & 0 deletions pytket/pytket/_tket/tailoring.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ class UniversalFrameRandomisation:
def sample_circuits(self, circuit: pytket._tket.circuit.Circuit, samples: int) -> List[pytket._tket.circuit.Circuit]: ...

def apply_clifford_basis_change(pauli: pytket._tket.pauli.QubitPauliString, circuit: pytket._tket.circuit.Circuit) -> pytket._tket.pauli.QubitPauliString: ...
def apply_clifford_basis_change_tensor(pauli: pytket._tket.pauli.QubitPauliTensor, circuit: pytket._tket.circuit.Circuit) -> pytket._tket.pauli.QubitPauliTensor: ...
16 changes: 15 additions & 1 deletion pytket/tests/characterisation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
PauliFrameRandomisation,
UniversalFrameRandomisation,
apply_clifford_basis_change,
apply_clifford_basis_change_tensor,
)
from pytket.pauli import Pauli, QubitPauliString
from pytket.pauli import Pauli, QubitPauliString, QubitPauliTensor

import pytest # type: ignore

Expand Down Expand Up @@ -116,15 +117,24 @@ def test_apply_clifford_basis_change() -> None:
z_op = QubitPauliString(Qubit(0), Pauli.Z)
x_op = QubitPauliString(Qubit(0), Pauli.X)
assert apply_clifford_basis_change(z_op, circ_0) == x_op
t = apply_clifford_basis_change_tensor(QubitPauliTensor(z_op), circ_0)
assert t.string == x_op
assert t.coeff == 1

circ_1 = Circuit(2).CX(0, 1)
zz_op = QubitPauliString([Qubit(0), Qubit(1)], [Pauli.Z, Pauli.Z])
iz_op = QubitPauliString([Qubit(0), Qubit(1)], [Pauli.I, Pauli.Z])
assert apply_clifford_basis_change(zz_op, circ_1) == iz_op
t = apply_clifford_basis_change_tensor(QubitPauliTensor(zz_op), circ_1)
assert t.string == iz_op
assert t.coeff == 1

circ_2 = Circuit(2).H(0).CX(0, 1).S(1).X(0)
zz_op = QubitPauliString([Qubit(0), Qubit(1)], [Pauli.Z, Pauli.Z])
assert apply_clifford_basis_change(zz_op, circ_2) == iz_op
t = apply_clifford_basis_change_tensor(QubitPauliTensor(zz_op), circ_2)
assert t.string == iz_op
assert t.coeff == -1

circ_3 = (
Circuit(4).H(0).H(1).H(2).H(3).CX(0, 1).CX(1, 2).CX(2, 3).S(0).Y(1).Z(2).X(3)
Expand All @@ -136,6 +146,10 @@ def test_apply_clifford_basis_change() -> None:
[Qubit(0), Qubit(1), Qubit(2), Qubit(3)], [Pauli.Y, Pauli.X, Pauli.Y, Pauli.I]
)
assert apply_clifford_basis_change(yxzi_op, circ_3) == yxyi_op
t = apply_clifford_basis_change_tensor(QubitPauliTensor(yxzi_op), circ_3)

assert t.string == yxyi_op
assert t.coeff == 1


if __name__ == "__main__":
Expand Down

0 comments on commit ea4ffbf

Please sign in to comment.