-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
035cea1
commit f6604d3
Showing
4 changed files
with
202 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from abc import ABC, abstractmethod | ||
from typing import Dict | ||
from dataclasses import field | ||
from quam.core import quam_dataclass, QuamComponent | ||
from quam.components.pulses import Pulse | ||
|
||
|
||
@quam_dataclass | ||
class SingleQubitGate(QuamComponent, ABC): | ||
@property | ||
def qubit(self): | ||
from ..qubit import Qubit | ||
|
||
if isinstance(self.parent, Qubit): | ||
return self.parent | ||
elif hasattr(self.parent, "parent") and isinstance(self.parent.parent, Qubit): | ||
return self.parent.parent | ||
else: | ||
raise AttributeError( | ||
"SingleQubitGate is not attached to a qubit. 1Q_gate: {self}" | ||
) | ||
|
||
def __call__(self): | ||
self.execute() | ||
|
||
@abstractmethod | ||
def execute(self, *args, **kwargs): # TODO Accomodate differing arguments | ||
pass | ||
|
||
|
||
@quam_dataclass | ||
class SinglePulseGate(SingleQubitGate): | ||
"""Single-qubit gate for a qubit consisting of a single pulse""" | ||
|
||
pulse_label: str | ||
|
||
def execute(self, amplitude_scale=None, duration=None): | ||
self.qubit.xy.play( # TODO Introduce a "play" method to the qubit | ||
self.pulse_label, amplitude_scale=amplitude_scale, duration=duration | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
from abc import ABC, abstractmethod | ||
from typing import Dict | ||
from dataclasses import field | ||
from copy import copy | ||
|
||
from quam.components.pulses import Pulse | ||
from quam.core import quam_dataclass, QuamComponent | ||
from quam.utils import string_reference as str_ref | ||
|
||
|
||
__all__ = ["TwoQubitGate", "CZGate"] | ||
|
||
|
||
@quam_dataclass | ||
class TwoQubitGate(QuamComponent, ABC): | ||
@property | ||
def qubit_pair(self): | ||
from ..qubit_pair import QubitPair | ||
|
||
if isinstance(self.parent, QubitPair): | ||
return self.parent | ||
elif hasattr(self.parent, "parent") and isinstance( | ||
self.parent.parent, QubitPair | ||
): | ||
return self.parent.parent | ||
else: | ||
raise AttributeError( | ||
"TwoQubitGate is not attached to a QubitPair. 2Q_gate: {self}" | ||
) | ||
|
||
@property | ||
def qubit_control(self): | ||
return self.qubit_pair.qubit_control | ||
|
||
@property | ||
def qubit_target(self): | ||
return self.qubit_pair.qubit_target | ||
|
||
def __call__(self): | ||
self.execute() | ||
|
||
|
||
@quam_dataclass | ||
class CZGate(TwoQubitGate): | ||
"""CZ Operation for a qubit pair""" | ||
|
||
# Pulses will be added to qubit elements | ||
# The reason we don't add "flux_to_q1" directly to q1.z is because it is part of | ||
# the CZ operation, i.e. it is only applied as part of a CZ operation | ||
|
||
flux_pulse_control: Pulse | ||
|
||
phase_shift_control: float = 0.0 | ||
phase_shift_target: float = 0.0 | ||
|
||
@property | ||
def gate_label(self) -> str: | ||
try: | ||
return self.parent.get_attr_name(self) | ||
except AttributeError: | ||
return "CZ" | ||
|
||
@property | ||
def flux_pulse_control_label(self) -> str: | ||
if self.flux_pulse_control.id is not None: | ||
pulse_label = self.flux_pulse_control.id | ||
else: | ||
pulse_label = "flux_pulse_control" | ||
|
||
return f"{self.gate_label}{str_ref.DELIMITER}{pulse_label}" | ||
|
||
def execute(self, amplitude_scale=None): | ||
self.qubit_control.z.play( | ||
self.flux_pulse_control_label, | ||
validate=False, | ||
amplitude_scale=amplitude_scale, | ||
) | ||
self.qubit_control.align(self.qubit_target) | ||
|
||
|
||
self.qubit_control.xy.frame_rotation(self.phase_shift_control) | ||
self.qubit_target.xy.frame_rotation(self.phase_shift_target) | ||
self.qubit_control.align(self.qubit_target) | ||
|
||
@property | ||
def config_settings(self): | ||
return {"after": [self.qubit_control.z]} | ||
|
||
def apply_to_config(self, config: dict) -> None: | ||
pulse = copy(self.flux_pulse_control) | ||
pulse.id = self.flux_pulse_control_label | ||
pulse.parent = None # Reset parent so it can be attached to new parent | ||
pulse.parent = self.qubit_control.z | ||
|
||
if self.flux_pulse_control_label in self.qubit_control.z.operations: | ||
raise ValueError( | ||
"Pulse name already exists in pulse operations. " | ||
f"Channel: {self.qubit_control.z.get_reference()}, " | ||
f"Pulse: {self.flux_pulse_control.get_reference()}, " | ||
f"Pulse name: {self.flux_pulse_control_label}" | ||
) | ||
|
||
pulse.apply_to_config(config) | ||
|
||
element_config = config["elements"][self.qubit_control.z.name] | ||
element_config["operations"][self.flux_pulse_control_label] = pulse.pulse_name |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from typing import Dict, Any | ||
from dataclasses import field | ||
|
||
from quam.core import quam_dataclass, QuamComponent | ||
from .gates.single_qubit_gates import SingleQubitGate | ||
from .gates.two_qubit_gates import TwoQubitGate | ||
|
||
|
||
__all__ = ["Qubit"] | ||
|
||
|
||
@quam_dataclass | ||
class Qubit(QuamComponent): | ||
id: str | ||
gates: Dict[str, SingleQubitGate] = field(default_factory=dict) | ||
|
||
def __matmul__(self, other): | ||
"""Allows access to qubit pairs using the '@' operator, e.g. (q1 @ q2)""" | ||
if not isinstance(other, Qubit): | ||
raise ValueError( | ||
"Cannot create a qubit pair (q1 @ q2) with a non-qubit object, " | ||
f"where q1={self} and q2={other}" | ||
) | ||
|
||
if self is other: | ||
raise ValueError( | ||
"Cannot create a qubit pair with same qubit (q1 @ q1), where q1={self}" | ||
) | ||
|
||
if not hasattr(self._root, "qubit_pairs"): | ||
raise AttributeError( | ||
"Qubit pairs not found in the root component. " | ||
"Please add a 'qubit_pairs' attribute to the root component." | ||
) | ||
|
||
for qubit_pair in self._root.qubit_pairs: | ||
if qubit_pair.qubit_control is self and qubit_pair.qubit_target is other: | ||
return qubit_pair | ||
else: | ||
raise ValueError( | ||
"Qubit pair not found: qubit_control={self.name}, " | ||
"qubit_target={other.name}" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from typing import Dict | ||
from dataclasses import field | ||
|
||
from quam.core import quam_dataclass, QuamComponent | ||
from quam.components.qubit import Qubit | ||
from quam.components.gates.two_qubit_gates import TwoQubitGate | ||
|
||
|
||
@quam_dataclass | ||
class QubitPair(QuamComponent): | ||
qubit_control: Qubit # TODO Discuss alternatives to "control" and "target" | ||
qubit_target: Qubit | ||
gates: Dict[str, TwoQubitGate] = field(default_factory=dict) |