Coverage for src/braket/circuits/gates.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 typing import Iterable
16import braket.ir.jaqcd as ir
17import numpy as np
18from braket.circuits import circuit
19from braket.circuits.angled_gate import AngledGate
20from braket.circuits.gate import Gate
21from braket.circuits.instruction import Instruction
22from braket.circuits.quantum_operator_helpers import (
23 is_unitary,
24 verify_quantum_operator_matrix_dimensions,
25)
26from braket.circuits.qubit import QubitInput
27from braket.circuits.qubit_set import QubitSet, QubitSetInput
29"""
30To add a new gate:
31 1. Implement the class and extend `Gate`
32 2. Add a method with the `@circuit.subroutine(register=True)` decorator. Method name
33 will be added into the `Circuit` class. This method is the default way
34 clients add this gate to a circuit.
35 3. Register the class with the `Gate` class via `Gate.register_gate()`.
36"""
38# Single qubit gates #
41class H(Gate):
42 """Hadamard gate."""
44 def __init__(self):
45 super().__init__(qubit_count=1, ascii_symbols=["H"])
47 def to_ir(self, target: QubitSet):
48 return ir.H.construct(target=target[0])
50 def to_matrix(self) -> np.ndarray:
51 return 1.0 / np.sqrt(2.0) * np.array([[1.0, 1.0], [1.0, -1.0]], dtype=complex)
53 @staticmethod
54 @circuit.subroutine(register=True)
55 def h(target: QubitSetInput) -> Iterable[Instruction]:
56 """Registers this function into the circuit class.
58 Args:
59 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
61 Returns:
62 Iterable[Instruction]: `Iterable` of H instructions.
64 Examples:
65 >>> circ = Circuit().h(0)
66 >>> circ = Circuit().h([0, 1, 2])
67 """
68 return [Instruction(Gate.H(), target=qubit) for qubit in QubitSet(target)]
71Gate.register_gate(H)
74class I(Gate): # noqa: E742, E261
75 """Identity gate."""
77 def __init__(self):
78 super().__init__(qubit_count=1, ascii_symbols=["I"])
80 def to_ir(self, target: QubitSet):
81 return ir.I.construct(target=target[0])
83 def to_matrix(self) -> np.ndarray:
84 return np.array([[1.0, 0.0], [0.0, 1.0]], dtype=complex)
86 @staticmethod
87 @circuit.subroutine(register=True)
88 def i(target: QubitSetInput) -> Iterable[Instruction]:
89 """Registers this function into the circuit class.
91 Args:
92 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
94 Returns:
95 Iterable[Instruction]: `Iterable` of I instructions.
97 Examples:
98 >>> circ = Circuit().i(0)
99 >>> circ = Circuit().i([0, 1, 2])
100 """
101 return [Instruction(Gate.I(), target=qubit) for qubit in QubitSet(target)]
104Gate.register_gate(I)
107class X(Gate):
108 """Pauli-X gate."""
110 def __init__(self):
111 super().__init__(qubit_count=1, ascii_symbols=["X"])
113 def to_ir(self, target: QubitSet):
114 return ir.X.construct(target=target[0])
116 def to_matrix(self) -> np.ndarray:
117 return np.array([[0.0, 1.0], [1.0, 0.0]], dtype=complex)
119 @staticmethod
120 @circuit.subroutine(register=True)
121 def x(target: QubitSetInput) -> Iterable[Instruction]:
122 """Registers this function into the circuit class.
124 Args:
125 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
127 Returns:
128 Iterable[Instruction]: `Iterable` of X instructions.
130 Examples:
131 >>> circ = Circuit().x(0)
132 >>> circ = Circuit().x([0, 1, 2])
133 """
134 return [Instruction(Gate.X(), target=qubit) for qubit in QubitSet(target)]
137Gate.register_gate(X)
140class Y(Gate):
141 """Pauli-Y gate."""
143 def __init__(self):
144 super().__init__(qubit_count=1, ascii_symbols=["Y"])
146 def to_ir(self, target: QubitSet):
147 return ir.Y.construct(target=target[0])
149 def to_matrix(self) -> np.ndarray:
150 return np.array([[0.0, -1.0j], [1.0j, 0.0]], dtype=complex)
152 @staticmethod
153 @circuit.subroutine(register=True)
154 def y(target: QubitSetInput) -> Iterable[Instruction]:
155 """Registers this function into the circuit class.
157 Args:
158 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
160 Returns:
161 Iterable[Instruction]: `Iterable` of Y instructions.
163 Examples:
164 >>> circ = Circuit().y(0)
165 >>> circ = Circuit().y([0, 1, 2])
166 """
167 return [Instruction(Gate.Y(), target=qubit) for qubit in QubitSet(target)]
170Gate.register_gate(Y)
173class Z(Gate):
174 """Pauli-Z gate."""
176 def __init__(self):
177 super().__init__(qubit_count=1, ascii_symbols=["Z"])
179 def to_ir(self, target: QubitSet):
180 return ir.Z.construct(target=target[0])
182 def to_matrix(self) -> np.ndarray:
183 return np.array([[1.0, 0.0], [0.0, -1.0]], dtype=complex)
185 @staticmethod
186 @circuit.subroutine(register=True)
187 def z(target: QubitSetInput) -> Iterable[Instruction]:
188 """Registers this function into the circuit class.
190 Args:
191 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
193 Returns:
194 Iterable[Instruction]: `Iterable` of Z instructions.
196 Examples:
197 >>> circ = Circuit().z(0)
198 >>> circ = Circuit().z([0, 1, 2])
199 """
200 return [Instruction(Gate.Z(), target=qubit) for qubit in QubitSet(target)]
203Gate.register_gate(Z)
206class S(Gate):
207 """S gate."""
209 def __init__(self):
210 super().__init__(qubit_count=1, ascii_symbols=["S"])
212 def to_ir(self, target: QubitSet):
213 return ir.S.construct(target=target[0])
215 def to_matrix(self) -> np.ndarray:
217 return np.array([[1.0, 0.0], [0.0, 1.0j]], dtype=complex)
219 @staticmethod
220 @circuit.subroutine(register=True)
221 def s(target: QubitSetInput) -> Iterable[Instruction]:
222 """Registers this function into the circuit class.
224 Args:
225 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
227 Returns:
228 Iterable[Instruction]: `Iterable` of S instructions.
230 Examples:
231 >>> circ = Circuit().s(0)
232 >>> circ = Circuit().s([0, 1, 2])
233 """
234 return [Instruction(Gate.S(), target=qubit) for qubit in QubitSet(target)]
237Gate.register_gate(S)
240class Si(Gate):
241 """Conjugate transpose of S gate."""
243 def __init__(self):
244 super().__init__(qubit_count=1, ascii_symbols=["Si"])
246 def to_ir(self, target: QubitSet):
247 return ir.Si.construct(target=target[0])
249 def to_matrix(self) -> np.ndarray:
250 return np.array([[1, 0], [0, -1j]], dtype=complex)
252 @staticmethod
253 @circuit.subroutine(register=True)
254 def si(target: QubitSetInput) -> Iterable[Instruction]:
255 """Registers this function into the circuit class.
257 Args:
258 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
260 Returns:
261 Iterable[Instruction]: Iterable of Si instructions.
263 Examples:
264 >>> circ = Circuit().si(0)
265 >>> circ = Circuit().si([0, 1, 2])
266 """
267 return [Instruction(Gate.Si(), target=qubit) for qubit in QubitSet(target)]
270Gate.register_gate(Si)
273class T(Gate):
274 """T gate."""
276 def __init__(self):
277 super().__init__(qubit_count=1, ascii_symbols=["T"])
279 def to_ir(self, target: QubitSet):
280 return ir.T.construct(target=target[0])
282 def to_matrix(self) -> np.ndarray:
283 return np.array([[1.0, 0.0], [0.0, np.exp(1j * np.pi / 4)]], dtype=complex)
285 @staticmethod
286 @circuit.subroutine(register=True)
287 def t(target: QubitSetInput) -> Iterable[Instruction]:
288 """Registers this function into the circuit class.
290 Args:
291 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
293 Returns:
294 Iterable[Instruction]: `Iterable` of T instructions.
296 Examples:
297 >>> circ = Circuit().t(0)
298 >>> circ = Circuit().t([0, 1, 2])
299 """
300 return [Instruction(Gate.T(), target=qubit) for qubit in QubitSet(target)]
303Gate.register_gate(T)
306class Ti(Gate):
307 """Conjugate transpose of T gate."""
309 def __init__(self):
310 super().__init__(qubit_count=1, ascii_symbols=["Ti"])
312 def to_ir(self, target: QubitSet):
313 return ir.Ti.construct(target=target[0])
315 def to_matrix(self) -> np.ndarray:
316 return np.array([[1.0, 0.0], [0.0, np.exp(-1j * np.pi / 4)]], dtype=complex)
318 @staticmethod
319 @circuit.subroutine(register=True)
320 def ti(target: QubitSetInput) -> Iterable[Instruction]:
321 """Registers this function into the circuit class.
323 Args:
324 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
326 Returns:
327 Iterable[Instruction]: `Iterable` of Ti instructions.
329 Examples:
330 >>> circ = Circuit().ti(0)
331 >>> circ = Circuit().ti([0, 1, 2])
332 """
333 return [Instruction(Gate.Ti(), target=qubit) for qubit in QubitSet(target)]
336Gate.register_gate(Ti)
339class V(Gate):
340 """Square root of not gate."""
342 def __init__(self):
343 super().__init__(qubit_count=1, ascii_symbols=["V"])
345 def to_ir(self, target: QubitSet):
346 return ir.V.construct(target=target[0])
348 def to_matrix(self) -> np.ndarray:
349 return np.array([[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]], dtype=complex)
351 @staticmethod
352 @circuit.subroutine(register=True)
353 def v(target: QubitSetInput) -> Iterable[Instruction]:
354 """Registers this function into the circuit class.
356 Args:
357 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
359 Returns:
360 Iterable[Instruction]: `Iterable` of V instructions.
362 Examples:
363 >>> circ = Circuit().v(0)
364 >>> circ = Circuit().v([0, 1, 2])
365 """
366 return [Instruction(Gate.V(), target=qubit) for qubit in QubitSet(target)]
369Gate.register_gate(V)
372class Vi(Gate):
373 """Conjugate transpose of square root of not gate."""
375 def __init__(self):
376 super().__init__(qubit_count=1, ascii_symbols=["Vi"])
378 def to_ir(self, target: QubitSet):
379 return ir.Vi.construct(target=target[0])
381 def to_matrix(self) -> np.ndarray:
382 return np.array(([[0.5 - 0.5j, 0.5 + 0.5j], [0.5 + 0.5j, 0.5 - 0.5j]]), dtype=complex)
384 @staticmethod
385 @circuit.subroutine(register=True)
386 def vi(target: QubitSetInput) -> Iterable[Instruction]:
387 """Registers this function into the circuit class.
389 Args:
390 target (Qubit, int, or iterable of Qubit / int): Target qubit(s)
392 Returns:
393 Iterable[Instruction]: `Iterable` of Vi instructions.
395 Examples:
396 >>> circ = Circuit().vi(0)
397 >>> circ = Circuit().vi([0, 1, 2])
398 """
399 return [Instruction(Gate.Vi(), target=qubit) for qubit in QubitSet(target)]
402Gate.register_gate(Vi)
405# Single qubit gates with rotation #
408class Rx(AngledGate):
409 """X-axis rotation gate.
411 Args:
412 angle (float): angle in radians.
413 """
415 def __init__(self, angle: float):
416 super().__init__(angle=angle, qubit_count=1, ascii_symbols=["Rx({:.3g})".format(angle)])
418 def to_ir(self, target: QubitSet):
419 return ir.Rx.construct(target=target[0], angle=self.angle)
421 def to_matrix(self) -> np.ndarray:
422 cos = np.cos(self.angle / 2)
423 sin = np.sin(self.angle / 2)
424 return np.array([[cos, -1j * sin], [-1j * sin, cos]], dtype=complex)
426 @staticmethod
427 @circuit.subroutine(register=True)
428 def rx(target: QubitInput, angle: float) -> Instruction:
429 """Registers this function into the circuit class.
431 Args:
432 target (Qubit or int): Target qubit index.
433 angle (float): Angle in radians.
435 Returns:
436 Instruction: Rx instruction.
438 Examples:
439 >>> circ = Circuit().rx(0, 0.15)
440 """
441 return [Instruction(Gate.Rx(angle), target=qubit) for qubit in QubitSet(target)]
444Gate.register_gate(Rx)
447class Ry(AngledGate):
448 """Y-axis rotation gate.
450 Args:
451 angle (float): angle in radians.
452 """
454 def __init__(self, angle: float):
455 super().__init__(angle=angle, qubit_count=1, ascii_symbols=["Ry({:.3g})".format(angle)])
457 def to_ir(self, target: QubitSet):
458 return ir.Ry.construct(target=target[0], angle=self.angle)
460 def to_matrix(self) -> np.ndarray:
461 cos = np.cos(self.angle / 2)
462 sin = np.sin(self.angle / 2)
463 return np.array([[cos, -sin], [+sin, cos]], dtype=complex)
465 @staticmethod
466 @circuit.subroutine(register=True)
467 def ry(target: QubitInput, angle: float) -> Instruction:
468 """Registers this function into the circuit class.
470 Args:
471 target (Qubit or int): Target qubit index.
472 angle (float): Angle in radians.
474 Returns:
475 Instruction: Ry instruction.
477 Examples:
478 >>> circ = Circuit().ry(0, 0.15)
479 """
480 return [Instruction(Gate.Ry(angle), target=qubit) for qubit in QubitSet(target)]
483Gate.register_gate(Ry)
486class Rz(AngledGate):
487 """Z-axis rotation gate.
489 Args:
490 angle (float): angle in radians.
491 """
493 def __init__(self, angle: float):
494 super().__init__(angle=angle, qubit_count=1, ascii_symbols=["Rz({:.3g})".format(angle)])
496 def to_ir(self, target: QubitSet):
497 return ir.Rz.construct(target=target[0], angle=self.angle)
499 def to_matrix(self) -> np.ndarray:
500 return np.array(
501 [[np.exp(-1j * self.angle / 2), 0], [0, np.exp(1j * self.angle / 2)]], dtype=complex
502 )
504 @staticmethod
505 @circuit.subroutine(register=True)
506 def rz(target: QubitInput, angle: float) -> Instruction:
507 """Registers this function into the circuit class.
509 Args:
510 target (Qubit or int): Target qubit index.
511 angle (float): Angle in radians.
513 Returns:
514 Instruction: Rz instruction.
516 Examples:
517 >>> circ = Circuit().rz(0, 0.15)
518 """
519 return [Instruction(Gate.Rz(angle), target=qubit) for qubit in QubitSet(target)]
522Gate.register_gate(Rz)
525class PhaseShift(AngledGate):
526 """Phase shift gate.
528 Args:
529 angle (float): angle in radians.
530 """
532 def __init__(self, angle: float):
533 super().__init__(angle=angle, qubit_count=1, ascii_symbols=["PHASE({:.3g})".format(angle)])
535 def to_ir(self, target: QubitSet):
536 return ir.PhaseShift.construct(target=target[0], angle=self.angle)
538 def to_matrix(self) -> np.ndarray:
539 return np.array([[1.0, 0.0], [0.0, np.exp(1j * self.angle)]], dtype=complex)
541 @staticmethod
542 @circuit.subroutine(register=True)
543 def phaseshift(target: QubitInput, angle: float) -> Instruction:
544 """Registers this function into the circuit class.
546 Args:
547 target (Qubit or int): Target qubit index.
548 angle (float): Angle in radians.
550 Returns:
551 Instruction: PhaseShift instruction.
553 Examples:
554 >>> circ = Circuit().phaseshift(0, 0.15)
555 """
556 return [Instruction(Gate.PhaseShift(angle), target=qubit) for qubit in QubitSet(target)]
559Gate.register_gate(PhaseShift)
562# Two qubit gates #
565class CNot(Gate):
566 """Controlled NOT gate."""
568 def __init__(self):
569 super().__init__(qubit_count=2, ascii_symbols=["C", "X"])
571 def to_ir(self, target: QubitSet):
572 return ir.CNot.construct(control=target[0], target=target[1])
574 def to_matrix(self) -> np.ndarray:
575 return np.array(
576 [
577 [1.0, 0.0, 0.0, 0.0],
578 [0.0, 1.0, 0.0, 0.0],
579 [0.0, 0.0, 0.0, 1.0],
580 [0.0, 0.0, 1.0, 0.0],
581 ],
582 dtype=complex,
583 )
585 @staticmethod
586 @circuit.subroutine(register=True)
587 def cnot(control: QubitInput, target: QubitInput) -> Instruction:
588 """Registers this function into the circuit class.
590 Args:
591 control (Qubit or int): Control qubit index.
592 target (Qubit or int): Target qubit index.
594 Returns:
595 Instruction: CNot instruction.
597 Examples:
598 >>> circ = Circuit().cnot(0, 1)
599 """
600 return Instruction(Gate.CNot(), target=[control, target])
603Gate.register_gate(CNot)
606class Swap(Gate):
607 """Swap gate."""
609 def __init__(self):
610 super().__init__(qubit_count=2, ascii_symbols=["SWAP", "SWAP"])
612 def to_ir(self, target: QubitSet):
613 return ir.Swap.construct(targets=[target[0], target[1]])
615 def to_matrix(self) -> np.ndarray:
616 return np.array(
617 [
618 [1.0, 0.0, 0.0, 0.0],
619 [0.0, 0.0, 1.0, 0.0],
620 [0.0, 1.0, 0.0, 0.0],
621 [0.0, 0.0, 0.0, 1.0],
622 ],
623 dtype=complex,
624 )
626 @staticmethod
627 @circuit.subroutine(register=True)
628 def swap(target1: QubitInput, target2: QubitInput) -> Instruction:
629 """Registers this function into the circuit class.
631 Args:
632 target1 (Qubit or int): Target qubit 1 index.
633 target2 (Qubit or int): Target qubit 2 index.
635 Returns:
636 Instruction: Swap instruction.
638 Examples:
639 >>> circ = Circuit().swap(0, 1)
640 """
641 return Instruction(Gate.Swap(), target=[target1, target2])
644Gate.register_gate(Swap)
647class ISwap(Gate):
648 """ISwap gate."""
650 def __init__(self):
651 super().__init__(qubit_count=2, ascii_symbols=["ISWAP", "ISWAP"])
653 def to_ir(self, target: QubitSet):
654 return ir.ISwap.construct(targets=[target[0], target[1]])
656 def to_matrix(self) -> np.ndarray:
657 return np.array(
658 [
659 [1.0, 0.0, 0.0, 0.0],
660 [0.0, 0.0, 1.0j, 0.0],
661 [0.0, 1.0j, 0.0, 0.0],
662 [0.0, 0.0, 0.0, 1.0],
663 ],
664 dtype=complex,
665 )
667 @staticmethod
668 @circuit.subroutine(register=True)
669 def iswap(target1: QubitInput, target2: QubitInput) -> Instruction:
670 """Registers this function into the circuit class.
672 Args:
673 target1 (Qubit or int): Target qubit 1 index.
674 target2 (Qubit or int): Target qubit 2 index.
676 Returns:
677 Instruction: ISwap instruction.
679 Examples:
680 >>> circ = Circuit().iswap(0, 1)
681 """
682 return Instruction(Gate.ISwap(), target=[target1, target2])
685Gate.register_gate(ISwap)
688class PSwap(AngledGate):
689 """PSwap gate.
691 Args:
692 angle (float): angle in radians.
693 """
695 def __init__(self, angle: float):
696 super().__init__(
697 angle=angle,
698 qubit_count=2,
699 ascii_symbols=["PSWAP({:.3g})".format(angle), "PSWAP({:.3g})".format(angle)],
700 )
702 def to_ir(self, target: QubitSet):
703 return ir.PSwap.construct(targets=[target[0], target[1]], angle=self.angle)
705 def to_matrix(self) -> np.ndarray:
706 return np.array(
707 [
708 [1.0, 0.0, 0.0, 0.0],
709 [0.0, 0.0, np.exp(1j * self.angle), 0.0],
710 [0.0, np.exp(1j * self.angle), 0.0, 0.0],
711 [0.0, 0.0, 0.0, 1.0],
712 ],
713 dtype=complex,
714 )
716 @staticmethod
717 @circuit.subroutine(register=True)
718 def pswap(target1: QubitInput, target2: QubitInput, angle: float) -> Instruction:
719 """Registers this function into the circuit class.
721 Args:
722 target1 (Qubit or int): Target qubit 1 index.
723 target2 (Qubit or int): Target qubit 2 index.
725 Returns:
726 Instruction: PSwap instruction.
728 Examples:
729 >>> circ = Circuit().pswap(0, 1, 0.15)
730 """
731 return Instruction(Gate.PSwap(angle), target=[target1, target2])
734Gate.register_gate(PSwap)
737class XY(AngledGate):
738 """XY gate.
740 Reference: https://arxiv.org/abs/1912.04424v1
742 Args:
743 angle (float): angle in radians.
744 """
746 def __init__(self, angle: float):
747 super().__init__(
748 angle=angle,
749 qubit_count=2,
750 ascii_symbols=["XY({:.3g})".format(angle), "XY({:.3g})".format(angle)],
751 )
753 def to_ir(self, target: QubitSet):
754 return ir.XY.construct(targets=[target[0], target[1]], angle=self.angle)
756 def to_matrix(self) -> np.ndarray:
757 cos = np.cos(self.angle / 2)
758 sin = np.sin(self.angle / 2)
759 return np.array(
760 [
761 [1.0, 0.0, 0.0, 0.0],
762 [0.0, cos, 1.0j * sin, 0.0],
763 [0.0, 1.0j * sin, cos, 0.0],
764 [0.0, 0.0, 0.0, 1.0],
765 ],
766 dtype=complex,
767 )
769 @staticmethod
770 @circuit.subroutine(register=True)
771 def xy(target1: QubitInput, target2: QubitInput, angle: float) -> Instruction:
772 """Registers this function into the circuit class.
774 Args:
775 target1 (Qubit or int): Target qubit 1 index.
776 target2 (Qubit or int): Target qubit 2 index.
778 Returns:
779 Instruction: XY instruction.
781 Examples:
782 >>> circ = Circuit().xy(0, 1, 0.15)
783 """
784 return Instruction(Gate.XY(angle), target=[target1, target2])
787Gate.register_gate(XY)
790class CPhaseShift(AngledGate):
791 """Controlled phase shift gate.
793 Args:
794 angle (float): angle in radians.
795 """
797 def __init__(self, angle: float):
798 super().__init__(
799 angle=angle, qubit_count=2, ascii_symbols=["C", "PHASE({:.3g})".format(angle)]
800 )
802 def to_ir(self, target: QubitSet):
803 return ir.CPhaseShift.construct(control=target[0], target=target[1], angle=self.angle)
805 def to_matrix(self) -> np.ndarray:
806 return np.diag([1.0, 1.0, 1.0, np.exp(1j * self.angle)])
808 @staticmethod
809 @circuit.subroutine(register=True)
810 def cphaseshift(control: QubitInput, target: QubitInput, angle: float) -> Instruction:
811 """Registers this function into the circuit class.
813 Args:
814 control (Qubit or int): Control qubit index.
815 target (Qubit or int): Target qubit index.
816 angle (float): Angle in radians.
818 Returns:
819 Instruction: CPhaseShift instruction.
821 Examples:
822 >>> circ = Circuit().cphaseshift(0, 1, 0.15)
823 """
824 return Instruction(Gate.CPhaseShift(angle), target=[control, target])
827Gate.register_gate(CPhaseShift)
830class CPhaseShift00(AngledGate):
831 """Controlled phase shift gate for phasing the \\|00> state.
833 Args:
834 angle (float): angle in radians.
835 """
837 def __init__(self, angle: float):
838 super().__init__(
839 angle=angle, qubit_count=2, ascii_symbols=["C", "PHASE00({:.3g})".format(angle)]
840 )
842 def to_ir(self, target: QubitSet):
843 return ir.CPhaseShift00.construct(control=target[0], target=target[1], angle=self.angle)
845 def to_matrix(self) -> np.ndarray:
846 return np.diag([np.exp(1j * self.angle), 1.0, 1.0, 1.0])
848 @staticmethod
849 @circuit.subroutine(register=True)
850 def cphaseshift00(control: QubitInput, target: QubitInput, angle: float) -> Instruction:
851 """Registers this function into the circuit class.
853 Args:
854 control (Qubit or int): Control qubit index.
855 target (Qubit or int): Target qubit index.
856 angle (float): Angle in radians.
858 Returns:
859 Instruction: CPhaseShift00 instruction.
861 Examples:
862 >>> circ = Circuit().cphaseshift00(0, 1, 0.15)
863 """
864 return Instruction(Gate.CPhaseShift00(angle), target=[control, target])
867Gate.register_gate(CPhaseShift00)
870class CPhaseShift01(AngledGate):
871 """Controlled phase shift gate for phasing the \\|01> state.
873 Args:
874 angle (float): angle in radians.
875 """
877 def __init__(self, angle: float):
878 super().__init__(
879 angle=angle, qubit_count=2, ascii_symbols=["C", "PHASE01({:.3g})".format(angle)]
880 )
882 def to_ir(self, target: QubitSet):
883 return ir.CPhaseShift01.construct(control=target[0], target=target[1], angle=self.angle)
885 def to_matrix(self) -> np.ndarray:
886 return np.diag([1.0, np.exp(1j * self.angle), 1.0, 1.0])
888 @staticmethod
889 @circuit.subroutine(register=True)
890 def cphaseshift01(control: QubitInput, target: QubitInput, angle: float) -> Instruction:
891 """Registers this function into the circuit class.
893 Args:
894 control (Qubit or int): Control qubit index.
895 target (Qubit or int): Target qubit index.
896 angle (float): Angle in radians.
898 Returns:
899 Instruction: CPhaseShift01 instruction.
901 Examples:
902 >>> circ = Circuit().cphaseshift01(0, 1, 0.15)
903 """
904 return Instruction(Gate.CPhaseShift01(angle), target=[control, target])
907Gate.register_gate(CPhaseShift01)
910class CPhaseShift10(AngledGate):
911 """Controlled phase shift gate for phasing the \\|10> state.
913 Args:
914 angle (float): angle in radians.
915 """
917 def __init__(self, angle: float):
918 super().__init__(
919 angle=angle, qubit_count=2, ascii_symbols=["C", "PHASE10({:.3g})".format(angle)]
920 )
922 def to_ir(self, target: QubitSet):
923 return ir.CPhaseShift10.construct(control=target[0], target=target[1], angle=self.angle)
925 def to_matrix(self) -> np.ndarray:
926 return np.diag([1.0, 1.0, np.exp(1j * self.angle), 1.0])
928 @staticmethod
929 @circuit.subroutine(register=True)
930 def cphaseshift10(control: QubitInput, target: QubitInput, angle: float) -> Instruction:
931 """Registers this function into the circuit class.
933 Args:
934 control (Qubit or int): Control qubit index.
935 target (Qubit or int): Target qubit index.
936 angle (float): Angle in radians.
938 Returns:
939 Instruction: CPhaseShift10 instruction.
941 Examples:
942 >>> circ = Circuit().cphaseshift10(0, 1, 0.15)
943 """
944 return Instruction(Gate.CPhaseShift10(angle), target=[control, target])
947Gate.register_gate(CPhaseShift10)
950class CY(Gate):
951 """Controlled Pauli-Y gate."""
953 def __init__(self):
954 super().__init__(qubit_count=2, ascii_symbols=["C", "Y"])
956 def to_ir(self, target: QubitSet):
957 return ir.CY.construct(control=target[0], target=target[1])
959 def to_matrix(self) -> np.ndarray:
960 return np.array(
961 [
962 [1.0, 0.0, 0.0, 0.0],
963 [0.0, 1.0, 0.0, 0.0],
964 [0.0, 0.0, 0.0, -1.0j],
965 [0.0, 0.0, +1.0j, 0.0],
966 ],
967 dtype=complex,
968 )
970 @staticmethod
971 @circuit.subroutine(register=True)
972 def cy(control: QubitInput, target: QubitInput) -> Instruction:
973 """Registers this function into the circuit class.
975 Args:
976 control (Qubit or int): Control qubit index.
977 target (Qubit or int): Target qubit index.
979 Returns:
980 Instruction: CY instruction.
982 Examples:
983 >>> circ = Circuit().cy(0, 1)
984 """
985 return Instruction(Gate.CY(), target=[control, target])
988Gate.register_gate(CY)
991class CZ(Gate):
992 """Controlled Pauli-Z gate."""
994 def __init__(self):
995 super().__init__(qubit_count=2, ascii_symbols=["C", "Z"])
997 def to_ir(self, target: QubitSet):
998 return ir.CZ.construct(control=target[0], target=target[1])
1000 def to_matrix(self) -> np.ndarray:
1001 return np.diag([1.0, 1.0, 1.0, -1.0])
1003 @staticmethod
1004 @circuit.subroutine(register=True)
1005 def cz(control: QubitInput, target: QubitInput) -> Instruction:
1006 """Registers this function into the circuit class.
1008 Args:
1009 control (Qubit or int): Control qubit index.
1010 target (Qubit or int): Target qubit index.
1012 Returns:
1013 Instruction: CZ instruction.
1015 Examples:
1016 >>> circ = Circuit().cz(0, 1)
1017 """
1018 return Instruction(Gate.CZ(), target=[control, target])
1021Gate.register_gate(CZ)
1024class XX(AngledGate):
1025 """Ising XX coupling gate.
1027 Reference: https://arxiv.org/abs/1707.06356
1029 Args:
1030 angle (float): angle in radians.
1031 """
1033 def __init__(self, angle: float):
1034 super().__init__(
1035 angle=angle,
1036 qubit_count=2,
1037 ascii_symbols=["XX({:.3g})".format(angle), "XX({:.3g})".format(angle)],
1038 )
1040 def to_ir(self, target: QubitSet):
1041 return ir.XX.construct(targets=[target[0], target[1]], angle=self.angle)
1043 def to_matrix(self) -> np.ndarray:
1044 cos = np.cos(self.angle / 2)
1045 isin = 1.0j * np.sin(self.angle / 2)
1046 return np.array(
1047 [
1048 [cos, 0.0, 0.0, -isin],
1049 [0.0, cos, -isin, 0.0],
1050 [0.0, -isin, cos, 0.0],
1051 [-isin, 0.0, 0.0, cos],
1052 ],
1053 dtype=complex,
1054 )
1056 @staticmethod
1057 @circuit.subroutine(register=True)
1058 def xx(target1: QubitInput, target2: QubitInput, angle: float) -> Instruction:
1059 """Registers this function into the circuit class.
1061 Args:
1062 target1 (Qubit or int): Target qubit 1 index.
1063 target2 (Qubit or int): Target qubit 2 index.
1064 angle (float): Angle in radians.
1066 Returns:
1067 Instruction: XX instruction.
1069 Examples:
1070 >>> circ = Circuit().xx(0, 1, 0.15)
1071 """
1072 return Instruction(Gate.XX(angle), target=[target1, target2])
1075Gate.register_gate(XX)
1078class YY(AngledGate):
1079 """Ising YY coupling gate.
1081 Reference: https://arxiv.org/abs/1707.06356
1083 Args:
1084 angle (float): angle in radians.
1085 """
1087 def __init__(self, angle: float):
1088 super().__init__(
1089 angle=angle,
1090 qubit_count=2,
1091 ascii_symbols=["YY({:.3g})".format(angle), "YY({:.3g})".format(angle)],
1092 )
1094 def to_ir(self, target: QubitSet):
1095 return ir.YY.construct(targets=[target[0], target[1]], angle=self.angle)
1097 def to_matrix(self) -> np.ndarray:
1098 cos = np.cos(self.angle / 2)
1099 isin = 1.0j * np.sin(self.angle / 2)
1100 return np.array(
1101 [
1102 [cos, 0.0, 0.0, isin],
1103 [0.0, cos, -isin, 0.0],
1104 [0.0, -isin, cos, 0.0],
1105 [isin, 0.0, 0.0, cos],
1106 ],
1107 dtype=complex,
1108 )
1110 @staticmethod
1111 @circuit.subroutine(register=True)
1112 def yy(target1: QubitInput, target2: QubitInput, angle: float) -> Instruction:
1113 """Registers this function into the circuit class.
1115 Args:
1116 target1 (Qubit or int): Target qubit 1 index.
1117 target2 (Qubit or int): Target qubit 2 index.
1118 angle (float): Angle in radians.
1120 Returns:
1121 Instruction: YY instruction.
1123 Examples:
1124 >>> circ = Circuit().yy(0, 1, 0.15)
1125 """
1126 return Instruction(Gate.YY(angle), target=[target1, target2])
1129Gate.register_gate(YY)
1132class ZZ(AngledGate):
1133 """Ising ZZ coupling gate.
1135 Reference: https://arxiv.org/abs/1707.06356
1137 Args:
1138 angle (float): angle in radians.
1139 """
1141 def __init__(self, angle: float):
1142 super().__init__(
1143 angle=angle,
1144 qubit_count=2,
1145 ascii_symbols=["ZZ({:.3g})".format(angle), "ZZ({:.3g})".format(angle)],
1146 )
1148 def to_ir(self, target: QubitSet):
1149 return ir.ZZ.construct(targets=[target[0], target[1]], angle=self.angle)
1151 def to_matrix(self) -> np.ndarray:
1152 return np.array(
1153 [
1154 [np.exp(-1j * (self.angle / 2)), 0.0, 0.0, 0.0],
1155 [0.0, np.exp(1j * (self.angle / 2)), 0.0, 0.0],
1156 [0.0, 0.0, np.exp(1j * (self.angle / 2)), 0.0],
1157 [0.0, 0.0, 0.0, np.exp(-1j * (self.angle / 2))],
1158 ],
1159 dtype=complex,
1160 )
1162 @staticmethod
1163 @circuit.subroutine(register=True)
1164 def zz(target1: QubitInput, target2: QubitInput, angle: float) -> Instruction:
1165 """Registers this function into the circuit class.
1167 Args:
1168 target1 (Qubit or int): Target qubit 1 index.
1169 target2 (Qubit or int): Target qubit 2 index.
1170 angle (float): Angle in radians.
1172 Returns:
1173 Instruction: ZZ instruction.
1175 Examples:
1176 >>> circ = Circuit().zz(0, 1, 0.15)
1177 """
1178 return Instruction(Gate.ZZ(angle), target=[target1, target2])
1181Gate.register_gate(ZZ)
1184# Three qubit gates #
1187class CCNot(Gate):
1188 """CCNOT gate or Toffoli gate."""
1190 def __init__(self):
1191 super().__init__(qubit_count=3, ascii_symbols=["C", "C", "X"])
1193 def to_ir(self, target: QubitSet):
1194 return ir.CCNot.construct(controls=[target[0], target[1]], target=target[2])
1196 def to_matrix(self) -> np.ndarray:
1197 return np.array(
1198 [
1199 [1, 0, 0, 0, 0, 0, 0, 0],
1200 [0, 1, 0, 0, 0, 0, 0, 0],
1201 [0, 0, 1, 0, 0, 0, 0, 0],
1202 [0, 0, 0, 1, 0, 0, 0, 0],
1203 [0, 0, 0, 0, 1, 0, 0, 0],
1204 [0, 0, 0, 0, 0, 1, 0, 0],
1205 [0, 0, 0, 0, 0, 0, 0, 1],
1206 [0, 0, 0, 0, 0, 0, 1, 0],
1207 ],
1208 dtype=complex,
1209 )
1211 @staticmethod
1212 @circuit.subroutine(register=True)
1213 def ccnot(control1: QubitInput, control2: QubitInput, target: QubitInput) -> Instruction:
1214 """Registers this function into the circuit class.
1216 Args:
1217 control1 (Qubit or int): Control qubit 1 index.
1218 control2 (Qubit or int): Control qubit 2 index.
1219 target (Qubit or int): Target qubit index.
1221 Returns:
1222 Instruction: CCNot instruction.
1224 Examples:
1225 >>> circ = Circuit().ccnot(0, 1, 2)
1226 """
1227 return Instruction(Gate.CCNot(), target=[control1, control2, target])
1230Gate.register_gate(CCNot)
1233class CSwap(Gate):
1234 """Controlled Swap gate."""
1236 def __init__(self):
1237 super().__init__(qubit_count=3, ascii_symbols=["C", "SWAP", "SWAP"])
1239 def to_ir(self, target: QubitSet):
1240 return ir.CSwap.construct(control=target[0], targets=[target[1], target[2]])
1242 def to_matrix(self) -> np.ndarray:
1243 return np.array(
1244 [
1245 [1, 0, 0, 0, 0, 0, 0, 0],
1246 [0, 1, 0, 0, 0, 0, 0, 0],
1247 [0, 0, 1, 0, 0, 0, 0, 0],
1248 [0, 0, 0, 1, 0, 0, 0, 0],
1249 [0, 0, 0, 0, 1, 0, 0, 0],
1250 [0, 0, 0, 0, 0, 0, 1, 0],
1251 [0, 0, 0, 0, 0, 1, 0, 0],
1252 [0, 0, 0, 0, 0, 0, 0, 1],
1253 ],
1254 dtype=complex,
1255 )
1257 @staticmethod
1258 @circuit.subroutine(register=True)
1259 def cswap(control: QubitInput, target1: QubitInput, target2: QubitInput) -> Instruction:
1260 """Registers this function into the circuit class.
1262 Args:
1263 control (Qubit or int): Control qubit index
1264 target1 (Qubit or int): Target qubit 1 index.
1265 target2 (Qubit or int): Target qubit 2 index.
1267 Returns:
1268 Instruction: CSwap instruction.
1270 Examples:
1271 >>> circ = Circuit().cswap(0, 1, 2)
1272 """
1273 return Instruction(Gate.CSwap(), target=[control, target1, target2])
1276Gate.register_gate(CSwap)
1279class Unitary(Gate):
1280 """Arbitrary unitary gate
1282 Args:
1283 matrix (numpy.ndarray): Unitary matrix which defines the gate.
1284 display_name (str): Name to be used for an instance of this unitary gate
1285 for circuit diagrams. Defaults to `U`.
1287 Raises:
1288 ValueError: If `matrix` is not a two-dimensional square matrix,
1289 or has a dimension length which is not a positive exponent of 2,
1290 or is non-unitary.
1291 """
1293 def __init__(self, matrix: np.ndarray, display_name: str = "U"):
1294 verify_quantum_operator_matrix_dimensions(matrix)
1295 self._matrix = np.array(matrix, dtype=complex)
1296 qubit_count = int(np.log2(self._matrix.shape[0]))
1298 if not is_unitary(self._matrix):
1299 raise ValueError(f"{self._matrix} is not unitary")
1301 super().__init__(qubit_count=qubit_count, ascii_symbols=[display_name] * qubit_count)
1303 def to_matrix(self):
1304 return np.array(self._matrix)
1306 def to_ir(self, target: QubitSet):
1307 return ir.Unitary.construct(
1308 targets=[qubit for qubit in target],
1309 matrix=Unitary._transform_matrix_to_ir(self._matrix),
1310 )
1312 @staticmethod
1313 def _transform_matrix_to_ir(matrix: np.ndarray):
1314 return [[[element.real, element.imag] for element in row] for row in matrix.tolist()]
1316 @staticmethod
1317 @circuit.subroutine(register=True)
1318 def unitary(targets: QubitSet, matrix: np.ndarray, display_name: str = "U") -> Instruction:
1319 """Registers this function into the circuit class.
1321 Args:
1322 targets (QubitSet): Target qubits.
1323 matrix (numpy.ndarray): Unitary matrix which defines the gate. Matrix should be
1324 compatible with the supplied targets, with 2 ** len(targets) == matrix.shape[0].
1325 display_name (str): Name to be used for an instance of this unitary gate
1326 for circuit diagrams. Defaults to `U`.
1328 Returns:
1329 Instruction: Unitary instruction.
1331 Raises:
1332 ValueError: If `matrix` is not a two-dimensional square matrix,
1333 or has a dimension length which is not compatible with the `targets`,
1334 or is non-unitary,
1336 Examples:
1337 >>> circ = Circuit().unitary(matrix=np.array([[0, 1],[1, 0]]), targets=[0])
1338 """
1339 if 2 ** len(targets) != matrix.shape[0]:
1340 raise ValueError("Dimensions of the supplied unitary are incompatible with the targets")
1342 return Instruction(Gate.Unitary(matrix, display_name), target=targets)
1345Gate.register_gate(Unitary)