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

Fix Channel.__hash__ in multiprocessing contexts #11251

Merged
merged 2 commits into from
Nov 15, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions qiskit/pulse/channels.py
Original file line number Diff line number Diff line change
@@ -96,7 +96,6 @@ def __init__(self, index: int):
"""
self._validate_index(index)
self._index = index
self._hash = hash((self.__class__.__name__, self._index))

@property
def index(self) -> Union[int, ParameterExpression]:
@@ -156,7 +155,7 @@ def __eq__(self, other: "Channel") -> bool:
return type(self) is type(other) and self._index == other._index

def __hash__(self):
return self._hash
return hash((type(self), self._index))


class PulseChannel(Channel, metaclass=ABCMeta):
5 changes: 1 addition & 4 deletions qiskit/pulse/instructions/instruction.py
Original file line number Diff line number Diff line change
@@ -53,7 +53,6 @@ def __init__(
"""
self._operands = operands
self._name = name
self._hash = None
self._validate()

def _validate(self):
@@ -301,9 +300,7 @@ def __eq__(self, other: "Instruction") -> bool:
return isinstance(other, type(self)) and self.operands == other.operands

def __hash__(self) -> int:
if self._hash is None:
self._hash = hash((type(self), self.operands, self.name))
return self._hash
return hash((type(self), self.operands, self.name))

def __add__(self, other):
"""Return a new schedule with `other` inserted within `self` at `start_time`.
43 changes: 18 additions & 25 deletions qiskit/pulse/model/frames.py
Original file line number Diff line number Diff line change
@@ -33,28 +33,6 @@ class Frame(ABC):
The default initial phase for every frame is 0.
"""

def __init__(self, identifier):
"""Create ``Frame``.

Args:
identifier: A unique identifier used to hash the Frame.
"""
self._hash = hash((type(self), identifier))

def __eq__(self, other: "Frame") -> bool:
"""Return True iff self and other are equal, specifically, iff they have the same type and hash.

Args:
other: The frame to compare to this one.

Returns:
True iff equal.
"""
return type(self) is type(other) and self._hash == other._hash

def __hash__(self) -> int:
return self._hash


class GenericFrame(Frame):
"""Pulse module GenericFrame.
@@ -74,7 +52,6 @@ def __init__(self, name: str):
name: A unique identifier used to identify the frame.
"""
self._name = name
super().__init__(name)

@property
def name(self) -> str:
@@ -84,6 +61,12 @@ def name(self) -> str:
def __repr__(self) -> str:
return f"GenericFrame({self._name})"

def __eq__(self, other):
return type(self) is type(other) and self._name == other._name

def __hash__(self):
return hash((type(self), self._name))


class QubitFrame(Frame):
"""A frame associated with the driving of a qubit.
@@ -102,7 +85,6 @@ def __init__(self, index: int):
"""
self._validate_index(index)
self._index = index
super().__init__("QubitFrame" + str(index))

@property
def index(self) -> int:
@@ -122,6 +104,12 @@ def _validate_index(self, index) -> None:
def __repr__(self) -> str:
return f"QubitFrame({self._index})"

def __eq__(self, other):
return type(self) is type(other) and self._index == other._index

def __hash__(self):
return hash((type(self), self._index))


class MeasurementFrame(Frame):
"""A frame associated with the measurement of a qubit.
@@ -141,7 +129,6 @@ def __init__(self, index: int):
"""
self._validate_index(index)
self._index = index
super().__init__("MeasurementFrame" + str(index))

@property
def index(self) -> int:
@@ -160,3 +147,9 @@ def _validate_index(self, index) -> None:

def __repr__(self) -> str:
return f"MeasurementFrame({self._index})"

def __eq__(self, other):
return type(self) is type(other) and self._index == other._index

def __hash__(self):
return hash((type(self), self._index))
3 changes: 1 addition & 2 deletions qiskit/pulse/model/mixed_frames.py
Original file line number Diff line number Diff line change
@@ -47,7 +47,6 @@ def __init__(self, pulse_target: PulseTarget, frame: Frame):
"""
self._pulse_target = pulse_target
self._frame = frame
self._hash = hash((self._pulse_target, self._frame, type(self)))

@property
def pulse_target(self) -> PulseTarget:
@@ -75,4 +74,4 @@ def __eq__(self, other: "MixedFrame") -> bool:
return self._pulse_target == other._pulse_target and self._frame == other._frame

def __hash__(self) -> int:
return self._hash
return hash((self._pulse_target, self._frame, type(self)))
14 changes: 6 additions & 8 deletions qiskit/pulse/model/pulse_target.py
Original file line number Diff line number Diff line change
@@ -59,7 +59,6 @@ def __init__(self, name: str):
name: A string identifying the port.
"""
self._name = name
self._hash = hash((name, type(self)))

@property
def name(self) -> str:
@@ -78,12 +77,12 @@ def __eq__(self, other: "Port") -> bool:
"""
return type(self) is type(other) and self._name == other._name

def __hash__(self) -> int:
return hash((self._name, type(self)))

def __repr__(self) -> str:
return f"Port({self._name})"

def __hash__(self) -> int:
return self._hash


class LogicalElement(PulseTarget, ABC):
"""Base class of logical elements.
@@ -104,7 +103,6 @@ def __init__(self, index: Tuple[int, ...]):
"""
self._validate_index(index)
self._index = index
self._hash = hash((index, type(self)))

@property
def index(self) -> Tuple[int, ...]:
@@ -132,13 +130,13 @@ def __eq__(self, other: "LogicalElement") -> bool:
"""
return type(self) is type(other) and self._index == other._index

def __hash__(self) -> int:
return hash((self._index, type(self)))

def __repr__(self) -> str:
ind_str = str(self._index) if len(self._index) > 1 else f"({self._index[0]})"
return type(self).__name__ + ind_str

def __hash__(self) -> int:
return self._hash


class Qubit(LogicalElement):
"""Qubit logical element.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
Fixed the :func:`hash` of Qiskit Pulse ``Channel`` objects (such as :class:`.DriveChannel`) in
cases where the channel was transferred from one Python process to another that used a different
hash seed.