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: Unpickling an AbstractInstruction will result in an AbstractInstruction instead of a quil Instruction #1801

Merged
merged 8 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
64 changes: 63 additions & 1 deletion pyquil/quilbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@
Callable,
ClassVar,
Optional,
TypeVar,
Union,
)

import numpy as np
from deprecated.sphinx import deprecated
from typing_extensions import Self
from typing_extensions import Self, Type

from pyquil.quilatom import (
Expression,
Expand Down Expand Up @@ -104,6 +105,22 @@ def __hash__(self) -> int:
return hash(str(self))


_T = TypeVar("_T", bound=type)


def _add_reduce_method(cls: _T) -> _T:
def __reduce__(self: Any) -> tuple[Callable[[Any], AbstractInstruction], tuple[Any]]:
init_fn, args = super(self, cls).__reduce__()
obj = init_fn(*args)
return (
_convert_to_py_instruction,
(obj,),
)

cls.__reduce__ = __reduce__ # type: ignore
return cls


def _convert_to_rs_instruction(instr: Union[AbstractInstruction, quil_rs.Instruction]) -> quil_rs.Instruction:
if isinstance(instr, quil_rs.Instruction):
return instr
Expand Down Expand Up @@ -319,6 +336,7 @@ def _convert_to_py_instructions(instrs: Iterable[quil_rs.Instruction]) -> list[A
]


@_add_reduce_method
class Gate(quil_rs.Gate, AbstractInstruction):
"""A quantum gate instruction."""

Expand Down Expand Up @@ -488,6 +506,7 @@ def _strip_modifiers(gate: Gate, limit: Optional[int] = None) -> Gate:
return stripped


@_add_reduce_method
class Measurement(quil_rs.Measurement, AbstractInstruction):
"""A Quil measurement instruction."""

Expand Down Expand Up @@ -565,6 +584,7 @@ def __deepcopy__(self, memo: dict) -> "Measurement":
return Measurement._from_rs_measurement(super().__deepcopy__(memo))


@_add_reduce_method
class Reset(quil_rs.Reset, AbstractInstruction):
"""The RESET instruction."""

Expand Down Expand Up @@ -644,6 +664,7 @@ def _from_rs_reset(cls, reset: quil_rs.Reset) -> "ResetQubit":
raise ValueError("reset.qubit should not be None")


@_add_reduce_method
class DefGate(quil_rs.GateDefinition, AbstractInstruction):
"""A DEFGATE directive."""

Expand Down Expand Up @@ -840,6 +861,7 @@ def __str__(self) -> str:
return super().to_quil_or_debug()


@_add_reduce_method
class JumpTarget(quil_rs.Label, AbstractInstruction):
"""Representation of a target that can be jumped to."""

Expand Down Expand Up @@ -872,6 +894,7 @@ def __deepcopy__(self, memo: dict) -> "JumpTarget":
return JumpTarget._from_rs_label(super().__deepcopy__(memo))


@_add_reduce_method
class JumpWhen(quil_rs.JumpWhen, AbstractInstruction):
"""The JUMP-WHEN instruction."""

Expand Down Expand Up @@ -923,6 +946,7 @@ def __deepcopy__(self, memo: dict) -> "JumpWhen":
return JumpWhen._from_rs_jump_when(super().__deepcopy__(memo))


@_add_reduce_method
class JumpUnless(quil_rs.JumpUnless, AbstractInstruction):
"""The JUMP-UNLESS instruction."""

Expand Down Expand Up @@ -1011,6 +1035,7 @@ class Nop(SimpleInstruction):
instruction = quil_rs.Instruction.new_nop()


@_add_reduce_method
class UnaryClassicalInstruction(quil_rs.UnaryLogic, AbstractInstruction):
"""Base class for unary classical instructions."""

Expand Down Expand Up @@ -1061,6 +1086,7 @@ class ClassicalNot(UnaryClassicalInstruction):
op = quil_rs.UnaryOperator.Not


@_add_reduce_method
class LogicalBinaryOp(quil_rs.BinaryLogic, AbstractInstruction):
"""Base class for binary logical classical instructions."""

Expand Down Expand Up @@ -1142,6 +1168,7 @@ class ClassicalExclusiveOr(LogicalBinaryOp):
op = quil_rs.BinaryOperator.Xor


@_add_reduce_method
class ArithmeticBinaryOp(quil_rs.Arithmetic, AbstractInstruction):
"""Base class for binary arithmetic classical instructions."""

Expand Down Expand Up @@ -1216,6 +1243,7 @@ class ClassicalDiv(ArithmeticBinaryOp):
op = quil_rs.ArithmeticOperator.Divide


@_add_reduce_method
class ClassicalMove(quil_rs.Move, AbstractInstruction):
"""The MOVE instruction."""

Expand Down Expand Up @@ -1259,6 +1287,7 @@ def __deepcopy__(self, memo: dict) -> "ClassicalMove":
return ClassicalMove._from_rs_move(super().__deepcopy__(memo))


@_add_reduce_method
class ClassicalExchange(quil_rs.Exchange, AbstractInstruction):
"""The EXCHANGE instruction."""

Expand Down Expand Up @@ -1306,6 +1335,7 @@ def __deepcopy__(self, memo: dict) -> "ClassicalExchange":
return ClassicalExchange._from_rs_exchange(super().__deepcopy__(memo))


@_add_reduce_method
class ClassicalConvert(quil_rs.Convert, AbstractInstruction):
"""The CONVERT instruction."""

Expand Down Expand Up @@ -1349,6 +1379,7 @@ def __deepcopy__(self, memo: dict) -> "ClassicalConvert":
return ClassicalConvert._from_rs_convert(super().__deepcopy__(memo))


@_add_reduce_method
class ClassicalLoad(quil_rs.Load, AbstractInstruction):
"""The LOAD instruction."""

Expand Down Expand Up @@ -1420,6 +1451,7 @@ def _to_py_arithmetic_operand(operand: quil_rs.ArithmeticOperand) -> Union[Memor
return inner


@_add_reduce_method
class ClassicalStore(quil_rs.Store, AbstractInstruction):
"""The STORE instruction."""

Expand Down Expand Up @@ -1473,6 +1505,7 @@ def __deepcopy__(self, memo: dict) -> "ClassicalStore":
return ClassicalStore._from_rs_store(super().__deepcopy__(memo))


@_add_reduce_method
class ClassicalComparison(quil_rs.Comparison, AbstractInstruction):
"""Base class for ternary comparison instructions."""

Expand Down Expand Up @@ -1588,6 +1621,7 @@ class ClassicalGreaterEqual(ClassicalComparison):
op = quil_rs.ComparisonOperator.GreaterThanOrEqual


@_add_reduce_method
class Jump(quil_rs.Jump, AbstractInstruction):
"""Representation of an unconditional jump instruction (JUMP)."""

Expand Down Expand Up @@ -1624,6 +1658,7 @@ def __deepcopy__(self, memo: dict) -> "Jump":
return Jump._from_rs_jump(super().__deepcopy__(memo))


@_add_reduce_method
class Pragma(quil_rs.Pragma, AbstractInstruction):
"""A PRAGMA instruction.

Expand Down Expand Up @@ -1712,6 +1747,7 @@ def __deepcopy__(self, memo: dict) -> "Pragma":
return Pragma._from_rs_pragma(super().__deepcopy__(memo))


@_add_reduce_method
class Declare(quil_rs.Declaration, AbstractInstruction):
"""A DECLARE directive.

Expand Down Expand Up @@ -1838,6 +1874,7 @@ def __deepcopy__(self, memo: dict) -> "Declare":
return Declare._from_rs_declaration(super().__deepcopy__(memo))


@_add_reduce_method
class Include(quil_rs.Include, AbstractInstruction):
"""An INCLUDE directive."""

Expand All @@ -1859,6 +1896,7 @@ def __deepcopy__(self, memo: dict) -> "Include":
return Include._from_rs_include(super().__deepcopy__(memo))


@_add_reduce_method
class Pulse(quil_rs.Pulse, AbstractInstruction):
"""A PULSE instruction."""

Expand Down Expand Up @@ -1926,6 +1964,7 @@ def __deepcopy__(self, memo: dict) -> "Pulse":
return Pulse._from_rs_pulse(super().__deepcopy__(memo))


@_add_reduce_method
class SetFrequency(quil_rs.SetFrequency, AbstractInstruction):
"""A SET-FREQUENCY instruction."""

Expand Down Expand Up @@ -1983,6 +2022,7 @@ def __deepcopy__(self, memo: dict) -> "SetFrequency":
return SetFrequency._from_rs_set_frequency(super().__deepcopy__(memo))


@_add_reduce_method
class ShiftFrequency(quil_rs.ShiftFrequency, AbstractInstruction):
"""The SHIFT-FREQUENCY instruction."""

Expand Down Expand Up @@ -2040,6 +2080,7 @@ def __deepcopy__(self, memo: dict) -> "ShiftFrequency":
return ShiftFrequency._from_rs_shift_frequency(super().__deepcopy__(memo))


@_add_reduce_method
class SetPhase(quil_rs.SetPhase, AbstractInstruction):
"""The SET-PHASE instruction."""

Expand Down Expand Up @@ -2097,6 +2138,7 @@ def __deepcopy__(self, memo: dict) -> "SetPhase":
return SetPhase._from_rs_set_phase(super().__deepcopy__(memo))


@_add_reduce_method
class ShiftPhase(quil_rs.ShiftPhase, AbstractInstruction):
"""The SHIFT-PHASE instruction."""

Expand Down Expand Up @@ -2154,6 +2196,7 @@ def __deepcopy__(self, memo: dict) -> "ShiftPhase":
return ShiftPhase._from_rs_shift_phase(super().__deepcopy__(memo))


@_add_reduce_method
class SwapPhases(quil_rs.SwapPhases, AbstractInstruction):
"""The SWAP-PHASES instruction."""

Expand Down Expand Up @@ -2211,6 +2254,7 @@ def __deepcopy__(self, memo: dict) -> "SwapPhases":
return SwapPhases._from_rs_swap_phases(super().__deepcopy__(memo))


@_add_reduce_method
class SetScale(quil_rs.SetScale, AbstractInstruction):
"""The SET-SCALE instruction."""

Expand Down Expand Up @@ -2268,6 +2312,7 @@ def __deepcopy__(self, memo: dict) -> "SetScale":
return SetScale._from_rs_set_scale(super().__deepcopy__(memo))


@_add_reduce_method
class Capture(quil_rs.Capture, AbstractInstruction):
"""The CAPTURE instruction."""

Expand Down Expand Up @@ -2352,6 +2397,7 @@ def __deepcopy__(self, memo: dict) -> "Capture":
return Capture._from_rs_capture(super().__deepcopy__(memo))


@_add_reduce_method
class RawCapture(quil_rs.RawCapture, AbstractInstruction):
"""The RAW-CAPTURE instruction."""

Expand Down Expand Up @@ -2440,6 +2486,7 @@ def __deepcopy__(self, memo: dict) -> "RawCapture":
return RawCapture._from_rs_raw_capture(super().__deepcopy__(memo))


@_add_reduce_method
class Delay(quil_rs.Delay, AbstractInstruction):
"""The DELAY instruction."""

Expand Down Expand Up @@ -2534,6 +2581,7 @@ def _from_rs_delay(cls, delay: quil_rs.Delay) -> "DelayQubits":
return Delay._from_rs_delay.__func__(cls, delay) # type: ignore


@_add_reduce_method
class Fence(quil_rs.Fence, AbstractInstruction):
"""The FENCE instruction."""

Expand Down Expand Up @@ -2579,6 +2627,7 @@ def __new__(cls) -> Self:
return super().__new__(cls, [])


@_add_reduce_method
class DefWaveform(quil_rs.WaveformDefinition, AbstractInstruction):
"""A waveform definition."""

Expand Down Expand Up @@ -2637,6 +2686,7 @@ def __deepcopy__(self, memo: dict) -> "DefWaveform":
return DefWaveform._from_rs_waveform_definition(super().__deepcopy__(memo))


@_add_reduce_method
class DefCircuit(quil_rs.CircuitDefinition, AbstractInstruction):
"""A circuit definition."""

Expand Down Expand Up @@ -2707,6 +2757,7 @@ def __deepcopy__(self, memo: dict) -> "DefCircuit":
return DefCircuit._from_rs_circuit_definition(super().__deepcopy__(memo))


@_add_reduce_method
class DefCalibration(quil_rs.Calibration, AbstractInstruction):
"""A calibration definition."""

Expand Down Expand Up @@ -2789,6 +2840,7 @@ def __deepcopy__(self, memo: dict) -> "DefCalibration":
return DefCalibration._from_rs_calibration(super().__deepcopy__(memo))


@_add_reduce_method
class DefMeasureCalibration(quil_rs.MeasureCalibrationDefinition, AbstractInstruction):
"""A measure calibration definition."""

Expand Down Expand Up @@ -2843,6 +2895,15 @@ def instrs(self) -> list[AbstractInstruction]:
def instrs(self, instrs: list[AbstractInstruction]) -> None:
quil_rs.MeasureCalibrationDefinition.instructions.__set__(self, _convert_to_rs_instructions(instrs)) # type: ignore[attr-defined] # noqa

@property # type: ignore[override]
def instructions(self) -> list[AbstractInstruction]:
"""The instructions in the calibration."""
return self.instrs

@instructions.setter
def instructions(self, instructions: list[AbstractInstruction]) -> None:
self.instrs = instructions

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this include work from #1799 then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, it's based on the branch from #1799, so the commit with that fix is included here. I'll squash & merge #1799 first so we get two distinct changelog entries for the fix.

def out(self) -> str:
"""Return the instruction as a valid Quil string."""
return super().to_quil()
Expand All @@ -2857,6 +2918,7 @@ def __deepcopy__(self, memo: dict) -> "DefMeasureCalibration":
return DefMeasureCalibration._from_rs_measure_calibration_definition(super().__deepcopy__(memo))


@_add_reduce_method
class DefFrame(quil_rs.FrameDefinition, AbstractInstruction):
"""A frame definition."""

Expand Down
Loading
Loading