Commit 0ab10b7e authored by Daniel J. Weigand's avatar Daniel J. Weigand Committed by Tobias Bonsen
Browse files

Fix repr collisions

parent fdcc3b0b
Loading
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -3,6 +3,10 @@
## Unreleased

### Breaking changes
- Operations - Prevent collisions by changing logic for checking Operation uniqueness to use `Operation.hash` instead of `str(Operation)`. (!738, #209)
  - `Operation.hash` now returns `str` rather than `int`.
  - `str(Operation)` is no longer required to be unique (except with the ZI backend).
  - `schedule.operations.keys()` can no longer be used to get a repr of the Operations.
- Qblox backend - Make q1asm generation functions `acquire_append` and `acquire_average` private. (!739)

### Merged branches and closed issues
+25 −2
Original line number Diff line number Diff line
@@ -1089,6 +1089,25 @@ def generate_hardware_config( # noqa: PLR0912, PLR0915
    return hardware_config


def _get_operations_by_repr(schedule: Schedule) -> dict[str, Operation]:
    operations_dict_with_repr_keys = {
        str(op): op for op in schedule.operations.values()
    }
    if len(schedule.operations) != len(operations_dict_with_repr_keys):
        all_reprs = set()
        colliding_ops = []
        for operation in schedule.operations.values():
            repr_key = str(operation)
            if repr_key in all_reprs:
                colliding_ops.append(operation)
            all_reprs.add(repr_key)
        raise ValueError(
            "Multiple operations with different content have the same repr."
            f"Colliding operations are {colliding_ops}."
        )
    return operations_dict_with_repr_keys


def compile_backend(
    schedule: Schedule,
    config: CompilationConfig | dict[str, Any] | None = None,
@@ -1217,8 +1236,12 @@ def compile_backend(
    for dev in devices:
        device_dict[dev.name] = dev

    operations_dict_with_repr_keys = _get_operations_by_repr(schedule)

    numerical_wf_dict = construct_waveform_table(
        timing_table, operations_dict=schedule.operations, device_dict=device_dict
        timing_table,
        operations_dict=operations_dict_with_repr_keys,
        device_dict=device_dict,
    )

    ################################################
@@ -1260,7 +1283,7 @@ def compile_backend(
                timing_table=timing_table,
                numerical_wf_dict=numerical_wf_dict,
                repetitions=schedule.repetitions,
                operations=schedule.operations,
                operations=operations_dict_with_repr_keys,
                bin_mode=bin_mode,
            )

+2 −2
Original line number Diff line number Diff line
@@ -49,9 +49,9 @@ class Rxy(Operation):

        # this solves an issue where different rotations with the same rotation angle
        # modulo a full period are treated as distinct operations in the OperationDict
        theta = (theta + 180) % 360 - 180
        theta = round((theta + 180) % 360 - 180, 8)

        phi = phi % 360
        phi = round(phi % 360, 8)

        tex = r"$R_{xy}^{" + f"{theta:.0f}, {phi:.0f}" + r"}$"
        plot_func = (
+5 −3
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ class Operation(JSONSchemaValMixin, UserDict):
        self._update()

    def __hash__(self) -> int:
        return self.hash
        return make_hash(self.data)

    def _update(self) -> None:
        """Update the Operation's internals."""
@@ -142,11 +142,13 @@ class Operation(JSONSchemaValMixin, UserDict):
        return self._duration

    @property
    def hash(self) -> int:
    def hash(self) -> str:
        """
        A hash based on the contents of the Operation.

        Needs to be a str for easy compatibility with json.
        """
        return make_hash(self.data)
        return str(hash(self))

    @classmethod
    def _get_signature(cls, parameters: dict) -> str:
+3 −0
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ class ReferenceMagnitude:

        return cls(value, unit)

    def __hash__(self):
        return hash((self.value, self.unit))


class ShiftClockPhase(Operation):
    """
Loading