示例#1
0
    def add(self, other: OperatorBase) -> OperatorBase:
        if not self.num_qubits == other.num_qubits:
            raise ValueError(
                "Sum over operators with different numbers of qubits, {} and {}, is not well "
                "defined".format(self.num_qubits, other.num_qubits)
            )

        if isinstance(other, PauliOp) and self.primitive == other.primitive:
            return PauliOp(self.primitive, coeff=self.coeff + other.coeff)

        # pylint: disable=cyclic-import
        from .pauli_sum_op import PauliSumOp

        if (
            isinstance(other, PauliOp)
            and isinstance(self.coeff, (int, float, complex))
            and isinstance(other.coeff, (int, float, complex))
        ):
            return PauliSumOp(
                SparsePauliOp(self.primitive, coeffs=[self.coeff])
                + SparsePauliOp(other.primitive, coeffs=[other.coeff])
            )

        if isinstance(other, PauliSumOp) and isinstance(self.coeff, (int, float, complex)):
            return PauliSumOp(SparsePauliOp(self.primitive, coeffs=[self.coeff])) + other

        return SummedOp([self, other])
示例#2
0
def init_observable(observable: BaseOperator | PauliSumOp) -> SparsePauliOp:
    """Initialize observable by converting the input to a :class:`~qiskit.quantum_info.SparsePauliOp`.

    Args:
        observable: The observable.

    Returns:
        The observable as :class:`~qiskit.quantum_info.SparsePauliOp`.

    Raises:
        TypeError: If the observable is a :class:`~qiskit.opflow.PauliSumOp` and has a parameterized
            coefficient.
    """
    if isinstance(observable, SparsePauliOp):
        return observable
    elif isinstance(observable, PauliSumOp):
        if isinstance(observable.coeff, ParameterExpression):
            raise TypeError(
                f"Observable must have numerical coefficient, not {type(observable.coeff)}."
            )
        return observable.coeff * observable.primitive
    elif isinstance(observable, BasePauli):
        return SparsePauliOp(observable)
    elif isinstance(observable, BaseOperator):
        return SparsePauliOp.from_operator(observable)
    else:
        return SparsePauliOp(observable)
示例#3
0
def _to_sparse_pauli_op(operator):
    """Cast the operator to a SparsePauliOp.

    For Opflow objects, return a global coefficient that must be multiplied to the evolution time.
    Since this coefficient might contain unbound parameters it cannot be absorbed into the
    coefficients of the SparsePauliOp.
    """
    # pylint: disable=cyclic-import
    from qiskit.opflow import PauliSumOp, PauliOp

    if isinstance(operator, PauliSumOp):
        sparse_pauli = operator.primitive
        sparse_pauli._coeffs *= operator.coeff
    elif isinstance(operator, PauliOp):
        sparse_pauli = SparsePauliOp(operator.primitive)
        sparse_pauli._coeffs *= operator.coeff
    elif isinstance(operator, Pauli):
        sparse_pauli = SparsePauliOp(operator)
    elif isinstance(operator, SparsePauliOp):
        sparse_pauli = operator
    else:
        raise ValueError(
            f"Unsupported operator type for evolution: {type(operator)}.")

    return sparse_pauli
    def _replace_pauli_sums(cls, operator):
        try:
            from qiskit.providers.aer.library import SaveExpectationValue
        except ImportError as ex:
            raise MissingOptionalLibraryError(
                libname="qiskit-aer",
                name="AerPauliExpectation",
                pip_install="pip install qiskit-aer",
            ) from ex
        # The 'expval_measurement' label on the save instruction is special - the
        # CircuitSampler will look for it to know that the circuit is a Expectation
        # measurement, and not simply a
        # circuit to replace with a DictStateFn
        if operator.__class__ == ListOp:
            return operator.traverse(cls._replace_pauli_sums)

        if isinstance(operator, PauliSumOp):
            save_instruction = SaveExpectationValue(operator.primitive,
                                                    "expval_measurement")
            return CircuitStateFn(save_instruction,
                                  coeff=operator.coeff,
                                  is_measurement=True,
                                  from_operator=True)

        # Change to Pauli representation if necessary
        if {"Pauli"} != operator.primitive_strings():
            logger.warning(
                "Measured Observable is not composed of only Paulis, converting to "
                "Pauli representation, which can be expensive.")
            # Setting massive=False because this conversion is implicit. User can perform this
            # action on the Observable with massive=True explicitly if they so choose.
            operator = operator.to_pauli_op(massive=False)

        if isinstance(operator, SummedOp):
            sparse_pauli = reduce(add,
                                  (meas.coeff * SparsePauliOp(meas.primitive)
                                   for meas in operator.oplist))
            save_instruction = SaveExpectationValue(sparse_pauli,
                                                    "expval_measurement")
            return CircuitStateFn(save_instruction,
                                  coeff=operator.coeff,
                                  is_measurement=True,
                                  from_operator=True)

        if isinstance(operator, PauliOp):
            sparse_pauli = operator.coeff * SparsePauliOp(operator.primitive)
            save_instruction = SaveExpectationValue(sparse_pauli,
                                                    "expval_measurement")
            return CircuitStateFn(save_instruction,
                                  is_measurement=True,
                                  from_operator=True)

        raise TypeError(
            f"Conversion of OperatorStateFn of {operator.__class__.__name__} is not defined."
        )
示例#5
0
    def test_add(self):
        """ add test """
        pauli_sum = 3 * X + Y
        self.assertIsInstance(pauli_sum, PauliSumOp)
        expected = PauliSumOp(3.0 * SparsePauliOp(Pauli("X")) +
                              SparsePauliOp(Pauli("Y")))
        self.assertEqual(pauli_sum, expected)

        pauli_sum = X + Y
        summed_op = SummedOp([X, Y])
        self.assertEqual(pauli_sum, summed_op)
示例#6
0
    def test_adjoint(self):
        """ adjoint test """
        pauli_sum = PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[2]),
                               coeff=3)
        expected = PauliSumOp(SparsePauliOp(Pauli("XYZX")), coeff=-6)

        self.assertEqual(pauli_sum.adjoint(), expected)

        pauli_sum = PauliSumOp(SparsePauliOp(Pauli("XYZY"), coeffs=[2]),
                               coeff=3j)
        expected = PauliSumOp(SparsePauliOp(Pauli("XYZY")), coeff=-6j)
        self.assertEqual(pauli_sum.adjoint(), expected)
示例#7
0
    def test_coder_operators(self):
        """Test runtime encoder and decoder for operators."""
        x = Parameter("x")
        y = x + 1
        qc = QuantumCircuit(1)
        qc.h(0)
        coeffs = np.array([1, 2, 3, 4, 5, 6])
        table = PauliTable.from_labels(
            ["III", "IXI", "IYY", "YIZ", "XYZ", "III"])
        op = (2.0 * I ^ I)
        z2_symmetries = Z2Symmetries(
            [Pauli("IIZI"), Pauli("ZIII")],
            [Pauli("IIXI"), Pauli("XIII")], [1, 3], [-1, 1])
        isqrt2 = 1 / np.sqrt(2)
        sparse = scipy.sparse.csr_matrix([[0, isqrt2, 0, isqrt2]])

        subtests = (
            PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[2]), coeff=3),
            PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[1]), coeff=y),
            PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[1 + 2j]),
                       coeff=3 - 2j),
            PauliSumOp.from_list([("II", -1.052373245772859),
                                  ("IZ", 0.39793742484318045)]),
            PauliSumOp(SparsePauliOp(table, coeffs), coeff=10),
            MatrixOp(primitive=np.array([[0, -1j], [1j, 0]]), coeff=x),
            PauliOp(primitive=Pauli("Y"), coeff=x),
            CircuitOp(qc, coeff=x),
            EvolvedOp(op, coeff=x),
            TaperedPauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[2]),
                              z2_symmetries),
            StateFn(qc, coeff=x),
            CircuitStateFn(qc, is_measurement=True),
            DictStateFn("1" * 3, is_measurement=True),
            VectorStateFn(np.ones(2**3, dtype=complex)),
            OperatorStateFn(CircuitOp(QuantumCircuit(1))),
            SparseVectorStateFn(sparse),
            Statevector([1, 0]),
            CVaRMeasurement(Z, 0.2),
            ComposedOp([(X ^ Y ^ Z), (Z ^ X ^ Y ^ Z).to_matrix_op()]),
            SummedOp([X ^ X * 2, Y ^ Y], 2),
            TensoredOp([(X ^ Y), (Z ^ I)]),
            (Z ^ Z) ^ (I ^ 2),
        )
        for op in subtests:
            with self.subTest(op=op):
                encoded = json.dumps(op, cls=RuntimeEncoder)
                self.assertIsInstance(encoded, str)
                decoded = json.loads(encoded, cls=RuntimeDecoder)
                self.assertEqual(op, decoded)
    def test_grouped_pauli_statefn(self):
        """grouped pauli test with statefn"""
        grouped_pauli = PauliSumOp(SparsePauliOp(["Y"]), grouping_type="TPB")
        observable = OperatorStateFn(grouped_pauli, is_measurement=True)

        converter = PauliBasisChange(
            replacement_fn=PauliBasisChange.measurement_replacement_fn)
        cob = converter.convert(observable)

        expected = PauliSumOp(SparsePauliOp(["Z"]), grouping_type="TPB")
        self.assertEqual(cob[0].primitive, expected)
        circuit = QuantumCircuit(1)
        circuit.sdg(0)
        circuit.h(0)
        self.assertEqual(cob[1].primitive, circuit)
示例#9
0
    def test_equals(self):
        """ equality test """

        self.assertNotEqual((X ^ X) + (Y ^ Y), X + Y)
        self.assertEqual((X ^ X) + (Y ^ Y), (Y ^ Y) + (X ^ X))

        theta = ParameterVector("theta", 2)
        pauli_sum0 = theta[0] * (X + Z)
        pauli_sum1 = theta[1] * (X + Z)
        expected = PauliSumOp(
            SparsePauliOp(Pauli("X")) + SparsePauliOp(Pauli("Z")),
            coeff=1.0 * theta[0],
        )
        self.assertEqual(pauli_sum0, expected)
        self.assertNotEqual(pauli_sum1, expected)
示例#10
0
 def _expand_dim(self, num_qubits: int) -> "PauliSumOp":
     return PauliSumOp(
         self.primitive.tensor(  # type:ignore
             SparsePauliOp(Pauli("I" * num_qubits))
         ),
         coeff=self.coeff,
     )
示例#11
0
def _expval_params(operator, variance=False):

    # Convert O to SparsePauliOp representation
    if isinstance(operator, Pauli):
        operator = SparsePauliOp(operator)
    elif not isinstance(operator, SparsePauliOp):
        operator = SparsePauliOp.from_operator(Operator(operator))
    if not isinstance(operator, SparsePauliOp):
        raise ExtensionError("Invalid input operator")

    params = {}

    # Add Pauli basis components of O
    for pauli, coeff in operator.label_iter():
        if pauli in params:
            coeff1 = params[pauli][0]
            params[pauli] = (coeff1 + coeff.real, 0)
        else:
            params[pauli] = (coeff.real, 0)

    # Add Pauli basis components of O^2
    if variance:
        for pauli, coeff in operator.dot(operator).label_iter():
            if pauli in params:
                coeff1, coeff2 = params[pauli]
                params[pauli] = (coeff1, coeff2 + coeff.real)
            else:
                params[pauli] = (0, coeff.real)

    # Convert to list
    return list(params.items())
示例#12
0
    def test_permute(self):
        """permute test"""
        pauli_sum = PauliSumOp(SparsePauliOp((X ^ Y ^ Z).primitive))
        expected = PauliSumOp(SparsePauliOp((X ^ I ^ Y ^ Z ^ I).primitive))

        self.assertEqual(pauli_sum.permute([1, 2, 4]), expected)

        pauli_sum = PauliSumOp(SparsePauliOp((X ^ Y ^ Z).primitive))
        expected = PauliSumOp(SparsePauliOp((Z ^ Y ^ X).primitive))
        self.assertEqual(pauli_sum.permute([2, 1, 0]), expected)

        with self.assertRaises(OpflowError):
            pauli_sum.permute([1, 2, 1])

        with self.assertRaises(OpflowError):
            pauli_sum.permute([1, 2, -1])
示例#13
0
def _sort_simplify(sparse_pauli):
    sparse_pauli = sparse_pauli.simplify()
    indices = sparse_pauli.paulis.argsort()
    table = sparse_pauli.paulis[indices]
    coeffs = sparse_pauli.coeffs[indices]
    sparse_pauli = SparsePauliOp(table, coeffs)
    return sparse_pauli
示例#14
0
    def compose(
        self, other: OperatorBase, permutation: Optional[List[int]] = None, front: bool = False
    ) -> OperatorBase:

        new_self, other = self._expand_shorter_operator_and_permute(other, permutation)
        new_self = cast(PauliOp, new_self)

        if front:
            return other.compose(new_self)
        # If self is identity, just return other.
        if not any(new_self.primitive.x + new_self.primitive.z):
            return other * new_self.coeff

        # Both Paulis
        if isinstance(other, PauliOp):
            product = new_self.primitive.dot(other.primitive)
            return PrimitiveOp(product, coeff=new_self.coeff * other.coeff)

        # pylint: disable=cyclic-import
        from .pauli_sum_op import PauliSumOp

        if isinstance(other, PauliSumOp):
            return PauliSumOp(
                SparsePauliOp(new_self.primitive).dot(other.primitive),
                coeff=new_self.coeff * other.coeff,
            )

        # pylint: disable=cyclic-import
        from ..state_fns.circuit_state_fn import CircuitStateFn
        from .circuit_op import CircuitOp

        if isinstance(other, (CircuitOp, CircuitStateFn)):
            return new_self.to_circuit_op().compose(other)

        return super(PauliOp, new_self).compose(other)
示例#15
0
    def test_decoder_import(self):
        """Test runtime decoder importing modules."""
        script = """
import sys
import json
from qiskit.providers.ibmq.runtime import RuntimeDecoder
if __name__ == '__main__':
    obj = json.loads(sys.argv[1], cls=RuntimeDecoder)
    print(obj.__class__.__name__)
"""
        temp_fp = tempfile.NamedTemporaryFile(mode='w', delete=False)
        self.addCleanup(os.remove, temp_fp.name)
        temp_fp.write(script)
        temp_fp.close()

        subtests = (
            PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[2]), coeff=3),
            DictStateFn("1" * 3, is_measurement=True),
            Statevector([1, 0]),
        )
        for op in subtests:
            with self.subTest(op=op):
                encoded = json.dumps(op, cls=RuntimeEncoder)
                self.assertIsInstance(encoded, str)
                cmd = ["python", temp_fp.name, encoded]
                proc = subprocess.run(cmd,
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE,
                                      universal_newlines=True,
                                      check=True)
                self.assertIn(op.__class__.__name__, proc.stdout)
示例#16
0
    def permute(self, permutation: List[int]) -> "PauliSumOp":
        """Permutes the sequence of ``PauliSumOp``.

        Args:
            permutation: A list defining where each Pauli should be permuted. The Pauli at index
                j of the primitive should be permuted to position permutation[j].

        Returns:
              A new PauliSumOp representing the permuted operator. For operator (X ^ Y ^ Z) and
              indices=[1,2,4], it returns (X ^ I ^ Y ^ Z ^ I).

        Raises:
            OpflowError: if indices do not define a new index for each qubit.
        """
        if len(permutation) != self.num_qubits:
            raise OpflowError(
                "List of indices to permute must have the same size as Pauli Operator"
            )
        length = max(permutation) + 1
        spop = self.primitive.tensor(
            SparsePauliOp(Pauli("I" * (length - self.num_qubits))))
        permutation = [i for i in range(length) if i not in permutation
                       ] + permutation
        permu_arr = np.arange(length)[np.argsort(permutation)]
        spop.paulis.x = spop.paulis.x[:, permu_arr]
        spop.paulis.z = spop.paulis.z[:, permu_arr]
        return PauliSumOp(spop, self.coeff)
def save_expval_params(pauli=False):
    """Dictionary of labels and params, qubits for exp val snapshots."""
    if pauli:
        X_wpo = Pauli('X')
        Y_wpo = Pauli('Y')
        Z_wpo = Pauli('Z')
        H_wpo = np.sqrt(0.5) * (SparsePauliOp('X') + SparsePauliOp('Z'))
        IX_wpo = Pauli('IX')
        IY_wpo = Pauli('IY')
        IZ_wpo = Pauli('IZ')
        IH_wpo = np.sqrt(0.5) * (SparsePauliOp('IX') + SparsePauliOp('IZ'))
        XX_wpo = Pauli('XX')
        YY_wpo = Pauli('YY')
        ZZ_wpo = Pauli('ZZ')
    else:
        X_wpo = np.array([[0, 1], [1, 0]], dtype=complex)
        Y_wpo = np.array([[0, -1j], [1j, 0]], dtype=complex)
        Z_wpo = np.array([[1, 0], [0, -1]], dtype=complex)
        H_wpo = np.array([[1, 1], [1, -1]], dtype=complex) / np.sqrt(2)
        IX_wpo = np.kron(np.eye(2), X_wpo)
        IY_wpo = np.kron(np.eye(2), Y_wpo)
        IZ_wpo = np.kron(np.eye(2), Z_wpo)
        IH_wpo = np.kron(np.eye(2), H_wpo)
        XX_wpo = np.kron(X_wpo, X_wpo)
        YY_wpo = np.kron(Y_wpo, Y_wpo)
        ZZ_wpo = np.kron(Z_wpo, Z_wpo)
    return {
        "<H[0]>": (H_wpo, [0]),
        "<H[1]>": (H_wpo, [1]),
        "<X[0]>": (X_wpo, [0]),
        "<X[1]>": (X_wpo, [1]),
        "<Y[1]>": (Y_wpo, [0]),
        "<Y[1]>": (Y_wpo, [1]),
        "<Z[0]>": (Z_wpo, [0]),
        "<Z[1]>": (Z_wpo, [1]),
        "<H[0], I[1]>": (IH_wpo, [0, 1]),
        "<I[0], H[1]>": (IH_wpo, [1, 0]),
        "<X[0], I[1]>": (IX_wpo, [0, 1]),
        "<I[0], X[1]>": (IX_wpo, [1, 0]),
        "<Y[0], I[1]>": (IY_wpo, [0, 1]),
        "<I[0], Y[1]>": (IY_wpo, [1, 0]),
        "<Z[0], I[1]>": (IZ_wpo, [0, 1]),
        "<I[0], Z[1]>": (IZ_wpo, [1, 0]),
        "<X[0], X[1]>": (XX_wpo, [0, 1]),
        "<Y[0], Y[1]>": (YY_wpo, [0, 1]),
        "<Z[0], Z[1]>": (ZZ_wpo, [0, 1]),
    }
示例#18
0
 def test_matrix_iter(self):
     """Test PauliSumOp dense matrix_iter method."""
     labels = ["III", "IXI", "IYY", "YIZ", "XYZ", "III"]
     coeffs = np.array([1, 2, 3, 4, 5, 6])
     table = PauliTable.from_labels(labels)
     coeff = 10
     op = PauliSumOp(SparsePauliOp(table, coeffs), coeff)
     for idx, i in enumerate(op.matrix_iter()):
         self.assertTrue(np.array_equal(i, coeff * coeffs[idx] * Pauli(labels[idx]).to_matrix()))
示例#19
0
    def test_add(self):
        """add test"""
        pauli_sum = 3 * X + Y
        self.assertIsInstance(pauli_sum, PauliSumOp)
        expected = PauliSumOp(3.0 * SparsePauliOp(Pauli("X")) + SparsePauliOp(Pauli("Y")))
        self.assertEqual(pauli_sum, expected)

        pauli_sum = X + Y
        summed_op = SummedOp([X, Y])
        self.assertEqual(pauli_sum, summed_op)

        a = Parameter("a")
        b = Parameter("b")
        actual = a * PauliSumOp.from_list([("X", 2)]) + b * PauliSumOp.from_list([("Y", 1)])
        expected = SummedOp(
            [PauliSumOp.from_list([("X", 2)], a), PauliSumOp.from_list([("Y", 1)], b)]
        )
        self.assertEqual(actual, expected)
示例#20
0
 def test_construct(self):
     """ constructor test """
     sparse_pauli = SparsePauliOp(Pauli("XYZX"), coeffs=[2.0])
     coeff = 3.0
     pauli_sum = PauliSumOp(sparse_pauli, coeff=coeff)
     self.assertIsInstance(pauli_sum, PauliSumOp)
     self.assertEqual(pauli_sum.primitive, sparse_pauli)
     self.assertEqual(pauli_sum.coeff, coeff)
     self.assertEqual(pauli_sum.num_qubits, 4)
示例#21
0
def _convert_to_paulisumop(operator):
    """Attempt to convert the operator to a PauliSumOp."""
    if isinstance(operator, PauliSumOp):
        return operator

    try:
        primitive = SparsePauliOp(operator.primitive)
        return PauliSumOp(primitive, operator.coeff)
    except Exception as exc:
        raise ValueError(f"Invalid type of the operator {type(operator)} "
                         "must be PauliSumOp, or castable to one.") from exc
示例#22
0
 def test_matrix_iter_sparse(self):
     """Test PauliSumOp sparse matrix_iter method."""
     labels = ['III', 'IXI', 'IYY', 'YIZ', 'XYZ', 'III']
     coeffs = np.array([1, 2, 3, 4, 5, 6])
     coeff = 10
     table = PauliTable.from_labels(labels)
     op = PauliSumOp(SparsePauliOp(table, coeffs), coeff)
     for idx, i in enumerate(op.matrix_iter(sparse=True)):
         self.assertTrue(
             np.array_equal(i.toarray(), coeff * coeffs[idx] *
                            Pauli(labels[idx]).to_matrix()))
示例#23
0
    def test_bksf_edge_op_aij(self):
        """Test BKSF mapping, edge operator aij"""
        edge_matrix = np.triu(np.ones((4, 4)))
        edge_list = np.array(
            np.nonzero(np.triu(edge_matrix) - np.diag(np.diag(edge_matrix))))
        qterm_a01 = _edge_operator_aij(edge_list, 0, 1)
        qterm_a02 = _edge_operator_aij(edge_list, 0, 2)
        qterm_a03 = _edge_operator_aij(edge_list, 0, 3)
        qterm_a12 = _edge_operator_aij(edge_list, 1, 2)
        qterm_a13 = _edge_operator_aij(edge_list, 1, 3)
        qterm_a23 = _edge_operator_aij(edge_list, 2, 3)

        ref_qterm_a01 = SparsePauliOp("IIIIIX")
        ref_qterm_a02 = SparsePauliOp("IIIIXZ")
        ref_qterm_a03 = SparsePauliOp("IIIXZZ")
        ref_qterm_a12 = SparsePauliOp("IIXIZZ")
        ref_qterm_a13 = SparsePauliOp("IXZZIZ")
        ref_qterm_a23 = SparsePauliOp("XZZZZI")

        with self.subTest("Test edge operator a01"):
            self.assertEqual(qterm_a01, ref_qterm_a01)
        with self.subTest("Test edge operator a02"):
            self.assertEqual(qterm_a02, ref_qterm_a02)
        with self.subTest("Test edge operator a03"):
            self.assertEqual(qterm_a03, ref_qterm_a03)
        with self.subTest("Test edge operator a12"):
            self.assertEqual(qterm_a12, ref_qterm_a12)
        with self.subTest("Test edge operator a13"):
            self.assertEqual(qterm_a13, ref_qterm_a13)
        with self.subTest("Test edge operator a23"):
            self.assertEqual(qterm_a23, ref_qterm_a23)
示例#24
0
def init_observable(observable: BaseOperator | PauliSumOp) -> SparsePauliOp:
    """Initialize observable"""
    if isinstance(observable, SparsePauliOp):
        return observable
    if isinstance(observable, PauliSumOp):
        if isinstance(observable.coeff, ParameterExpression):
            raise TypeError(
                f"observable must have numerical coefficient, not {type(observable.coeff)}"
            )
        return observable.coeff * observable.primitive
    if isinstance(observable, BaseOperator):
        return SparsePauliOp.from_operator(observable)
    return SparsePauliOp(observable)
示例#25
0
    def test_bksf_edge_op_bi(self):
        """Test BKSF mapping, edge operator bi"""
        edge_matrix = np.triu(np.ones((4, 4)))
        edge_list = np.array(
            np.nonzero(np.triu(edge_matrix) - np.diag(np.diag(edge_matrix))))
        qterm_b0 = _edge_operator_bi(edge_list, 0)
        qterm_b1 = _edge_operator_bi(edge_list, 1)
        qterm_b2 = _edge_operator_bi(edge_list, 2)
        qterm_b3 = _edge_operator_bi(edge_list, 3)

        ref_qterm_b0 = SparsePauliOp("IIIZZZ")
        ref_qterm_b1 = SparsePauliOp("IZZIIZ")
        ref_qterm_b2 = SparsePauliOp("ZIZIZI")
        ref_qterm_b3 = SparsePauliOp("ZZIZII")

        with self.subTest("Test edge operator b0"):
            self.assertEqual(qterm_b0, ref_qterm_b0)
        with self.subTest("Test edge operator b1"):
            self.assertEqual(qterm_b1, ref_qterm_b1)
        with self.subTest("Test edge operator b2"):
            self.assertEqual(qterm_b2, ref_qterm_b2)
        with self.subTest("Test edge operator b3"):
            self.assertEqual(qterm_b3, ref_qterm_b3)
示例#26
0
    def __init__(self,
                 operator,
                 label="expectation_value_variance",
                 unnormalized=False,
                 pershot=False,
                 conditional=False):
        r"""Instruction to save the expectation value and variance of a Hermitian operator.

        The expectation value of a Hermitian operator :math:`H` for a
        simulator in quantum state :math`\rho`is given by
        :math:`\langle H\rangle = \mbox{Tr}[H.\rho]`. The variance is given by
        :math:`\sigma^2 = \langle H^2 \rangle - \langle H \rangle>^2`.

        Args:
            operator (Pauli or SparsePauliOp or Operator): a Hermitian operator.
            label (str): the key for retrieving saved data from results.
            unnormalized (bool): If True return save the unnormalized accumulated
                                 or conditional accumulated expectation value
                                 over all shot [Default: False].
            pershot (bool): if True save a list of expectation values for each shot
                            of the simulation rather than the average over
                            all shots [Default: False].
            conditional (bool): if True save the average or pershot data
                                conditional on the current classical register
                                values [Default: False].

        Raises:
            ExtensionError: if the input operator is invalid or not Hermitian.

        .. note::

            This instruction can be directly appended to a circuit using
            the :func:`save_expectation_value` circuit method.
        """
        # Convert O to SparsePauliOp representation
        if isinstance(operator, Pauli):
            operator = SparsePauliOp(operator)
        elif not isinstance(operator, SparsePauliOp):
            operator = SparsePauliOp.from_operator(Operator(operator))
        if not allclose(operator.coeffs.imag, 0):
            raise ExtensionError("Input operator is not Hermitian.")
        params = _expval_params(operator, variance=True)
        super().__init__('save_expval_var',
                         operator.num_qubits,
                         label,
                         unnormalized=unnormalized,
                         pershot=pershot,
                         conditional=conditional,
                         params=params)
示例#27
0
    def tensor(self, other: OperatorBase) -> OperatorBase:
        # Both Paulis
        if isinstance(other, PauliOp):
            return PauliOp(self.primitive.tensor(other.primitive), coeff=self.coeff * other.coeff)

        # pylint: disable=cyclic-import
        from .pauli_sum_op import PauliSumOp
        if isinstance(other, PauliSumOp):
            new_primitive = SparsePauliOp(self.primitive).tensor(other.primitive)
            return PauliSumOp(new_primitive, coeff=self.coeff * other.coeff)

        from .circuit_op import CircuitOp
        if isinstance(other, CircuitOp):
            return self.to_circuit_op().tensor(other)

        return TensoredOp([self, other])
示例#28
0
    def add(self, other: OperatorBase) -> OperatorBase:
        if not self.num_qubits == other.num_qubits:
            raise ValueError(
                f"Sum of operators with different numbers of qubits, {self.num_qubits} and "
                f"{other.num_qubits}, is not well defined"
            )

        if isinstance(other, PauliSumOp):
            return PauliSumOp(self.coeff * self.primitive + other.coeff * other.primitive, coeff=1)

        if isinstance(other, PauliOp):
            return PauliSumOp(
                self.coeff * self.primitive + other.coeff * SparsePauliOp(other.primitive)
            )

        return SummedOp([self, other])
示例#29
0
    def equals(self, other: OperatorBase) -> bool:
        self_reduced, other_reduced = self.reduce(), other.reduce()

        if isinstance(other_reduced, PauliOp):
            other_reduced = PauliSumOp(
                SparsePauliOp(other_reduced.primitive,
                              coeffs=[other_reduced.coeff]))

        if not isinstance(other_reduced, PauliSumOp):
            return False

        if isinstance(self_reduced.coeff, ParameterExpression) or isinstance(
                other_reduced.coeff, ParameterExpression):
            return (self_reduced.coeff == other_reduced.coeff
                    and self_reduced.primitive == other_reduced.primitive)
        return (len(self_reduced) == len(other_reduced)
                and self_reduced.primitive == other_reduced.primitive)
示例#30
0
def _fix_qubits(
    operator: Union[int, PauliSumOp, PauliOp, OperatorBase],
    has_side_chain_second_bead: bool = False,
) -> Union[int, PauliSumOp, PauliOp, OperatorBase]:
    """
    Assigns predefined values for turns qubits on positions 0, 1, 2, 3, 5 in the main chain
    without the loss of generality (see the paper https://arxiv.org/pdf/1908.02163.pdf). Qubits
    on these position are considered fixed and not subject to optimization.

    Args:
        operator: an operator whose qubits shall be fixed.

    Returns:
        An operator with relevant qubits changed to fixed values.
    """
    # operator might be 0 (int) because it is initialized as operator = 0; then we should not
    # attempt fixing qubits
    if (not isinstance(operator, PauliOp)
            and not isinstance(operator, PauliSumOp)
            and not isinstance(operator, OperatorBase)):
        return operator
    operator = operator.reduce()
    new_tables = []
    new_coeffs = []
    if isinstance(operator, PauliOp):
        table_z = np.copy(operator.primitive.z)
        table_x = np.copy(operator.primitive.x)
        _preset_binary_vals(table_z, has_side_chain_second_bead)
        return PauliOp(Pauli((table_z, table_x)))

    for hamiltonian in operator:
        table_z = np.copy(hamiltonian.primitive.paulis.z[0])
        table_x = np.copy(hamiltonian.primitive.paulis.x[0])
        coeffs = _calc_updated_coeffs(hamiltonian, table_z,
                                      has_side_chain_second_bead)
        _preset_binary_vals(table_z, has_side_chain_second_bead)
        new_table = np.concatenate((table_x, table_z), axis=0)
        new_tables.append(new_table)
        new_coeffs.append(coeffs)
    new_pauli_table = PauliTable(data=new_tables)
    operator_updated = PauliSumOp(
        SparsePauliOp(data=new_pauli_table, coeffs=new_coeffs))
    operator_updated = operator_updated.reduce()
    return operator_updated