Skip to content

Commit

Permalink
Merge pull request #118 from chensgit169/master
Browse files Browse the repository at this point in the history
Enhance module of ``QuantumGate``
  • Loading branch information
Zhaoyilunnn authored Nov 25, 2023
2 parents bc13569 + 6a6183d commit ac37a75
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 50 deletions.
18 changes: 3 additions & 15 deletions quafu/elements/element_gates/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
from .pauli import (
XGate,
YGate,
ZGate,
IdGate,
WGate,
SWGate,
SXGate,
SXdgGate,
SYGate,
SYdgGate,
)
from .pauli import *
from .clifford import HGate, SGate, SdgGate, TGate, TdgGate
from .phase import PhaseGate
from .rotation import RXGate, RYGate, RZGate, RXXGate, RYYGate, RZZGate
from .rotation import RXGate, RYGate, RZGate, RXXGate, RYYGate, RZZGate, PhaseGate
from .swap import SwapGate, ISwapGate
from .c11 import CXGate, CYGate, CZGate, CSGate, CTGate, CPGate
from .c12 import FredkinGate
Expand All @@ -35,7 +23,7 @@
"SYGate",
"SYdgGate",
"SWGate",
"PhaseGate",
"SWdgGate",
"RXGate",
"RYGate",
"RZGate",
Expand Down
23 changes: 20 additions & 3 deletions quafu/elements/element_gates/pauli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from quafu.elements.quantum_gate import FixedGate, SingleQubitGate

__all__ = ['IdGate', 'XGate', 'YGate', 'ZGate',
'WGate', 'SWGate',
'SXGate', 'SYGate', 'SXdgGate', 'SYdgGate']
'WGate', 'SWGate', 'SWdgGate',
'SXGate', 'SYGate', 'SXdgGate', 'SYdgGate'] # hint: "SZ" gate is S contained in Clifford gates


class IdGate(FixedGate, SingleQubitGate):
Expand Down Expand Up @@ -73,6 +73,22 @@ def to_qasm(self):
)


class SWdgGate(FixedGate, SingleQubitGate):
name = "SWdg"
matrix = SWMatrix

def __init__(self, pos: int):
FixedGate.__init__(self, pos)
self.symbol = "√W†"

def to_qasm(self):
return "rz(-pi/4) q[%d];\nrx(-pi/2) q[%d];\nrz(pi/4) q[%d]" % (
self.pos,
self.pos,
self.pos,
)


class SXGate(FixedGate, SingleQubitGate):
name = "SX"
matrix = np.array(
Expand All @@ -89,7 +105,7 @@ class SXdgGate(FixedGate, SingleQubitGate):

def __init__(self, pos: int):
FixedGate.__init__(self, pos)
self.symbol = "√X"
self.symbol = "√X"


class SYGate(FixedGate, SingleQubitGate):
Expand Down Expand Up @@ -124,6 +140,7 @@ def to_qasm(self):
SingleQubitGate.register_gate(ZGate)
SingleQubitGate.register_gate(WGate)
SingleQubitGate.register_gate(SWGate)
SingleQubitGate.register_gate(SWdgGate)
SingleQubitGate.register_gate(SXGate)
SingleQubitGate.register_gate(SXdgGate)
SingleQubitGate.register_gate(SYGate)
Expand Down
21 changes: 0 additions & 21 deletions quafu/elements/element_gates/phase.py

This file was deleted.

31 changes: 23 additions & 8 deletions quafu/elements/element_gates/rotation.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing import Dict

from quafu.elements.matrices import rx_mat, ry_mat, rz_mat, rxx_mat, ryy_mat, rzz_mat
from quafu.elements.matrices import rx_mat, ry_mat, rz_mat, rxx_mat, ryy_mat, rzz_mat, pmatrix
from ..quantum_gate import QuantumGate, SingleQubitGate, ParametricGate

__all__ = ['RXGate', 'RYGate', 'RZGate', 'RXXGate', 'RYYGate', 'RZZGate']
__all__ = ['RXGate', 'RYGate', 'RZGate', 'RXXGate', 'RYYGate', 'RZZGate', 'PhaseGate']


@QuantumGate.register('rx')
class RXGate(ParametricGate, SingleQubitGate):
name = "RX"

Expand All @@ -17,6 +18,7 @@ def matrix(self):
return rx_mat(self.paras)


@QuantumGate.register('ry')
class RYGate(ParametricGate, SingleQubitGate):
name = "RY"

Expand All @@ -28,6 +30,7 @@ def matrix(self):
return ry_mat(self.paras)


@QuantumGate.register('rz')
class RZGate(ParametricGate, SingleQubitGate):
name = "RZ"

Expand All @@ -39,6 +42,7 @@ def matrix(self):
return rz_mat(self.paras)


@QuantumGate.register('rxx')
class RXXGate(ParametricGate):
name = "RXX"

Expand All @@ -54,6 +58,7 @@ def named_pos(self) -> Dict:
return {'pos': self.pos}


@QuantumGate.register('ryy')
class RYYGate(ParametricGate):
name = "RYY"

Expand All @@ -69,6 +74,7 @@ def named_pos(self) -> Dict:
return {'pos': self.pos}


@QuantumGate.register('rzz')
class RZZGate(ParametricGate):
name = "RZZ"

Expand All @@ -84,9 +90,18 @@ def named_pos(self) -> Dict:
return {'pos': self.pos}


QuantumGate.register_gate(RXGate)
QuantumGate.register_gate(RYGate)
QuantumGate.register_gate(RZGate)
QuantumGate.register_gate(RXXGate)
QuantumGate.register_gate(RYYGate)
QuantumGate.register_gate(RZZGate)
@SingleQubitGate.register(name='p')
class PhaseGate(SingleQubitGate):
"""Ally of rz gate, but with a different name and global phase."""
name = "P"

def __init__(self, pos: int, paras: float = 0.0):
super().__init__(pos, paras=paras)

@property
def matrix(self):
return pmatrix(self.paras)

@property
def named_paras(self) -> Dict:
return {'phase': self.paras}
10 changes: 9 additions & 1 deletion quafu/elements/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,19 @@ def register_ins(cls, subclass, name: str = None):
assert issubclass(subclass, cls)

if name is None:
name = subclass.name
name = str(subclass.name).lower()
if name in cls.ins_classes:
raise ValueError(f"Name {name} already exists.")
cls.ins_classes[name] = subclass

@classmethod
def register(cls, name: str = None):
def wrapper(subclass):
cls.register_ins(subclass, name)
return subclass

return wrapper

@abstractmethod
def to_qasm(self):
pass
Expand Down
12 changes: 10 additions & 2 deletions quafu/elements/quantum_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,25 @@ def matrix(self):
", this should never happen.")

@classmethod
def register_gate(cls, subclass):
def register_gate(cls, subclass, name: str = None):
assert issubclass(subclass, cls)

name = subclass.name
name = str(subclass.name).lower() if name is None else name
assert isinstance(name, str)

if name in cls.gate_classes:
raise ValueError(f"Name {name} already exists.")
cls.gate_classes[name] = subclass
Instruction.register_ins(subclass, name)

@classmethod
def register(cls, name: str = None):
def wrapper(subclass):
cls.register_gate(subclass, name)
return subclass

return wrapper

def __str__(self):
properties_names = ['pos', 'paras', 'matrix']
properties_values = [getattr(self, x) for x in properties_names]
Expand Down
80 changes: 80 additions & 0 deletions tests/quafu/instruction/gates_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import unittest

from numpy import pi

import quafu.elements as qe
import quafu.elements.element_gates as qeg
import quafu.elements.element_gates.rotation


class TestGate(unittest.TestCase):
def test_instances(self):
gate_classes = qe.QuantumGate.gate_classes

# Paulis
x = qeg.XGate(pos=0)
y = qeg.YGate(pos=0)
z = qeg.ZGate(pos=0)
i = qeg.IdGate(pos=0)
w = qeg.WGate(pos=0)
sw = qeg.SWGate(pos=0)
swdg = qeg.SWdgGate(pos=0)
sx = qeg.SXGate(pos=0)
sxdg = qeg.SXdgGate(pos=0)
sy = qeg.SYGate(pos=0)
sydg = qeg.SYdgGate(pos=0)

# Clifford
h = qeg.HGate(pos=0)
s = qeg.SGate(pos=0)
sdg = qeg.SdgGate(pos=0)
t = qeg.TGate(pos=0)
tdg = qeg.TdgGate(pos=0)

# Rotation
ph = quafu.elements.element_gates.rotation.PhaseGate(pos=0, paras=pi)
rx = qeg.RXGate(pos=0, paras=pi)
ry = qeg.RYGate(pos=0, paras=pi)
rz = qeg.RZGate(pos=0, paras=pi)
rxx = qeg.RXXGate(q1=0, q2=3, paras=pi)
ryy = qeg.RYYGate(q1=0, q2=3, paras=pi)
rzz = qeg.RZZGate(q1=0, q2=3, paras=pi)

# Swap
swap = qeg.SwapGate(q1=0, q2=3)
iswap = qeg.ISwapGate(q1=0, q2=3)
fredkin = qeg.FredkinGate(ctrl=0, targ1=1, targ2=2)

# Control
cx = qeg.CXGate(ctrl=0, targ=1)
cy = qeg.CYGate(ctrl=0, targ=1)
cz = qeg.CZGate(ctrl=0, targ=1)
cs = qeg.CSGate(ctrl=0, targ=1)
ct = qeg.CTGate(ctrl=0, targ=1)
cp = qeg.CPGate(ctrl=0, targ=1, paras=pi)
mcx = qeg.MCXGate(ctrls=[0, 1, 2], targ=3)
mcy = qeg.MCYGate(ctrls=[0, 1, 2], targ=3)
mcz = qeg.MCZGate(ctrls=[0, 1, 2], targ=3)
toffoli = qeg.ToffoliGate(ctrl1=0, ctrl2=1, targ=2)

all_gates = [x, y, z, i, w, sw, swdg, sx, sxdg, sy, sydg,
h, s, sdg, t, tdg,
ph, rx, ry, rz, rxx, ryy, rzz, swap, iswap, fredkin, cx, cy, cz, cs, ct, cp, mcx, mcy, mcz,
toffoli]
self.assertEqual(len(all_gates), len(gate_classes))
for gate in all_gates:
self.assertIn(gate.name.lower(), gate_classes)

# TODO: test plots
# for gate in all_gates:
# print(gate.name)
# qc = QuantumCircuit(4)
# qc.add_gate(gate)
# qc.measure()
# qc.plot_circuit(title=gate.__class__.__name__)
# plt.savefig('./icons/%s.png' % gate.name, dpi=400, transparent=True)
# plt.close()


if __name__ == '__main__':
unittest.main()

0 comments on commit ac37a75

Please sign in to comment.