Skip to content

Commit

Permalink
Methods for GPI, GPI2, and AAMS gates. (#1395)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelontiveros authored May 16, 2024
1 parent 4df750b commit bc8c11c
Show file tree
Hide file tree
Showing 18 changed files with 534 additions and 4 deletions.
2 changes: 1 addition & 1 deletion pytket/binders/circuit/Circuit/add_op.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1333,7 +1333,7 @@ void init_circuit_add_op(py::class_<Circuit, std::shared_ptr<Circuit>> &c) {
[](Circuit *circ, const Expr &angle, unsigned qb,
const py::kwargs &kwargs) {
return add_gate_method_oneparam<unsigned>(
circ, OpType::GPI, angle, {qb}, kwargs);
circ, OpType::GPI2, angle, {qb}, kwargs);
},
"Appends a GPI2 gate with a possibly symbolic angle "
"(specified in half-turns)."
Expand Down
27 changes: 27 additions & 0 deletions pytket/binders/circuit_library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,5 +294,32 @@ PYBIND11_MODULE(circuit_library, library_m) {
library_m.def(
"TK1_to_TK1", &CircPool::tk1_to_tk1,
"A circuit of a single tk1 gate with given parameters");
library_m.def(
"Rx_using_GPI", &CircPool::Rx_using_GPI,
"Equivalent to Rx, using GPI and GPI2 gates");
library_m.def(
"Ry_using_GPI", &CircPool::Ry_using_GPI,
"Equivalent to Ry, using GPI and GPI2 gates");
library_m.def(
"Rz_using_GPI", &CircPool::Rz_using_GPI,
"Equivalent to Rz, using GPI gates");
library_m.def(
"XXPhase_using_AAMS", &CircPool::XXPhase_using_AAMS,
"Equivalent to XXPhase, using AAMS gates");
library_m.def(
"YYPhase_using_AAMS", &CircPool::YYPhase_using_AAMS,
"Equivalent to YYPhase, using AAMS gates");
library_m.def(
"ZZPhase_using_AAMS", &CircPool::ZZPhase_using_AAMS,
"Equivalent to ZZPhase, using AAMS, GPI and GPI2 gates");
library_m.def(
"CX_using_AAMS", &CircPool::CX_using_AAMS,
"Equivalent to CX, using AAMS, GPI and GPI2 gates");
library_m.def(
"TK1_using_GPI", &CircPool::TK1_using_GPI,
"Equivalent to TK1, using GPI and GPI2 gates");
library_m.def(
"TK2_using_AAMS", &CircPool::TK2_using_AAMS,
"Equivalent to TK2, using AAMS, GPI and GPI2 gates");
}
} // namespace tket
4 changes: 4 additions & 0 deletions pytket/binders/transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ PYBIND11_MODULE(transform, m) {
"Rebase from any gate set into the gate set supported by "
"ProjectQ (Rx, Ry, Rz, X, Y, Z, S, T, V, H, CX, CZ, CRz, "
"SWAP).")
.def_static(
"RebaseToIonQ", &Transforms::rebase_ionq,
"Rebase from any gate set into the gate set supported by "
"IonQ (GPI, GPI2, AAMS).")
.def_static(
"DecomposeCCX", &Transforms::decomp_CCX,
"Decomposes all 3-qubit Toffoli (CCX) gates into "
Expand Down
2 changes: 1 addition & 1 deletion pytket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def package(self):
cmake.install()

def requirements(self):
self.requires("tket/1.2.125@tket/stable")
self.requires("tket/1.2.126@tket/stable")
self.requires("tklog/0.3.3@tket/stable")
self.requires("tkrng/0.3.3@tket/stable")
self.requires("tkassert/0.3.4@tket/stable")
Expand Down
2 changes: 2 additions & 0 deletions pytket/docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Features:
* Add ``GreedyPauliSimp`` optimisation pass.
* Add ``BitWiseOp.ZERO`` and ``BitWiseOp.ONE`` to allow construction of constant
conditional expressions.
* Add target gateset ``(GPI, GPI2, AAMS)`` to ``auto_rebase_pass``.
* Add ``RebaseToIonQ`` transform.

Fixes:

Expand Down
38 changes: 37 additions & 1 deletion pytket/pytket/_tket/circuit_library.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ from __future__ import annotations
import pytket._tket.circuit
import sympy
import typing
__all__ = ['BRIDGE', 'BRIDGE_using_CX_0', 'BRIDGE_using_CX_1', 'C3X_normal_decomp', 'C4X_normal_decomp', 'CCX', 'CCX_modulo_phase_shift', 'CCX_normal_decomp', 'CH_using_CX', 'CRx_using_CX', 'CRx_using_TK2', 'CRy_using_CX', 'CRy_using_TK2', 'CRz_using_CX', 'CRz_using_TK2', 'CSWAP_using_CX', 'CSX_using_CX', 'CSXdg_using_CX', 'CS_using_CX', 'CSdg_using_CX', 'CU1_using_CX', 'CU1_using_TK2', 'CU3_using_CX', 'CV_using_CX', 'CVdg_using_CX', 'CX', 'CX_S_CX_reduced', 'CX_S_V_XC_reduced', 'CX_VS_CX_reduced', 'CX_V_CX_reduced', 'CX_V_S_XC_reduced', 'CX_XC_reduced', 'CX_using_ECR', 'CX_using_TK2', 'CX_using_XXPhase_0', 'CX_using_XXPhase_1', 'CX_using_ZZMax', 'CX_using_ZZPhase', 'CX_using_flipped_CX', 'CY_using_CX', 'CZ_using_CX', 'ECR_using_CX', 'ESWAP_using_CX', 'ESWAP_using_TK2', 'FSim_using_CX', 'FSim_using_TK2', 'H_CZ_H', 'ISWAP_using_CX', 'ISWAP_using_TK2', 'NPhasedX_using_PhasedX', 'PhasedISWAP_using_CX', 'PhasedISWAP_using_TK2', 'SWAP_using_CX_0', 'SWAP_using_CX_1', 'TK1_to_PhasedXRz', 'TK1_to_RzH', 'TK1_to_RzRx', 'TK1_to_RzSX', 'TK1_to_TK1', 'TK2_using_3xCX', 'TK2_using_CX', 'TK2_using_CX_and_swap', 'TK2_using_TK2_or_swap', 'TK2_using_ZZMax', 'TK2_using_ZZMax_and_swap', 'TK2_using_ZZPhase', 'TK2_using_ZZPhase_and_swap', 'TK2_using_normalised_TK2', 'X', 'X1_CX', 'XXPhase3_using_CX', 'XXPhase3_using_TK2', 'XXPhase_using_CX', 'XXPhase_using_TK2', 'YYPhase_using_CX', 'YYPhase_using_TK2', 'Z0_CX', 'ZZMax_using_CX', 'ZZPhase_using_CX', 'ZZPhase_using_TK2', 'approx_TK2_using_1xCX', 'approx_TK2_using_1xZZPhase', 'approx_TK2_using_2xCX', 'approx_TK2_using_2xZZPhase', 'ladder_down', 'ladder_down_2', 'ladder_up']
__all__ = ['BRIDGE', 'BRIDGE_using_CX_0', 'BRIDGE_using_CX_1', 'C3X_normal_decomp', 'C4X_normal_decomp', 'CCX', 'CCX_modulo_phase_shift', 'CCX_normal_decomp', 'CH_using_CX', 'CRx_using_CX', 'CRx_using_TK2', 'CRy_using_CX', 'CRy_using_TK2', 'CRz_using_CX', 'CRz_using_TK2', 'CSWAP_using_CX', 'CSX_using_CX', 'CSXdg_using_CX', 'CS_using_CX', 'CSdg_using_CX', 'CU1_using_CX', 'CU1_using_TK2', 'CU3_using_CX', 'CV_using_CX', 'CVdg_using_CX', 'CX', 'CX_S_CX_reduced', 'CX_S_V_XC_reduced', 'CX_VS_CX_reduced', 'CX_V_CX_reduced', 'CX_V_S_XC_reduced', 'CX_XC_reduced', 'CX_using_AAMS', 'CX_using_ECR', 'CX_using_TK2', 'CX_using_XXPhase_0', 'CX_using_XXPhase_1', 'CX_using_ZZMax', 'CX_using_ZZPhase', 'CX_using_flipped_CX', 'CY_using_CX', 'CZ_using_CX', 'ECR_using_CX', 'ESWAP_using_CX', 'ESWAP_using_TK2', 'FSim_using_CX', 'FSim_using_TK2', 'H_CZ_H', 'ISWAP_using_CX', 'ISWAP_using_TK2', 'NPhasedX_using_PhasedX', 'PhasedISWAP_using_CX', 'PhasedISWAP_using_TK2', 'Rx_using_GPI', 'Ry_using_GPI', 'Rz_using_GPI', 'SWAP_using_CX_0', 'SWAP_using_CX_1', 'TK1_to_PhasedXRz', 'TK1_to_RzH', 'TK1_to_RzRx', 'TK1_to_RzSX', 'TK1_to_TK1', 'TK1_using_GPI', 'TK2_using_3xCX', 'TK2_using_AAMS', 'TK2_using_CX', 'TK2_using_CX_and_swap', 'TK2_using_TK2_or_swap', 'TK2_using_ZZMax', 'TK2_using_ZZMax_and_swap', 'TK2_using_ZZPhase', 'TK2_using_ZZPhase_and_swap', 'TK2_using_normalised_TK2', 'X', 'X1_CX', 'XXPhase3_using_CX', 'XXPhase3_using_TK2', 'XXPhase_using_AAMS', 'XXPhase_using_CX', 'XXPhase_using_TK2', 'YYPhase_using_AAMS', 'YYPhase_using_CX', 'YYPhase_using_TK2', 'Z0_CX', 'ZZMax_using_CX', 'ZZPhase_using_AAMS', 'ZZPhase_using_CX', 'ZZPhase_using_TK2', 'approx_TK2_using_1xCX', 'approx_TK2_using_1xZZPhase', 'approx_TK2_using_2xCX', 'approx_TK2_using_2xZZPhase', 'ladder_down', 'ladder_down_2', 'ladder_up']
def BRIDGE() -> pytket._tket.circuit.Circuit:
"""
Just a BRIDGE[0,1,2] gate
Expand Down Expand Up @@ -131,6 +131,10 @@ def CX_XC_reduced() -> pytket._tket.circuit.Circuit:
"""
CX-reduced form of CX/XC
"""
def CX_using_AAMS() -> pytket._tket.circuit.Circuit:
"""
Equivalent to CX, using AAMS, GPI and GPI2 gates
"""
def CX_using_ECR() -> pytket._tket.circuit.Circuit:
"""
Equivalent to CX, using only ECR, Rx and U3 gates
Expand Down Expand Up @@ -211,6 +215,18 @@ def PhasedISWAP_using_TK2(arg0: sympy.Expr | float, arg1: sympy.Expr | float) ->
"""
Equivalent to PhasedISWAP, using a TK2 and Rz gates
"""
def Rx_using_GPI(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to Rx, using GPI and GPI2 gates
"""
def Ry_using_GPI(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to Ry, using GPI and GPI2 gates
"""
def Rz_using_GPI(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to Rz, using GPI gates
"""
def SWAP_using_CX_0() -> pytket._tket.circuit.Circuit:
"""
Equivalent to SWAP, using three CX, outer CX have control on qubit 0
Expand Down Expand Up @@ -239,12 +255,20 @@ def TK1_to_TK1(arg0: sympy.Expr | float, arg1: sympy.Expr | float, arg2: sympy.E
"""
A circuit of a single tk1 gate with given parameters
"""
def TK1_using_GPI(arg0: sympy.Expr | float, arg1: sympy.Expr | float, arg2: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to TK1, using GPI and GPI2 gates
"""
def TK2_using_3xCX(arg0: sympy.Expr | float, arg1: sympy.Expr | float, arg2: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Given expressions α, β and γ, return circuit equivalent to TK2(α, β, γ) using 3 CX and single-qubit gates.
Prefer using `_TK2_using_CX` unless you wish to explicitly use 3 CX or if α, β and γ are not normalised to the Weyl chamber.
"""
def TK2_using_AAMS(arg0: sympy.Expr | float, arg1: sympy.Expr | float, arg2: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to TK2, using AAMS, GPI and GPI2 gates
"""
def TK2_using_CX(arg0: sympy.Expr | float, arg1: sympy.Expr | float, arg2: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Given expressions α, β and γ, return circuit equivalent to TK2(α, β, γ) using up to 3 CX and single-qubit gates.
Expand Down Expand Up @@ -297,6 +321,10 @@ def XXPhase3_using_TK2(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit
"""
Equivalent to XXPhase3, using three TK2 gates
"""
def XXPhase_using_AAMS(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to XXPhase, using AAMS gates
"""
def XXPhase_using_CX(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to XXPhase, using CX and U3 gates
Expand All @@ -305,6 +333,10 @@ def XXPhase_using_TK2(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to XXPhase, using a TK2 gate
"""
def YYPhase_using_AAMS(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to YYPhase, using AAMS gates
"""
def YYPhase_using_CX(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to YYPhase, using two CX gates and one Ry, one Sdg and one S gate.
Expand All @@ -321,6 +353,10 @@ def ZZMax_using_CX() -> pytket._tket.circuit.Circuit:
"""
Equivalent to ZZMax, using CX, Rz and U3 gates
"""
def ZZPhase_using_AAMS(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to ZZPhase, using AAMS, GPI and GPI2 gates
"""
def ZZPhase_using_CX(arg0: sympy.Expr | float) -> pytket._tket.circuit.Circuit:
"""
Equivalent to ZZPhase, using CX and Rz gates
Expand Down
5 changes: 5 additions & 0 deletions pytket/pytket/_tket/transform.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,11 @@ class Transform:
Replace all single-qubit unitary gates outside the set {Z, X, S, V} that are recognized as Clifford operations with an equivalent sequence of gates from that set.
"""
@staticmethod
def RebaseToIonQ() -> Transform:
"""
Rebase from any gate set into the gate set supported by IonQ (GPI, GPI2, AAMS).
"""
@staticmethod
def RebaseToProjectQ() -> Transform:
"""
Rebase from any gate set into the gate set supported by ProjectQ (Rx, Ry, Rz, X, Y, Z, S, T, V, H, CX, CZ, CRz, SWAP).
Expand Down
9 changes: 9 additions & 0 deletions pytket/pytket/circuit_library/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
CX_using_ZZPhase,
CX_using_XXPhase_0,
CX_using_XXPhase_1,
CX_using_AAMS,
CX_VS_CX_reduced,
CX_V_CX_reduced,
CX_S_CX_reduced,
Expand Down Expand Up @@ -100,4 +101,12 @@
TK1_to_RzH,
TK1_to_RzSX,
TK1_to_TK1,
Rx_using_GPI,
Ry_using_GPI,
Rz_using_GPI,
XXPhase_using_AAMS,
YYPhase_using_AAMS,
ZZPhase_using_AAMS,
TK1_using_GPI,
TK2_using_AAMS,
)
3 changes: 3 additions & 0 deletions pytket/pytket/passes/auto_rebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class NoAutoRebase(Exception):
OpType.XXPhase: _library.CX_using_XXPhase_0,
OpType.ECR: _library.CX_using_ECR,
OpType.CZ: _library.H_CZ_H,
OpType.AAMS: _library.CX_using_AAMS,
}


Expand All @@ -43,6 +44,7 @@ def _TK2_using_TK2(a: Param, b: Param, c: Param) -> Circuit:
OpType.ZZPhase: _library.TK2_using_ZZPhase,
OpType.CX: _library.TK2_using_CX,
OpType.ZZMax: _library.TK2_using_ZZMax,
OpType.AAMS: _library.TK2_using_AAMS,
}

_TK2_CIRCS_WIRE_SWAP: Dict[OpType, Callable[[Param, Param, Param], "Circuit"]] = {
Expand Down Expand Up @@ -101,6 +103,7 @@ def get_tk2_decomposition(
frozenset({OpType.Rz, OpType.SX}): _TK1_to_X_SX_Rz,
frozenset({OpType.Rz, OpType.SX}): _library.TK1_to_RzSX,
frozenset({OpType.U3}): _TK1_to_U,
frozenset({OpType.GPI, OpType.GPI2}): _library.TK1_using_GPI,
}


Expand Down
45 changes: 45 additions & 0 deletions pytket/pytket/utils/symbolic.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,48 @@ def symb_fsim(params: ParamsType) -> ImmutableMatrix:
)


def symb_gpi(params: ParamsType) -> ImmutableMatrix:
t = sympy.exp(I * sympy.pi * params[0])

return ImmutableMatrix( # type: ignore
[
[0, 1 / t],
[t, 0],
]
)


def symb_gpi2(params: ParamsType) -> ImmutableMatrix:
t = sympy.exp(I * sympy.pi * params[0])
c = 1 / sympy.sqrt(2) # type: ignore

return c * ImmutableMatrix( # type: ignore
[
[1, -I / t],
[-I * t, 1],
]
)


def symb_aams(params: ParamsType) -> ImmutableMatrix:
alpha, beta, gamma = params
c = sympy.cos(sympy.pi / 2 * alpha)
s = sympy.sin(sympy.pi / 2 * alpha)
s1 = -I * sympy.exp(I * sympy.pi * (-beta - gamma)) * s
s2 = -I * sympy.exp(I * sympy.pi * (-beta + gamma)) * s
s3 = -I * sympy.exp(I * sympy.pi * (beta - gamma)) * s
s4 = -I * sympy.exp(I * sympy.pi * (beta + gamma)) * s

return ImmutableMatrix( # type: ignore
[
[c, 0, 0, s1],
[0, c, s2, 0],
[0, s3, c, 0],
[s4, 0, 0, c],
]
)


# end symbolic matrix definitions


Expand Down Expand Up @@ -282,6 +324,9 @@ class SymGateRegister:
OpType.PhasedX: symb_phasedx,
OpType.ESWAP: symb_eswap,
OpType.FSim: symb_fsim,
OpType.GPI: symb_gpi,
OpType.GPI2: symb_gpi2,
OpType.AAMS: symb_aams,
}

@classmethod
Expand Down
10 changes: 10 additions & 0 deletions pytket/tests/transform_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,16 @@ def test_auto_rebase() -> None:
_library.CX(),
_library.TK1_to_TK1,
),
(
{OpType.GPI, OpType.GPI2, OpType.AAMS},
_library.CX_using_AAMS(),
_library.TK1_using_GPI,
),
(
{OpType.GPI, OpType.GPI2, OpType.AAMS},
_library.TK2_using_AAMS,
_library.TK1_using_GPI,
),
]

circ = get_test_circuit()
Expand Down
2 changes: 1 addition & 1 deletion tket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

class TketConan(ConanFile):
name = "tket"
version = "1.2.125"
version = "1.2.126"
package_type = "library"
license = "Apache 2"
homepage = "https://github.com/CQCL/tket"
Expand Down
27 changes: 27 additions & 0 deletions tket/include/tket/Circuit/CircPool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ const Circuit &CX_using_XXPhase_0();
/** Equivalent to CX, using only XXPhase, Rx and Rz gates */
const Circuit &CX_using_XXPhase_1();

/** Equivalent to CX, using only AAMS, GPI and GPI2 gates */
const Circuit &CX_using_AAMS();

/**
* CX-reduced form of CX/V,S/CX
*
Expand Down Expand Up @@ -536,6 +539,30 @@ Circuit CnU_gray_code_decomp(unsigned n, const Gate_ptr &gate);
Circuit CnSU2_linear_decomp(
unsigned n, const Expr &alpha, const Expr &theta, const Expr &beta);

/** Equivalent to Rx, using GPI and GPI2 gates */
Circuit Rx_using_GPI(const Expr &theta);

/** Equivalent to Ry, using GPI and GPI2 gates */
Circuit Ry_using_GPI(const Expr &theta);

/** Equivalent to Rz, using GPI gates */
Circuit Rz_using_GPI(const Expr &theta);

/** Equivalent to XXPhase, using AAMS gates */
Circuit XXPhase_using_AAMS(const Expr &theta);

/** Equivalent to YYPhase, using AAMS gates */
Circuit YYPhase_using_AAMS(const Expr &theta);

/** Equivalent to ZZPhase, using AAMS, GPI and GPI2 gates */
Circuit ZZPhase_using_AAMS(const Expr &theta);

/** Equivalent to TK1, using GPI and GPI2 gates */
Circuit TK1_using_GPI(const Expr &alpha, const Expr &beta, const Expr &gamma);

/** Equivalent to TK2, using AAMS, GPI and GPI2 gates */
Circuit TK2_using_AAMS(const Expr &alpha, const Expr &beta, const Expr &gamma);

} // namespace CircPool

} // namespace tket
4 changes: 4 additions & 0 deletions tket/include/tket/Transformations/Rebase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ Transform rebase_TK();
// Singleqs: Rz, PhasedX
Transform rebase_UMD();

// Multiqs: AAMS
// Singleqs: GPI, GPI2
Transform rebase_ionq();

} // namespace Transforms

} // namespace tket
Loading

0 comments on commit bc8c11c

Please sign in to comment.