Skip to content

Commit

Permalink
add decompositions used in extensions to auto_rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
ss2165 committed Feb 17, 2022
1 parent 8fd47c3 commit a8f1dab
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 8 deletions.
114 changes: 114 additions & 0 deletions pytket/pytket/passes/_decompositions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Copyright 2019-2022 Cambridge Quantum Computing
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Union
from sympy import Expr # type: ignore
from pytket.circuit import Circuit, OpType # type: ignore

Param = Union[float, "Expr"]


def approx_0_mod_2(x: Param, eps: float = 1e-10) -> bool:
"""Check if parameter is approximately 0 mod 2 up to eps precision.
:param param: Parameter, float or sympy expression.
:type param: Param
:param eps: Tolerance, defaults to 1e-10
:type eps: float, optional
:return: Approximately 0 boolean.
:rtype: bool
"""
if isinstance(x, Expr) and not x.is_constant():
return False
x = float(x)
x %= 2
return min(x, 2 - x) < eps


def int_half(angle: float) -> int:
"""Assume angle is approximately an even integer, and return the half
:param angle: Float angle
:type angle: float
:return: Integer half of angle
:rtype: int
"""
#
two_x = round(angle)
assert not two_x % 2
return two_x // 2


def _TK1_to_RxRy(a: Param, b: Param, c: Param) -> Circuit:
return Circuit(1).Rx(-0.5, 0).Ry(c, 0).Rx(b, 0).Ry(a, 0).Rx(0.5, 0)


def _TK1_to_X_SX_Rz(a: Param, b: Param, c: Param) -> Circuit:
circ = Circuit(1)
correction_phase = 0.0

# all phase identities use, for integer k,
# Rx(2k) = Rz(2k) = (-1)^{k}I

# _approx_0_mod_2 checks if parameters are constant
# so they can be assumed to be constant
if approx_0_mod_2(b):
circ.Rz(a + c, 0)
# b = 2k, if k is odd, then Rx(b) = -I
correction_phase += int_half(float(b))

elif approx_0_mod_2(b + 1):
# Use Rx(2k-1) = i(-1)^{k}X
correction_phase += -0.5 + int_half(float(b) - 1)
if approx_0_mod_2(a - c):
circ.X(0)
# a - c = 2m
# overall operation is (-1)^{m}Rx(2k -1)
correction_phase += int_half(float(a - c))

else:
circ.Rz(c, 0).X(0).Rz(a, 0)

elif approx_0_mod_2(b - 0.5) and approx_0_mod_2(a) and approx_0_mod_2(c):
# a = 2k, b = 2m+0.5, c = 2n
# Rz(2k)Rx(2m + 0.5)Rz(2n) = (-1)^{k+m+n}e^{-i \pi /4} SX
circ.SX(0)
correction_phase += (
int_half(float(b) - 0.5) + int_half(float(a)) + int_half(float(c)) - 0.25
)

elif approx_0_mod_2(b + 0.5) and approx_0_mod_2(a) and approx_0_mod_2(c):
# a = 2k, b = 2m-0.5, c = 2n
# Rz(2k)Rx(2m - 0.5)Rz(2n) = (-1)^{k+m+n}e^{i \pi /4} X.SX
circ.X(0).SX(0)
correction_phase += (
int_half(float(b) + 0.5) + int_half(float(a)) + int_half(float(c)) + 0.25
)
elif approx_0_mod_2(a - 0.5) and approx_0_mod_2(c - 0.5):
# Rz(2k + 0.5)Rx(b)Rz(2m + 0.5) = -i(-1)^{k+m}SX.Rz(1-b).SX
circ.SX(0).Rz(1 - b, 0).SX(0)
correction_phase += int_half(float(a) - 0.5) + int_half(float(c) - 0.5) - 0.5
else:
circ.Rz(c + 0.5, 0).SX(0).Rz(b - 1, 0).SX(0).Rz(a + 0.5, 0)
correction_phase += -0.5

circ.add_phase(correction_phase)
return circ


def _TK1_to_U(a: Param, b: Param, c: Param) -> Circuit:
circ = Circuit(1)
circ.add_gate(OpType.U3, [b, a - 0.5, c + 0.5], [0])
circ.add_phase(-0.5 * (a + c))
return circ
21 changes: 13 additions & 8 deletions pytket/pytket/passes/auto_rebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Set, Union, Callable, Dict, FrozenSet, TYPE_CHECKING
from typing import Set, Callable, Dict, FrozenSet
from pytket.circuit import Circuit, OpType # type: ignore
from pytket._tket.circuit import _library # type: ignore
from pytket.passes import RebaseCustom # type: ignore
from pytket.passes import RebaseCustom, SquashCustom # type: ignore

if TYPE_CHECKING:
from sympy import Expr # type: ignore
from ._decompositions import Param, _TK1_to_X_SX_Rz, _TK1_to_RxRy, _TK1_to_U


class NoAutoRebase(Exception):
Expand All @@ -30,7 +29,7 @@ class NoAutoRebase(Exception):
OpType.ZZMax: _library._CX_using_ZZMax,
OpType.XXPhase: _library._CX_using_XXPhase_0,
OpType.ECR: _library._CX_using_ECR,
OpType.CZ: lambda: Circuit(2).H(1).CZ(0, 1).H(1),
OpType.CZ: _library._H_CZ_H,
}


Expand All @@ -49,14 +48,16 @@ def get_cx_decomposition(gateset: Set[OpType]) -> Circuit:
raise NoAutoRebase("No known decomposition from CX to available gateset.")


Param = Union[str, "Expr"]

_TK1_circs: Dict[FrozenSet[OpType], Callable[[Param, Param, Param], "Circuit"]] = {
frozenset({OpType.TK1}): _library._TK1_to_TK1,
frozenset({OpType.PhasedX, OpType.Rz}): _library._TK1_to_PhasedXRz,
frozenset({OpType.Rx, OpType.Rz}): _library._TK1_to_RzRx,
frozenset({OpType.Ry, OpType.Rx}): _TK1_to_RxRy,
frozenset({OpType.Rz, OpType.H}): _library._TK1_to_RzH,
frozenset({OpType.Rz, OpType.SX, OpType.X}): _TK1_to_X_SX_Rz,
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,
}


Expand All @@ -71,7 +72,11 @@ def get_TK1_decomposition_function(
:return: TK1 decomposition function.
:rtype: Callable[[Param, Param, Param], "Circuit"]
"""
if any((matching := k).issubset(gateset) for k in _TK1_circs):
subsets = [k for k in _TK1_circs if k.issubset(gateset)]
if subsets:
# find the largest available subset
# as in general more available gates leads to smaller circuits
matching = max(subsets, key=len)
return _TK1_circs[matching]
raise NoAutoRebase("No known decomposition from TK1 to available gateset.")

Expand Down

0 comments on commit a8f1dab

Please sign in to comment.