-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
pauli.py
85 lines (70 loc) · 3.08 KB
/
pauli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# This code is part of Qiskit.
#
# (C) Copyright IBM 2020
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""
Simulator command to perform multiple pauli gates in a single pass
"""
from qiskit.circuit.quantumcircuitdata import CircuitInstruction
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit.library.standard_gates.x import XGate
from qiskit.circuit.library.standard_gates.y import YGate
from qiskit.circuit.library.standard_gates.z import ZGate
from qiskit.circuit.gate import Gate
from qiskit.circuit.exceptions import CircuitError
class PauliGate(Gate):
r"""A multi-qubit Pauli gate.
This gate exists for optimization purposes for the
quantum statevector simulation, since applying multiple
pauli gates to different qubits at once can be done via
a single pass on the statevector.
The functionality is equivalent to applying
the pauli gates sequentially using standard Qiskit gates.
Can be applied to a :class:`~qiskit.circuit.QuantumCircuit`
with the :meth:`~qiskit.circuit.QuantumCircuit.pauli` method.
"""
def __init__(self, label):
super().__init__("pauli", len(label), [label])
def _define(self):
"""
gate pauli (p1 a1,...,pn an) { p1 a1; ... ; pn an; }
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit
gates = {"X": XGate, "Y": YGate, "Z": ZGate}
q = QuantumRegister(len(self.params[0]), "q")
qc = QuantumCircuit(q, name=f"{self.name}({self.params[0]})")
paulis = self.params[0]
for i, p in enumerate(reversed(paulis)):
if p == "I":
continue
qc._append(CircuitInstruction(gates[p](), (q[i],), ()))
self.definition = qc
def inverse(self, annotated: bool = False):
r"""Return inverted pauli gate (itself)."""
return PauliGate(self.params[0]) # self-inverse
def __array__(self, dtype=None, copy=None):
"""Return a Numpy.array for the pauli gate.
i.e. tensor product of the paulis"""
# pylint: disable=cyclic-import
from qiskit.quantum_info.operators import Pauli
return Pauli(self.params[0]).__array__(dtype=dtype, copy=copy)
def validate_parameter(self, parameter):
if isinstance(parameter, str):
if all(c in ["I", "X", "Y", "Z"] for c in parameter):
return parameter
else:
raise CircuitError(
f"Parameter string {parameter} should contain only 'I', 'X', 'Y', 'Z' characters"
)
else:
raise CircuitError(
f"Parameter {parameter} should be a string of 'I', 'X', 'Y', 'Z' characters"
)