Source code for pyquil.quilbase

##############################################################################
# Copyright 2016-2018 Rigetti Computing
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
##############################################################################
"""Contains the core pyQuil objects that correspond to Quil instructions."""

import abc
from collections.abc import Container, Iterable, Sequence
from typing import (
    TYPE_CHECKING,
    Any,
    Callable,
    ClassVar,
    Optional,
    TypeVar,
    Union,
)

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

from pyquil.quilatom import (
    Expression,
    FormalArgument,
    Frame,
    Label,
    LabelPlaceholder,
    MemoryReference,
    Parameter,
    ParameterDesignator,
    Qubit,
    QubitDesignator,
    QubitPlaceholder,
    Waveform,
    _convert_to_py_expression,
    _convert_to_py_expressions,
    _convert_to_py_qubit,
    _convert_to_py_qubits,
    _convert_to_py_waveform,
    _convert_to_rs_expression,
    _convert_to_rs_expressions,
    _convert_to_rs_qubit,
    _convert_to_rs_qubits,
    unpack_qubit,
)

if TYPE_CHECKING:  # avoids circular import
    from pyquil.paulis import PauliSum

import quil.expression as quil_rs_expr
import quil.instructions as quil_rs


class _InstructionMeta(abc.ABCMeta):
    """A metaclass that allows us to group all instruction types from quil-rs and pyQuil as an `AbstractInstruction`.

    As such, this should _only_ be used as a metaclass for `AbstractInstruction`.
    """

    def __init__(self, *args: Any, **_: Any):
        self.__name = args[0]
        try:
            self.__is_abstract_instruction = args[1][0] == AbstractInstruction
        except Exception:
            self.__is_abstract_instruction = False

    def __instancecheck__(self, __instance: Any) -> bool:
        # Already an Instruction, return True
        if isinstance(__instance, quil_rs.Instruction):
            return True

        # __instance is not an Instruction or AbstractInstruction, return False
        if self.__name not in ["AbstractInstruction", "DefGate"] and not self.__is_abstract_instruction:
            return False

        # __instance is a subclass of AbstractInstruction, do the normal check
        return super().__instancecheck__(__instance)


[docs] class AbstractInstruction(metaclass=_InstructionMeta): """Abstract class for representing single instructions.""" def __str__(self) -> str: return self.__repr__() def __eq__(self, other: object) -> bool: return isinstance(other, self.__class__) and str(self) == str(other) def __ne__(self, other: object) -> bool: return not self.__eq__(other) 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(cls, self).__reduce__() # type: ignore 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 if isinstance(instr, quil_rs.Arithmetic): return quil_rs.Instruction.from_arithmetic(instr) if isinstance(instr, quil_rs.BinaryLogic): return quil_rs.Instruction.from_binary_logic(instr) if isinstance(instr, quil_rs.Call): return quil_rs.Instruction.from_call(instr) if isinstance(instr, quil_rs.Capture): return quil_rs.Instruction.from_capture(instr) if isinstance(instr, quil_rs.CircuitDefinition): return quil_rs.Instruction.from_circuit_definition(instr) if isinstance(instr, quil_rs.Calibration): return quil_rs.Instruction.from_calibration_definition(instr) if isinstance(instr, quil_rs.Convert): return quil_rs.Instruction.from_convert(instr) if isinstance(instr, quil_rs.Declaration): return quil_rs.Instruction.from_declaration(instr) if isinstance(instr, quil_rs.Delay): return quil_rs.Instruction.from_delay(instr) if isinstance(instr, quil_rs.Exchange): return quil_rs.Instruction.from_exchange(instr) if isinstance(instr, quil_rs.Fence): return quil_rs.Instruction.from_fence(instr) if isinstance(instr, quil_rs.FrameDefinition): return quil_rs.Instruction.from_frame_definition(instr) if isinstance(instr, quil_rs.Gate): return quil_rs.Instruction.from_gate(instr) if isinstance(instr, quil_rs.GateDefinition): return quil_rs.Instruction.from_gate_definition(instr) if isinstance(instr, Halt): return quil_rs.Instruction.new_halt() if isinstance(instr, Include): return quil_rs.Instruction.from_include(instr) if isinstance(instr, quil_rs.Load): return quil_rs.Instruction.from_load(instr) if isinstance(instr, quil_rs.MeasureCalibrationDefinition): return quil_rs.Instruction.from_measure_calibration_definition(instr) if isinstance(instr, quil_rs.Measurement): return quil_rs.Instruction.from_measurement(instr) if isinstance(instr, Nop): return quil_rs.Instruction.new_nop() if isinstance(instr, quil_rs.Pragma): return quil_rs.Instruction.from_pragma(instr) if isinstance(instr, quil_rs.Pulse): return quil_rs.Instruction.from_pulse(instr) if isinstance(instr, quil_rs.RawCapture): return quil_rs.Instruction.from_raw_capture(instr) if isinstance(instr, quil_rs.Reset): return quil_rs.Instruction.from_reset(instr) if isinstance(instr, quil_rs.SetFrequency): return quil_rs.Instruction.from_set_frequency(instr) if isinstance(instr, quil_rs.SetPhase): return quil_rs.Instruction.from_set_phase(instr) if isinstance(instr, quil_rs.SetScale): return quil_rs.Instruction.from_set_scale(instr) if isinstance(instr, quil_rs.ShiftFrequency): return quil_rs.Instruction.from_shift_frequency(instr) if isinstance(instr, quil_rs.ShiftPhase): return quil_rs.Instruction.from_shift_phase(instr) if isinstance(instr, quil_rs.SwapPhases): return quil_rs.Instruction.from_swap_phases(instr) if isinstance(instr, quil_rs.Store): return quil_rs.Instruction.from_store(instr) if isinstance(instr, Wait): return quil_rs.Instruction.new_wait() if isinstance(instr, quil_rs.WaveformDefinition): return quil_rs.Instruction.from_waveform_definition(instr) if isinstance(instr, quil_rs.Label): return quil_rs.Instruction.from_label(instr) if isinstance(instr, quil_rs.Move): return quil_rs.Instruction.from_move(instr) if isinstance(instr, quil_rs.Jump): return quil_rs.Instruction.from_jump(instr) if isinstance(instr, quil_rs.JumpWhen): return quil_rs.Instruction.from_jump_when(instr) if isinstance(instr, quil_rs.JumpUnless): return quil_rs.Instruction.from_jump_unless(instr) if isinstance(instr, quil_rs.UnaryLogic): return quil_rs.Instruction.from_unary_logic(instr) if isinstance(instr, quil_rs.Comparison): return quil_rs.Instruction.from_comparison(instr) raise ValueError(f"{type(instr)} is not an Instruction") def _convert_to_rs_instructions(instrs: Iterable[AbstractInstruction]) -> list[quil_rs.Instruction]: return [_convert_to_rs_instruction(instr) for instr in instrs] def _convert_to_py_instruction(instr: Any) -> AbstractInstruction: if isinstance(instr, quil_rs.Instruction): if instr.is_nop(): return Nop() if instr.is_halt(): return Halt() if instr.is_wait(): return Wait() return _convert_to_py_instruction(instr.inner()) if isinstance(instr, quil_rs.Arithmetic): return ArithmeticBinaryOp._from_rs_arithmetic(instr) if isinstance(instr, quil_rs.BinaryLogic): return LogicalBinaryOp._from_rs_binary_logic(instr) if isinstance(instr, quil_rs.Calibration): return DefCalibration._from_rs_calibration(instr) if isinstance(instr, quil_rs.Call): return Call._from_rs_call(instr) if isinstance(instr, quil_rs.Capture): return Capture._from_rs_capture(instr) if isinstance(instr, quil_rs.CircuitDefinition): return DefCircuit._from_rs_circuit_definition(instr) if isinstance(instr, quil_rs.Convert): return ClassicalConvert._from_rs_convert(instr) if isinstance(instr, quil_rs.Comparison): return ClassicalComparison._from_rs_comparison(instr) if isinstance(instr, quil_rs.Declaration): return Declare._from_rs_declaration(instr) if isinstance(instr, quil_rs.Delay): if len(instr.frame_names) > 0: return DelayFrames._from_rs_delay(instr) if len(instr.qubits) > 0: return DelayQubits._from_rs_delay(instr) return Delay._from_rs_delay(instr) if isinstance(instr, quil_rs.Exchange): return ClassicalExchange._from_rs_exchange(instr) if isinstance(instr, quil_rs.Fence): if len(instr.qubits) == 0: return FenceAll() return Fence._from_rs_fence(instr) if isinstance(instr, quil_rs.FrameDefinition): return DefFrame._from_rs_frame_definition(instr) if isinstance(instr, quil_rs.GateDefinition): return DefGate._from_rs_gate_definition(instr) if isinstance(instr, quil_rs.Gate): return Gate._from_rs_gate(instr) if isinstance(instr, quil_rs.Include): return Include._from_rs_include(instr) if isinstance(instr, quil_rs.Jump): return Jump._from_rs_jump(instr) if isinstance(instr, quil_rs.JumpWhen): return JumpWhen._from_rs_jump_when(instr) if isinstance(instr, quil_rs.JumpUnless): return JumpUnless._from_rs_jump_unless(instr) if isinstance(instr, quil_rs.Label): return JumpTarget._from_rs_label(instr) if isinstance(instr, quil_rs.Load): return ClassicalLoad._from_rs_load(instr) if isinstance(instr, quil_rs.MeasureCalibrationDefinition): return DefMeasureCalibration._from_rs_measure_calibration_definition(instr) if isinstance(instr, quil_rs.Measurement): return Measurement._from_rs_measurement(instr) if isinstance(instr, quil_rs.Move): return ClassicalMove._from_rs_move(instr) if isinstance(instr, quil_rs.Pragma): return Pragma._from_rs_pragma(instr) if isinstance(instr, quil_rs.Pulse): return Pulse._from_rs_pulse(instr) if isinstance(instr, quil_rs.RawCapture): return RawCapture._from_rs_raw_capture(instr) if isinstance(instr, quil_rs.Reset): if instr.qubit is None: return Reset._from_rs_reset(instr) else: return ResetQubit._from_rs_reset(instr) if isinstance(instr, quil_rs.SetFrequency): return SetFrequency._from_rs_set_frequency(instr) if isinstance(instr, quil_rs.SetPhase): return SetPhase._from_rs_set_phase(instr) if isinstance(instr, quil_rs.SetScale): return SetScale._from_rs_set_scale(instr) if isinstance(instr, quil_rs.ShiftFrequency): return ShiftFrequency._from_rs_shift_frequency(instr) if isinstance(instr, quil_rs.ShiftPhase): return ShiftPhase._from_rs_shift_phase(instr) if isinstance(instr, quil_rs.SwapPhases): return SwapPhases._from_rs_swap_phases(instr) if isinstance(instr, quil_rs.Store): return ClassicalStore._from_rs_store(instr) if isinstance(instr, quil_rs.UnaryLogic): return UnaryClassicalInstruction._from_rs_unary_logic(instr) if isinstance(instr, quil_rs.WaveformDefinition): return DefWaveform._from_rs_waveform_definition(instr) if isinstance(instr, quil_rs.Instruction): raise NotImplementedError(f"The {type(instr)} Instruction hasn't been mapped to an AbstractInstruction yet.") elif isinstance(instr, AbstractInstruction): return instr raise ValueError(f"{type(instr)} is not a valid Instruction type") def _convert_to_py_instructions(instrs: Iterable[quil_rs.Instruction]) -> list[AbstractInstruction]: return [_convert_to_py_instruction(instr) for instr in instrs] RESERVED_WORDS: Container[str] = [ "DEFGATE", "DEFCIRCUIT", "MEASURE", "LABEL", "HALT", "JUMP", "JUMP-WHEN", "JUMP-UNLESS", "RESET", "WAIT", "NOP", "INCLUDE", "PRAGMA", "DECLARE", "NEG", "NOT", "AND", "IOR", "XOR", "TRUE", "FALSE", "OR", ]
[docs] @_add_reduce_method class Gate(quil_rs.Gate, AbstractInstruction): """A quantum gate instruction.""" def __new__( cls, name: str, params: Sequence[ParameterDesignator], qubits: Sequence[Union[Qubit, QubitPlaceholder, FormalArgument, int]], modifiers: Sequence[quil_rs.GateModifier] = [], ) -> Self: """Initialize a new gate instruction.""" return super().__new__( cls, name, _convert_to_rs_expressions(params), _convert_to_rs_qubits(qubits), list(modifiers) ) @classmethod def _from_rs_gate(cls, gate: quil_rs.Gate) -> Self: return super().__new__(cls, gate.name, gate.parameters, gate.qubits, gate.modifiers)
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Sequence[QubitDesignator]: """Get the qubits the gate operates on.""" if indices: return self.get_qubit_indices() else: return _convert_to_py_qubits(super().qubits)
@property # type: ignore[override] def qubits(self) -> list[QubitDesignator]: """Get the qubits the gate operates on.""" return self.get_qubits(indices=False) # type: ignore @qubits.setter def qubits(self, qubits: Sequence[Union[Qubit, QubitPlaceholder, FormalArgument]]) -> None: quil_rs.Gate.qubits.__set__(self, _convert_to_rs_qubits(qubits)) # type: ignore @property def params(self) -> Sequence[ParameterDesignator]: """Get the parameters the gate operates on.""" return _convert_to_py_expressions(super().parameters) @params.setter def params(self, params: Sequence[ParameterDesignator]) -> None: quil_rs.Gate.parameters.__set__(self, _convert_to_rs_expressions(params)) # type: ignore @property # type: ignore[override] def modifiers(self) -> list[str]: """Get all modifiers applied to the gate.""" return [str(modifier).upper() for modifier in super().modifiers] @modifiers.setter def modifiers(self, modifiers: Union[list[str], list[quil_rs.GateModifier]]) -> None: modifiers = [ self._to_rs_gate_modifier(modifier) if isinstance(modifier, str) else modifier for modifier in modifiers ] quil_rs.Gate.modifiers.__set__(self, modifiers) # type: ignore[attr-defined] def _to_rs_gate_modifier(self, modifier: str) -> quil_rs.GateModifier: modifier = modifier.upper() if modifier == "CONTROLLED": return quil_rs.GateModifier.Controlled if modifier == "DAGGER": return quil_rs.GateModifier.Dagger if modifier == "FORKED": return quil_rs.GateModifier.Forked raise ValueError(f"{modifier} is not a valid Gate modifier.")
[docs] def get_qubit_indices(self) -> list[int]: """Get the qubits the gate operates on, as integer indices.""" return [qubit.to_fixed() for qubit in super().qubits]
[docs] def controlled( self, control_qubit: Union[ quil_rs.Qubit, QubitDesignator, Sequence[Union[QubitDesignator, quil_rs.Qubit]], ], ) -> "Gate": """Add the CONTROLLED modifier to the gate with the given control qubit or Sequence of control qubits.""" if isinstance(control_qubit, Sequence): for qubit in control_qubit: self._update_super(super().controlled(_convert_to_rs_qubit(qubit))) else: self._update_super(super().controlled(_convert_to_rs_qubit(control_qubit))) return self
[docs] def forked( self, fork_qubit: Union[quil_rs.Qubit, QubitDesignator], alt_params: Union[Sequence[ParameterDesignator], Sequence[quil_rs_expr.Expression]], ) -> "Gate": """Add the FORKED modifier to the gate with the given fork qubit and given additional parameters.""" forked = super().forked(_convert_to_rs_qubit(fork_qubit), _convert_to_rs_expressions(alt_params)) self._update_super(forked) return self
[docs] def dagger(self) -> "Gate": """Add the DAGGER modifier to the gate.""" self._update_super(super().dagger()) return self
[docs] def out(self) -> str: """Return the Gate as a valid Quil string.""" return super().to_quil()
def _update_super(self, gate: quil_rs.Gate) -> None: """Update the state of the super class using a new gate. The super class does not mutate the value of a gate when adding modifiers with methods like `dagger()`, but pyQuil does. """ quil_rs.Gate.name.__set__(self, gate.name) # type: ignore[attr-defined] quil_rs.Gate.parameters.__set__(self, gate.parameters) # type: ignore[attr-defined] quil_rs.Gate.modifiers.__set__(self, gate.modifiers) # type: ignore[attr-defined] quil_rs.Gate.qubits.__set__(self, gate.qubits) # type: ignore[attr-defined] def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Gate": return Gate._from_rs_gate(super().__deepcopy__(memo))
def _strip_modifiers(gate: Gate, limit: Optional[int] = None) -> Gate: """Remove modifiers from :py:class:`Gate`. This function removes up to ``limit`` gate modifiers from the given gate, starting from the leftmost gate modifier. :param gate: A gate. :param limit: An upper bound on how many modifiers to remove. """ if limit is None: limit = len(gate.modifiers) # We walk the modifiers from left-to-right, tracking indices to identify # qubits/params introduced by gate modifiers. # # Invariants: # - gate.qubits[0:qubit_index] are qubits introduced by gate modifiers # - gate.params[param_index:] are parameters introduced by gate modifiers qubit_index = 0 param_index = len(gate.params) for m in gate.modifiers[:limit]: if m == "CONTROLLED": qubit_index += 1 elif m == "FORKED": if param_index % 2 != 0: raise ValueError("FORKED gate has an invalid number of parameters.") param_index //= 2 qubit_index += 1 elif m == "DAGGER": pass else: raise TypeError(f"Unsupported gate modifier {m}") stripped = Gate(gate.name, gate.params[:param_index], gate.qubits[qubit_index:]) stripped.modifiers = gate.modifiers[limit:] return stripped
[docs] @_add_reduce_method class Measurement(quil_rs.Measurement, AbstractInstruction): """A Quil measurement instruction.""" def __new__( cls, qubit: QubitDesignator, classical_reg: Optional[MemoryReference], ) -> Self: """Initialize a new measurement instruction.""" target = cls._reg_to_target(classical_reg) return super().__new__(cls, _convert_to_rs_qubit(qubit), target) @classmethod def _reg_to_target(cls, classical_reg: Optional[MemoryReference]) -> Optional[quil_rs.MemoryReference]: if isinstance(classical_reg, quil_rs.MemoryReference): return classical_reg if classical_reg is not None: return quil_rs.MemoryReference.parse(str(classical_reg)) return None @classmethod def _from_rs_measurement(cls, measurement: quil_rs.Measurement) -> "Measurement": return super().__new__(cls, measurement.qubit, measurement.target) @property # type: ignore[override] def qubit(self) -> QubitDesignator: """Get the qubit the instruction measures.""" return _convert_to_py_qubit(super().qubit) @qubit.setter def qubit(self, qubit: QubitDesignator) -> None: quil_rs.Measurement.qubit.__set__(self, _convert_to_rs_qubit(qubit)) # type: ignore[attr-defined] @property def classical_reg(self) -> Optional[MemoryReference]: """Get the MemoryReference that this instruction writes to, if any.""" target = super().target if target is None: return None return MemoryReference._from_rs_memory_reference(target) @classical_reg.setter def classical_reg(self, classical_reg: Optional[MemoryReference]) -> None: target = self._reg_to_target(classical_reg) quil_rs.Measurement.target.__set__(self, target) # type: ignore[attr-defined]
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Union[set[QubitDesignator], set[int]]: """Get the qubit this instruction measures.""" if indices: return self.get_qubit_indices() else: return {_convert_to_py_qubit(super().qubit)}
[docs] def get_qubit_indices(self) -> set[int]: """Get the qubit this instruction measures, as an integer index.""" return {super().qubit.to_fixed()}
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Measurement": return Measurement._from_rs_measurement(super().__deepcopy__(memo))
[docs] @_add_reduce_method class Reset(quil_rs.Reset, AbstractInstruction): """The RESET instruction.""" def __new__(cls, qubit: Optional[Union[Qubit, QubitPlaceholder, FormalArgument, int]] = None) -> Self: """Initialize a new reset instruction.""" rs_qubit: Optional[quil_rs.Qubit] = None if qubit is not None: rs_qubit = _convert_to_rs_qubit(qubit) return super().__new__(cls, rs_qubit) @classmethod def _from_rs_reset(cls, reset: quil_rs.Reset) -> "Reset": return super().__new__(cls, reset.qubit)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Optional[set[QubitDesignator]]: """Get the qubit this instruction resets.""" if super().qubit is None: return None if indices: return self.get_qubit_indices() # type: ignore return {_convert_to_py_qubit(super().qubit)} # type: ignore
[docs] def get_qubit_indices(self) -> Optional[set[int]]: """Get the qubit this instruction resets, as an integer index.""" if super().qubit is None: return None return {super().qubit.to_fixed()} # type: ignore
@property # type: ignore[override] def qubit(self) -> Optional[QubitDesignator]: """Get the qubit this instruction resets, if any.""" if super().qubit: return _convert_to_py_qubit(super().qubit) # type: ignore return None @qubit.setter def qubit(self, qubit: Optional[QubitDesignator]) -> None: rs_qubit: Optional[quil_rs.Qubit] = None if qubit is not None: rs_qubit = _convert_to_rs_qubit(qubit) quil_rs.Reset.qubit.__set__(self, rs_qubit) # type: ignore[attr-defined] def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Reset": copy = Reset._from_rs_reset(super().__deepcopy__(memo)) copy.__class__ = self.__class__ return copy
[docs] class ResetQubit(Reset): """A targeted RESET instruction.""" def __new__(cls, qubit: Union[Qubit, QubitPlaceholder, FormalArgument, int]) -> Self: """Initialize a new reset instruction, with a target qubit.""" if qubit is None: raise TypeError("qubit should not be None") return super().__new__(cls, qubit) @classmethod def _from_rs_reset(cls, reset: quil_rs.Reset) -> "ResetQubit": if reset.qubit is not None: qubit = _convert_to_py_qubit(reset.qubit) return ResetQubit.__new__(cls, qubit) raise ValueError("reset.qubit should not be None")
[docs] @_add_reduce_method class DefGate(quil_rs.GateDefinition, AbstractInstruction): """A DEFGATE directive.""" def __new__( cls, name: str, matrix: Union[list[list[Expression]], np.ndarray, np.matrix], parameters: Optional[list[Parameter]] = None, ) -> Self: """Initialize a new gate definition. :param name: The name of the newly defined gate. :param matrix: The matrix defining this gate. :param parameters: list of parameters that are used in this gate """ DefGate._validate_matrix(matrix, parameters is not None and len(parameters) > 0) specification = DefGate._convert_to_matrix_specification(matrix) rs_parameters = [param.name for param in parameters or []] return super().__new__(cls, name, rs_parameters, specification) @classmethod def _from_rs_gate_definition(cls, gate_definition: quil_rs.GateDefinition) -> Self: return super().__new__(cls, gate_definition.name, gate_definition.parameters, gate_definition.specification) @staticmethod def _convert_to_matrix_specification( matrix: Union[list[list[Expression]], np.ndarray, np.matrix], ) -> quil_rs.GateSpecification: to_rs_matrix = np.vectorize(_convert_to_rs_expression, otypes=["O"]) return quil_rs.GateSpecification.from_matrix(to_rs_matrix(np.asarray(matrix))) @staticmethod def _validate_matrix( matrix: Union[list[list[Expression]], np.ndarray, np.matrix], contains_parameters: bool ) -> None: if isinstance(matrix, list): rows = len(matrix) if not all([len(row) == rows for row in matrix]): raise ValueError("Matrix must be square.") elif isinstance(matrix, (np.ndarray, np.matrix)): rows, cols = matrix.shape if rows != cols: raise ValueError("Matrix must be square.") else: raise TypeError("Matrix argument must be a list or NumPy array/matrix") if 0 != rows & (rows - 1): raise ValueError(f"Dimension of matrix must be a power of 2, got {rows}") if not contains_parameters: np_matrix = np.asarray(matrix) is_unitary = np.allclose(np.eye(rows), np_matrix.dot(np_matrix.T.conj())) if not is_unitary: raise ValueError("Matrix must be unitary.")
[docs] def out(self) -> str: """Return the Gate as a valid Quil string.""" return super().to_quil()
[docs] def get_constructor(self) -> Union[Callable[..., Gate], Callable[..., Callable[..., Gate]]]: """Return a function that constructs this gate on variable qubit indices. For example, `mygate.get_constructor()(1) applies the gate to qubit 1.` """ if self.parameters: return lambda *params: lambda *qubits: Gate( name=self.name, params=list(params), qubits=list(map(unpack_qubit, qubits)) ) else: return lambda *qubits: Gate(name=self.name, params=[], qubits=list(map(unpack_qubit, qubits)))
[docs] def num_args(self) -> int: """Get the number of qubit arguments the gate takes.""" rows = len(self.matrix) return int(np.log2(rows))
@property def matrix(self) -> np.ndarray: """Get the matrix that defines this GateDefinition.""" to_py_matrix = np.vectorize(_convert_to_py_expression, otypes=["O"]) return to_py_matrix(np.asarray(super().specification.to_matrix())) # type: ignore[no-any-return] @matrix.setter def matrix(self, matrix: np.ndarray) -> None: quil_rs.GateDefinition.specification.__set__(self, DefGate._convert_to_matrix_specification(matrix)) # type: ignore[attr-defined] # noqa @property # type: ignore[override] def parameters(self) -> list[Parameter]: """Get the parameters this gate definition takes.""" return [Parameter(name) for name in super().parameters] @parameters.setter def parameters(self, parameters: Optional[list[Parameter]]) -> None: quil_rs.GateDefinition.parameters.__set__(self, [param.name for param in parameters or []]) # type: ignore[attr-defined] # noqa def __hash__(self) -> int: return hash(self.out()) def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "DefGate": return DefGate._from_rs_gate_definition(super().__deepcopy__(memo))
[docs] class DefPermutationGate(DefGate): """A gate defined by a permutation of numbers.""" def __new__(cls, name: str, permutation: Union[list[int], np.ndarray]) -> Self: """Initialize a new gate definition with a permutation.""" specification = DefPermutationGate._convert_to_permutation_specification(permutation) gate_definition = quil_rs.GateDefinition(name, [], specification) return super()._from_rs_gate_definition(gate_definition) @staticmethod def _convert_to_permutation_specification(permutation: Union[list[int], np.ndarray]) -> quil_rs.GateSpecification: return quil_rs.GateSpecification.from_permutation([int(x) for x in permutation]) @property def permutation(self) -> list[int]: """Get the permutation that defines the gate.""" return super().specification.to_permutation() @permutation.setter def permutation(self, permutation: list[int]) -> None: specification = DefPermutationGate._convert_to_permutation_specification(permutation) quil_rs.GateDefinition.specification.__set__(self, specification) # type: ignore[attr-defined]
[docs] def num_args(self) -> int: """Get the number of arguments the gate takes.""" return int(np.log2(len(self.permutation)))
def __str__(self) -> str: return super().to_quil_or_debug()
[docs] class DefGateByPaulis(DefGate): """A gate definition defined by the exponentiation of a PauliSum.""" def __new__( cls, gate_name: str, parameters: list[Parameter], arguments: list[QubitDesignator], body: "PauliSum", ) -> Self: """Initialize a new gate, defined by a PauliSum.""" specification = DefGateByPaulis._convert_to_pauli_specification(body, arguments) rs_parameters = [param.name for param in parameters] gate_definition = quil_rs.GateDefinition(gate_name, rs_parameters, specification) return super()._from_rs_gate_definition(gate_definition) @staticmethod def _convert_to_pauli_specification( body: "PauliSum", arguments: list[QubitDesignator] ) -> quil_rs.GateSpecification: if isinstance(body, Sequence): from pyquil.paulis import PauliSum body = PauliSum(body) return quil_rs.GateSpecification.from_pauli_sum(body._to_rs_pauli_sum(arguments)) @property def arguments(self) -> list[FormalArgument]: """Get the arguments the gate takes.""" return [FormalArgument(arg) for arg in super().specification.to_pauli_sum().arguments] @arguments.setter def arguments(self, arguments: list[QubitDesignator]) -> None: pauli_sum = super().specification.to_pauli_sum() pauli_sum.arguments = [str(arg) for arg in arguments] quil_rs.GateDefinition.specification.__set__(self, quil_rs.GateSpecification.from_pauli_sum(pauli_sum)) # type: ignore[attr-defined] # noqa @property def body(self) -> "PauliSum": """Get the PauliSum that defines the gate.""" from pyquil.paulis import PauliSum # avoids circular import return PauliSum._from_rs_pauli_sum(super().specification.to_pauli_sum()) @body.setter def body(self, body: "PauliSum") -> None: specification = quil_rs.GateSpecification.from_pauli_sum(body._to_rs_pauli_sum()) quil_rs.GateDefinition.specification.__set__(self, specification) # type: ignore[attr-defined]
[docs] def num_args(self) -> int: """Get the number of arguments the gate takes.""" return len(self.arguments)
def __str__(self) -> str: return super().to_quil_or_debug()
[docs] @_add_reduce_method class JumpTarget(quil_rs.Label, AbstractInstruction): """Representation of a target that can be jumped to.""" def __new__(cls, label: Union[Label, LabelPlaceholder]) -> Self: """Initialize a new target.""" return super().__new__(cls, label.target) @classmethod def _from_rs_label(cls, label: quil_rs.Label) -> "JumpTarget": return super().__new__(cls, label.target) @property def label(self) -> Union[Label, LabelPlaceholder]: """Get the target as a label.""" if super().target.is_placeholder(): return LabelPlaceholder._from_rs_target(super().target) return Label._from_rs_target(super().target) def __repr__(self) -> str: return f"<JumpTarget {str(self.label)}>"
[docs] def out(self) -> str: """Return the target as valid Quil. Raises an error if the target is an unresolved placeholder.""" return super().to_quil()
def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "JumpTarget": return JumpTarget._from_rs_label(super().__deepcopy__(memo))
[docs] @_add_reduce_method class JumpWhen(quil_rs.JumpWhen, AbstractInstruction): """The JUMP-WHEN instruction.""" def __new__(cls, target: Union[Label, LabelPlaceholder], condition: MemoryReference) -> Self: """Initialize a new JumpWhen instruction. :param target: The target to jump to if the condition is true. :param condition: A memory reference that determines if the jump should be performed. The memory reference must refer to an INTEGER or BIT. The jump will be performed if the value in the reference is not 0 when the instruction is evaluated. """ return super().__new__(cls, target.target, condition._to_rs_memory_reference()) @classmethod def _from_rs_jump_when(cls, jump_when: quil_rs.JumpWhen) -> Self: return super().__new__(cls, jump_when.target, jump_when.condition)
[docs] def out(self) -> str: """Return the instruction as valid Quil. Raises an error if the target is an unresolved placeholder.""" return super().to_quil()
@property # type: ignore[override] def condition(self) -> MemoryReference: """Get the MemoryReference the instruction uses to determine if the jump should be performed or not.""" return MemoryReference._from_rs_memory_reference(super().condition) @condition.setter def condition(self, condition: MemoryReference) -> None: quil_rs.JumpWhen.condition.__set__(self, condition._to_rs_memory_reference()) # type: ignore[attr-defined] @property # type: ignore[override] def target(self) -> Union[Label, LabelPlaceholder]: """Get the target the instruction will jump to if the condition bit is not 1.""" if super().target.is_placeholder(): return LabelPlaceholder._from_rs_target(super().target) return Label._from_rs_target(super().target) @target.setter def target(self, target: Union[Label, LabelPlaceholder]) -> None: quil_rs.JumpWhen.target.__set__(self, target) # type: ignore[attr-defined] def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "JumpWhen": return JumpWhen._from_rs_jump_when(super().__deepcopy__(memo))
[docs] @_add_reduce_method class JumpUnless(quil_rs.JumpUnless, AbstractInstruction): """The JUMP-UNLESS instruction.""" def __new__(cls, target: Union[Label, LabelPlaceholder], condition: MemoryReference) -> Self: """Initialize a new JumpUnless instruction. :param target: The target to jump to if the condition is true. :param condition: A memory reference that determines if the jump should be performed. The memory reference must refer to an INTEGER or BIT. The jump will be performed if the value in the reference is 0 when the instruction is evaluated. """ return super().__new__(cls, target.target, condition._to_rs_memory_reference()) @classmethod def _from_rs_jump_unless(cls, jump_unless: quil_rs.JumpUnless) -> Self: return super().__new__(cls, jump_unless.target, jump_unless.condition)
[docs] def out(self) -> str: """Return the instruction as valid Quil. Raises an error if the target is an unresolved placeholder.""" return super().to_quil()
@property # type: ignore[override] def condition(self) -> MemoryReference: """Get the MemoryReference the instruction uses to determine if the jump should be performed or not.""" return MemoryReference._from_rs_memory_reference(super().condition) @condition.setter def condition(self, condition: MemoryReference) -> None: quil_rs.JumpUnless.condition.__set__(self, condition._to_rs_memory_reference()) # type: ignore[attr-defined] @property # type: ignore[override] def target(self) -> Union[Label, LabelPlaceholder]: """Get the target the instruction will jump to if the condition bit is not 1.""" if super().target.is_placeholder(): return LabelPlaceholder._from_rs_target(super().target) return Label._from_rs_target(super().target) @target.setter def target(self, target: Union[Label, LabelPlaceholder]) -> None: quil_rs.JumpUnless.target.__set__(self, target) # type: ignore[attr-defined] def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "JumpUnless": return JumpUnless._from_rs_jump_unless(super().__deepcopy__(memo))
[docs] class SimpleInstruction(AbstractInstruction): """Base class for simple instructions with no arguments.""" instruction: ClassVar[quil_rs.Instruction]
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return self.instruction.to_quil()
def __str__(self) -> str: return self.out() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "SimpleInstruction": return self
[docs] class Halt(SimpleInstruction): """The HALT instruction.""" instruction = quil_rs.Instruction.new_halt()
[docs] class Wait(SimpleInstruction): """The WAIT instruction.""" instruction = quil_rs.Instruction.new_wait()
[docs] class Nop(SimpleInstruction): """The NOP instruction.""" instruction = quil_rs.Instruction.new_nop()
[docs] @_add_reduce_method class UnaryClassicalInstruction(quil_rs.UnaryLogic, AbstractInstruction): """Base class for unary classical instructions.""" op: ClassVar[quil_rs.UnaryOperator] def __new__(cls, target: MemoryReference) -> "UnaryClassicalInstruction": """Initialize a new unary classical instruction.""" return super().__new__(cls, cls.op, target._to_rs_memory_reference()) @classmethod def _from_rs_unary_logic(cls, unary_logic: quil_rs.UnaryLogic) -> Self: return super().__new__(cls, unary_logic.operator, unary_logic.operand) @property def target(self) -> MemoryReference: """The MemoryReference that the instruction operates on.""" return MemoryReference._from_rs_memory_reference(super().operand) @target.setter def target(self, target: MemoryReference) -> None: quil_rs.UnaryLogic.operand.__set__(self, target._to_rs_memory_reference()) # type: ignore
[docs] def out(self) -> str: """Return the instruction as a valid Quil string. Raises an error if the instruction contains placeholders.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "UnaryClassicalInstruction": copy = UnaryClassicalInstruction._from_rs_unary_logic(super().__deepcopy__(memo)) copy.__class__ = self.__class__ return copy
[docs] class ClassicalNeg(UnaryClassicalInstruction): """The NEG instruction.""" op = quil_rs.UnaryOperator.Neg
[docs] class ClassicalNot(UnaryClassicalInstruction): """The NOT instruction.""" op = quil_rs.UnaryOperator.Not
[docs] @_add_reduce_method class LogicalBinaryOp(quil_rs.BinaryLogic, AbstractInstruction): """Base class for binary logical classical instructions.""" op: ClassVar[quil_rs.BinaryOperator] def __new__(cls, left: MemoryReference, right: Union[MemoryReference, int]) -> Self: """Initialize the operands of the binary logical instruction.""" destination = left._to_rs_memory_reference() source = cls._to_rs_binary_operand(right) return super().__new__(cls, cls.op, destination, source) @classmethod def _from_rs_binary_logic(cls, binary_logic: quil_rs.BinaryLogic) -> "LogicalBinaryOp": return super().__new__(cls, binary_logic.operator, binary_logic.destination, binary_logic.source) @staticmethod def _to_rs_binary_operand(operand: Union[MemoryReference, int]) -> quil_rs.BinaryOperand: if isinstance(operand, MemoryReference): return quil_rs.BinaryOperand.from_memory_reference(operand._to_rs_memory_reference()) return quil_rs.BinaryOperand.from_literal_integer(operand) @staticmethod def _to_py_binary_operand(operand: quil_rs.BinaryOperand) -> Union[MemoryReference, int]: if operand.is_literal_integer(): return operand.to_literal_integer() return MemoryReference._from_rs_memory_reference(operand.to_memory_reference()) @property def left(self) -> MemoryReference: """The left hand side of the binary expression.""" return MemoryReference._from_rs_memory_reference(super().destination) @left.setter def left(self, left: MemoryReference) -> None: destination = left._to_rs_memory_reference() quil_rs.BinaryLogic.destination.__set__(self, destination) # type: ignore[attr-defined] @property def right(self) -> Union[MemoryReference, int]: """The right hand side of the binary expression.""" return self._to_py_binary_operand(super().source) @right.setter def right(self, right: Union[MemoryReference, int]) -> None: source = self._to_rs_binary_operand(right) quil_rs.BinaryLogic.source.__set__(self, source) # type: ignore[attr-defined]
[docs] def out(self) -> str: """Return the instruction as a valid Quil string. Raises an error if the instruction contains placeholders.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "LogicalBinaryOp": copy = LogicalBinaryOp._from_rs_binary_logic(super().__deepcopy__(memo)) copy.__class__ = self.__class__ return copy
[docs] class ClassicalAnd(LogicalBinaryOp): """The AND instruction.""" op = quil_rs.BinaryOperator.And
[docs] class ClassicalInclusiveOr(LogicalBinaryOp): """The IOR instruction.""" op = quil_rs.BinaryOperator.Ior
[docs] class ClassicalExclusiveOr(LogicalBinaryOp): """The XOR instruction.""" op = quil_rs.BinaryOperator.Xor
[docs] @_add_reduce_method class ArithmeticBinaryOp(quil_rs.Arithmetic, AbstractInstruction): """Base class for binary arithmetic classical instructions.""" op: ClassVar[quil_rs.ArithmeticOperator] def __new__(cls, left: MemoryReference, right: Union[MemoryReference, int, float]) -> Self: """Initialize the operands of the binary arithmetic instruction.""" right_operand = _to_rs_arithmetic_operand(right) return super().__new__(cls, cls.op, left._to_rs_memory_reference(), right_operand) @classmethod def _from_rs_arithmetic(cls, arithmetic: quil_rs.Arithmetic) -> "ArithmeticBinaryOp": return super().__new__(cls, arithmetic.operator, arithmetic.destination, arithmetic.source) @property def left(self) -> MemoryReference: """The left hand side of the binary expression.""" return MemoryReference._from_rs_memory_reference(super().destination) @left.setter def left(self, left: MemoryReference) -> None: quil_rs.Arithmetic.destination.__set__( # type: ignore[attr-defined] self, left._to_rs_memory_reference() ) @property def right(self) -> Union[MemoryReference, int, float]: """The left hand side of the binary expression.""" return _to_py_arithmetic_operand(super().source) @right.setter def right(self, right: Union[MemoryReference, int, float]) -> None: quil_rs.Arithmetic.source.__set__(self, _to_rs_arithmetic_operand(right)) # type: ignore[attr-defined]
[docs] def out(self) -> str: """Return the instruction as a valid Quil string. Raises an error if the instruction contains placeholders.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "ArithmeticBinaryOp": copy = ArithmeticBinaryOp._from_rs_arithmetic(super().__deepcopy__(memo)) copy.__class__ = self.__class__ return copy
[docs] class ClassicalAdd(ArithmeticBinaryOp): """The ADD instruction.""" op = quil_rs.ArithmeticOperator.Add
[docs] class ClassicalSub(ArithmeticBinaryOp): """The SUB instruction.""" op = quil_rs.ArithmeticOperator.Subtract
[docs] class ClassicalMul(ArithmeticBinaryOp): """The MUL instruction.""" op = quil_rs.ArithmeticOperator.Multiply
[docs] class ClassicalDiv(ArithmeticBinaryOp): """The DIV instruction.""" op = quil_rs.ArithmeticOperator.Divide
[docs] @_add_reduce_method class ClassicalMove(quil_rs.Move, AbstractInstruction): """The MOVE instruction.""" def __new__(cls, left: MemoryReference, right: Union[MemoryReference, int, float]) -> "ClassicalMove": """Initialize a new MOVE instruction.""" return super().__new__(cls, left._to_rs_memory_reference(), _to_rs_arithmetic_operand(right)) @classmethod def _from_rs_move(cls, move: quil_rs.Move) -> Self: return super().__new__(cls, move.destination, move.source) @property def left(self) -> MemoryReference: """The left hand side (or "destination") of the move instruction.""" return MemoryReference._from_rs_memory_reference(super().destination) @left.setter def left(self, left: MemoryReference) -> None: quil_rs.Move.destination.__set__(self, left._to_rs_memory_reference()) # type: ignore @property def right(self) -> Union[MemoryReference, int, float]: """The right hand side (or "source") of the move instruction.""" return _to_py_arithmetic_operand(super().source) @right.setter def right(self, right: Union[MemoryReference, int, float]) -> None: quil_rs.Move.source.__set__(self, _to_rs_arithmetic_operand(right)) # type: ignore
[docs] def out(self) -> str: """Return the move instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "ClassicalMove": return ClassicalMove._from_rs_move(super().__deepcopy__(memo))
[docs] @_add_reduce_method class ClassicalExchange(quil_rs.Exchange, AbstractInstruction): """The EXCHANGE instruction.""" def __new__( cls, left: MemoryReference, right: MemoryReference, ) -> "ClassicalExchange": """Initialize a new EXCHANGE instruction.""" return super().__new__(cls, left._to_rs_memory_reference(), right._to_rs_memory_reference()) @classmethod def _from_rs_exchange(cls, exchange: quil_rs.Exchange) -> Self: return super().__new__(cls, exchange.left, exchange.right) @property # type: ignore[override] def left(self) -> MemoryReference: """The left hand side of the exchange instruction.""" return MemoryReference._from_rs_memory_reference(super().left) @left.setter def left(self, left: MemoryReference) -> None: quil_rs.Exchange.left.__set__(self, left._to_rs_memory_reference()) # type: ignore @property # type: ignore[override] def right(self) -> MemoryReference: """The left hand side of the exchange instruction.""" return MemoryReference._from_rs_memory_reference(super().right) @right.setter def right(self, right: MemoryReference) -> None: quil_rs.Exchange.right.__set__(self, right._to_rs_memory_reference()) # type: ignore
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "ClassicalExchange": return ClassicalExchange._from_rs_exchange(super().__deepcopy__(memo))
[docs] @_add_reduce_method class ClassicalConvert(quil_rs.Convert, AbstractInstruction): """The CONVERT instruction.""" def __new__(cls, left: MemoryReference, right: MemoryReference) -> "ClassicalConvert": """Initialize a new CONVERT instruction.""" return super().__new__(cls, left._to_rs_memory_reference(), right._to_rs_memory_reference()) @classmethod def _from_rs_convert(cls, convert: quil_rs.Convert) -> Self: return super().__new__(cls, convert.destination, convert.source) @property def left(self) -> MemoryReference: """Return the left hand side (or "destination") of the conversion instruction.""" return MemoryReference._from_rs_memory_reference(super().destination) @left.setter def left(self, memory_reference: MemoryReference) -> None: quil_rs.Convert.destination.__set__(self, memory_reference._to_rs_memory_reference()) # type: ignore @property def right(self) -> MemoryReference: """Return the right hand side (or "source") of the conversion instruction.""" return MemoryReference._from_rs_memory_reference(super().source) @right.setter def right(self, memory_reference: MemoryReference) -> None: quil_rs.Convert.source.__set__(self, memory_reference._to_rs_memory_reference()) # type: ignore
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "ClassicalConvert": return ClassicalConvert._from_rs_convert(super().__deepcopy__(memo))
[docs] @_add_reduce_method class ClassicalLoad(quil_rs.Load, AbstractInstruction): """The LOAD instruction.""" def __new__(cls, target: MemoryReference, left: str, right: MemoryReference) -> "ClassicalLoad": """Initialize a new LOAD instruction.""" return super().__new__(cls, target._to_rs_memory_reference(), left, right._to_rs_memory_reference()) @classmethod def _from_rs_load(cls, load: quil_rs.Load) -> Self: return super().__new__(cls, load.destination, load.source, load.offset) @property def target(self) -> MemoryReference: """The MemoryReference that the instruction loads into.""" return MemoryReference._from_rs_memory_reference(super().destination) @target.setter def target(self, target: MemoryReference) -> None: quil_rs.Load.destination.__set__(self, target._to_rs_memory_reference()) # type: ignore @property def left(self) -> str: """The left hand side of the LOAD instruction.""" return super().source @left.setter def left(self, left: str) -> None: quil_rs.Load.source.__set__(self, left) # type: ignore @property def right(self) -> MemoryReference: """The right hand side of the LOAD instruction.""" return MemoryReference._from_rs_memory_reference(super().offset) @right.setter def right(self, right: MemoryReference) -> None: quil_rs.Load.offset.__set__(self, right._to_rs_memory_reference()) # type: ignore
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "ClassicalLoad": return ClassicalLoad._from_rs_load(super().__deepcopy__(memo))
def _to_rs_arithmetic_operand(operand: Union[MemoryReference, int, float]) -> quil_rs.ArithmeticOperand: if isinstance(operand, MemoryReference): return quil_rs.ArithmeticOperand.from_memory_reference(operand._to_rs_memory_reference()) if isinstance(operand, int): return quil_rs.ArithmeticOperand.from_literal_integer(operand) if isinstance(operand, float): return quil_rs.ArithmeticOperand.from_literal_real(operand) raise TypeError(f"{type(operand)} is not a valid ArithmeticOperand") def _to_py_arithmetic_operand(operand: quil_rs.ArithmeticOperand) -> Union[MemoryReference, int, float]: if not isinstance(operand, quil_rs.ArithmeticOperand): raise TypeError(f"{type(operand)} is not an ArithmeticOperand") inner = operand.inner() if isinstance(inner, quil_rs.MemoryReference): return MemoryReference._from_rs_memory_reference(inner) return inner
[docs] @_add_reduce_method class ClassicalStore(quil_rs.Store, AbstractInstruction): """The STORE instruction.""" def __new__(cls, target: str, left: MemoryReference, right: Union[MemoryReference, int, float]) -> "ClassicalStore": """Initialize a new STORE instruction.""" rs_right = _to_rs_arithmetic_operand(right) return super().__new__(cls, target, left._to_rs_memory_reference(), rs_right) @classmethod def _from_rs_store(cls, store: quil_rs.Store) -> Self: return super().__new__(cls, store.destination, store.offset, store.source) @property def target(self) -> str: """The target of the STORE instruction.""" return super().destination @target.setter def target(self, target: str) -> None: quil_rs.Store.destination.__set__(self, target) # type: ignore @property def left(self) -> MemoryReference: """The left hand side of the STORE instruction.""" return MemoryReference._from_rs_memory_reference(super().offset) @left.setter def left(self, left: MemoryReference) -> None: quil_rs.Store.offset.__set__(self, left._to_rs_memory_reference()) # type: ignore @property def right(self) -> Union[MemoryReference, int, float]: """The left hand side of the STORE instruction.""" return _to_py_arithmetic_operand(super().source) @right.setter def right(self, right: Union[MemoryReference, int, float]) -> None: quil_rs.Store.source.__set__(self, _to_rs_arithmetic_operand(right)) # type: ignore
[docs] def out(self) -> str: """Return a valid Quil string representation of the instruction.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "ClassicalStore": return ClassicalStore._from_rs_store(super().__deepcopy__(memo))
[docs] @_add_reduce_method class ClassicalComparison(quil_rs.Comparison, AbstractInstruction): """Base class for ternary comparison instructions.""" op: ClassVar[quil_rs.ComparisonOperator] def __new__( cls, target: MemoryReference, left: MemoryReference, right: Union[MemoryReference, int, float], ) -> "ClassicalComparison": """Initialize a new comparison instruction.""" rs_target, rs_left, rs_right = ( target._to_rs_memory_reference(), left._to_rs_memory_reference(), cls._to_comparison_operand(right), ) return super().__new__(cls, cls.op, rs_target, rs_left, rs_right) @classmethod def _from_rs_comparison(cls, comparison: quil_rs.Comparison) -> Self: return super().__new__(cls, comparison.operator, comparison.destination, comparison.lhs, comparison.rhs) @staticmethod def _to_comparison_operand(operand: Union[MemoryReference, int, float]) -> quil_rs.ComparisonOperand: if isinstance(operand, MemoryReference): return quil_rs.ComparisonOperand.from_memory_reference(operand._to_rs_memory_reference()) elif isinstance(operand, int): return quil_rs.ComparisonOperand.from_literal_integer(operand) elif isinstance(operand, float): return quil_rs.ComparisonOperand.from_literal_real(operand) raise TypeError(f"{type(operand)} is not a valid ComparisonOperand") @staticmethod def _to_py_operand(operand: quil_rs.ComparisonOperand) -> Union[MemoryReference, int, float]: if not isinstance(operand, quil_rs.ComparisonOperand): raise TypeError(f"{type(operand)} is not an ComparisonOperand") inner = operand.inner() if isinstance(inner, quil_rs.MemoryReference): return MemoryReference._from_rs_memory_reference(inner) return inner @property def target(self) -> MemoryReference: """The target of the comparison.""" return MemoryReference._from_rs_memory_reference(super().destination) @target.setter def target(self, target: MemoryReference) -> None: quil_rs.Comparison.destination.__set__(self, target._to_rs_memory_reference()) # type: ignore @property def left(self) -> MemoryReference: """The left hand side of the comparison.""" return MemoryReference._from_rs_memory_reference(super().lhs) @left.setter def left(self, left: MemoryReference) -> None: quil_rs.Comparison.lhs.__set__(self, left._to_rs_memory_reference()) # type: ignore @property def right(self) -> Union[MemoryReference, int, float]: """The right hand side of the comparison.""" return self._to_py_operand(super().rhs) @right.setter def right(self, right: MemoryReference) -> None: quil_rs.Comparison.rhs.__set__(self, quil_rs.ComparisonOperand(right._to_rs_memory_reference())) # type: ignore
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "ClassicalComparison": copy = ClassicalComparison._from_rs_comparison(super().__deepcopy__(memo)) copy.__class__ = self.__class__ return copy
[docs] class ClassicalEqual(ClassicalComparison): """The EQ comparison instruction.""" op = quil_rs.ComparisonOperator.Equal
[docs] class ClassicalLessThan(ClassicalComparison): """The LT comparison instruction.""" op = quil_rs.ComparisonOperator.LessThan
[docs] class ClassicalLessEqual(ClassicalComparison): """The LE comparison instruction.""" op = quil_rs.ComparisonOperator.LessThanOrEqual
[docs] class ClassicalGreaterThan(ClassicalComparison): """The GT comparison instruction.""" op = quil_rs.ComparisonOperator.GreaterThan
[docs] class ClassicalGreaterEqual(ClassicalComparison): """The GE comparison instruction.""" op = quil_rs.ComparisonOperator.GreaterThanOrEqual
[docs] @_add_reduce_method class Jump(quil_rs.Jump, AbstractInstruction): """Representation of an unconditional jump instruction (JUMP).""" def __new__(cls, target: Union[Label, LabelPlaceholder]) -> Self: """Initialize a new jump instruction.""" return super().__new__(cls, target.target) @classmethod def _from_rs_jump(cls, jump: quil_rs.Jump) -> Self: return super().__new__(cls, jump.target) @property # type: ignore[override] def target(self) -> Union[Label, LabelPlaceholder]: """Get the target of the jump.""" if super().target.is_placeholder(): return LabelPlaceholder._from_rs_target(super().target) return Label._from_rs_target(super().target) @target.setter def target(self, target: Union[Label, LabelPlaceholder]) -> None: quil_rs.Jump.target.__set__(self, target.target) # type: ignore[attr-defined]
[docs] def out(self) -> str: """Return the instruction as a valid Quil string. Raises an error if the target is an unresolved placeholder.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Jump": return Jump._from_rs_jump(super().__deepcopy__(memo))
[docs] @_add_reduce_method class Pragma(quil_rs.Pragma, AbstractInstruction): """A PRAGMA instruction. This is printed in QUIL as: PRAGMA <command> <arg1> <arg2> ... <argn> "<freeform_string>" """ def __new__( cls, command: str, args: Sequence[Union[Qubit, FormalArgument, int, str]] = (), freeform_string: str = "", ) -> Self: """Initialize a new PRAGMA instruction.""" data = freeform_string or None return super().__new__(cls, command, Pragma._to_pragma_arguments(args), data) @classmethod def _from_rs_pragma(cls, pragma: quil_rs.Pragma) -> "Pragma": return super().__new__(cls, pragma.name, pragma.arguments, pragma.data) @staticmethod def _to_pragma_arguments(args: Sequence[Union[QubitDesignator, str]]) -> list[quil_rs.PragmaArgument]: pragma_arguments = [] for arg in args: if isinstance(arg, Qubit): pragma_arguments.append(quil_rs.PragmaArgument.from_integer(arg.index)) elif isinstance(arg, int): pragma_arguments.append(quil_rs.PragmaArgument.from_integer(arg)) elif isinstance(arg, (str, FormalArgument)): pragma_arguments.append(quil_rs.PragmaArgument.from_identifier(str(arg))) else: raise TypeError(f"{type(arg)} isn't a valid PRAGMA argument") return pragma_arguments @staticmethod def _to_py_arguments(args: list[quil_rs.PragmaArgument]) -> list[QubitDesignator]: arguments: list[QubitDesignator] = [] for arg in args: if arg.is_integer(): arguments.append(Qubit(arg.to_integer())) else: arguments.append(FormalArgument(arg.to_identifier())) return arguments
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property def command(self) -> str: """Get the pragma command identifier.""" return super().name @command.setter def command(self, command: str) -> None: quil_rs.Pragma.name.__set__(self, command) # type: ignore[attr-defined] @property def args(self) -> tuple[QubitDesignator]: """Get the arguments of the PRAGMA command.""" return tuple(Pragma._to_py_arguments(super().arguments)) # type: ignore[return-value] @args.setter def args(self, args: Sequence[Union[QubitDesignator, str]]) -> None: quil_rs.Pragma.arguments.__set__(self, Pragma._to_pragma_arguments(args)) # type: ignore[attr-defined] @property def freeform_string(self) -> str: """Get the PRAGMA's freeform string.""" return super().data or "" @freeform_string.setter def freeform_string(self, freeform_string: str) -> None: quil_rs.Pragma.data.__set__(self, freeform_string) # type: ignore[attr-defined] def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Pragma": return Pragma._from_rs_pragma(super().__deepcopy__(memo))
[docs] @_add_reduce_method class Declare(quil_rs.Declaration, AbstractInstruction): """A DECLARE directive. This is printed in Quil as:: DECLARE <name> <memory-type> (SHARING <other-name> (OFFSET <amount> <type>)* )? """ def __new__( cls, name: str, memory_type: str, memory_size: int = 1, shared_region: Optional[str] = None, offsets: Optional[Sequence[tuple[int, str]]] = None, ) -> Self: """Initialize a new DECLARE directive.""" vector = quil_rs.Vector(Declare._memory_type_to_scalar_type(memory_type), memory_size) sharing = None if shared_region is not None: sharing = quil_rs.Sharing(shared_region, Declare._to_rs_offsets(offsets)) return super().__new__(cls, name, vector, sharing) @classmethod def _from_rs_declaration(cls, declaration: quil_rs.Declaration) -> "Declare": return super().__new__(cls, declaration.name, declaration.size, declaration.sharing) @staticmethod def _memory_type_to_scalar_type(memory_type: str) -> quil_rs.ScalarType: memory_type = memory_type.upper() if memory_type == "BIT": return quil_rs.ScalarType.Bit if memory_type == "INTEGER": return quil_rs.ScalarType.Integer if memory_type == "REAL": return quil_rs.ScalarType.Real if memory_type == "OCTET": return quil_rs.ScalarType.Octet raise ValueError(f"{memory_type} is not a valid scalar type.") @staticmethod def _to_rs_offsets(offsets: Optional[Sequence[tuple[int, str]]]) -> list[quil_rs.Offset]: if offsets is None: return [] return [ quil_rs.Offset(offset, Declare._memory_type_to_scalar_type(memory_type)) for offset, memory_type in offsets ] @property def memory_type(self) -> str: """Get the type of memory being declared.""" return str(super().size.data_type).upper() @memory_type.setter def memory_type(self, memory_type: str) -> None: vector = super().size vector.data_type = Declare._memory_type_to_scalar_type(memory_type) quil_rs.Declaration.size.__set__(self, vector) # type: ignore[attr-defined] @property def memory_size(self) -> int: """Get the number of elements being declared.""" return super().size.length @memory_size.setter def memory_size(self, memory_size: int) -> None: vector = super().size vector.length = memory_size quil_rs.Declaration.size.__set__(self, vector) # type: ignore[attr-defined] @property def shared_region(self) -> Optional[str]: """Get the memory region this declaration is sharing with, if any.""" sharing = super().sharing if sharing is None: return None return sharing.name @shared_region.setter def shared_region(self, shared_region: Optional[str]) -> None: sharing = None if not shared_region else quil_rs.Sharing(shared_region, []) current_sharing = super().sharing if sharing and isinstance(current_sharing, quil_rs.Sharing): sharing.offsets = current_sharing.offsets quil_rs.Declaration.sharing.__set__(self, sharing) # type: ignore[attr-defined] @property def offsets(self) -> list[tuple[int, str]]: """Get the offsets for this declaration.""" sharing = super().sharing if sharing is None: return [] return [(offset.offset, str(offset.data_type).upper()) for offset in sharing.offsets] @offsets.setter def offsets(self, offsets: Optional[list[tuple[int, str]]]) -> None: sharing = super().sharing if sharing is None: raise ValueError("DECLARE without a shared region cannot use offsets") sharing.offsets = Declare._to_rs_offsets(offsets) quil_rs.Declaration.sharing.__set__(self, sharing) # type: ignore[attr-defined]
[docs] def asdict(self) -> dict[str, Union[Sequence[tuple[int, str]], Optional[str], int]]: """Get the DECLARE directive as a dictionary.""" return { "name": self.name, "memory_type": self.memory_type, "memory_size": self.memory_size, "shared_region": self.shared_region, "offsets": self.offsets, }
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Declare": return Declare._from_rs_declaration(super().__deepcopy__(memo))
[docs] @_add_reduce_method class Include(quil_rs.Include, AbstractInstruction): """An INCLUDE directive."""
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
@classmethod def _from_rs_include(cls, include: quil_rs.Include) -> "Include": return super().__new__(cls, include.filename) def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Include": return Include._from_rs_include(super().__deepcopy__(memo))
[docs] @_add_reduce_method class Pulse(quil_rs.Pulse, AbstractInstruction): """A PULSE instruction.""" def __new__(cls, frame: Frame, waveform: Waveform, nonblocking: bool = False) -> Self: """Initialize a new Pulse instruction.""" return super().__new__(cls, not nonblocking, frame, waveform) @classmethod def _from_rs_pulse(cls, pulse: quil_rs.Pulse) -> "Pulse": return super().__new__(cls, pulse.blocking, pulse.frame, pulse.waveform)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug()
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Union[set[QubitDesignator], set[int]]: """Get the qubits the pulse operates on.""" if indices: return self.get_qubit_indices() else: return set(_convert_to_py_qubits(super().frame.qubits))
[docs] def get_qubit_indices(self) -> set[int]: """Get the qubits the pulse operates on, as integer indices.""" return {qubit.to_fixed() for qubit in super().frame.qubits}
@property # type: ignore[override] def frame(self) -> Frame: """Get the frame the pulse operates on.""" return Frame._from_rs_frame_identifier(super().frame) @frame.setter def frame(self, frame: Frame) -> None: quil_rs.Pulse.frame.__set__(self, frame) # type: ignore[attr-defined] @property # type: ignore[override] def waveform(self) -> Waveform: """Get the waveform of the pulse.""" return _convert_to_py_waveform(super().waveform) @waveform.setter def waveform(self, waveform: Waveform) -> None: quil_rs.Pulse.waveform.__set__(self, waveform) # type: ignore[attr-defined] @property def nonblocking(self) -> bool: """Return whether the pulse is non-blocking.""" return not super().blocking @nonblocking.setter def nonblocking(self, nonblocking: bool) -> None: quil_rs.Pulse.blocking.__set__(self, not nonblocking) # type: ignore[attr-defined] def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Pulse": return Pulse._from_rs_pulse(super().__deepcopy__(memo))
[docs] @_add_reduce_method class SetFrequency(quil_rs.SetFrequency, AbstractInstruction): """A SET-FREQUENCY instruction.""" def __new__(cls, frame: Frame, freq: ParameterDesignator) -> Self: """Initialize a new SET-FREQUENCY instruction.""" return super().__new__(cls, frame, _convert_to_rs_expression(freq)) @classmethod def _from_rs_set_frequency(cls, set_frequency: quil_rs.SetFrequency) -> "SetFrequency": return super().__new__(cls, set_frequency.frame, set_frequency.frequency)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property # type: ignore[override] def frame(self) -> Frame: """Get the frame the frequency is set on.""" return Frame._from_rs_frame_identifier(super().frame) @frame.setter def frame(self, frame: Frame) -> None: quil_rs.SetFrequency.frame.__set__(self, frame) # type: ignore[attr-defined] @property def freq(self) -> ParameterDesignator: """Get the frequency that is set.""" return _convert_to_py_expression(super().frequency) @freq.setter def freq(self, freq: ParameterDesignator) -> None: quil_rs.SetFrequency.frequency.__set__(self, _convert_to_rs_expression(freq)) # type: ignore[attr-defined]
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Union[set[QubitDesignator], set[int]]: """Get the qubits the frequency is set on.""" if indices: return self.get_qubit_indices() return set(self.frame.qubits)
[docs] def get_qubit_indices(self) -> set[int]: """Get the qubits the frequency is set on, as integer indices.""" return {qubit.to_fixed() for qubit in super().frame.qubits}
def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "SetFrequency": return SetFrequency._from_rs_set_frequency(super().__deepcopy__(memo))
[docs] @_add_reduce_method class ShiftFrequency(quil_rs.ShiftFrequency, AbstractInstruction): """The SHIFT-FREQUENCY instruction.""" def __new__(cls, frame: Frame, freq: ParameterDesignator) -> Self: """Initialize a new SHIFT-FREQUENCY instruction.""" return super().__new__(cls, frame, _convert_to_rs_expression(freq)) @classmethod def _from_rs_shift_frequency(cls, shift_frequency: quil_rs.ShiftFrequency) -> "ShiftFrequency": return super().__new__(cls, shift_frequency.frame, shift_frequency.frequency)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property # type: ignore[override] def frame(self) -> Frame: """Get the frame the frequency is shifted on.""" return Frame._from_rs_frame_identifier(super().frame) @frame.setter def frame(self, frame: Frame) -> None: quil_rs.ShiftFrequency.frame.__set__(self, frame) # type: ignore[attr-defined] @property def freq(self) -> ParameterDesignator: """Get the parameter that defines how the frequency is shifted.""" return _convert_to_py_expression(super().frequency) @freq.setter def freq(self, freq: ParameterDesignator) -> None: quil_rs.ShiftFrequency.frequency.__set__(self, _convert_to_rs_expression(freq)) # type: ignore[attr-defined]
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Union[set[QubitDesignator], set[int]]: """Get the qubits the frequency is shifted on.""" if indices: return self.get_qubit_indices() return set(self.frame.qubits)
[docs] def get_qubit_indices(self) -> set[int]: """Get the qubits the frequency is shifted on, as integer indices.""" return {qubit.to_fixed() for qubit in super().frame.qubits}
def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "ShiftFrequency": return ShiftFrequency._from_rs_shift_frequency(super().__deepcopy__(memo))
[docs] @_add_reduce_method class SetPhase(quil_rs.SetPhase, AbstractInstruction): """The SET-PHASE instruction.""" def __new__(cls, frame: Frame, phase: ParameterDesignator) -> Self: """Initialize a new SET-PHASE instruction.""" return super().__new__(cls, frame, _convert_to_rs_expression(phase)) @classmethod def _from_rs_set_phase(cls, set_phase: quil_rs.SetPhase) -> "SetPhase": return super().__new__(cls, set_phase.frame, set_phase.phase)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property # type: ignore[override] def frame(self) -> Frame: """Get the frame the phase is set on.""" return Frame._from_rs_frame_identifier(super().frame) @frame.setter def frame(self, frame: Frame) -> None: quil_rs.SetPhase.frame.__set__(self, frame) # type: ignore[attr-defined] @property # type: ignore[override] def phase(self) -> ParameterDesignator: """Get the phase this instruction sets.""" return _convert_to_py_expression(super().phase) @phase.setter def phase(self, phase: ParameterDesignator) -> None: quil_rs.SetPhase.phase.__set__(self, _convert_to_rs_expression(phase)) # type: ignore[attr-defined]
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Union[set[QubitDesignator], set[int]]: """Get the quibts the phase is set on.""" if indices: return self.get_qubit_indices() return set(self.frame.qubits)
[docs] def get_qubit_indices(self) -> set[int]: """Get the quibts the phase is set on, as integer indices.""" return {qubit.to_fixed() for qubit in super().frame.qubits}
def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "SetPhase": return SetPhase._from_rs_set_phase(super().__deepcopy__(memo))
[docs] @_add_reduce_method class ShiftPhase(quil_rs.ShiftPhase, AbstractInstruction): """The SHIFT-PHASE instruction.""" def __new__(cls, frame: Frame, phase: ParameterDesignator) -> Self: """Initialize a new SHIFT-PHASE instruction.""" return super().__new__(cls, frame, _convert_to_rs_expression(phase)) @classmethod def _from_rs_shift_phase(cls, shift_phase: quil_rs.ShiftPhase) -> "ShiftPhase": return super().__new__(cls, shift_phase.frame, shift_phase.phase)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property # type: ignore[override] def frame(self) -> Frame: """Get the frame the phase is shifted on.""" return Frame._from_rs_frame_identifier(super().frame) @frame.setter def frame(self, frame: Frame) -> None: quil_rs.ShiftPhase.frame.__set__(self, frame) # type: ignore[attr-defined] @property # type: ignore[override] def phase(self) -> ParameterDesignator: """Get the parameter that defines how the phase is shifted.""" return _convert_to_py_expression(super().phase) @phase.setter def phase(self, phase: ParameterDesignator) -> None: quil_rs.ShiftPhase.phase.__set__(self, _convert_to_rs_expression(phase)) # type: ignore[attr-defined]
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Union[set[QubitDesignator], set[int]]: """Get the qubits the phase is shifted on.""" if indices: return self.get_qubit_indices() return set(self.frame.qubits)
[docs] def get_qubit_indices(self) -> set[int]: """Get the qubits the phase is shifted on, as integer indices.""" return {qubit.to_fixed() for qubit in super().frame.qubits}
def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "ShiftPhase": return ShiftPhase._from_rs_shift_phase(super().__deepcopy__(memo))
[docs] @_add_reduce_method class SwapPhases(quil_rs.SwapPhases, AbstractInstruction): """The SWAP-PHASES instruction.""" def __new__(cls, frameA: Frame, frameB: Frame) -> Self: """Initialize a new SWAP-PHASES instruction.""" return super().__new__(cls, frameA, frameB) @classmethod def _from_rs_swap_phases(cls, swap_phases: quil_rs.SwapPhases) -> "SwapPhases": return super().__new__(cls, swap_phases.frame_1, swap_phases.frame_2) @property def frameA(self) -> Frame: """The first frame of the SWAP-PHASES instruction.""" return Frame._from_rs_frame_identifier(super().frame_1) @frameA.setter def frameA(self, frame: Frame) -> None: quil_rs.SwapPhases.frame_1.__set__(self, frame) # type: ignore[attr-defined] @property def frameB(self) -> Frame: """The second frame of the SWAP-PHASES instruction.""" return Frame._from_rs_frame_identifier(super().frame_2) @frameB.setter def frameB(self, frame: Frame) -> None: quil_rs.SwapPhases.frame_2.__set__(self, frame) # type: ignore[attr-defined]
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug()
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Union[set[QubitDesignator], set[int]]: """Get the qubits the swap-phases instruction operates on.""" if indices: return self.get_qubit_indices() return set(self.frameA.qubits) | set(self.frameB.qubits)
[docs] def get_qubit_indices(self) -> set[int]: """Get the qubits the swap-phases instruction operates on, as integer indices.""" return {qubit.to_fixed() for qubit in super().frame_1.qubits + super().frame_2.qubits}
def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "SwapPhases": return SwapPhases._from_rs_swap_phases(super().__deepcopy__(memo))
[docs] @_add_reduce_method class SetScale(quil_rs.SetScale, AbstractInstruction): """The SET-SCALE instruction.""" def __new__(cls, frame: Frame, scale: ParameterDesignator) -> Self: """Initialize a new SET-SCALE instruction.""" return super().__new__(cls, frame, _convert_to_rs_expression(scale)) @classmethod def _from_rs_set_scale(cls, set_scale: quil_rs.SetScale) -> "SetScale": return super().__new__(cls, set_scale.frame, set_scale.scale)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property # type: ignore[override] def frame(self) -> Frame: """Get the frame the scale is set on.""" return Frame._from_rs_frame_identifier(super().frame) @frame.setter def frame(self, frame: Frame) -> None: quil_rs.SetScale.frame.__set__(self, frame) # type: ignore[attr-defined] @property # type: ignore[override] def scale(self) -> ParameterDesignator: """Get the scale that is set.""" return _convert_to_py_expression(super().scale) @scale.setter def scale(self, scale: ParameterDesignator) -> None: quil_rs.SetScale.scale.__set__(self, _convert_to_rs_expression(scale)) # type: ignore[attr-defined]
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Union[set[QubitDesignator], set[int]]: """Get the qubits the scale is set on.""" if indices: return self.get_qubit_indices() return set(self.frame.qubits)
[docs] def get_qubit_indices(self) -> set[int]: """Get the qubits the scale is set on, as integer indices.""" return {qubit.to_fixed() for qubit in super().frame.qubits}
def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "SetScale": return SetScale._from_rs_set_scale(super().__deepcopy__(memo))
[docs] @_add_reduce_method class Call(quil_rs.Call, AbstractInstruction): """An instruction that calls an external function declared with a `PRAGMA EXTERN` instruction. These calls are generally specific to a particular hardware or virtual machine backend. For further detail, see: * `Other instructions and Directives <https://github.com/quil-lang/quil/blob/master/rfcs/extern-call.md>`_ in the Quil specification. * `EXTERN / CALL RFC <https://github.com/quil-lang/quil/blob/master/rfcs/extern-call.md>`_ * `quil#87 <https://github.com/quil-lang/quil/issues/87>`_ """ @classmethod def _from_rs_call(cls, call: quil_rs.Call) -> "Call": return super().__new__(cls, call.name, call.arguments)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Call": return Call._from_rs_call(super().__deepcopy__(memo))
[docs] @_add_reduce_method class Capture(quil_rs.Capture, AbstractInstruction): """The CAPTURE instruction.""" def __new__( cls, frame: Frame, kernel: Waveform, memory_region: MemoryReference, nonblocking: bool = False, ) -> Self: """Initialize a new CAPTURE instruction.""" rs_memory_reference = _convert_to_rs_expression(memory_region).to_address() return super().__new__(cls, not nonblocking, frame, rs_memory_reference, kernel) @classmethod def _from_rs_capture(cls, capture: quil_rs.Capture) -> "Capture": return super().__new__(cls, capture.blocking, capture.frame, capture.memory_reference, capture.waveform) @property # type: ignore[override] def frame(self) -> Frame: """Get the frame this instruction captures.""" return Frame._from_rs_frame_identifier(super().frame) @frame.setter def frame(self, frame: Frame) -> None: quil_rs.Capture.frame.__set__(self, frame) # type: ignore[attr-defined] @property def kernel(self) -> Waveform: """Get the kernel waveform.""" return _convert_to_py_waveform(super().waveform) @kernel.setter def kernel(self, kernel: Waveform) -> None: quil_rs.Capture.waveform.__set__(self, kernel) # type: ignore[attr-defined] @property def memory_region(self) -> MemoryReference: """Get the memory reference that the capture is written to.""" return MemoryReference._from_rs_memory_reference(super().memory_reference) @memory_region.setter def memory_region(self, memory_region: MemoryReference) -> None: rs_memory_reference = _convert_to_rs_expression(memory_region).to_address() quil_rs.Capture.memory_reference.__set__(self, rs_memory_reference) # type: ignore[attr-defined] @property def nonblocking(self) -> bool: """Whether the capture is non-blocking.""" return not super().blocking @nonblocking.setter def nonblocking(self, nonblocking: bool) -> None: quil_rs.Capture.blocking.__set__(self, not nonblocking) # type: ignore[attr-defined]
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug()
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Union[set[QubitDesignator], set[int]]: """Get the qubits the capture instruction operates on.""" if indices: return self.get_qubit_indices() else: return set(_convert_to_py_qubits(super().frame.qubits))
[docs] def get_qubit_indices(self) -> set[int]: """Get the qubits the capture instruction operates on, as integer indices.""" return {qubit.to_fixed() for qubit in super().frame.qubits}
def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Capture": return Capture._from_rs_capture(super().__deepcopy__(memo))
[docs] @_add_reduce_method class RawCapture(quil_rs.RawCapture, AbstractInstruction): """The RAW-CAPTURE instruction.""" def __new__( cls, frame: Frame, duration: float, memory_region: MemoryReference, nonblocking: bool = False, ) -> Self: """Initialize a new RAW-CAPTURE instruction.""" rs_duration = _convert_to_rs_expression(duration) rs_memory_reference = _convert_to_rs_expression(memory_region).to_address() return super().__new__(cls, not nonblocking, frame, rs_duration, rs_memory_reference) @classmethod def _from_rs_raw_capture(cls, raw_capture: quil_rs.RawCapture) -> "RawCapture": return super().__new__( cls, raw_capture.blocking, raw_capture.frame, raw_capture.duration, raw_capture.memory_reference ) @property # type: ignore[override] def frame(self) -> Frame: """Get the frame this instruction operates on.""" return Frame._from_rs_frame_identifier(super().frame) @frame.setter def frame(self, frame: Frame) -> None: quil_rs.RawCapture.frame.__set__(self, frame) # type: ignore[attr-defined] @property # type: ignore[override] def duration(self) -> complex: """Get the duration of the capture.""" return super().duration.to_number() @duration.setter def duration(self, duration: float) -> None: rs_duration = _convert_to_rs_expression(duration) quil_rs.RawCapture.duration.__set__(self, rs_duration) # type: ignore[attr-defined] @property def memory_region(self) -> MemoryReference: """Get the memory region that the capture is written to.""" return MemoryReference._from_rs_memory_reference(super().memory_reference) @memory_region.setter def memory_region(self, memory_region: MemoryReference) -> None: rs_memory_reference = _convert_to_rs_expression(memory_region).to_address() quil_rs.RawCapture.memory_reference.__set__(self, rs_memory_reference) # type: ignore[attr-defined] @property def nonblocking(self) -> bool: """Whether the capture is non-blocking.""" return not super().blocking @nonblocking.setter def nonblocking(self, nonblocking: bool) -> None: quil_rs.RawCapture.blocking.__set__(self, not nonblocking) # type: ignore[attr-defined]
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug()
[docs] @deprecated( version="4.0", reason="The indices flag will be removed, use get_qubit_indices() instead.", ) def get_qubits(self, indices: bool = True) -> Union[set[QubitDesignator], set[int]]: """Get the qubits the raw-capture instruction operates on.""" if indices: return self.get_qubit_indices() else: return set(_convert_to_py_qubits(super().frame.qubits))
[docs] def get_qubit_indices(self) -> set[int]: """Get the qubits the raw-capture instruction operates on, as integer indices.""" return {qubit.to_fixed() for qubit in super().frame.qubits}
def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "RawCapture": return RawCapture._from_rs_raw_capture(super().__deepcopy__(memo))
[docs] @_add_reduce_method class Delay(quil_rs.Delay, AbstractInstruction): """The DELAY instruction.""" def __new__(cls, frames: list[Frame], qubits: Sequence[Union[int, Qubit, FormalArgument]], duration: float) -> Self: """Initialize a new DELAY instruction.""" frame_names = [frame.name for frame in frames] rs_qubits = _convert_to_rs_qubits(Delay._join_frame_qubits(frames, list(qubits))) expression = quil_rs_expr.Expression.from_number(complex(duration)) return super().__new__(cls, expression, frame_names, rs_qubits) @classmethod def _from_rs_delay(cls, delay: quil_rs.Delay) -> "Delay": return super().__new__(cls, delay.duration, delay.frame_names, delay.qubits) @staticmethod def _join_frame_qubits( frames: Sequence[Frame], qubits: Sequence[Union[int, Qubit, FormalArgument]] ) -> list[Union[int, Qubit, FormalArgument]]: merged_qubits = set(qubits) for frame in frames: merged_qubits.update(frame.qubits) # type: ignore return list(merged_qubits)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property # type: ignore[override] def qubits(self) -> list[QubitDesignator]: """Get the qubits the delay operates on.""" return _convert_to_py_qubits(super().qubits) @qubits.setter def qubits(self, qubits: Sequence[Union[int, Qubit, FormalArgument]]) -> None: quil_rs.Delay.qubits.__set__(self, _convert_to_rs_qubits(qubits)) # type: ignore @property def frames(self) -> list[Frame]: """Get the frames the delay operates on.""" return [Frame(self.qubits, name) for name in super().frame_names] @frames.setter def frames(self, frames: list[Frame]) -> None: new_qubits = Delay._join_frame_qubits(frames, []) frame_names = [frame.name for frame in frames] quil_rs.Delay.qubits.__set__(self, _convert_to_rs_qubits(new_qubits)) # type: ignore[attr-defined] quil_rs.Delay.frame_names.__set__(self, frame_names) # type: ignore[attr-defined] @property # type: ignore[override] def duration(self) -> float: """Get the duration of the delay.""" return super().duration.to_real() @duration.setter def duration(self, duration: float) -> None: expression = quil_rs_expr.Expression.from_number(complex(duration)) quil_rs.Delay.duration.__set__(self, expression) # type: ignore[attr-defined] def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Delay": copy = Delay._from_rs_delay(super().__deepcopy__(memo)) copy.__class__ = self.__class__ return copy
[docs] class DelayFrames(Delay): """A DELAY instruction that operates on frames.""" def __new__(cls, frames: list[Frame], duration: float) -> Self: """Initialize a new DELAY instruction that operates on frames.""" return super().__new__(cls, frames, [], duration) @classmethod def _from_rs_delay(cls, delay: quil_rs.Delay) -> "DelayFrames": return Delay._from_rs_delay.__func__(cls, delay) # type: ignore
[docs] class DelayQubits(Delay): """Initialize a new DELAY instruction that operates on qubits.""" def __new__(cls, qubits: Sequence[Union[Qubit, FormalArgument]], duration: float) -> Self: """Initialize a new DELAY instruction that operates on qubits.""" return super().__new__(cls, [], qubits, duration) @classmethod def _from_rs_delay(cls, delay: quil_rs.Delay) -> "DelayQubits": return Delay._from_rs_delay.__func__(cls, delay) # type: ignore
[docs] @_add_reduce_method class Fence(quil_rs.Fence, AbstractInstruction): """The FENCE instruction.""" def __new__(cls, qubits: list[Union[Qubit, FormalArgument]]) -> Self: """Initialize a new FENCE instruction.""" return super().__new__(cls, _convert_to_rs_qubits(qubits)) @classmethod def _from_rs_fence(cls, fence: quil_rs.Fence) -> "Fence": return super().__new__(cls, fence.qubits)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property # type: ignore[override] def qubits(self) -> list[QubitDesignator]: """Get the qubits the fence operates on. Note: If qubits is empty, then the instruction fences all qubits. """ return _convert_to_py_qubits(super().qubits) @qubits.setter def qubits(self, qubits: list[Union[Qubit, FormalArgument]]) -> None: quil_rs.Fence.qubits.__set__(self, _convert_to_rs_qubits(qubits)) # type: ignore[attr-defined] def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "Fence": return Fence._from_rs_fence(super().__deepcopy__(memo))
[docs] class FenceAll(Fence): """A FENCE instruction that operates on all qubits.""" def __new__(cls) -> Self: """Initialize a new FenceAll instruction.""" return super().__new__(cls, [])
[docs] @_add_reduce_method class DefWaveform(quil_rs.WaveformDefinition, AbstractInstruction): """A waveform definition.""" def __new__( cls, name: str, parameters: list[Parameter], entries: list[Union[complex, Expression]], ) -> Self: """Initialize a new waveform definition.""" rs_waveform = DefWaveform._build_rs_waveform(parameters, entries) return super().__new__(cls, name, rs_waveform) @classmethod def _from_rs_waveform_definition(cls, waveform_definition: quil_rs.WaveformDefinition) -> "DefWaveform": return super().__new__(cls, waveform_definition.name, waveform_definition.definition) @staticmethod def _build_rs_waveform(parameters: list[Parameter], entries: list[Union[complex, Expression]]) -> quil_rs.Waveform: rs_parameters = [parameter.name for parameter in parameters] return quil_rs.Waveform(_convert_to_rs_expressions(entries), rs_parameters)
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property def parameters(self) -> list[Parameter]: """Get the parameters of the waveform.""" return [Parameter(parameter) for parameter in super().definition.parameters] @parameters.setter def parameters(self, parameters: list[Parameter]) -> None: waveform = super().definition waveform.parameters = [parameter.name for parameter in parameters] quil_rs.WaveformDefinition.definition.__set__(self, waveform) # type: ignore[attr-defined] @property def entries(self) -> Sequence[ParameterDesignator]: """Get the entries in the waveform definition.""" return _convert_to_py_expressions(super().definition.matrix) @entries.setter def entries(self, entries: list[Union[complex, Expression]]) -> None: waveform = super().definition waveform.matrix = _convert_to_rs_expressions(entries) quil_rs.WaveformDefinition.definition.__set__(self, waveform) # type: ignore[attr-defined] def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "DefWaveform": return DefWaveform._from_rs_waveform_definition(super().__deepcopy__(memo))
[docs] @_add_reduce_method class DefCircuit(quil_rs.CircuitDefinition, AbstractInstruction): """A circuit definition.""" def __new__( cls, name: str, parameters: list[Parameter], qubits: list[FormalArgument], instructions: list[AbstractInstruction], ) -> Self: """Initialize a new circuit definition.""" rs_parameters = [parameter.name for parameter in parameters] rs_qubits = [qubit.name for qubit in qubits] rs_instructions = _convert_to_rs_instructions(instructions) return super().__new__(cls, name, rs_parameters, rs_qubits, rs_instructions) @classmethod def _from_rs_circuit_definition(cls, circuit_definition: quil_rs.CircuitDefinition) -> "DefCircuit": return super().__new__( cls, circuit_definition.name, circuit_definition.parameters, circuit_definition.qubit_variables, circuit_definition.instructions, )
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property # type: ignore[override] def parameters(self) -> list[Parameter]: """Get the parameters of the circuit.""" return [Parameter(parameter) for parameter in super().parameters] @parameters.setter def parameters(self, parameters: list[Parameter]) -> None: rs_parameters = [parameter.name for parameter in parameters] quil_rs.CircuitDefinition.parameters.__set__(self, rs_parameters) # type: ignore[attr-defined] @property # type: ignore[override] def qubit_variables(self) -> list[FormalArgument]: """Get the qubit parameters of the circuit.""" return [FormalArgument(qubit) for qubit in super().qubit_variables] @qubit_variables.setter def qubit_variables(self, qubits: list[FormalArgument]) -> None: rs_qubits = [qubit.name for qubit in qubits] quil_rs.CircuitDefinition.qubit_variables.__set__(self, rs_qubits) # type: ignore[attr-defined] @property # type: ignore[override] def instructions(self) -> list[AbstractInstruction]: """Get the instructions in the circuit.""" return _convert_to_py_instructions(super().instructions) @instructions.setter def instructions(self, instructions: list[AbstractInstruction]) -> None: rs_instructions = _convert_to_rs_instructions(instructions) quil_rs.CircuitDefinition.instructions.__set__(self, rs_instructions) # type: ignore[attr-defined] def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "DefCircuit": return DefCircuit._from_rs_circuit_definition(super().__deepcopy__(memo))
[docs] @_add_reduce_method class DefCalibration(quil_rs.Calibration, AbstractInstruction): """A calibration definition.""" def __new__( cls, name: str, parameters: Sequence[ParameterDesignator], qubits: Sequence[Union[Qubit, FormalArgument]], instrs: Sequence[AbstractInstruction], modifiers: Optional[list[quil_rs.GateModifier]] = None, ) -> Self: """Initialize a new calibration definition.""" return super().__new__( cls, quil_rs.CalibrationIdentifier( name, _convert_to_rs_expressions(parameters), _convert_to_rs_qubits(qubits), modifiers or [], ), _convert_to_rs_instructions(instrs), ) @classmethod def _from_rs_calibration(cls, calibration: quil_rs.Calibration) -> "DefCalibration": return super().__new__(cls, calibration.identifier, calibration.instructions) @property # type: ignore[override] def parameters(self) -> Sequence[ParameterDesignator]: """The parameters of the calibration.""" return _convert_to_py_expressions(super().identifier.parameters) @parameters.setter def parameters(self, parameters: Sequence[ParameterDesignator]) -> None: identifier = super().identifier identifier.parameters = _convert_to_rs_expressions(parameters) quil_rs.Calibration.identifier.__set__(self, identifier) # type: ignore[attr-defined] # noqa @property # type: ignore[override] def qubits(self) -> list[QubitDesignator]: """The qubits the calibration operates on.""" return _convert_to_py_qubits(super().identifier.qubits) @qubits.setter def qubits(self, qubits: Sequence[QubitDesignator]) -> None: identifier = super().identifier identifier.qubits = _convert_to_rs_qubits(qubits) quil_rs.Calibration.identifier.__set__(self, identifier) # type: ignore[attr-defined] @property def instrs(self) -> list[AbstractInstruction]: """The instructions in the calibration.""" return _convert_to_py_instructions(super().instructions) @instrs.setter def instrs(self, instrs: Sequence[AbstractInstruction]) -> None: quil_rs.Calibration.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 @property def name(self) -> str: """Get the name of the calibration.""" return super().identifier.name @name.setter def name(self, name: str) -> None: identifier = super().identifier identifier.name = name quil_rs.Calibration.identifier.__set__(self, identifier) # type: ignore
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "DefCalibration": return DefCalibration._from_rs_calibration(super().__deepcopy__(memo))
[docs] @_add_reduce_method class DefMeasureCalibration(quil_rs.MeasureCalibrationDefinition, AbstractInstruction): """A measure calibration definition.""" def __new__( cls, qubit: Optional[Union[Qubit, FormalArgument]], memory_reference: MemoryReference, instrs: list[AbstractInstruction], ) -> Self: """Initialize a new measure calibration definition.""" rs_qubit = None if not qubit else _convert_to_rs_qubit(qubit) return super().__new__( cls, quil_rs.MeasureCalibrationIdentifier(rs_qubit, str(memory_reference)), _convert_to_rs_instructions(instrs), ) @classmethod def _from_rs_measure_calibration_definition( cls, calibration: quil_rs.MeasureCalibrationDefinition ) -> "DefMeasureCalibration": return super().__new__(cls, calibration.identifier, calibration.instructions) @property # type: ignore[override] def qubit(self) -> Optional[QubitDesignator]: """Get the qubit this calibration matches.""" qubit = super().identifier.qubit if not qubit: return None return _convert_to_py_qubit(qubit) @qubit.setter def qubit(self, qubit: QubitDesignator) -> None: identifier = super().identifier identifier.qubit = _convert_to_rs_qubit(qubit) quil_rs.MeasureCalibrationDefinition.identifier.__set__(self, identifier) # type: ignore[attr-defined] # noqa @property def memory_reference(self) -> Optional[MemoryReference]: """Get the memory reference this calibration writes to.""" return MemoryReference._from_parameter_str(super().identifier.parameter) @memory_reference.setter def memory_reference(self, memory_reference: MemoryReference) -> None: identifier = super().identifier identifier.parameter = memory_reference.out() quil_rs.MeasureCalibrationDefinition.identifier.__set__(self, identifier) # type: ignore[attr-defined] # noqa @property def instrs(self) -> list[AbstractInstruction]: """Get the instructions in the calibration.""" return _convert_to_py_instructions(super().instructions) @instrs.setter 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
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "DefMeasureCalibration": return DefMeasureCalibration._from_rs_measure_calibration_definition(super().__deepcopy__(memo))
[docs] @_add_reduce_method class DefFrame(quil_rs.FrameDefinition, AbstractInstruction): """A frame definition.""" def __new__( cls, frame: Frame, direction: Optional[str] = None, initial_frequency: Optional[float] = None, hardware_object: Optional[str] = None, sample_rate: Optional[float] = None, center_frequency: Optional[float] = None, enable_raw_capture: Optional[str] = None, channel_delay: Optional[float] = None, ) -> Self: """Get the frame definition.""" attributes = { key: DefFrame._to_attribute_value(value) for key, value in zip( [ "DIRECTION", "INITIAL-FREQUENCY", "HARDWARE-OBJECT", "SAMPLE-RATE", "CENTER-FREQUENCY", "ENABLE-RAW-CAPTURE", "CHANNEL-DELAY", ], [ direction, initial_frequency, hardware_object, sample_rate, center_frequency, enable_raw_capture, channel_delay, ], ) if value is not None } return super().__new__(cls, frame, attributes) @classmethod def _from_rs_frame_definition(cls, def_frame: quil_rs.FrameDefinition) -> "DefFrame": return super().__new__(cls, def_frame.identifier, def_frame.attributes) @classmethod def _from_rs_attribute_values( cls, frame: quil_rs.FrameIdentifier, attributes: dict[str, quil_rs.AttributeValue] ) -> "DefFrame": return super().__new__(cls, frame, attributes) @staticmethod def _to_attribute_value(value: Union[str, float]) -> quil_rs.AttributeValue: if isinstance(value, str): return quil_rs.AttributeValue.from_string(value) if isinstance(value, (int, float, complex)): return quil_rs.AttributeValue.from_expression(quil_rs_expr.Expression.from_number(complex(value))) raise ValueError(f"{type(value)} is not a valid AttributeValue")
[docs] def out(self) -> str: """Return the instruction as a valid Quil string.""" return super().to_quil()
def __str__(self) -> str: return super().to_quil_or_debug() @property def frame(self) -> Frame: """Get the frame identifier.""" return Frame._from_rs_frame_identifier(super().identifier) @frame.setter def frame(self, frame: Frame) -> None: quil_rs.FrameDefinition.identifier.__set__(self, frame) # type: ignore[attr-defined]
[docs] def set_attribute(self, name: str, value: Union[str, float]) -> None: """Set an attribute on the frame definition.""" updated = super().attributes updated.update({name: DefFrame._to_attribute_value(value)}) quil_rs.FrameDefinition.attributes.__set__(self, updated) # type: ignore[attr-defined]
[docs] def get_attribute(self, name: str) -> Optional[Union[str, float]]: """Get an attribute's value on the frame definition.""" value = super().attributes.get(name, None) if value is None: return None if value.is_string(): return value.to_string() return value.to_expression().to_number().real
def __getitem__(self, name: str) -> Union[str, float]: if not isinstance(name, str): raise TypeError("Frame attribute keys must be strings") value = self.get_attribute(name) if value is None: raise AttributeError(f"Attribute {name} not found") return value def __setitem__(self, name: str, value: Union[str, float]) -> None: if not isinstance(name, str): raise TypeError("Frame attribute keys must be strings") self.set_attribute(name, value) @property @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use get_attribute('DIRECTION') instead.", ) def direction(self) -> Optional[str]: """Get the DIRECTION attribute of the frame.""" return self.get_attribute("DIRECTION") # type: ignore @direction.setter @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use set_attribute('DIRECTION') instead.", ) def direction(self, direction: str) -> None: self.set_attribute("DIRECTION", direction) @property @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use set_attribute('INITIAL-FREQUENCY') instead.", # noqa: E501 ) def initial_frequency(self) -> Optional[float]: """Get the INITIAL-FREQUENCY attribute of the frame.""" return self.get_attribute("INITIAL-FREQUENCY") # type: ignore @initial_frequency.setter @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use set_attribute('INITIAL-FREQUENCY') instead.", # noqa: E501 ) def initial_frequency(self, initial_frequency: float) -> None: self.set_attribute("INITIAL-FREQUENCY", initial_frequency) @property @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use get_attribute('HARDWARE-OBJECT') instead.", ) def hardware_object(self) -> Optional[str]: """Get the HARDWARE-OBJECT attribute of the frame.""" return self.get_attribute("HARDWARE-OBJECT") # type: ignore @hardware_object.setter @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use set_attribute('HARDWARE-OBJECT') instead.", ) def hardware_object(self, hardware_object: str) -> None: self.set_attribute("HARDWARE-OBJECT", hardware_object) @property @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use get_attribute('SAMPLE-RATE') instead.", ) def sample_rate(self) -> Frame: """Get the SAMPLE-RATE attribute of the frame.""" return self.get_attribute("SAMPLE-RATE") # type: ignore @sample_rate.setter @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use set_attribute('SAMPLE-RATE') instead.", ) def sample_rate(self, sample_rate: float) -> None: self.set_attribute("SAMPLE-RATE", sample_rate) @property @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use get_attribute('CENTER-FREQUENCY') instead.", ) def center_frequency(self) -> Frame: """Get the CENTER-FREQUENCY attribute of the frame.""" return self.get_attribute("CENTER-FREQUENCY") # type: ignore @center_frequency.setter @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use set_attribute('CENTER-FREQUENCY') instead.", ) def center_frequency(self, center_frequency: float) -> None: self.set_attribute("CENTER-FREQUENCY", center_frequency) @property @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use get_attribute('CHANNEL-DELAY') instead.", ) def channel_delay(self) -> Frame: """Get the CHANNEL-DELAY attribute of the frame.""" return self.get_attribute("CHANNEL-DELAY") # type: ignore @channel_delay.setter @deprecated( version="4.0", reason="Quil now supports generic key/value pairs in DEFFRAMEs. Use set_attribute('CHANNEL-DELAY') instead.", ) def channel_delay(self, channel_delay: float) -> None: self.set_attribute("CHANNEL-DELAY", channel_delay) def __copy__(self) -> Self: return self def __deepcopy__(self, memo: dict) -> "DefFrame": return DefFrame._from_rs_frame_definition(super().__deepcopy__(memo))