Esempio n. 1
0
    def compose(self, other, qargs=None, front=False):
        """Return the composition channel self∘other.

        Args:
            other (SparsePauliOp): an operator object.
            qargs (list or None): a list of subsystem positions to compose other on.
            front (bool or None): If False compose in standard order other(self(input))
                          otherwise compose in reverse order self(other(input))
                          [default: False]

        Returns:
            SparsePauliOp: The composed operator.

        Raises:
            QiskitError: if other cannot be converted to an Operator or has
            incompatible dimensions.
        """
        # pylint: disable=invalid-name
        if qargs is None:
            qargs = getattr(other, 'qargs', None)

        if not isinstance(other, SparsePauliOp):
            other = SparsePauliOp(other)

        # Validate composition dimensions and qargs match
        self._op_shape.compose(other._op_shape, qargs, front)

        # Implement composition of the Pauli table
        x1, x2 = PauliTable._block_stack(self.table.X, other.table.X)
        z1, z2 = PauliTable._block_stack(self.table.Z, other.table.Z)
        c1, c2 = PauliTable._block_stack(self.coeffs, other.coeffs)

        if qargs is not None:
            ret_x, ret_z = x1.copy(), z1.copy()
            x1 = x1[:, qargs]
            z1 = z1[:, qargs]
            ret_x[:, qargs] = x1 ^ x2
            ret_z[:, qargs] = z1 ^ z2
            table = np.hstack([ret_x, ret_z])
        else:
            table = np.hstack((x1 ^ x2, z1 ^ z2))

        # Take product of coefficients and add phase correction
        coeffs = c1 * c2
        # We pick additional phase terms for the products
        # X.Y = i * Z, Y.Z = i * X, Z.X = i * Y
        # Y.X = -i * Z, Z.Y = -i * X, X.Z = -i * Y
        if front:
            plus_i = (x1 & ~z1 & x2 & z2) | (x1 & z1 & ~x2 & z2) | (~x1 & z1
                                                                    & x2 & ~z2)
            minus_i = (x2 & ~z2 & x1 & z1) | (x2 & z2 & ~x1
                                              & z1) | (~x2 & z2 & x1 & ~z1)
        else:
            minus_i = (x1 & ~z1 & x2 & z2) | (x1 & z1 & ~x2
                                              & z2) | (~x1 & z1 & x2 & ~z2)
            plus_i = (x2 & ~z2 & x1 & z1) | (x2 & z2 & ~x1 & z1) | (~x2 & z2
                                                                    & x1 & ~z1)
        coeffs *= 1j**np.array(np.sum(plus_i, axis=1), dtype=int)
        coeffs *= (-1j)**np.array(np.sum(minus_i, axis=1), dtype=int)
        return SparsePauliOp(table, coeffs)
Esempio n. 2
0
 def from_list(obj):
     """Construct from a list [(pauli_str, coeffs)]"""
     obj = list(obj)  # To convert zip or other iterable
     num_qubits = len(PauliTable._from_label(obj[0][0]))
     size = len(obj)
     coeffs = np.zeros(size, dtype=complex)
     labels = np.zeros(size, dtype='<U{}'.format(num_qubits))
     for i, item in enumerate(obj):
         labels[i] = item[0]
         coeffs[i] = item[1]
     table = PauliTable.from_labels(labels)
     return SparsePauliOp(table, coeffs)
def pauli_basis(num_qubits, weight=False, pauli_list=False):
    """Return the ordered PauliTable or PauliList for the n-qubit Pauli basis.

    Args:
        num_qubits (int): number of qubits
        weight (bool): if True optionally return the basis sorted by Pauli weight
                       rather than lexicographic order (Default: False)
        pauli_list (bool): if True, the return type becomes PauliList, otherwise PauliTable.

    Returns:
        PauliTable, PauliList: the Paulis for the basis
    """
    if pauli_list:
        pauli_1q = PauliList(["I", "X", "Y", "Z"])
    else:
        warnings.warn(
            "The pauli_basis function with PauliTable output is deprecated as of Qiskit Terra "
            "0.19.0 and will be removed no sooner than 3 months after the releasedate. "
            "Use PauliList by pauli_list=True instead.",
            DeprecationWarning,
            stacklevel=2,
        )
        pauli_1q = PauliTable(
            np.array(
                [[False, False], [True, False], [True, True], [False, True]],
                dtype=bool))
    if num_qubits == 1:
        return pauli_1q
    pauli = pauli_1q
    for _ in range(num_qubits - 1):
        pauli = pauli_1q.tensor(pauli)
    if weight:
        return pauli.sort(weight=True)
    return pauli
Esempio n. 4
0
def pauli_basis(num_qubits, weight=False, pauli_list=False):
    """Return the ordered PauliTable or PauliList for the n-qubit Pauli basis.

    Args:
        num_qubits (int): number of qubits
        weight (bool): if True optionally return the basis sorted by Pauli weight
                       rather than lexicographic order (Default: False)
        pauli_list (bool): if True, the return type becomes PauliList, otherwise PauliTable.

    Returns:
        PauliTable, PauliList: the Paulis for the basis
    """
    if pauli_list:
        pauli_1q = PauliList(["I", "X", "Y", "Z"])
    else:
        warnings.warn(
            "The return type of 'pauli_basis' will change from PauliTable to PauliList in a "
            "future release of Qiskit Terra.  Returning PauliTable is deprecated as of "
            "Qiskit Terra 0.19, and will be removed in a future release.  To immediately switch "
            "to the new behaviour, pass the keyword argument 'pauli_list=True'.",
            FutureWarning,
            stacklevel=2,
        )
        pauli_1q = PauliTable(
            np.array(
                [[False, False], [True, False], [True, True], [False, True]],
                dtype=bool))
    if num_qubits == 1:
        return pauli_1q
    pauli = pauli_1q
    for _ in range(num_qubits - 1):
        pauli = pauli_1q.tensor(pauli)
    if weight:
        return pauli.sort(weight=True)
    return pauli
Esempio n. 5
0
    def __init__(self, data, coeffs=None):
        """Initialize an operator object.

        Args:
            data (PauliTable): Pauli table of terms.
            coeffs (np.ndarray): complex coefficients for Pauli terms.

        Raises:
            QiskitError: If the input data or coeffs are invalid.
        """
        if isinstance(data, SparsePauliOp):
            table = data._table
            coeffs = data._coeffs
        else:
            table = PauliTable(data)
            if coeffs is None:
                coeffs = np.ones(table.size, dtype=np.complex)
        # Initialize PauliTable
        self._table = table

        # Initialize Coeffs
        self._coeffs = np.asarray(coeffs, dtype=complex)
        if self._coeffs.shape != (self._table.size, ):
            raise QiskitError("coeff vector is incorrect shape for number"
                              " of Paulis {} != {}".format(self._coeffs.shape,
                                                           self._table.size))
        # Initialize BaseOperator
        super().__init__(self._table._input_dims, self._table._output_dims)
Esempio n. 6
0
 def _from_label(label):
     """Return the symplectic representation of a Pauli stabilizer string"""
     # Check if first character is '+' or '-'
     phase = False
     if label[0] in ['-', '+']:
         phase = (label[0] == '-')
         label = label[1:]
     return PauliTable._from_label(label), phase
Esempio n. 7
0
 def _to_label(pauli, phase):
     """Return the Pauli stabilizer string from symplectic representation."""
     # pylint: disable=arguments-differ
     # Cast in symplectic representation
     # This should avoid a copy if the pauli is already a row
     # in the symplectic table
     label = PauliTable._to_label(pauli)
     if phase:
         return '-' + label
     return '+' + label
Esempio n. 8
0
    def compose(self, other, qargs=None, front=False):
        if qargs is None:
            qargs = getattr(other, "qargs", None)

        if not isinstance(other, SparsePauliOp):
            other = SparsePauliOp(other)

        # Validate composition dimensions and qargs match
        self._op_shape.compose(other._op_shape, qargs, front)

        # Implement composition of the Pauli table
        x1, x2 = PauliTable._block_stack(self.table.X, other.table.X)
        z1, z2 = PauliTable._block_stack(self.table.Z, other.table.Z)
        c1, c2 = PauliTable._block_stack(self.coeffs, other.coeffs)

        if qargs is not None:
            ret_x, ret_z = x1.copy(), z1.copy()
            x1 = x1[:, qargs]
            z1 = z1[:, qargs]
            ret_x[:, qargs] = x1 ^ x2
            ret_z[:, qargs] = z1 ^ z2
            table = np.hstack([ret_x, ret_z])
        else:
            table = np.hstack((x1 ^ x2, z1 ^ z2))

        # Take product of coefficients and add phase correction
        coeffs = c1 * c2
        # We pick additional phase terms for the products
        # X.Y = i * Z, Y.Z = i * X, Z.X = i * Y
        # Y.X = -i * Z, Z.Y = -i * X, X.Z = -i * Y
        if front:
            plus_i = (x1 & ~z1 & x2 & z2) | (x1 & z1 & ~x2 & z2) | (~x1 & z1
                                                                    & x2 & ~z2)
            minus_i = (x2 & ~z2 & x1 & z1) | (x2 & z2 & ~x1
                                              & z1) | (~x2 & z2 & x1 & ~z1)
        else:
            minus_i = (x1 & ~z1 & x2 & z2) | (x1 & z1 & ~x2
                                              & z2) | (~x1 & z1 & x2 & ~z2)
            plus_i = (x2 & ~z2 & x1 & z1) | (x2 & z2 & ~x1 & z1) | (~x2 & z2
                                                                    & x1 & ~z1)
        coeffs *= 1j**np.array(np.sum(plus_i, axis=1), dtype=int)
        coeffs *= (-1j)**np.array(np.sum(minus_i, axis=1), dtype=int)
        return SparsePauliOp(table, coeffs)
Esempio n. 9
0
    def _to_matrix(pauli, phase, sparse=False):
        """"Return the Pauli stabilizer matrix from symplectic representation.

        Args:
            pauli (array): symplectic Pauli vector.
            phase (bool): the phase value for the Pauli.
            sparse (bool): if True return a sparse CSR matrix, otherwise
                           return a dense Numpy array (Default: False).

        Returns:
            array: if sparse=False.
            csr_matrix: if sparse=True.
        """
        # pylint: disable=arguments-differ
        mat = PauliTable._to_matrix(pauli, sparse=sparse, real_valued=True)
        if phase:
            mat *= -1
        return mat
Esempio n. 10
0
 def __getitem__(self, key):
     sumopcoeff = self.obj.coeff * self.obj.primitive.coeffs[key]
     mat = PauliTable._to_matrix(
         self.obj.primitive.table.array[key], sparse=sparse)
     return sumopcoeff * mat
Esempio n. 11
0
 def pauli(self, value):
     if not isinstance(value, PauliTable):
         value = PauliTable(value)
     self._array[:, :] = value._array
Esempio n. 12
0
 def __getitem__(self, key):
     coeff = self.obj.coeffs[key]
     mat = PauliTable._to_matrix(self.obj.table.array[key],
                                 sparse=sparse)
     return coeff * mat
Esempio n. 13
0
 def __getitem__(self, key):
     coeff = self.obj.coeffs[key]
     pauli = PauliTable._to_label(self.obj.table.array[key])
     return (pauli, coeff)
Esempio n. 14
0
 def table(self, value):
     if not isinstance(value, PauliTable):
         value = PauliTable(value)
     self._table.array = value.array
Esempio n. 15
0
 def table(self):
     """DEPRECATED - Return the the PauliTable."""
     return PauliTable(np.column_stack((self.paulis.x, self.paulis.z)))
Esempio n. 16
0
 def table(self, value):
     if not isinstance(value, PauliTable):
         value = PauliTable(value)
     self._pauli_list = PauliList(value)
Esempio n. 17
0
 def pauli(self):
     """Return PauliTable"""
     return PauliTable(self._array)