diff --git a/src/braket/circuits/ascii_circuit_diagram.py b/src/braket/circuits/ascii_circuit_diagram.py index f43f37a36..85de40a11 100644 --- a/src/braket/circuits/ascii_circuit_diagram.py +++ b/src/braket/circuits/ascii_circuit_diagram.py @@ -22,8 +22,8 @@ from braket.circuits.gate import Gate from braket.circuits.instruction import Instruction from braket.circuits.noise import Noise -from braket.circuits.qubit_set import QubitSet from braket.circuits.result_type import ResultType +from braket.registers.qubit_set import QubitSet class AsciiCircuitDiagram(CircuitDiagram): diff --git a/src/braket/circuits/circuit.py b/src/braket/circuits/circuit.py index 7e3bfcd4d..34bde9b98 100644 --- a/src/braket/circuits/circuit.py +++ b/src/braket/circuits/circuit.py @@ -39,8 +39,6 @@ from braket.circuits.observable import Observable from braket.circuits.observables import TensorProduct from braket.circuits.parameterizable import Parameterizable -from braket.circuits.qubit import QubitInput -from braket.circuits.qubit_set import QubitSet, QubitSetInput from braket.circuits.result_type import ( ObservableParameterResultType, ObservableResultType, @@ -60,6 +58,8 @@ from braket.pulse import ArbitraryWaveform, Frame from braket.pulse.ast.qasm_parser import ast_to_qasm from braket.pulse.pulse_sequence import PulseSequence, _validate_uniqueness +from braket.registers.qubit import QubitInput +from braket.registers.qubit_set import QubitSet, QubitSetInput SubroutineReturn = TypeVar( "SubroutineReturn", Iterable[Instruction], Instruction, ResultType, Iterable[ResultType] diff --git a/src/braket/circuits/compiler_directive.py b/src/braket/circuits/compiler_directive.py index cd40a596c..3ca677ff7 100644 --- a/src/braket/circuits/compiler_directive.py +++ b/src/braket/circuits/compiler_directive.py @@ -16,8 +16,8 @@ from typing import Any, Sequence, Tuple from braket.circuits.operator import Operator -from braket.circuits.qubit_set import QubitSet from braket.circuits.serialization import IRType, SerializationProperties +from braket.registers.qubit_set import QubitSet class CompilerDirective(Operator): diff --git a/src/braket/circuits/gate.py b/src/braket/circuits/gate.py index 81f2499d1..135a892c3 100644 --- a/src/braket/circuits/gate.py +++ b/src/braket/circuits/gate.py @@ -18,12 +18,12 @@ from braket.circuits.basis_state import BasisState, BasisStateInput from braket.circuits.quantum_operator import QuantumOperator -from braket.circuits.qubit_set import QubitSet from braket.circuits.serialization import ( IRType, OpenQASMSerializationProperties, SerializationProperties, ) +from braket.registers.qubit_set import QubitSet class Gate(QuantumOperator): diff --git a/src/braket/circuits/gate_calibrations.py b/src/braket/circuits/gate_calibrations.py index 01694a1e7..3c5abefd7 100644 --- a/src/braket/circuits/gate_calibrations.py +++ b/src/braket/circuits/gate_calibrations.py @@ -17,13 +17,13 @@ from typing import Any, Dict, List, Optional, Tuple from braket.circuits.gate import Gate -from braket.circuits.qubit_set import QubitSet from braket.circuits.serialization import ( IRType, OpenQASMSerializationProperties, QubitReferenceType, ) from braket.pulse.pulse_sequence import PulseSequence +from braket.registers.qubit_set import QubitSet class GateCalibrations: diff --git a/src/braket/circuits/gates.py b/src/braket/circuits/gates.py index ac57d05b4..a68d9eade 100644 --- a/src/braket/circuits/gates.py +++ b/src/braket/circuits/gates.py @@ -39,11 +39,11 @@ is_unitary, verify_quantum_operator_matrix_dimensions, ) -from braket.circuits.qubit import QubitInput -from braket.circuits.qubit_set import QubitSet, QubitSetInput from braket.circuits.serialization import OpenQASMSerializationProperties from braket.pulse.ast.qasm_parser import ast_to_qasm from braket.pulse.pulse_sequence import PulseSequence +from braket.registers.qubit import QubitInput +from braket.registers.qubit_set import QubitSet, QubitSetInput """ To add a new gate: diff --git a/src/braket/circuits/instruction.py b/src/braket/circuits/instruction.py index 148711c79..6211e1221 100644 --- a/src/braket/circuits/instruction.py +++ b/src/braket/circuits/instruction.py @@ -20,9 +20,9 @@ from braket.circuits.gate import Gate from braket.circuits.operator import Operator from braket.circuits.quantum_operator import QuantumOperator -from braket.circuits.qubit import QubitInput -from braket.circuits.qubit_set import QubitSet, QubitSetInput from braket.circuits.serialization import IRType, SerializationProperties +from braket.registers.qubit import QubitInput +from braket.registers.qubit_set import QubitSet, QubitSetInput # InstructionOperator is a type alias, and it can be expanded to include other operators InstructionOperator = Operator diff --git a/src/braket/circuits/moments.py b/src/braket/circuits/moments.py index f1387d023..70cc81bcd 100644 --- a/src/braket/circuits/moments.py +++ b/src/braket/circuits/moments.py @@ -31,8 +31,8 @@ from braket.circuits.compiler_directive import CompilerDirective from braket.circuits.instruction import Instruction from braket.circuits.noise import Noise -from braket.circuits.qubit import Qubit -from braket.circuits.qubit_set import QubitSet +from braket.registers.qubit import Qubit +from braket.registers.qubit_set import QubitSet class MomentType(str, Enum): diff --git a/src/braket/circuits/noise.py b/src/braket/circuits/noise.py index 5abf19f60..498f70fdc 100644 --- a/src/braket/circuits/noise.py +++ b/src/braket/circuits/noise.py @@ -21,12 +21,12 @@ from braket.circuits.free_parameter_expression import FreeParameterExpression from braket.circuits.parameterizable import Parameterizable from braket.circuits.quantum_operator import QuantumOperator -from braket.circuits.qubit_set import QubitSet from braket.circuits.serialization import ( IRType, OpenQASMSerializationProperties, SerializationProperties, ) +from braket.registers.qubit_set import QubitSet class Noise(QuantumOperator): diff --git a/src/braket/circuits/noise_helpers.py b/src/braket/circuits/noise_helpers.py index 29ade8cf9..2238a2d61 100644 --- a/src/braket/circuits/noise_helpers.py +++ b/src/braket/circuits/noise_helpers.py @@ -23,7 +23,7 @@ from braket.circuits.moments import Moments from braket.circuits.noise import Noise from braket.circuits.quantum_operator_helpers import is_unitary -from braket.circuits.qubit_set import QubitSet, QubitSetInput +from braket.registers.qubit_set import QubitSet, QubitSetInput if TYPE_CHECKING: # pragma: no cover from braket.circuits.circuit import Circuit diff --git a/src/braket/circuits/noise_model/circuit_instruction_criteria.py b/src/braket/circuits/noise_model/circuit_instruction_criteria.py index 2e5928857..0a8c11bdf 100644 --- a/src/braket/circuits/noise_model/circuit_instruction_criteria.py +++ b/src/braket/circuits/noise_model/circuit_instruction_criteria.py @@ -16,7 +16,7 @@ from braket.circuits.instruction import Instruction from braket.circuits.noise_model.criteria import Criteria -from braket.circuits.qubit_set import QubitSetInput +from braket.registers.qubit_set import QubitSetInput class CircuitInstructionCriteria(Criteria): diff --git a/src/braket/circuits/noise_model/criteria_input_parsing.py b/src/braket/circuits/noise_model/criteria_input_parsing.py index 193525f3b..a47d8d78c 100644 --- a/src/braket/circuits/noise_model/criteria_input_parsing.py +++ b/src/braket/circuits/noise_model/criteria_input_parsing.py @@ -14,7 +14,7 @@ from typing import Iterable, Optional, Set, Tuple, Union from braket.circuits.quantum_operator import QuantumOperator -from braket.circuits.qubit_set import QubitSetInput +from braket.registers.qubit_set import QubitSetInput def parse_operator_input( diff --git a/src/braket/circuits/noise_model/gate_criteria.py b/src/braket/circuits/noise_model/gate_criteria.py index 3505391d8..571c6cb61 100644 --- a/src/braket/circuits/noise_model/gate_criteria.py +++ b/src/braket/circuits/noise_model/gate_criteria.py @@ -21,7 +21,7 @@ parse_operator_input, parse_qubit_input, ) -from braket.circuits.qubit_set import QubitSetInput +from braket.registers.qubit_set import QubitSetInput class GateCriteria(CircuitInstructionCriteria): diff --git a/src/braket/circuits/noise_model/initialization_criteria.py b/src/braket/circuits/noise_model/initialization_criteria.py index 6229573bc..e40d4e9de 100644 --- a/src/braket/circuits/noise_model/initialization_criteria.py +++ b/src/braket/circuits/noise_model/initialization_criteria.py @@ -14,7 +14,7 @@ from abc import abstractmethod from braket.circuits.noise_model.criteria import Criteria -from braket.circuits.qubit_set import QubitSetInput +from braket.registers.qubit_set import QubitSetInput class InitializationCriteria(Criteria): diff --git a/src/braket/circuits/noise_model/noise_model.py b/src/braket/circuits/noise_model/noise_model.py index 76cdffa2a..b6805e338 100644 --- a/src/braket/circuits/noise_model/noise_model.py +++ b/src/braket/circuits/noise_model/noise_model.py @@ -25,8 +25,8 @@ from braket.circuits.noise_model.criteria import Criteria, CriteriaKey, CriteriaKeyResult from braket.circuits.noise_model.initialization_criteria import InitializationCriteria from braket.circuits.noise_model.result_type_criteria import ResultTypeCriteria -from braket.circuits.qubit_set import QubitSetInput from braket.circuits.result_types import ObservableResultType +from braket.registers.qubit_set import QubitSetInput @dataclass diff --git a/src/braket/circuits/noise_model/observable_criteria.py b/src/braket/circuits/noise_model/observable_criteria.py index e6affc94c..46c0e3e7c 100644 --- a/src/braket/circuits/noise_model/observable_criteria.py +++ b/src/braket/circuits/noise_model/observable_criteria.py @@ -20,8 +20,8 @@ ) from braket.circuits.noise_model.result_type_criteria import ResultTypeCriteria from braket.circuits.observable import Observable -from braket.circuits.qubit_set import QubitSetInput from braket.circuits.result_type import ObservableResultType, ResultType +from braket.registers.qubit_set import QubitSetInput class ObservableCriteria(ResultTypeCriteria): diff --git a/src/braket/circuits/noise_model/qubit_initialization_criteria.py b/src/braket/circuits/noise_model/qubit_initialization_criteria.py index 0646845ce..dade3a0e4 100644 --- a/src/braket/circuits/noise_model/qubit_initialization_criteria.py +++ b/src/braket/circuits/noise_model/qubit_initialization_criteria.py @@ -16,7 +16,7 @@ from braket.circuits.noise_model.criteria import Criteria, CriteriaKey, CriteriaKeyResult from braket.circuits.noise_model.criteria_input_parsing import parse_qubit_input from braket.circuits.noise_model.initialization_criteria import InitializationCriteria -from braket.circuits.qubit_set import QubitSet, QubitSetInput +from braket.registers.qubit_set import QubitSet, QubitSetInput class QubitInitializationCriteria(InitializationCriteria): diff --git a/src/braket/circuits/noise_model/unitary_gate_criteria.py b/src/braket/circuits/noise_model/unitary_gate_criteria.py index c87292980..7642a143e 100644 --- a/src/braket/circuits/noise_model/unitary_gate_criteria.py +++ b/src/braket/circuits/noise_model/unitary_gate_criteria.py @@ -18,7 +18,7 @@ from braket.circuits.noise_model.circuit_instruction_criteria import CircuitInstructionCriteria from braket.circuits.noise_model.criteria import Criteria, CriteriaKey, CriteriaKeyResult from braket.circuits.noise_model.criteria_input_parsing import parse_qubit_input -from braket.circuits.qubit_set import QubitSetInput +from braket.registers.qubit_set import QubitSetInput class UnitaryGateCriteria(CircuitInstructionCriteria): diff --git a/src/braket/circuits/noises.py b/src/braket/circuits/noises.py index 75cec6c42..11dac20e8 100644 --- a/src/braket/circuits/noises.py +++ b/src/braket/circuits/noises.py @@ -36,9 +36,9 @@ is_cptp, verify_quantum_operator_matrix_dimensions, ) -from braket.circuits.qubit import QubitInput -from braket.circuits.qubit_set import QubitSet, QubitSetInput from braket.circuits.serialization import OpenQASMSerializationProperties +from braket.registers.qubit import QubitInput +from braket.registers.qubit_set import QubitSet, QubitSetInput """ To add a new Noise implementation: diff --git a/src/braket/circuits/observable.py b/src/braket/circuits/observable.py index c63304c91..6b70d3384 100644 --- a/src/braket/circuits/observable.py +++ b/src/braket/circuits/observable.py @@ -21,12 +21,12 @@ from braket.circuits.gate import Gate from braket.circuits.quantum_operator import QuantumOperator -from braket.circuits.qubit_set import QubitSet from braket.circuits.serialization import ( IRType, OpenQASMSerializationProperties, SerializationProperties, ) +from braket.registers.qubit_set import QubitSet class Observable(QuantumOperator): diff --git a/src/braket/circuits/observables.py b/src/braket/circuits/observables.py index b27170230..9b1a4904b 100644 --- a/src/braket/circuits/observables.py +++ b/src/braket/circuits/observables.py @@ -29,8 +29,8 @@ is_hermitian, verify_quantum_operator_matrix_dimensions, ) -from braket.circuits.qubit_set import QubitSet from braket.circuits.serialization import IRType, OpenQASMSerializationProperties +from braket.registers.qubit_set import QubitSet class H(StandardObservable): diff --git a/src/braket/circuits/qubit.py b/src/braket/circuits/qubit.py index 479a453e3..f82e91fa0 100644 --- a/src/braket/circuits/qubit.py +++ b/src/braket/circuits/qubit.py @@ -11,58 +11,4 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -from __future__ import annotations - -import numbers -from typing import Union - -QubitInput = Union["Qubit", int] - - -class Qubit(int): - """ - A quantum bit index. The index of this qubit is locally scoped towards the contained - circuit. This may not be the exact qubit index on the quantum device. - """ - - def __new__(cls, index: int): - """ - Args: - index (int): Index of the qubit. - - Raises: - ValueError: If `index` is less than zero. - - Examples: - >>> Qubit(0) - >>> Qubit(1) - """ - if not isinstance(index, numbers.Integral): - raise TypeError(f"Supplied qubit index, {index}, must be an integer.") - if index < 0: - raise ValueError(f"Supplied qubit index, {index}, cannot be less than zero.") - return super().__new__(cls, index) - - def __repr__(self): - return f"Qubit({super().__repr__()})" - - def __str__(self): - return self.__repr__() - - @staticmethod - def new(qubit: QubitInput) -> Qubit: - """ - Helper constructor - if input is a `Qubit` it returns the same value, - else a new `Qubit` is constructed. - - Args: - qubit (QubitInput): `Qubit` index. If `type == Qubit` then the `qubit` is returned. - - Returns: - Qubit: The qubit. - """ - - if isinstance(qubit, Qubit): - return qubit - else: - return Qubit(qubit) +from braket.registers import Qubit, QubitInput # noqa: F401 diff --git a/src/braket/circuits/qubit_set.py b/src/braket/circuits/qubit_set.py index d4571e91a..b2c1bbfc3 100644 --- a/src/braket/circuits/qubit_set.py +++ b/src/braket/circuits/qubit_set.py @@ -11,83 +11,4 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -from __future__ import annotations - -from typing import Any, Dict, Iterable, Union - -from boltons.setutils import IndexedSet - -from braket.circuits.qubit import Qubit, QubitInput - -QubitSetInput = Union[QubitInput, Iterable[QubitInput]] - - -def _flatten(other: Any) -> Any: - if isinstance(other, Iterable) and not isinstance(other, str): - for item in other: - yield from _flatten(item) - else: - yield other - - -class QubitSet(IndexedSet): - """ - An ordered, unique set of quantum bits. - - Note: - QubitSet implements `__hash__()` but is a mutable object, therefore be careful when - mutating this object. - """ - - def __init__(self, qubits: QubitSetInput = None): - """ - Args: - qubits (QubitSetInput): Qubits to be included in the `QubitSet`. Default is `None`. - - Examples: - >>> qubits = QubitSet([0, 1]) - >>> for qubit in qubits: - ... print(qubit) - ... - Qubit(0) - Qubit(1) - - >>> qubits = QubitSet([0, 1, [2, 3]]) - >>> for qubit in qubits: - ... print(qubit) - ... - Qubit(0) - Qubit(1) - Qubit(2) - Qubit(3) - """ - - _qubits = [Qubit.new(qubit) for qubit in _flatten(qubits)] if qubits is not None else None - super().__init__(_qubits) - - def map(self, mapping: Dict[QubitInput, QubitInput]) -> QubitSet: - """ - Creates a new `QubitSet` where this instance's qubits are mapped to the values in `mapping`. - If this instance contains a qubit that is not in the `mapping` that qubit is not modified. - - Args: - mapping (Dict[QubitInput, QubitInput]): A dictionary of qubit mappings to - apply. Key is the qubit in this instance to target, and the value is what - the key will be changed to. - - Returns: - QubitSet: A new QubitSet with the `mapping` applied. - - Examples: - >>> qubits = QubitSet([0, 1]) - >>> mapping = {0: 10, Qubit(1): Qubit(11)} - >>> qubits.map(mapping) - QubitSet([Qubit(10), Qubit(11)]) - """ - - new_qubits = [mapping.get(qubit, qubit) for qubit in self] - - return QubitSet(new_qubits) - - def __hash__(self): - return hash(tuple(self)) +from braket.registers.qubit_set import QubitSet, QubitSetInput # noqa: F401 diff --git a/src/braket/circuits/result_type.py b/src/braket/circuits/result_type.py index d711e273b..787d9ee0d 100644 --- a/src/braket/circuits/result_type.py +++ b/src/braket/circuits/result_type.py @@ -18,13 +18,13 @@ from braket.circuits.free_parameter import FreeParameter from braket.circuits.observable import Observable from braket.circuits.observables import Sum -from braket.circuits.qubit import QubitInput -from braket.circuits.qubit_set import QubitSet, QubitSetInput from braket.circuits.serialization import ( IRType, OpenQASMSerializationProperties, SerializationProperties, ) +from braket.registers.qubit import QubitInput +from braket.registers.qubit_set import QubitSet, QubitSetInput class ResultType: diff --git a/src/braket/circuits/result_types.py b/src/braket/circuits/result_types.py index d73c7fbda..25ff63716 100644 --- a/src/braket/circuits/result_types.py +++ b/src/braket/circuits/result_types.py @@ -22,13 +22,13 @@ from braket.circuits.free_parameter import FreeParameter from braket.circuits.observable import Observable from braket.circuits.observables import Sum -from braket.circuits.qubit_set import QubitSet, QubitSetInput from braket.circuits.result_type import ( ObservableParameterResultType, ObservableResultType, ResultType, ) from braket.circuits.serialization import IRType, OpenQASMSerializationProperties +from braket.registers.qubit_set import QubitSet, QubitSetInput """ To add a new result type: diff --git a/src/braket/circuits/unitary_calculation.py b/src/braket/circuits/unitary_calculation.py index 628d230e9..2059976e9 100644 --- a/src/braket/circuits/unitary_calculation.py +++ b/src/braket/circuits/unitary_calculation.py @@ -19,8 +19,8 @@ from braket.circuits.compiler_directive import CompilerDirective from braket.circuits.gate import Gate from braket.circuits.instruction import Instruction -from braket.circuits.qubit_set import QubitSet from braket.default_simulator.linalg_utils import multiply_matrix +from braket.registers.qubit_set import QubitSet def _einsum_subscripts(targets: QubitSet, qubit_count: int) -> str: diff --git a/src/braket/pulse/pulse_sequence.py b/src/braket/pulse/pulse_sequence.py index 3606bbd11..0a3dba154 100644 --- a/src/braket/pulse/pulse_sequence.py +++ b/src/braket/pulse/pulse_sequence.py @@ -22,7 +22,6 @@ from oqpy import BitVar, PhysicalQubits, Program from oqpy.timing import OQDurationLiteral -from braket.circuits.qubit_set import QubitSet from braket.parametric.free_parameter import FreeParameter from braket.parametric.free_parameter_expression import FreeParameterExpression from braket.parametric.parameterizable import Parameterizable @@ -36,6 +35,7 @@ from braket.pulse.frame import Frame from braket.pulse.pulse_sequence_trace import PulseSequenceTrace from braket.pulse.waveforms import Waveform +from braket.registers.qubit_set import QubitSet class PulseSequence: diff --git a/src/braket/registers/__init__.py b/src/braket/registers/__init__.py new file mode 100644 index 000000000..0f433333b --- /dev/null +++ b/src/braket/registers/__init__.py @@ -0,0 +1,15 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file 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. + +from braket.registers.qubit import Qubit, QubitInput # noqa: F401 +from braket.registers.qubit_set import QubitSet, QubitSetInput # noqa: F401 diff --git a/src/braket/registers/qubit.py b/src/braket/registers/qubit.py new file mode 100644 index 000000000..479a453e3 --- /dev/null +++ b/src/braket/registers/qubit.py @@ -0,0 +1,68 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file 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. + +from __future__ import annotations + +import numbers +from typing import Union + +QubitInput = Union["Qubit", int] + + +class Qubit(int): + """ + A quantum bit index. The index of this qubit is locally scoped towards the contained + circuit. This may not be the exact qubit index on the quantum device. + """ + + def __new__(cls, index: int): + """ + Args: + index (int): Index of the qubit. + + Raises: + ValueError: If `index` is less than zero. + + Examples: + >>> Qubit(0) + >>> Qubit(1) + """ + if not isinstance(index, numbers.Integral): + raise TypeError(f"Supplied qubit index, {index}, must be an integer.") + if index < 0: + raise ValueError(f"Supplied qubit index, {index}, cannot be less than zero.") + return super().__new__(cls, index) + + def __repr__(self): + return f"Qubit({super().__repr__()})" + + def __str__(self): + return self.__repr__() + + @staticmethod + def new(qubit: QubitInput) -> Qubit: + """ + Helper constructor - if input is a `Qubit` it returns the same value, + else a new `Qubit` is constructed. + + Args: + qubit (QubitInput): `Qubit` index. If `type == Qubit` then the `qubit` is returned. + + Returns: + Qubit: The qubit. + """ + + if isinstance(qubit, Qubit): + return qubit + else: + return Qubit(qubit) diff --git a/src/braket/registers/qubit_set.py b/src/braket/registers/qubit_set.py new file mode 100644 index 000000000..ea012bc27 --- /dev/null +++ b/src/braket/registers/qubit_set.py @@ -0,0 +1,93 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file 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. + +from __future__ import annotations + +from typing import Any, Dict, Iterable, Union + +from boltons.setutils import IndexedSet + +from braket.registers.qubit import Qubit, QubitInput + +QubitSetInput = Union[QubitInput, Iterable[QubitInput]] + + +def _flatten(other: Any) -> Any: + if isinstance(other, Iterable) and not isinstance(other, str): + for item in other: + yield from _flatten(item) + else: + yield other + + +class QubitSet(IndexedSet): + """ + An ordered, unique set of quantum bits. + + Note: + QubitSet implements `__hash__()` but is a mutable object, therefore be careful when + mutating this object. + """ + + def __init__(self, qubits: QubitSetInput = None): + """ + Args: + qubits (QubitSetInput): Qubits to be included in the `QubitSet`. Default is `None`. + + Examples: + >>> qubits = QubitSet([0, 1]) + >>> for qubit in qubits: + ... print(qubit) + ... + Qubit(0) + Qubit(1) + + >>> qubits = QubitSet([0, 1, [2, 3]]) + >>> for qubit in qubits: + ... print(qubit) + ... + Qubit(0) + Qubit(1) + Qubit(2) + Qubit(3) + """ + + _qubits = [Qubit.new(qubit) for qubit in _flatten(qubits)] if qubits is not None else None + super().__init__(_qubits) + + def map(self, mapping: Dict[QubitInput, QubitInput]) -> QubitSet: + """ + Creates a new `QubitSet` where this instance's qubits are mapped to the values in `mapping`. + If this instance contains a qubit that is not in the `mapping` that qubit is not modified. + + Args: + mapping (Dict[QubitInput, QubitInput]): A dictionary of qubit mappings to + apply. Key is the qubit in this instance to target, and the value is what + the key will be changed to. + + Returns: + QubitSet: A new QubitSet with the `mapping` applied. + + Examples: + >>> qubits = QubitSet([0, 1]) + >>> mapping = {0: 10, Qubit(1): Qubit(11)} + >>> qubits.map(mapping) + QubitSet([Qubit(10), Qubit(11)]) + """ + + new_qubits = [mapping.get(qubit, qubit) for qubit in self] + + return QubitSet(new_qubits) + + def __hash__(self): + return hash(tuple(self)) diff --git a/test/unit_tests/braket/circuits/test_noise_helpers.py b/test/unit_tests/braket/circuits/test_noise_helpers.py index 421cf69c0..f2c956eab 100644 --- a/test/unit_tests/braket/circuits/test_noise_helpers.py +++ b/test/unit_tests/braket/circuits/test_noise_helpers.py @@ -20,7 +20,7 @@ from braket.circuits.moments import Moments from braket.circuits.noise import Noise from braket.circuits.noise_helpers import apply_noise_to_gates, apply_noise_to_moments -from braket.circuits.qubit_set import QubitSet +from braket.registers.qubit_set import QubitSet invalid_data_noise_type = [Gate.X(), None, 1.5] invalid_data_target_gates_type = [[-1, "foo"], [1.5, None, -1], "X", [Gate.X, "CNot"]] diff --git a/test/unit_tests/braket/pulse/ast/test_approximation_parser.py b/test/unit_tests/braket/pulse/ast/test_approximation_parser.py index 786c6b7e6..c4199e81b 100644 --- a/test/unit_tests/braket/pulse/ast/test_approximation_parser.py +++ b/test/unit_tests/braket/pulse/ast/test_approximation_parser.py @@ -19,12 +19,12 @@ from openpulse import ast from oqpy import IntVar -from braket.circuits.qubit_set import QubitSet from braket.pulse import ArbitraryWaveform, ConstantWaveform, DragGaussianWaveform, GaussianWaveform from braket.pulse.ast.approximation_parser import _ApproximationParser from braket.pulse.frame import Frame from braket.pulse.port import Port from braket.pulse.pulse_sequence import PulseSequence +from braket.registers.qubit_set import QubitSet from braket.timings.time_series import TimeSeries, _all_close diff --git a/test/unit_tests/braket/circuits/test_qubit.py b/test/unit_tests/braket/registers/test_qubit.py similarity index 97% rename from test/unit_tests/braket/circuits/test_qubit.py rename to test/unit_tests/braket/registers/test_qubit.py index b961986c1..98f89cf8d 100644 --- a/test/unit_tests/braket/circuits/test_qubit.py +++ b/test/unit_tests/braket/registers/test_qubit.py @@ -14,7 +14,7 @@ import numpy as np import pytest -from braket.circuits import Qubit +from braket.registers import Qubit @pytest.fixture diff --git a/test/unit_tests/braket/circuits/test_qubit_set.py b/test/unit_tests/braket/registers/test_qubit_set.py similarity index 97% rename from test/unit_tests/braket/circuits/test_qubit_set.py rename to test/unit_tests/braket/registers/test_qubit_set.py index 4a7eda395..1fd8d7212 100644 --- a/test/unit_tests/braket/circuits/test_qubit_set.py +++ b/test/unit_tests/braket/registers/test_qubit_set.py @@ -13,7 +13,7 @@ import pytest -from braket.circuits import Qubit, QubitSet +from braket.registers import Qubit, QubitSet @pytest.fixture