Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unifying interfaces after iqcs merging #136

Closed
wants to merge 12 commits into from
12 changes: 4 additions & 8 deletions quafu/circuits/quantum_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,15 +182,11 @@ def layered_circuit(self) -> np.ndarray:
gateQlist = [[] for i in range(num)]
used_qubits = []
for gate in gatelist:
if (
isinstance(gate, SingleQubitGate)
or isinstance(gate, Delay)
or isinstance(gate, QuantumPulse)
):
gateQlist[gate.pos].append(gate)
if len(gate.pos) == 1:
p = gate.pos[0]
gateQlist[p].append(gate)
if gate.pos not in used_qubits:
used_qubits.append(gate.pos)

elif (
isinstance(gate, Barrier)
or isinstance(gate, MultiQubitGate)
Expand All @@ -202,7 +198,7 @@ def layered_circuit(self) -> np.ndarray:
for j in range(pos1 + 1, pos2 + 1):
gateQlist[j].append(None)

if isinstance(gate, MultiQubitGate) or isinstance(gate, XYResonance):
if isinstance(gate, (MultiQubitGate, XYResonance)):
for pos in gate.pos:
if pos not in used_qubits:
used_qubits.append(pos)
Expand Down
45 changes: 35 additions & 10 deletions quafu/elements/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,62 @@
# limitations under the License.

from abc import ABC, abstractmethod
from typing import Dict, List, Optional, Union
from typing import Dict, List, Optional, Union, Any

from .parameters import ParameterType

__all__ = ["Instruction", "Barrier", "Measure", "PosType", "Reset"]

PosType = Union[int, List[int]]
PosType = Union[int] # TODO: include qubits


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.
pos: Qubit position(s) list of the instruction on the circuit.
paras: Parameter list of the instruction.

Properties:
symbol: Text symbolic representation of this gate.

Functions:
register_gate: Register a new gate class.
to_qasm: Convert this gate to QASM format.
update_paras: Update the parameters of this gate.

"""

ins_classes = {}

def __init__(
self,
pos: PosType,
pos: Union[PosType, List[PosType]],
paras: Optional[Union[ParameterType, List[ParameterType]]] = None,
*args,
**kwargs,
):
self.__init_pos__(pos)
self.__init_paras__(paras)
self._symbol = None

def __init_pos__(self, pos: Any):
"""If pos is not a list of PoseType objects, make it so."""
if isinstance(pos, PosType):
pos = [pos]
elif not isinstance(pos, List):
raise ValueError('pos must be in PoseType or a list of PoseType objects')
self.pos = pos

def __init_paras__(self, paras: Any):
"""If paras is not a list of ParameterType objects, make it so."""
if paras is None:
paras = []
elif not isinstance(paras, List):
if not isinstance(paras, ParameterType):
raise ValueError('paras must be in ParameterType or a list of ParameterType objects')
paras = [paras]
self.paras = paras
self._symbol = None

@property
@abstractmethod
Expand Down Expand Up @@ -95,6 +121,7 @@ def to_qasm(self):
pass


@Instruction.register('barrier')
class Barrier(Instruction):
"""
Barrier instruction.
Expand Down Expand Up @@ -137,6 +164,7 @@ def to_qasm(self):
)


@Instruction.register('reset')
class Reset(Instruction):
name = "reset"

Expand Down Expand Up @@ -168,6 +196,7 @@ def to_qasm(self):
)


@Instruction.register('measure')
class Measure(Instruction):
"""
Measure instruction.
Expand Down Expand Up @@ -195,7 +224,3 @@ def to_qasm(self):
]
qasm = "".join(lines)
return qasm


Instruction.register_ins(Barrier)
Instruction.register_ins(Measure)
15 changes: 13 additions & 2 deletions quafu/elements/oracle.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,19 @@ def named_paras(self) -> Dict:
return self._named_pos

def to_qasm(self):
# TODO: this is similar to QuantumCircuit.to_qasm
raise NotImplemented
if len(self.gate_structure) > 0:
return super().to_qasm()
else:
# TODO: decompose matrix in a Just-In-Time style
raise NotImplemented

@property
def circuit(self):
from quafu import QuantumCircuit
qc = QuantumCircuit(self.qubit_num)
for gate in self.insides:
qc.add_gate(gate)
return qc

def __instantiate_gates__(self) -> None:
"""
Expand Down
32 changes: 13 additions & 19 deletions quafu/elements/quantum_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@


import copy
from abc import ABC, abstractmethod
from abc import ABC
from typing import Callable, Dict, Iterable, List, Optional, Union

import numpy as np
Expand Down Expand Up @@ -61,26 +61,22 @@ class QuantumGate(Instruction, ABC):
"""Base class for standard and combined quantum gates, namely unitary operation
upon quantum states.

Attributes:
pos: Position of this gate in the circuit.
paras: Parameters of this gate.

Properties:
symbol: Text symbolic representation of this gate.
matrix: Matrix representation of this gate.

Functions:
register_gate: Register a new gate class.
to_qasm: Convert this gate to QASM format.
update_paras: Update the parameters of this gate.

see docstring of Instruction for other members.
"""

gate_classes = {}

def __init__(
self,
pos: PosType,
pos: Union[PosType, List[PosType]],
paras: Optional[Union[ParameterType, List[ParameterType]]] = None,
matrix: Optional[Union[ndarray, Callable]] = None,
):
Expand Down Expand Up @@ -160,14 +156,17 @@ def symbol(self, symbol: str):
self._symbol = symbol

@property
@abstractmethod
def matrix(self):
if self._matrix is not None:
def matrix(self) -> ndarray:
"""Return numpy.ndarray matrix representation, real-time updated with parameters, if any."""
if isinstance(self._matrix, ndarray):
return self._matrix
elif isinstance(self._matrix, Callable):
paras = [float(p) for p in self.paras] # TODO: check that if float() is well supported
return self._matrix(paras)
else:
raise NotImplementedError(
"Matrix is not implemented for %s" % self.__class__.__name__
+ ", this should never happen."
+ ". This should never happen, please report it on our github page."
)

def to_qasm(self) -> str:
Expand Down Expand Up @@ -370,8 +369,8 @@ class ControlledGate(MultiQubitGate):
def __init__(
self,
targ_name: str,
ctrls: PosType,
targs: PosType,
ctrls: Union[PosType, List[PosType]],
targs: Union[PosType, List[PosType]],
paras: Optional[Union[ParameterType, List[ParameterType]]] = None,
tar_matrix: MatrixType = None,
):
Expand Down Expand Up @@ -408,11 +407,6 @@ def symbol(self):
def symbol(self, symbol):
self._symbol = symbol

@property
def matrix(self):
# TODO: update matrix when paras of controlled-gate changed
return self._matrix

@property
def ct_nums(self):
targ_num = len(self.targs)
Expand All @@ -423,7 +417,7 @@ def ct_nums(self):
@property
def targ_matrix(self):
if isinstance(self._targ_matrix, Callable):
return self._targ_matrix(self.paras)
return self._targ_matrix(*self.paras)
else:
return self._targ_matrix

Expand Down
Loading