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.gate import Gate
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"
25# InstructionOperator is a type alias, and it can be expanded to include other operators
26InstructionOperator = Gate
29class Instruction:
30 """
31 An instruction is a quantum directive that describes the task to perform on a quantum device.
32 """
34 def __init__(self, operator: InstructionOperator, target: QubitSetInput):
35 """
36 InstructionOperator includes objects of type Gate only.
38 Args:
39 operator (InstructionOperator): Operator for the instruction.
40 target (int, Qubit, or iterable of int / Qubit): Target qubits that the operator is
41 applied to.
43 Raises:
44 ValueError: If `operator` is empty or any integer in `target` does not meet the Qubit
45 or QubitSet class requirements.
46 TypeError: If a Qubit class can't be constructed from `target` due to an incorrect
47 `typing`.
49 Examples:
50 >>> Instruction(Gate.CNot(), [0, 1])
51 Instruction('operator': CNOT, 'target': QubitSet(Qubit(0), Qubit(1)))
52 >>> instr = Instruction(Gate.CNot()), QubitSet([0, 1])])
53 Instruction('operator': CNOT, 'target': QubitSet(Qubit(0), Qubit(1)))
54 >>> instr = Instruction(Gate.H(), 0)
55 Instruction('operator': H, 'target': QubitSet(Qubit(0),))
56 >>> instr = Instruction(Gate.Rx(0.12), 0)
57 Instruction('operator': Rx, 'target': QubitSet(Qubit(0),))
58 """
59 if not operator:
60 raise ValueError("Operator cannot be empty")
61 self._operator = operator
62 self._target = QubitSet(target)
64 @property
65 def operator(self) -> InstructionOperator:
66 """Operator: The operator for the instruction, for example, `Gate`."""
67 return self._operator
69 @property
70 def target(self) -> QubitSet:
71 """
72 QubitSet: Target qubits that the operator is applied to.
74 Note:
75 Don't mutate this property, any mutations can have unexpected consequences.
76 """
77 return self._target
79 def to_ir(self):
80 """
81 Converts the operator into the canonical intermediate representation.
82 If the operator is passed in a request, this method is called before it is passed.
83 """
84 return self._operator.to_ir([int(qubit) for qubit in self._target])
86 def copy(
87 self, target_mapping: Dict[QubitInput, QubitInput] = {}, target: QubitSetInput = None
88 ) -> Instruction:
89 """
90 Return a shallow copy of the instruction.
92 Note:
93 If `target_mapping` is specified, then `self.target` is mapped to the specified
94 qubits. This is useful apply an instruction to a circuit and change the target qubits.
96 Args:
97 target_mapping (dictionary[int or Qubit, int or Qubit], optional): A dictionary of
98 qubit mappings to apply to the target. Key is the qubit in this `target` and the
99 value is what the key is changed to. Default = {}.
100 target (int, Qubit, or iterable of int / Qubit, optional): Target qubits for the new
101 instruction.
103 Returns:
104 Instruction: A shallow copy of the instruction.
106 Raises:
107 TypeError: If both `target_mapping` and `target` are supplied.
109 Examples:
110 >>> instr = Instruction(Gate.H(), 0)
111 >>> new_instr = instr.copy()
112 >>> new_instr.target
113 QubitSet(Qubit(0))
114 >>> new_instr = instr.copy(target_mapping={0: 5})
115 >>> new_instr.target
116 QubitSet(Qubit(5))
117 >>> new_instr = instr.copy(target=[5])
118 >>> new_instr.target
119 QubitSet(Qubit(5))
120 """
121 if target_mapping and target is not None:
122 raise TypeError("Only 'target_mapping' or 'target' can be supplied, but not both.")
123 elif target is not None:
124 return Instruction(self._operator, target)
125 else:
126 return Instruction(self._operator, self._target.map(target_mapping))
128 def __repr__(self):
129 return f"Instruction('operator': {self._operator}, 'target': {self._target})"
131 def __eq__(self, other):
132 if isinstance(other, Instruction):
133 return (self._operator, self._target) == (other._operator, other._target)
134 return NotImplemented