From 3c6a8c59a1c20c0ae72b81ea0aaa2053ca63139a Mon Sep 17 00:00:00 2001 From: chensgit169 Date: Fri, 22 Sep 2023 16:27:13 +0800 Subject: [PATCH] restructure quantum element module, enhance docstrings --- doc/source/apiref/apiref_0.3.5.rst | 16 +++- src/quafu/circuits/quantum_circuit.py | 17 +++- .../element_gates/matrices/mat_lib.py | 4 + .../elements/quantum_element/__init__.py | 6 +- .../elements/quantum_element/instruction.py | 77 +++++++++------ .../{pulses/quantum_pulse.py => pulses.py} | 38 ++++++++ .../quantum_element/pulses/__init__.py | 11 --- .../quantum_element/quantum_element.py | 93 ------------------- .../elements/quantum_element/quantum_gate.py | 4 + 9 files changed, 132 insertions(+), 134 deletions(-) rename src/quafu/elements/quantum_element/{pulses/quantum_pulse.py => pulses.py} (86%) delete mode 100644 src/quafu/elements/quantum_element/pulses/__init__.py delete mode 100644 src/quafu/elements/quantum_element/quantum_element.py diff --git a/doc/source/apiref/apiref_0.3.5.rst b/doc/source/apiref/apiref_0.3.5.rst index 019330e..8aed751 100644 --- a/doc/source/apiref/apiref_0.3.5.rst +++ b/doc/source/apiref/apiref_0.3.5.rst @@ -5,16 +5,30 @@ API Reference This page is still under refinement, the contents you see may be incomplete at present. +Quantum Circuit +------------------ .. autoclass:: quafu.QuantumCircuit :members: cnot, add_gate, barrier :undoc-members: add_pulse -.. autoclass:: quafu.User +Quantum Elements +------------------ +.. hint:: + hello + +.. autoclass:: quafu.elements.quantum_element.Instruction :members: + +Task and User +------------------ + .. autoclass:: quafu.Task :members: config, send, retrieve +.. autoclass:: quafu.User + :members: + .. autoclass:: quafu.results.results.Result :members: diff --git a/src/quafu/circuits/quantum_circuit.py b/src/quafu/circuits/quantum_circuit.py index c14e67c..4d72462 100644 --- a/src/quafu/circuits/quantum_circuit.py +++ b/src/quafu/circuits/quantum_circuit.py @@ -17,7 +17,7 @@ import numpy as np import quafu.elements.element_gates as qeg -from quafu.elements.quantum_element.pulses.quantum_pulse import QuantumPulse +from quafu.elements.quantum_element.pulses import QuantumPulse from ..elements.quantum_element import ( Barrier, Delay, @@ -51,6 +51,9 @@ def used_qubits(self) -> List: return self._used_qubits def add_gate(self, gate: QuantumGate): + """ + Add quantum gate to circuit, with some checking. + """ pos = np.array(gate.pos) if np.any(pos >= self.num): raise CircuitError(f"Gate position out of range: {gate.pos}") @@ -570,6 +573,9 @@ def cnot(self, ctrl: int, tar: int) -> "QuantumCircuit": return self def cx(self, ctrl: int, tar: int) -> "QuantumCircuit": + """ + Ally of cnot. + """ return self.cnot(ctrl=ctrl, tar=tar) def cy(self, ctrl: int, tar: int) -> "QuantumCircuit": @@ -597,6 +603,7 @@ def cz(self, ctrl: int, tar: int) -> "QuantumCircuit": def cs(self, ctrl: int, tar: int) -> "QuantumCircuit": """ Control-S gate. + Args: ctrl (int): control qubit. tar (int): target qubit. @@ -607,6 +614,7 @@ def cs(self, ctrl: int, tar: int) -> "QuantumCircuit": def ct(self, ctrl: int, tar: int) -> "QuantumCircuit": """ Control-T gate. + Args: ctrl (int): control qubit. tar (int): target qubit. @@ -700,6 +708,7 @@ def delay(self, pos, duration, unit="ns") -> "QuantumCircuit": def xy(self, qs: int, qe: int, duration: int, unit: str = "ns") -> "QuantumCircuit": """ XY resonance time evolution for quantum simulator + Args: qs: start position of resonant qubits. qe: end position of resonant qubits. @@ -713,6 +722,7 @@ def xy(self, qs: int, qe: int, duration: int, unit: str = "ns") -> "QuantumCircu def rxx(self, q1: int, q2: int, theta): """ Rotation about 2-qubit XX axis. + Args: q1 (int): qubit the gate act. q2 (int): qubit the gate act. @@ -724,6 +734,7 @@ def rxx(self, q1: int, q2: int, theta): def ryy(self, q1: int, q2: int, theta): """ Rotation about 2-qubit YY axis. + Args: q1 (int): qubit the gate act. q2 (int): qubit the gate act. @@ -735,6 +746,7 @@ def ryy(self, q1: int, q2: int, theta): def rzz(self, q1: int, q2: int, theta): """ Rotation about 2-qubit ZZ axis. + Args: q1 (int): qubit the gate act. q2 (int): qubit the gate act. @@ -746,6 +758,7 @@ def rzz(self, q1: int, q2: int, theta): def mcx(self, ctrls: List[int], targ: int): """ Multi-controlled X gate. + Args: ctrls: A list of control qubits. targ: Target qubits. @@ -755,6 +768,7 @@ def mcx(self, ctrls: List[int], targ: int): def mcy(self, ctrls: List[int], targ: int): """ Multi-controlled Y gate. + Args: ctrls: A list of control qubits. targ: Target qubits. @@ -764,6 +778,7 @@ def mcy(self, ctrls: List[int], targ: int): def mcz(self, ctrls: List[int], targ: int): """ Multi-controlled Z gate. + Args: ctrls: A list of control qubits. targ: Target qubits. diff --git a/src/quafu/elements/element_gates/matrices/mat_lib.py b/src/quafu/elements/element_gates/matrices/mat_lib.py index b40ebec..d9fb60c 100644 --- a/src/quafu/elements/element_gates/matrices/mat_lib.py +++ b/src/quafu/elements/element_gates/matrices/mat_lib.py @@ -1,5 +1,9 @@ import numpy as np +""" +Matrices library for quantum gates. +""" + IdMatrix = np.eye(2, dtype=complex) XMatrix = np.array([[0., 1.], [1., 0.]], dtype=complex) YMatrix = np.array([[0., -1.j], [1.j, 0.]], dtype=complex) diff --git a/src/quafu/elements/quantum_element/__init__.py b/src/quafu/elements/quantum_element/__init__.py index 7dd3936..a24e913 100644 --- a/src/quafu/elements/quantum_element/__init__.py +++ b/src/quafu/elements/quantum_element/__init__.py @@ -1,4 +1,6 @@ -from .quantum_element import Barrier, Delay, XYResonance, Measure +from .instruction import Instruction, Barrier, Measure +from .pulses import Delay, XYResonance + from .quantum_gate import QuantumGate, SingleQubitGate, MultiQubitGate, \ ParaSingleQubitGate, ParaMultiQubitGate, ControlledGate, FixedSingleQubitGate, FixedMultiQubitGate -from .instruction import Instruction + diff --git a/src/quafu/elements/quantum_element/instruction.py b/src/quafu/elements/quantum_element/instruction.py index e431121..a90e8a6 100644 --- a/src/quafu/elements/quantum_element/instruction.py +++ b/src/quafu/elements/quantum_element/instruction.py @@ -16,16 +16,30 @@ from typing import Union, List +__all__ = ['Instruction', 'Barrier', 'Measure', 'PosType', 'ParaType'] + PosType = Union[int, List[int]] -ParaType = Union[float, int] +ParaType = Union[float, int, List] class Instruction(ABC): + """Base class for ALL the possible instructions on Quafu superconducting quantum circuits. + + Attributes: + pos: Qubit position(s) of the instruction on the circuit. + paras: Parameters of the instruction. + + """ ins_classes = {} + def __init__(self, pos: PosType, paras: ParaType = None, *args, **kwargs): + self.pos = pos + self.paras = paras + @property @abstractmethod def name(self) -> str: + """Name of the instruction.""" raise NotImplementedError('name is not implemented for %s' % self.__class__.__name__ + ', this should never happen.') @@ -44,32 +58,43 @@ def register_ins(cls, subclass, name: str = None): raise ValueError(f"Name {name} already exists.") cls.ins_classes[name] = subclass - def __init__(self, pos: PosType, paras: ParaType = None, *args, **kwargs): - self.pos = pos - self.paras = paras - # @_ins_id.setter - # def sd_name(self, name: str): - # if self.sd_name is None: - # self.sd_name = name - # else: - # import warnings - # warnings.warn(message='Invalid assignment, names of standard ' - # 'instructions are not alterable.') - - # def to_dag_node(self): - # name = self.get_ins_id() - # label = self.__repr__() - # - # pos = self.pos - # paras = self.paras - # paras = {} if paras is None else paras - # duration = paras.get('duration', None) - # unit = paras.get('unit', None) - # channel = paras.get('channel', None) - # time_func = paras.get('time_func', None) - # - # return InstructionNode(name, pos, paras, duration, unit, channel, time_func, label) +class Barrier(Instruction): + """ + Barrier instruction. + """ + name = "barrier" + + def __init__(self, pos): + super().__init__(pos) + self.symbol = "||" + + @property + def pos(self): + return self.__pos + + @pos.setter + def pos(self, pos): + self.__pos = pos + + def __repr__(self): + return f"{self.__class__.__name__}" + + def to_qasm(self): + return "barrier " + ",".join(["q[%d]" % p for p in range(min(self.pos), max(self.pos) + 1)]) + + +class Measure(Instruction): + """ + Measure instruction. + """ + name = "measure" + def __init__(self, bitmap: dict): + super().__init__(list(bitmap.keys())) + self.qbits = bitmap.keys() + self.cbits = bitmap.values() +Instruction.register_ins(Barrier) +Instruction.register_ins(Measure) diff --git a/src/quafu/elements/quantum_element/pulses/quantum_pulse.py b/src/quafu/elements/quantum_element/pulses.py similarity index 86% rename from src/quafu/elements/quantum_element/pulses/quantum_pulse.py rename to src/quafu/elements/quantum_element/pulses.py index 1ed07c0..1a8994a 100644 --- a/src/quafu/elements/quantum_element/pulses/quantum_pulse.py +++ b/src/quafu/elements/quantum_element/pulses.py @@ -231,6 +231,44 @@ def __call__(self, return super().__call__(t, shift, offset, args) +class Delay(Instruction): + name = "delay" + + def __init__(self, pos: int, duration: int, unit="ns"): + if isinstance(duration, int): + self.duration = duration + else: + raise TypeError("duration must be int") + super().__init__(pos) + self.unit = unit + self.symbol = "Delay(%d%s)" % (duration, unit) + + def __repr__(self): + return f"{self.__class__.__name__}" + + def to_qasm(self): + return "delay(%d%s) q[%d]" % (self.duration, self.unit, self.pos) + + +class XYResonance(Instruction): + name = "XY" + + def __init__(self, qs: int, qe: int, duration: int, unit="ns"): + if isinstance(duration, int): + self.duration = duration + else: + raise TypeError("duration must be int") + super().__init__(list(range(qs, qe + 1))) + self.unit = unit + self.symbol = "XY(%d%s)" % (duration, unit) + + def to_qasm(self): + return "xy(%d%s) " % (self.duration, self.unit) + ",".join( + ["q[%d]" % p for p in range(min(self.pos), max(self.pos) + 1)]) + + QuantumPulse.register_pulse(RectPulse) QuantumPulse.register_pulse(FlattopPulse) QuantumPulse.register_pulse(GaussianPulse) +Instruction.register_ins(Delay) +Instruction.register_ins(XYResonance) diff --git a/src/quafu/elements/quantum_element/pulses/__init__.py b/src/quafu/elements/quantum_element/pulses/__init__.py deleted file mode 100644 index 34be485..0000000 --- a/src/quafu/elements/quantum_element/pulses/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# !/usr/bin/env python -# -*- coding:utf-8 -*- - -# @File: __init__.py.py -# @Version: 1.0 -# @Author: Yun-Hao Shi -# @Email: yhshi@iphy.ac.cn -# @Reminders: |0> has been in the past, |1> is still in the future -# @License: Copyright (c) 2023, IOP, CAS - -from .quantum_pulse import QuantumPulse diff --git a/src/quafu/elements/quantum_element/quantum_element.py b/src/quafu/elements/quantum_element/quantum_element.py deleted file mode 100644 index f182fbe..0000000 --- a/src/quafu/elements/quantum_element/quantum_element.py +++ /dev/null @@ -1,93 +0,0 @@ -# (C) Copyright 2023 Beijing Academy of Quantum Information Sciences -# -# 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 quafu.elements.quantum_element.instruction import Instruction - -""" -Base classes for ALL kinds of possible instructions on superconducting -quantum circuits. -""" - - -class Barrier(Instruction): - name = "barrier" - - def __init__(self, pos): - super().__init__(pos) - self.symbol = "||" - - @property - def pos(self): - return self.__pos - - @pos.setter - def pos(self, pos): - self.__pos = pos - - def __repr__(self): - return f"{self.__class__.__name__}" - - def to_qasm(self): - return "barrier " + ",".join(["q[%d]" % p for p in range(min(self.pos), max(self.pos) + 1)]) - - -class Delay(Instruction): - name = "delay" - - def __init__(self, pos: int, duration: int, unit="ns"): - if isinstance(duration, int): - self.duration = duration - else: - raise TypeError("duration must be int") - super().__init__(pos) - self.unit = unit - self.symbol = "Delay(%d%s)" % (duration, unit) - - def __repr__(self): - return f"{self.__class__.__name__}" - - def to_qasm(self): - return "delay(%d%s) q[%d]" % (self.duration, self.unit, self.pos) - - -class XYResonance(Instruction): - name = "XY" - - def __init__(self, qs: int, qe: int, duration: int, unit="ns"): - if isinstance(duration, int): - self.duration = duration - else: - raise TypeError("duration must be int") - super().__init__(list(range(qs, qe + 1))) - self.unit = unit - self.symbol = "XY(%d%s)" % (duration, unit) - - def to_qasm(self): - return "xy(%d%s) " % (self.duration, self.unit) + ",".join( - ["q[%d]" % p for p in range(min(self.pos), max(self.pos) + 1)]) - - -class Measure(Instruction): - name = "measure" - - def __init__(self, bitmap: dict): - super().__init__(list(bitmap.keys())) - self.qbits = bitmap.keys() - self.cbits = bitmap.values() - - -Instruction.register_ins(Barrier) -Instruction.register_ins(Delay) -Instruction.register_ins(XYResonance) -Instruction.register_ins(Measure) diff --git a/src/quafu/elements/quantum_element/quantum_gate.py b/src/quafu/elements/quantum_element/quantum_gate.py index 38e64a3..d4f2c55 100644 --- a/src/quafu/elements/quantum_element/quantum_gate.py +++ b/src/quafu/elements/quantum_element/quantum_gate.py @@ -17,6 +17,8 @@ def reorder_matrix(matrix: np.ndarray, pos: List): class QuantumGate(Instruction): + """Base class for standard and combined quantum gates. + """ gate_classes = {} def __init__(self, @@ -76,6 +78,7 @@ def to_qasm(self): return qstr +# gate types class SingleQubitGate(QuantumGate, ABC): def __init__(self, pos: int, paras: float = None): super().__init__(pos, paras=paras) @@ -130,6 +133,7 @@ def __init__(self, pos, paras): super().__init__(pos, paras) +# controlled gate types class ControlledGate(MultiQubitGate, ABC): """ Controlled gate class, where the matrix act non-trivaly on target qubits"""