Coverage for src/braket/circuits/instruction.py : 100%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Copyright 2019-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"). You
4# may not use this file except in compliance with the License. A copy of
5# the License is located at
6#
7# http://aws.amazon.com/apache2.0/
8#
9# or in the "license" file accompanying this file. This file is
10# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11# ANY KIND, either express or implied. See the License for the specific
12# language governing permissions and limitations under the License.
14from __future__ import annotations
16from typing import Dict
18from braket.circuits.operator import Operator
19from braket.circuits.qubit import QubitInput
20from braket.circuits.qubit_set import QubitSet, QubitSetInput
22# TODO: Add parameters support
23# TODO: Rename to QuantumInstruction, and change Operator to Gate, then rename "target" to "qubits"
26class Instruction:
27 """
28 An instruction is a quantum directive that describes the task to perform on a quantum device.
29 """
31 def __init__(self, operator: Operator, target: QubitSetInput):
32 """
33 Args:
34 operator (Operator): Operator for the instruction.
35 target (int, Qubit, or iterable of int / Qubit): Target qubits that the operator is
36 applied to.
38 Raises:
39 ValueError: If `operator` is empty or any integer in `target` does not meet the Qubit
40 or QubitSet class requirements.
41 TypeError: If a Qubit class can't be constructed from `target` due to an incorrect
42 `typing`.
44 Examples:
45 >>> Instruction(Gate.CNot(), [0, 1])
46 Instruction('operator': CNOT, 'target': QubitSet(Qubit(0), Qubit(1)))
47 >>> instr = Instruction(Gate.CNot()), QubitSet([0, 1])])
48 Instruction('operator': CNOT, 'target': QubitSet(Qubit(0), Qubit(1)))
49 >>> instr = Instruction(Gate.H(), 0)
50 Instruction('operator': H, 'target': QubitSet(Qubit(0),))
51 >>> instr = Instruction(Gate.Rx(0.12), 0)
52 Instruction('operator': Rx, 'target': QubitSet(Qubit(0),))
53 """
54 if not operator:
55 raise ValueError("Operator cannot be empty")
56 self._operator = operator
57 self._target = QubitSet(target)
59 @property
60 def operator(self) -> Operator:
61 """Operator: The operator for the instruction, for example, `Gate`."""
62 return self._operator
64 @property
65 def target(self) -> QubitSet:
66 """
67 QubitSet: Target qubits that the operator is applied to.
69 Note:
70 Don't mutate this property, any mutations can have unexpected consequences.
71 """
72 return self._target
74 def to_ir(self):
75 """
76 Converts the operator into the canonical intermediate representation.
77 If the operator is passed in a request, this method is called before it is passed.
78 """
79 return self._operator.to_ir([int(qubit) for qubit in self._target])
81 def copy(
82 self, target_mapping: Dict[QubitInput, QubitInput] = {}, target: QubitSetInput = None
83 ) -> Instruction:
84 """
85 Return a shallow copy of the instruction.
87 Note:
88 If `target_mapping` is specified, then `self.target` is mapped to the specified
89 qubits. This is useful apply an instruction to a circuit and change the target qubits.
91 Args:
92 target_mapping (dictionary[int or Qubit, int or Qubit], optional): A dictionary of
93 qubit mappings to apply to the target. Key is the qubit in this `target` and the
94 value is what the key is changed to. Default = {}.
95 target (int, Qubit, or iterable of int / Qubit, optional): Target qubits for the new
96 instruction.
98 Returns:
99 Instruction: A shallow copy of the instruction.
101 Raises:
102 TypeError: If both `target_mapping` and `target` are supplied.
104 Examples:
105 >>> instr = Instruction(Gate.H(), 0)
106 >>> new_instr = instr.copy()
107 >>> new_instr.target
108 QubitSet(Qubit(0))
109 >>> new_instr = instr.copy(target_mapping={0: 5})
110 >>> new_instr.target
111 QubitSet(Qubit(5))
112 >>> new_instr = instr.copy(target=[5])
113 >>> new_instr.target
114 QubitSet(Qubit(5))
115 """
116 if target_mapping and target is not None:
117 raise TypeError("Only 'target_mapping' or 'target' can be supplied, but not both.")
118 elif target is not None:
119 return Instruction(self._operator, target)
120 else:
121 return Instruction(self._operator, self._target.map(target_mapping))
123 def __repr__(self):
124 return f"Instruction('operator': {self._operator}, 'target': {self._target})"
126 def __eq__(self, other):
127 if isinstance(other, Instruction):
128 return (self._operator, self._target) == (other._operator, other._target)
129 return NotImplemented