mirror of https://github.com/Qiskit/qiskit.git
Remove deprecated classes and methods in quantum_info (#8070)
* remove deprecated * fix test * fix test * fix cyclic dependency * create releasenote * leave import path * fix lint * deprecate argument * Update qiskit/quantum_info/operators/symplectic/pauli.py * Remove already-expired deprecation * Revert unnecessary over-specific import * Flesh out detail in release note * Issue deprecation warning for old Pauli path * Reinstate buggy deprecated behaviour * Reinstate None default for Pauli data kwarg Co-authored-by: ikkoham <ikkoham@users.noreply.github.com> Co-authored-by: Matthew Treinish <mtreinish@kortar.org> Co-authored-by: Jake Lishman <jake.lishman@ibm.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
3241978340
commit
8455c9f459
|
@ -15,7 +15,7 @@
|
|||
import itertools
|
||||
import logging
|
||||
from copy import deepcopy
|
||||
from typing import List, Optional, Union, cast, Dict
|
||||
from typing import Dict, List, Optional, Union, cast
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
@ -317,7 +317,7 @@ class Z2Symmetries:
|
|||
and stacked_symmetries[row, col + symm_shape[1] // 2] == 1
|
||||
):
|
||||
sq_paulis.append(
|
||||
Pauli(np.zeros(symm_shape[1] // 2), np.zeros(symm_shape[1] // 2))
|
||||
Pauli((np.zeros(symm_shape[1] // 2), np.zeros(symm_shape[1] // 2)))
|
||||
)
|
||||
sq_paulis[row].z[col] = True
|
||||
sq_paulis[row].x[col] = False
|
||||
|
@ -347,7 +347,7 @@ class Z2Symmetries:
|
|||
and stacked_symmetries[row, col + symm_shape[1] // 2] == 0
|
||||
):
|
||||
sq_paulis.append(
|
||||
Pauli(np.zeros(symm_shape[1] // 2), np.zeros(symm_shape[1] // 2))
|
||||
Pauli((np.zeros(symm_shape[1] // 2), np.zeros(symm_shape[1] // 2)))
|
||||
)
|
||||
sq_paulis[row].z[col] = True
|
||||
sq_paulis[row].x[col] = True
|
||||
|
|
|
@ -32,7 +32,6 @@ Operators
|
|||
PauliTable
|
||||
StabilizerTable
|
||||
pauli_basis
|
||||
pauli_group
|
||||
|
||||
States
|
||||
======
|
||||
|
@ -124,7 +123,7 @@ Synthesis
|
|||
"""
|
||||
|
||||
from .operators import Operator, ScalarOp, Pauli, Clifford, SparsePauliOp
|
||||
from .operators import PauliList, PauliTable, StabilizerTable, pauli_basis, pauli_group
|
||||
from .operators import PauliList, PauliTable, StabilizerTable, pauli_basis
|
||||
from .operators.channel import Choi, SuperOp, Kraus, Stinespring, Chi, PTM
|
||||
from .operators.measures import process_fidelity, average_gate_fidelity, gate_error, diamond_norm
|
||||
from .operators.dihedral import CNOTDihedral
|
||||
|
|
|
@ -12,11 +12,22 @@
|
|||
|
||||
"""Quantum Operators."""
|
||||
|
||||
from .channel import PTM, Chi, Choi, Kraus, Stinespring, SuperOp
|
||||
from .dihedral import CNOTDihedral
|
||||
from .measures import (
|
||||
average_gate_fidelity,
|
||||
diamond_norm,
|
||||
gate_error,
|
||||
process_fidelity,
|
||||
)
|
||||
from .operator import Operator
|
||||
from .scalar_op import ScalarOp
|
||||
from .channel import Choi, SuperOp, Kraus, Stinespring, Chi, PTM
|
||||
from .measures import process_fidelity, average_gate_fidelity, gate_error, diamond_norm
|
||||
from .symplectic import Clifford, Pauli, PauliList, SparsePauliOp, PauliTable, StabilizerTable
|
||||
from .symplectic import pauli_basis
|
||||
from .pauli import pauli_group
|
||||
from .dihedral import CNOTDihedral
|
||||
from .symplectic import (
|
||||
Clifford,
|
||||
Pauli,
|
||||
PauliList,
|
||||
PauliTable,
|
||||
SparsePauliOp,
|
||||
StabilizerTable,
|
||||
pauli_basis,
|
||||
)
|
||||
|
|
|
@ -19,9 +19,8 @@ import numpy as np
|
|||
from qiskit.exceptions import QiskitError
|
||||
from qiskit.quantum_info.operators.base_operator import BaseOperator
|
||||
from qiskit.quantum_info.operators.operator import Operator
|
||||
from qiskit.quantum_info.operators.pauli import Pauli
|
||||
from qiskit.quantum_info.operators.symplectic.pauli import Pauli
|
||||
from qiskit.quantum_info.operators.scalar_op import ScalarOp
|
||||
from qiskit.quantum_info.synthesis.cnotdihedral_decompose import decompose_cnotdihedral
|
||||
from qiskit.quantum_info.operators.mixins import generate_apidocs, AdjointMixin
|
||||
from qiskit.circuit import QuantumCircuit, Instruction
|
||||
from .dihedral_circuits import _append_circuit
|
||||
|
@ -314,6 +313,8 @@ class CNOTDihedral(BaseOperator, AdjointMixin):
|
|||
*Scalable randomised benchmarking of non-Clifford gates*,
|
||||
npj Quantum Inf 2, 16012 (2016).
|
||||
"""
|
||||
from qiskit.quantum_info.synthesis.cnotdihedral_decompose import decompose_cnotdihedral
|
||||
|
||||
return decompose_cnotdihedral(self)
|
||||
|
||||
def to_instruction(self):
|
||||
|
|
|
@ -10,74 +10,26 @@
|
|||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
# pylint: disable=unused-import
|
||||
|
||||
|
||||
"""
|
||||
DEPRECATED Tools for working with Pauli Operators.
|
||||
"""
|
||||
|
||||
from warnings import warn
|
||||
import numpy as np
|
||||
from qiskit.exceptions import QiskitError
|
||||
from qiskit.quantum_info.operators.symplectic.pauli import Pauli
|
||||
import warnings
|
||||
|
||||
|
||||
def pauli_group(number_of_qubits, case="weight"):
|
||||
"""DEPRECATED: Return the Pauli group with 4^n elements.
|
||||
def __getattr__(name):
|
||||
if name == "Pauli":
|
||||
from qiskit.quantum_info import Pauli
|
||||
|
||||
This function is deprecated. Use :func:`~qiskit.quantum_info.pauli_basis`
|
||||
for equivalent functionality.
|
||||
warnings.warn(
|
||||
f"Importing from '{__name__}' is deprecated since Qiskit Terra 0.21 and the module"
|
||||
" will be removed in a future release. Import directly from 'qiskit.quantum_info'.",
|
||||
category=DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
The phases have been removed.
|
||||
case 'weight' is ordered by Pauli weights and
|
||||
case 'tensor' is ordered by I,X,Y,Z counting lowest qubit fastest.
|
||||
|
||||
Args:
|
||||
number_of_qubits (int): number of qubits
|
||||
case (str): determines ordering of group elements ('weight' or 'tensor')
|
||||
|
||||
Returns:
|
||||
list: list of Pauli objects
|
||||
|
||||
Raises:
|
||||
QiskitError: case is not 'weight' or 'tensor'
|
||||
QiskitError: number_of_qubits is larger than 4
|
||||
"""
|
||||
warn(
|
||||
"`insert_paulis` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date. For equivalent functionality to"
|
||||
"`qiskit.quantum_info.pauli_group` instead. "
|
||||
"`pauli_group(n)` is equivalent to `pauli_basis(n, weight=True)`, "
|
||||
'`pauli_group(n, case="tensor") is equivalent to `pauli_basis(n)`',
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
if number_of_qubits < 5:
|
||||
temp_set = []
|
||||
|
||||
if case == "weight":
|
||||
tmp = pauli_group(number_of_qubits, case="tensor")
|
||||
# sort on the weight of the Pauli operator
|
||||
return sorted(tmp, key=lambda x: -np.count_nonzero(np.array(x.to_label(), "c") == b"I"))
|
||||
elif case == "tensor":
|
||||
# the Pauli set is in tensor order II IX IY IZ XI ...
|
||||
for k in range(4**number_of_qubits):
|
||||
z = np.zeros(number_of_qubits, dtype=bool)
|
||||
x = np.zeros(number_of_qubits, dtype=bool)
|
||||
# looping over all the qubits
|
||||
for j in range(number_of_qubits):
|
||||
# making the Pauli for each j fill it in from the
|
||||
# end first
|
||||
element = (k // (4**j)) % 4
|
||||
if element == 1:
|
||||
x[j] = True
|
||||
elif element == 2:
|
||||
z[j] = True
|
||||
x[j] = True
|
||||
elif element == 3:
|
||||
z[j] = True
|
||||
temp_set.append(Pauli(z, x))
|
||||
return temp_set
|
||||
else:
|
||||
raise QiskitError(f"Only support 'weight' or 'tensor' cases but you have {case}.")
|
||||
|
||||
raise QiskitError("Only support number of qubits is less than 5")
|
||||
return Pauli
|
||||
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
||||
|
|
|
@ -21,7 +21,6 @@ from qiskit.circuit.library.standard_gates import IGate, XGate, YGate, ZGate, HG
|
|||
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
|
||||
from qiskit.quantum_info.synthesis.clifford_decompose import decompose_clifford
|
||||
from qiskit.quantum_info.operators.mixins import generate_apidocs, AdjointMixin
|
||||
from qiskit.quantum_info.operators.symplectic.base_pauli import _count_y
|
||||
from .stabilizer_table import StabilizerTable
|
||||
|
@ -384,6 +383,8 @@ class Clifford(BaseOperator, AdjointMixin):
|
|||
Phys. Rev. A 70, 052328 (2004).
|
||||
`arXiv:quant-ph/0406196 <https://arxiv.org/abs/quant-ph/0406196>`_
|
||||
"""
|
||||
from qiskit.quantum_info.synthesis.clifford_decompose import decompose_clifford
|
||||
|
||||
return decompose_clifford(self)
|
||||
|
||||
def to_instruction(self):
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
N-qubit Pauli Operator Class
|
||||
"""
|
||||
# pylint: disable=invalid-name
|
||||
# pylint: disable=bad-docstring-quotes # for deprecate_function decorator
|
||||
|
||||
import re
|
||||
import warnings
|
||||
from typing import Dict
|
||||
|
||||
import numpy as np
|
||||
|
@ -29,7 +29,6 @@ from qiskit.exceptions import QiskitError
|
|||
from qiskit.quantum_info.operators.mixins import generate_apidocs
|
||||
from qiskit.quantum_info.operators.scalar_op import ScalarOp
|
||||
from qiskit.quantum_info.operators.symplectic.base_pauli import BasePauli, _count_y
|
||||
from qiskit.utils.deprecation import deprecate_function
|
||||
|
||||
|
||||
class Pauli(BasePauli):
|
||||
|
@ -167,9 +166,6 @@ class Pauli(BasePauli):
|
|||
characters from ['+', '-', ''], ['1', ''], and ['i', 'j', ''] in this order,
|
||||
e.g. '', '-1j' while a Pauli string is 1 or more characters of 'I', 'X', 'Y' or 'Z',
|
||||
e.g. 'Z', 'XIYY'.
|
||||
x (np.ndarray): DEPRECATED, symplectic x vector.
|
||||
z (np.ndarray): DEPRECATED, symplectic z vector.
|
||||
label (str): DEPRECATED, string label.
|
||||
|
||||
Raises:
|
||||
QiskitError: if input array is invalid shape.
|
||||
|
@ -188,13 +184,27 @@ class Pauli(BasePauli):
|
|||
base_z, base_x, base_phase = self._from_scalar_op(data)
|
||||
elif isinstance(data, (QuantumCircuit, Instruction)):
|
||||
base_z, base_x, base_phase = self._from_circuit(data)
|
||||
elif x is not None: # DEPRECATED
|
||||
elif x is not None:
|
||||
if z is None:
|
||||
# Using old Pauli initialization with positional args instead of kwargs
|
||||
z = data
|
||||
base_z, base_x, base_phase = self._from_array_deprecated(z, x)
|
||||
elif label is not None: # DEPRECATED
|
||||
base_z, base_x, base_phase = self._from_label_deprecated(label)
|
||||
warnings.warn(
|
||||
"Passing 'z' and 'x' arrays separately to 'Pauli' is deprecated as of"
|
||||
" Qiskit Terra 0.17 and will be removed in version 0.23 or later."
|
||||
" Use a tuple instead, such as 'Pauli((z, x[, phase]))'.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
base_z, base_x, base_phase = self._from_array(z, x)
|
||||
elif label is not None:
|
||||
warnings.warn(
|
||||
"The 'label' keyword argument of 'Pauli' is deprecated as of"
|
||||
" Qiskit Terra 0.17 and will be removed in version 0.23 or later."
|
||||
" Pass the label positionally instead, such as 'Pauli(\"XYZ\")'.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
base_z, base_x, base_phase = self._from_label(label)
|
||||
else:
|
||||
raise QiskitError("Invalid input data for Pauli.")
|
||||
|
||||
|
@ -687,353 +697,6 @@ class Pauli(BasePauli):
|
|||
ret = ret.compose(next_instr, qargs=qargs)
|
||||
return ret._z, ret._x, ret._phase
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# DEPRECATED methods from old Pauli class
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
@classmethod
|
||||
@deprecate_function(
|
||||
"Initializing Pauli from `Pauli(label=l)` kwarg is deprecated as of "
|
||||
"version 0.17.0 and will be removed no earlier than 3 months after "
|
||||
"the release date. Use `Pauli(l)` instead."
|
||||
)
|
||||
def _from_label_deprecated(cls, label):
|
||||
# Deprecated wrapper of `_from_label` so that a deprecation warning
|
||||
# can be displaced during initialization with deprecated kwarg
|
||||
return cls._from_label(label)
|
||||
|
||||
@classmethod
|
||||
@deprecate_function(
|
||||
"Initializing Pauli from `Pauli(z=z, x=x)` kwargs is deprecated as of "
|
||||
"version 0.17.0 and will be removed no earlier than 3 months after "
|
||||
"the release date. Use tuple initialization `Pauli((z, x))` instead."
|
||||
)
|
||||
def _from_array_deprecated(cls, z, x):
|
||||
# Deprecated wrapper of `_from_array` so that a deprecation warning
|
||||
# can be displaced during initialization with deprecated kwarg
|
||||
return cls._from_array(z, x)
|
||||
|
||||
@staticmethod
|
||||
def _make_np_bool(arr):
|
||||
if not isinstance(arr, (list, np.ndarray, tuple)):
|
||||
arr = [arr]
|
||||
arr = np.asarray(arr).astype(bool)
|
||||
return arr
|
||||
|
||||
@staticmethod
|
||||
@deprecate_function(
|
||||
"`from_label` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date. Use Pauli(label) instead."
|
||||
)
|
||||
def from_label(label):
|
||||
"""DEPRECATED: Construct a Pauli from a string label.
|
||||
|
||||
This function is deprecated use ``Pauli(label)`` instead.
|
||||
|
||||
Args:
|
||||
label (str): Pauli string label.
|
||||
|
||||
Returns:
|
||||
Pauli: the constructed Pauli.
|
||||
|
||||
Raises:
|
||||
QiskitError: If the input list is empty or contains invalid
|
||||
Pauli strings.
|
||||
"""
|
||||
if isinstance(label, tuple):
|
||||
# Legacy usage from aqua
|
||||
label = "".join(label)
|
||||
return Pauli(label)
|
||||
|
||||
@staticmethod
|
||||
@deprecate_function(
|
||||
"sgn_prod is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date. Use `dot` instead."
|
||||
)
|
||||
def sgn_prod(p1, p2):
|
||||
r"""
|
||||
DEPRECATED: Multiply two Paulis and track the phase.
|
||||
|
||||
This function is deprecated. The Pauli class now handles full
|
||||
Pauli group multiplication using :meth:`compose` or :meth:`dot`.
|
||||
|
||||
$P_3 = P_1 \otimes P_2$: X*Y
|
||||
|
||||
Args:
|
||||
p1 (Pauli): pauli 1
|
||||
p2 (Pauli): pauli 2
|
||||
|
||||
Returns:
|
||||
Pauli: the multiplied pauli (without phase)
|
||||
complex: the sign of the multiplication, 1, -1, 1j or -1j
|
||||
"""
|
||||
pauli = p1.dot(p2)
|
||||
return pauli[:], (-1j) ** pauli.phase
|
||||
|
||||
@deprecate_function(
|
||||
"`to_spmatrix` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date. Use `to_matrix(sparse=True)` instead."
|
||||
)
|
||||
def to_spmatrix(self):
|
||||
r"""
|
||||
DEPRECATED Convert Pauli to a sparse matrix representation (CSR format).
|
||||
|
||||
This function is deprecated. Use :meth:`to_matrix` with kwarg
|
||||
``sparse=True`` instead.
|
||||
|
||||
Returns:
|
||||
scipy.sparse.csr_matrix: a sparse matrix with CSR format that
|
||||
represents the pauli.
|
||||
"""
|
||||
return self.to_matrix(sparse=True)
|
||||
|
||||
@deprecate_function(
|
||||
"`kron` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date of Qiskit Terra 0.17.0. "
|
||||
"Use `expand` instead, but note this does not change "
|
||||
"the operator in-place."
|
||||
)
|
||||
def kron(self, other):
|
||||
r"""DEPRECATED: Kronecker product of two paulis.
|
||||
|
||||
This function is deprecated. Use :meth:`expand` instead.
|
||||
|
||||
Order is $P_2 (other) \otimes P_1 (self)$
|
||||
|
||||
Args:
|
||||
other (Pauli): P2
|
||||
|
||||
Returns:
|
||||
Pauli: self
|
||||
"""
|
||||
pauli = self.expand(other)
|
||||
self._z = pauli._z
|
||||
self._x = pauli._x
|
||||
self._phase = pauli._phase
|
||||
self._op_shape = self._op_shape.expand(other._op_shape)
|
||||
return self
|
||||
|
||||
@deprecate_function(
|
||||
"`update_z` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date. Use `Pauli.z = val` or "
|
||||
"`Pauli.z[indices] = val` instead."
|
||||
)
|
||||
def update_z(self, z, indices=None):
|
||||
"""
|
||||
DEPRECATED: Update partial or entire z.
|
||||
|
||||
This function is deprecated. Use the setter for :attr:`Z` instead.
|
||||
|
||||
Args:
|
||||
z (numpy.ndarray or list): to-be-updated z
|
||||
indices (numpy.ndarray or list or optional): to-be-updated qubit indices
|
||||
|
||||
Returns:
|
||||
Pauli: self
|
||||
|
||||
Raises:
|
||||
QiskitError: when updating whole z, the number of qubits must be the same.
|
||||
"""
|
||||
phase = self.phase
|
||||
z = self._make_np_bool(z)
|
||||
if indices is None:
|
||||
if len(self.z) != len(z):
|
||||
raise QiskitError(
|
||||
"During updating whole z, you can not change the number of qubits."
|
||||
)
|
||||
self.z = z
|
||||
else:
|
||||
if not isinstance(indices, list) and not isinstance(indices, np.ndarray):
|
||||
indices = [indices]
|
||||
for p, idx in enumerate(indices):
|
||||
self.z[idx] = z[p]
|
||||
self.phase = phase
|
||||
return self
|
||||
|
||||
@deprecate_function(
|
||||
"`update_z` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date. Use `Pauli.x = val` or "
|
||||
"`Pauli.x[indices] = val` instead."
|
||||
)
|
||||
def update_x(self, x, indices=None):
|
||||
"""
|
||||
DEPRECATED: Update partial or entire x.
|
||||
|
||||
This function is deprecated. Use the setter for :attr:`X` instead.
|
||||
|
||||
Args:
|
||||
x (numpy.ndarray or list): to-be-updated x
|
||||
indices (numpy.ndarray or list or optional): to-be-updated qubit indices
|
||||
|
||||
Returns:
|
||||
Pauli: self
|
||||
|
||||
Raises:
|
||||
QiskitError: when updating whole x, the number of qubits must be the same.
|
||||
"""
|
||||
phase = self.phase
|
||||
x = self._make_np_bool(x)
|
||||
if indices is None:
|
||||
if len(self.x) != len(x):
|
||||
raise QiskitError(
|
||||
"During updating whole x, you can not change the number of qubits."
|
||||
)
|
||||
self.x = x
|
||||
else:
|
||||
if not isinstance(indices, list) and not isinstance(indices, np.ndarray):
|
||||
indices = [indices]
|
||||
for p, idx in enumerate(indices):
|
||||
self.x[idx] = x[p]
|
||||
self.phase = phase
|
||||
return self
|
||||
|
||||
@deprecate_function(
|
||||
"`insert_paulis` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date. For similar functionality use "
|
||||
"`Pauli.insert` instead."
|
||||
)
|
||||
def insert_paulis(self, indices=None, paulis=None, pauli_labels=None):
|
||||
"""
|
||||
DEPRECATED: Insert or append pauli to the targeted indices.
|
||||
|
||||
This function is deprecated. Similar functionality can be obtained
|
||||
using the :meth:`insert` method.
|
||||
|
||||
If indices is None, it means append at the end.
|
||||
|
||||
Args:
|
||||
indices (list[int]): the qubit indices to be inserted
|
||||
paulis (Pauli): the to-be-inserted or appended pauli
|
||||
pauli_labels (list[str]): the to-be-inserted or appended pauli label
|
||||
|
||||
Note:
|
||||
the indices refers to the location of original paulis,
|
||||
e.g. if indices = [0, 2], pauli_labels = ['Z', 'I'] and original pauli = 'ZYXI'
|
||||
the pauli will be updated to ZY'I'XI'Z'
|
||||
'Z' and 'I' are inserted before the qubit at 0 and 2.
|
||||
|
||||
Returns:
|
||||
Pauli: self
|
||||
|
||||
Raises:
|
||||
QiskitError: provide both `paulis` and `pauli_labels` at the same time
|
||||
"""
|
||||
if pauli_labels is not None:
|
||||
if paulis is not None:
|
||||
raise QiskitError("Please only provide either `paulis` or `pauli_labels`")
|
||||
if isinstance(pauli_labels, str):
|
||||
pauli_labels = list(pauli_labels)
|
||||
# since pauli label is in reversed order.
|
||||
label = "".join(pauli_labels[::-1])
|
||||
paulis = self.from_label(label)
|
||||
|
||||
# Insert and update self
|
||||
if indices is None: # append
|
||||
z = np.concatenate((self.z, paulis.z))
|
||||
x = np.concatenate((self.x, paulis.x))
|
||||
else:
|
||||
if not isinstance(indices, list):
|
||||
indices = [indices]
|
||||
z = np.insert(self.z, indices, paulis.z)
|
||||
x = np.insert(self.x, indices, paulis.x)
|
||||
pauli = Pauli((z, x, self.phase + paulis.phase))
|
||||
self._z = pauli._z
|
||||
self._x = pauli._x
|
||||
self._phase = pauli._phase
|
||||
self._op_shape = pauli._op_shape
|
||||
return self
|
||||
|
||||
@deprecate_function(
|
||||
"`append_paulis` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date. Use `Pauli.expand` instead."
|
||||
)
|
||||
def append_paulis(self, paulis=None, pauli_labels=None):
|
||||
"""
|
||||
DEPRECATED: Append pauli at the end.
|
||||
|
||||
Args:
|
||||
paulis (Pauli): the to-be-inserted or appended pauli
|
||||
pauli_labels (list[str]): the to-be-inserted or appended pauli label
|
||||
|
||||
Returns:
|
||||
Pauli: self
|
||||
"""
|
||||
return self.insert_paulis(None, paulis=paulis, pauli_labels=pauli_labels)
|
||||
|
||||
@deprecate_function(
|
||||
"`append_paulis` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date. For equivalent functionality "
|
||||
"use `Pauli.delete` instead."
|
||||
)
|
||||
def delete_qubits(self, indices):
|
||||
"""
|
||||
DEPRECATED: Delete pauli at the indices.
|
||||
|
||||
This function is deprecated. Equivalent functionality can be obtained
|
||||
using the :meth:`delete` method.
|
||||
|
||||
Args:
|
||||
indices(list[int]): the indices of to-be-deleted paulis
|
||||
|
||||
Returns:
|
||||
Pauli: self
|
||||
"""
|
||||
pauli = self.delete(indices)
|
||||
self._z = pauli._z
|
||||
self._x = pauli._x
|
||||
self._phase = pauli._phase
|
||||
self._op_shape = pauli._op_shape
|
||||
return self
|
||||
|
||||
@classmethod
|
||||
@deprecate_function(
|
||||
"`pauli_single` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date."
|
||||
)
|
||||
def pauli_single(cls, num_qubits, index, pauli_label):
|
||||
"""
|
||||
DEPRECATED: Generate single qubit pauli at index with pauli_label with length num_qubits.
|
||||
|
||||
Args:
|
||||
num_qubits (int): the length of pauli
|
||||
index (int): the qubit index to insert the single qubit
|
||||
pauli_label (str): pauli
|
||||
|
||||
Returns:
|
||||
Pauli: single qubit pauli
|
||||
"""
|
||||
tmp = Pauli(pauli_label)
|
||||
ret = Pauli((np.zeros(num_qubits, dtype=bool), np.zeros(num_qubits, dtype=bool)))
|
||||
ret.x[index] = tmp.x[0]
|
||||
ret.z[index] = tmp.z[0]
|
||||
ret.phase = tmp.phase
|
||||
return ret
|
||||
|
||||
@classmethod
|
||||
@deprecate_function(
|
||||
"`random` is deprecated and will be removed no earlier than "
|
||||
"3 months after the release date. "
|
||||
"Use `qiskit.quantum_info.random_pauli` instead"
|
||||
)
|
||||
def random(cls, num_qubits, seed=None):
|
||||
"""DEPRECATED: Return a random Pauli on number of qubits.
|
||||
|
||||
This function is deprecated use
|
||||
:func:`~qiskit.quantum_info.random_pauli` instead.
|
||||
|
||||
Args:
|
||||
num_qubits (int): the number of qubits
|
||||
seed (int): Optional. To set a random seed.
|
||||
Returns:
|
||||
Pauli: the random pauli
|
||||
"""
|
||||
# pylint: disable=cyclic-import
|
||||
from qiskit.quantum_info.operators.symplectic.random import (
|
||||
random_pauli,
|
||||
)
|
||||
|
||||
return random_pauli(num_qubits, group_phase=False, seed=seed)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Label parsing helper functions
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
upgrade:
|
||||
- |
|
||||
The deprecated function ``qiskit.quantum_info.pauli_group()`` has been removed.
|
||||
It was originally deprecated in Qiskit Terra 0.17.
|
||||
- |
|
||||
Several deprecated methods on :class:`.Pauli` have been removed, which were
|
||||
originally deprecated in Qiskit Terra 0.17. These were:
|
||||
|
||||
``sgn_prod``
|
||||
Use :meth:`.Pauli.compose` or :meth:`.Pauli.dot` instead.
|
||||
|
||||
``to_spmatrix``
|
||||
Use :meth:`.Pauli.to_matrix` with argument ``sparse=True`` instead.
|
||||
|
||||
``kron``
|
||||
Use :meth:`.Pauli.expand`, but beware that this returns a new object, rather
|
||||
than mutating the existing one.
|
||||
|
||||
``update_z`` and ``update_x``
|
||||
Set the ``z`` and ``x`` attributes of the object directly.
|
||||
|
||||
``insert_paulis``
|
||||
Use :meth:`.Pauli.insert`.
|
||||
|
||||
``append_paulis``
|
||||
Use :meth:`.Pauli.expand`.
|
||||
|
||||
``delete_qubits``
|
||||
Use :meth:`.Pauli.delete`.
|
||||
|
||||
``pauli_single``
|
||||
Construct the label manually and pass directly to the initializer, such as::
|
||||
|
||||
Pauli("I" * index + pauli_label + "I" * (num_qubits - index - len(pauli_label)))
|
||||
|
||||
``random``
|
||||
Use :func:`.quantum_info.random_pauli` instead.
|
||||
deprecations:
|
||||
- |
|
||||
The arguments ``x``, ``z`` and ``label`` to the initializer of
|
||||
:class:`.Pauli` were documented as deprecated in Qiskit Terra 0.17, but a bug
|
||||
prevented the expected warning from being shown at runtime. The warning will
|
||||
now correctly show, and the arguments will be removed in Qiskit Terra 0.23 or
|
||||
later. A pair of ``x`` and ``z`` should be passed positionally as a single
|
||||
tuple (``Pauli((z, x))``). A string ``label`` should be passed positionally
|
||||
in the first argument (``Pauli("XYZ")``).
|
|
@ -1,741 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2017.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Quick program to test the qi tools modules."""
|
||||
|
||||
import unittest
|
||||
from copy import deepcopy
|
||||
import numpy as np
|
||||
|
||||
from qiskit.quantum_info.operators import Pauli
|
||||
from qiskit.quantum_info import pauli_group
|
||||
from qiskit.test import QiskitTestCase
|
||||
|
||||
|
||||
class TestPauliAPI(QiskitTestCase):
|
||||
"""Tests for Pauli class API."""
|
||||
|
||||
def check(self, result):
|
||||
"""checks for result to be a Pauli 'IY'"""
|
||||
self.assertIsInstance(result, Pauli)
|
||||
self.assertEqual(result.num_qubits, 2)
|
||||
self.assertEqual(result.to_label(), "IY")
|
||||
|
||||
def test_ndarray_bool(self):
|
||||
"""Test creation from bool."""
|
||||
x = np.asarray([1, 0]).astype(bool)
|
||||
z = np.asarray([1, 0]).astype(bool)
|
||||
pauli = Pauli(x=x, z=z)
|
||||
self.check(pauli)
|
||||
|
||||
def test_ndarray_int(self):
|
||||
"""Test creation from int."""
|
||||
x = np.asarray([2, 0]).astype(int)
|
||||
z = np.asarray([2, 0]).astype(int)
|
||||
pauli = Pauli(x=x, z=z)
|
||||
self.check(pauli)
|
||||
|
||||
def test_list(self):
|
||||
"""Test creation from lists."""
|
||||
pauli = Pauli(x=[1, 0], z=[1, 0])
|
||||
self.check(pauli)
|
||||
|
||||
def test_tuple(self):
|
||||
"""Test creation from tuples."""
|
||||
pauli = Pauli(x=(1, 0), z=(1, 0))
|
||||
self.check(pauli)
|
||||
|
||||
def test_mix(self):
|
||||
"""Test creation from tuples and list."""
|
||||
pauli = Pauli(x=(1, 0), z=[1, 0])
|
||||
self.check(pauli)
|
||||
|
||||
|
||||
class TestPauli(QiskitTestCase):
|
||||
"""Tests for Pauli class."""
|
||||
|
||||
def setUp(self):
|
||||
"""Setup."""
|
||||
super().setUp()
|
||||
z = np.asarray([1, 0, 1, 0]).astype(bool)
|
||||
x = np.asarray([1, 1, 0, 0]).astype(bool)
|
||||
self.ref_p = Pauli(z, x)
|
||||
self.ref_label = "IZXY"
|
||||
self.ref_matrix = np.array(
|
||||
[
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 - 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 - 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 - 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 - 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 - 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 - 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 1.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 - 1.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
[
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 - 1.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
0.0 + 0.0j,
|
||||
],
|
||||
]
|
||||
)
|
||||
|
||||
def test_create_from_label(self):
|
||||
"""Test creation from pauli label."""
|
||||
label = "IZXY"
|
||||
pauli = Pauli(label=label)
|
||||
|
||||
self.assertEqual(pauli, self.ref_p)
|
||||
self.assertEqual(pauli.to_label(), self.ref_label)
|
||||
self.assertEqual(len(pauli), 4)
|
||||
|
||||
def test_create_from_z_x(self):
|
||||
"""Test creation for boolean vector."""
|
||||
self.assertEqual(self.ref_p.to_label(), "IZXY")
|
||||
self.assertEqual(len(self.ref_p), 4)
|
||||
|
||||
def test_random_pauli(self):
|
||||
"""Test random pauli creation."""
|
||||
length = 4
|
||||
q = Pauli.random(length, seed=42)
|
||||
self.log.info(q)
|
||||
self.assertEqual(q.num_qubits, length)
|
||||
self.assertEqual(len(q.z), length)
|
||||
self.assertEqual(len(q.x), length)
|
||||
self.assertEqual(len(q.to_label()), length)
|
||||
self.assertEqual(len(q.to_matrix()), 2**length)
|
||||
|
||||
def test_mul(self):
|
||||
"""Test multiplication."""
|
||||
p1 = self.ref_p
|
||||
p2 = Pauli.from_label("ZXXI")
|
||||
p3 = p1.dot(p2)
|
||||
self.assertEqual(len(p3), 4)
|
||||
self.assertEqual(p3[:].to_label(), "ZYIY")
|
||||
|
||||
def test_imul(self):
|
||||
"""Test in-place multiplication."""
|
||||
p1 = self.ref_p
|
||||
p2 = Pauli.from_label("ZXXI")
|
||||
p3 = deepcopy(p2)
|
||||
p2 *= p1
|
||||
self.assertTrue(p2 != p3)
|
||||
self.assertEqual(p2[:].to_label(), "ZYIY")
|
||||
|
||||
def test_equality_equal(self):
|
||||
"""Test equality operator: equal Paulis."""
|
||||
p1 = self.ref_p
|
||||
p2 = deepcopy(p1)
|
||||
self.assertTrue(p1 == p2)
|
||||
self.assertEqual(p1.to_label(), self.ref_label)
|
||||
self.assertEqual(p2.to_label(), self.ref_label)
|
||||
|
||||
def test_equality_different(self):
|
||||
"""Test equality operator: different Paulis."""
|
||||
p1 = self.ref_p
|
||||
p2 = deepcopy(p1)
|
||||
|
||||
p2.update_z(True, 1)
|
||||
self.assertFalse(p1 == p2)
|
||||
self.assertEqual(p1.to_label(), self.ref_label)
|
||||
self.assertEqual(p2.to_label(), "IZYY")
|
||||
|
||||
def test_inequality_equal(self):
|
||||
"""Test inequality operator: equal Paulis."""
|
||||
p1 = self.ref_p
|
||||
p2 = deepcopy(p1)
|
||||
|
||||
self.assertFalse(p1 != p2)
|
||||
|
||||
def test_inequality_different(self):
|
||||
"""Test inequality operator: different Paulis."""
|
||||
p1 = self.ref_p
|
||||
p2 = deepcopy(p1)
|
||||
p2.update_x(False, 1)
|
||||
self.assertTrue(p1 != p2)
|
||||
self.assertEqual(p2.to_label(), "IZIY")
|
||||
|
||||
def test_update_z(self):
|
||||
"""Test update_z method."""
|
||||
updated_z = np.asarray([0, 0, 0, 0]).astype(bool)
|
||||
self.ref_p.update_z(updated_z)
|
||||
np.testing.assert_equal(self.ref_p.z, np.asarray([False, False, False, False]))
|
||||
self.assertEqual(self.ref_p.to_label(), "IIXX")
|
||||
|
||||
def test_update_z_2(self):
|
||||
"""Test update_z method, update partial z."""
|
||||
updated_z = np.asarray([0, 1]).astype(bool)
|
||||
self.ref_p.update_z(updated_z, [0, 1])
|
||||
np.testing.assert_equal(self.ref_p.z, np.asarray([False, True, True, False]))
|
||||
self.assertEqual(self.ref_p.to_label(), "IZYX")
|
||||
|
||||
def test_update_x(self):
|
||||
"""Test update_x method."""
|
||||
updated_x = np.asarray([0, 1, 0, 1]).astype(bool)
|
||||
self.ref_p.update_x(updated_x)
|
||||
np.testing.assert_equal(self.ref_p.x, np.asarray([False, True, False, True]))
|
||||
self.assertEqual(self.ref_p.to_label(), "XZXZ")
|
||||
|
||||
def test_update_x_2(self):
|
||||
"""Test update_x method, update partial x."""
|
||||
updated_x = np.asarray([0, 1]).astype(bool)
|
||||
self.ref_p.update_x(updated_x, [1, 2])
|
||||
np.testing.assert_equal(self.ref_p.x, np.asarray([True, False, True, False]))
|
||||
self.assertEqual(self.ref_p.to_label(), "IYIY")
|
||||
|
||||
def test_to_matrix(self):
|
||||
"""Test pauli to matrix."""
|
||||
np.testing.assert_allclose(self.ref_p.to_matrix(), self.ref_matrix)
|
||||
|
||||
def test_delete_qubit(self):
|
||||
"""Test deleting single qubit."""
|
||||
p1 = self.ref_p
|
||||
p2 = deepcopy(p1)
|
||||
|
||||
p2.delete_qubits(0)
|
||||
self.assertTrue(p1 != p2)
|
||||
self.assertEqual(len(p2), 3)
|
||||
self.assertEqual(p2.to_label(), "IZX")
|
||||
|
||||
def test_delete_qubits(self):
|
||||
"""Test deleting multiple qubits."""
|
||||
p1 = self.ref_p
|
||||
p2 = deepcopy(p1)
|
||||
|
||||
p2.delete_qubits([0, 2])
|
||||
self.assertTrue(p1 != p2)
|
||||
self.assertEqual(len(p2), 2)
|
||||
self.assertEqual(p2.to_label(), "IX")
|
||||
|
||||
def test_append_pauli_labels(self):
|
||||
"""Test appending paulis via labels."""
|
||||
p1 = self.ref_p
|
||||
p2 = deepcopy(p1)
|
||||
|
||||
p2.append_paulis(pauli_labels=["Z", "Y", "I"])
|
||||
self.assertTrue(p1 != p2)
|
||||
self.assertEqual(len(p2), 7)
|
||||
self.assertEqual(p2.to_label(), "IYZ" + self.ref_label)
|
||||
|
||||
def test_append_paulis(self):
|
||||
"""Test appending paulis via pauli object."""
|
||||
p1 = self.ref_p
|
||||
p2 = deepcopy(p1)
|
||||
|
||||
p2.append_paulis(paulis=p1)
|
||||
self.assertTrue(p1 != p2)
|
||||
self.assertEqual(len(p2), 8)
|
||||
self.assertEqual(p2.to_label(), self.ref_label + self.ref_label)
|
||||
|
||||
def test_insert_pauli_labels_1(self):
|
||||
"""Test inserting paulis via labels."""
|
||||
p2 = deepcopy(self.ref_p)
|
||||
|
||||
p2.insert_paulis(indices=[1, 2], pauli_labels=["Y", "I"])
|
||||
self.assertTrue(self.ref_p != p2)
|
||||
self.assertEqual(len(p2), 6)
|
||||
self.assertEqual(p2.to_label(), "IZIXYY")
|
||||
|
||||
def test_insert_pauli_labels_2(self):
|
||||
"""Test inserting paulis via labels."""
|
||||
p2 = deepcopy(self.ref_p)
|
||||
|
||||
p2.insert_paulis(indices=[3, 2], pauli_labels=["Y", "I"])
|
||||
self.assertTrue(self.ref_p != p2)
|
||||
self.assertEqual(len(p2), 6)
|
||||
self.assertEqual(p2.to_label(), "IYZIXY")
|
||||
|
||||
def test_insert_paulis(self):
|
||||
"""Test inserting paulis via pauli object."""
|
||||
p1 = deepcopy(self.ref_p)
|
||||
|
||||
new_p = Pauli.from_label("XY")
|
||||
|
||||
p1.insert_paulis(indices=[0], paulis=new_p)
|
||||
|
||||
self.assertTrue(p1 != self.ref_p)
|
||||
self.assertEqual(len(p1), 6)
|
||||
self.assertEqual(p1.to_label(), self.ref_label + "XY")
|
||||
|
||||
def test_kron(self):
|
||||
"""Test kron production."""
|
||||
p1 = deepcopy(self.ref_p)
|
||||
p2 = deepcopy(self.ref_p)
|
||||
p2.kron(p1)
|
||||
self.assertTrue(p1 != p2)
|
||||
self.assertEqual(len(p2), 8)
|
||||
self.assertEqual(p2.to_label(), self.ref_label + self.ref_label)
|
||||
|
||||
def test_pauli_single(self):
|
||||
"""Test pauli single."""
|
||||
num_qubits = 5
|
||||
pz = Pauli.pauli_single(num_qubits, 2, "Z")
|
||||
self.assertTrue(pz.to_label(), "IIIZI")
|
||||
|
||||
py = Pauli.pauli_single(num_qubits, 4, "Y")
|
||||
self.assertTrue(py.to_label(), "IYIII")
|
||||
|
||||
px = Pauli.pauli_single(num_qubits, 3, "X")
|
||||
self.assertTrue(px.to_label(), "IIXII")
|
||||
|
||||
def test_pauli_group(self):
|
||||
"""Test pauli group."""
|
||||
self.log.info("Group in tensor order:")
|
||||
expected = [
|
||||
"III",
|
||||
"XII",
|
||||
"YII",
|
||||
"ZII",
|
||||
"IXI",
|
||||
"XXI",
|
||||
"YXI",
|
||||
"ZXI",
|
||||
"IYI",
|
||||
"XYI",
|
||||
"YYI",
|
||||
"ZYI",
|
||||
"IZI",
|
||||
"XZI",
|
||||
"YZI",
|
||||
"ZZI",
|
||||
"IIX",
|
||||
"XIX",
|
||||
"YIX",
|
||||
"ZIX",
|
||||
"IXX",
|
||||
"XXX",
|
||||
"YXX",
|
||||
"ZXX",
|
||||
"IYX",
|
||||
"XYX",
|
||||
"YYX",
|
||||
"ZYX",
|
||||
"IZX",
|
||||
"XZX",
|
||||
"YZX",
|
||||
"ZZX",
|
||||
"IIY",
|
||||
"XIY",
|
||||
"YIY",
|
||||
"ZIY",
|
||||
"IXY",
|
||||
"XXY",
|
||||
"YXY",
|
||||
"ZXY",
|
||||
"IYY",
|
||||
"XYY",
|
||||
"YYY",
|
||||
"ZYY",
|
||||
"IZY",
|
||||
"XZY",
|
||||
"YZY",
|
||||
"ZZY",
|
||||
"IIZ",
|
||||
"XIZ",
|
||||
"YIZ",
|
||||
"ZIZ",
|
||||
"IXZ",
|
||||
"XXZ",
|
||||
"YXZ",
|
||||
"ZXZ",
|
||||
"IYZ",
|
||||
"XYZ",
|
||||
"YYZ",
|
||||
"ZYZ",
|
||||
"IZZ",
|
||||
"XZZ",
|
||||
"YZZ",
|
||||
"ZZZ",
|
||||
]
|
||||
grp = pauli_group(3, case="tensor")
|
||||
for j in grp:
|
||||
self.log.info("==== j (tensor order) ====")
|
||||
self.log.info(j.to_label())
|
||||
self.assertEqual(expected.pop(0)[::-1], j.to_label())
|
||||
|
||||
self.log.info("Group in weight order:")
|
||||
expected = [
|
||||
"III",
|
||||
"XII",
|
||||
"YII",
|
||||
"ZII",
|
||||
"IXI",
|
||||
"IYI",
|
||||
"IZI",
|
||||
"IIX",
|
||||
"IIY",
|
||||
"IIZ",
|
||||
"XXI",
|
||||
"YXI",
|
||||
"ZXI",
|
||||
"XYI",
|
||||
"YYI",
|
||||
"ZYI",
|
||||
"XZI",
|
||||
"YZI",
|
||||
"ZZI",
|
||||
"XIX",
|
||||
"YIX",
|
||||
"ZIX",
|
||||
"IXX",
|
||||
"IYX",
|
||||
"IZX",
|
||||
"XIY",
|
||||
"YIY",
|
||||
"ZIY",
|
||||
"IXY",
|
||||
"IYY",
|
||||
"IZY",
|
||||
"XIZ",
|
||||
"YIZ",
|
||||
"ZIZ",
|
||||
"IXZ",
|
||||
"IYZ",
|
||||
"IZZ",
|
||||
"XXX",
|
||||
"YXX",
|
||||
"ZXX",
|
||||
"XYX",
|
||||
"YYX",
|
||||
"ZYX",
|
||||
"XZX",
|
||||
"YZX",
|
||||
"ZZX",
|
||||
"XXY",
|
||||
"YXY",
|
||||
"ZXY",
|
||||
"XYY",
|
||||
"YYY",
|
||||
"ZYY",
|
||||
"XZY",
|
||||
"YZY",
|
||||
"ZZY",
|
||||
"XXZ",
|
||||
"YXZ",
|
||||
"ZXZ",
|
||||
"XYZ",
|
||||
"YYZ",
|
||||
"ZYZ",
|
||||
"XZZ",
|
||||
"YZZ",
|
||||
"ZZZ",
|
||||
]
|
||||
grp = pauli_group(3, case="weight")
|
||||
for j in grp:
|
||||
self.log.info("==== j (weight order) ====")
|
||||
self.log.info(j.to_label())
|
||||
self.assertEqual(expected.pop(0)[::-1], j.to_label())
|
||||
|
||||
def test_sgn_prod(self):
|
||||
"""Test sgn prod."""
|
||||
p1 = Pauli(np.array([False]), np.array([True]))
|
||||
p2 = Pauli(np.array([True]), np.array([True]))
|
||||
|
||||
self.log.info("sign product:")
|
||||
p3, sgn = Pauli.sgn_prod(p1, p2)
|
||||
self.log.info("p1: %s", p1.to_label())
|
||||
self.log.info("p2: %s", p2.to_label())
|
||||
self.log.info("p3: %s", p3.to_label())
|
||||
self.log.info("sgn_prod(p1, p2): %s", str(sgn))
|
||||
self.assertEqual(p1.to_label(), "X")
|
||||
self.assertEqual(p2.to_label(), "Y")
|
||||
self.assertEqual(p3.to_label(), "Z")
|
||||
self.assertEqual(sgn, 1j)
|
||||
|
||||
self.log.info("sign product reverse:")
|
||||
p3, sgn = Pauli.sgn_prod(p2, p1) # pylint: disable=arguments-out-of-order
|
||||
self.log.info("p2: %s", p2.to_label())
|
||||
self.log.info("p1: %s", p1.to_label())
|
||||
self.log.info("p3: %s", p3.to_label())
|
||||
self.log.info("sgn_prod(p2, p1): %s", str(sgn))
|
||||
self.assertEqual(p1.to_label(), "X")
|
||||
self.assertEqual(p2.to_label(), "Y")
|
||||
self.assertEqual(p3.to_label(), "Z")
|
||||
self.assertEqual(sgn, -1j)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Reference in New Issue