From 06c030e4f34a352cf933ab3ec0cdd9a7b9913fe1 Mon Sep 17 00:00:00 2001 From: "Christopher J. Wood" Date: Mon, 27 Apr 2020 20:07:49 -0400 Subject: [PATCH] Add Cifford.from_label method (#4222) * Add Cifford.from_label method * Add release note * Add test Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .../operators/symplectic/clifford.py | 55 ++++++++++++++++++- .../clifford-from-label-4ac8a987109916ef.yaml | 6 ++ .../operators/symplectic/test_clifford.py | 12 ++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/clifford-from-label-4ac8a987109916ef.yaml diff --git a/qiskit/quantum_info/operators/symplectic/clifford.py b/qiskit/quantum_info/operators/symplectic/clifford.py index b82f39f342f2..e7f3b99ad3d6 100644 --- a/qiskit/quantum_info/operators/symplectic/clifford.py +++ b/qiskit/quantum_info/operators/symplectic/clifford.py @@ -15,11 +15,12 @@ Clifford operator class. """ # pylint: disable=invalid-name, abstract-method - +import re import numpy as np from qiskit.exceptions import QiskitError from qiskit.circuit import QuantumCircuit, Instruction +from qiskit.extensions.standard import IGate, XGate, YGate, ZGate, HGate, SGate from qiskit.quantum_info.operators.base_operator import BaseOperator from qiskit.quantum_info.operators.operator import Operator from qiskit.quantum_info.operators.scalar_op import ScalarOp @@ -389,6 +390,58 @@ def from_circuit(circuit): _append_circuit(clifford, circuit) return clifford + @staticmethod + def from_label(label): + """Return a tensor product of single-qubit Clifford gates. + + Args: + label (string): single-qubit operator string. + + Returns: + Clifford: The N-qubit Clifford operator. + + Raises: + QiskitError: if the label contains invalid characters. + + Additional Information: + The labels correspond to the single-qubit Cliffords are + + * - Label + - Stabilizer + - Destabilizer + * - ``"I"`` + - +Z + - +X + * - ``"X"`` + - -Z + - +X + * - ``"Y"`` + - -Z + - -X + * - ``"Z"`` + - +Z + - -X + * - ``"H"`` + - +X + - +Z + * - ``"S"`` + - +Z + - +Y + """ + # Check label is valid + label_gates = { + 'I': IGate(), 'X': XGate(), 'Y': YGate(), + 'Z': ZGate(), 'H': HGate(), 'S': SGate() + } + if re.match(r'^[IXYZHS\-+]+$', label) is None: + raise QiskitError('Label contains invalid characters.') + # Initialize an identity matrix and apply each gate + num_qubits = len(label) + op = Clifford(np.eye(2 * num_qubits, dtype=np.bool)) + for qubit, char in enumerate(reversed(label)): + _append_circuit(op, label_gates[char], qargs=[qubit]) + return op + # --------------------------------------------------------------------- # Internal helper functions # --------------------------------------------------------------------- diff --git a/releasenotes/notes/clifford-from-label-4ac8a987109916ef.yaml b/releasenotes/notes/clifford-from-label-4ac8a987109916ef.yaml new file mode 100644 index 000000000000..8b4047fb4b25 --- /dev/null +++ b/releasenotes/notes/clifford-from-label-4ac8a987109916ef.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Add :meth:`~qiskit.quantum_info.Clifford.from_label` method to the + :class:`qiskit.quantum_info.Clifford` class for initializing as the + tensor product of single-qubit I, X, Y, Z, H, or S gates. diff --git a/test/python/quantum_info/operators/symplectic/test_clifford.py b/test/python/quantum_info/operators/symplectic/test_clifford.py index fc472d9b2514..4d7c27247de7 100644 --- a/test/python/quantum_info/operators/symplectic/test_clifford.py +++ b/test/python/quantum_info/operators/symplectic/test_clifford.py @@ -788,6 +788,18 @@ def test_dict_round_trip(self, num_qubits): value = Clifford.from_dict(target.to_dict()) self.assertEqual(value, target) + def test_from_label(self): + """Test from_label method""" + label = 'IXYZHS' + CI = Clifford(IGate()) + CX = Clifford(XGate()) + CY = Clifford(YGate()) + CZ = Clifford(ZGate()) + CH = Clifford(HGate()) + CS = Clifford(SGate()) + target = CI.tensor(CX).tensor(CY).tensor(CZ).tensor(CH).tensor(CS) + self.assertEqual(Clifford.from_label(label), target) + if __name__ == '__main__': unittest.main()