示例#1
0
    def _recursive_convert(self, operator: OperatorBase) -> OperatorBase:
        if isinstance(operator, EvolvedOp):
            if isinstance(operator.primitive, PauliSumOp):
                operator = EvolvedOp(operator.primitive.to_pauli_op(),
                                     coeff=operator.coeff)
            if not {"Pauli"} == operator.primitive_strings():
                logger.warning(
                    "Evolved Hamiltonian 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 Hamiltonian with massive=True explicitly if they so choose.
                # TODO explore performance to see whether we should avoid doing this repeatedly
                pauli_ham = operator.primitive.to_pauli_op(massive=False)
                operator = EvolvedOp(pauli_ham, coeff=operator.coeff)

            if isinstance(operator.primitive, SummedOp):
                # TODO uncomment when we implement Abelian grouped evolution.
                # if operator.primitive.abelian:
                #     return self.evolution_for_abelian_paulisum(operator.primitive)
                # else:
                # Collect terms that are not the identity.
                oplist = [
                    x for x in operator.primitive
                    if not isinstance(x, PauliOp) or sum(x.primitive.x +
                                                         x.primitive.z) != 0
                ]
                # Collect the coefficients of any identity terms,
                # which become global phases when exponentiated.
                identity_phases = [
                    x.coeff for x in operator.primitive
                    if isinstance(x, PauliOp) and sum(x.primitive.x +
                                                      x.primitive.z) == 0
                ]
                # Construct sum without the identity operators.
                new_primitive = SummedOp(oplist,
                                         coeff=operator.primitive.coeff)
                trotterized = self.trotter.convert(new_primitive)
                circuit_no_identities = self._recursive_convert(trotterized)
                # Set the global phase of the QuantumCircuit to account for removed identity terms.
                global_phase = -sum(identity_phases) * operator.primitive.coeff
                circuit_no_identities.primitive.global_phase = global_phase
                return circuit_no_identities
            elif isinstance(operator.primitive, PauliOp):
                return self.evolution_for_pauli(operator.primitive)
            # Covers ListOp, ComposedOp, TensoredOp
            elif isinstance(operator.primitive, ListOp):
                converted_ops = [
                    self._recursive_convert(op)
                    for op in operator.primitive.oplist
                ]
                return operator.primitive.__class__(converted_ops,
                                                    coeff=operator.coeff)
        elif isinstance(operator, ListOp):
            return operator.traverse(self.convert).reduce()

        return operator
    def convert(self, operator: OperatorBase) -> OperatorBase:
        """Check if operator is a SummedOp, in which case covert it into a sum of mutually
        commuting sums, or if the Operator contains sub-Operators and ``traverse`` is True,
        attempt to convert any sub-Operators.

        Args:
            operator: The Operator to attempt to convert.

        Returns:
            The converted Operator.
        """
        if isinstance(operator, PauliSumOp):
            return self.group_subops(operator)

        if isinstance(operator, ListOp):
            if isinstance(operator, SummedOp) and all(
                    isinstance(op, PauliOp) for op in operator.oplist):
                # For now, we only support graphs over Paulis.
                return self.group_subops(operator)
            elif self._traverse:
                return operator.traverse(self.convert)
        elif isinstance(operator, OperatorStateFn) and self._traverse:
            return OperatorStateFn(
                self.convert(operator.primitive),
                is_measurement=operator.is_measurement,
                coeff=operator.coeff,
            )
        elif isinstance(operator, EvolvedOp) and self._traverse:
            return EvolvedOp(self.convert(operator.primitive),
                             coeff=operator.coeff)
        return operator
    def convert(self, operator: OperatorBase) -> OperatorBase:
        r"""
        Traverse the operator, replacing ``EvolvedOps`` with ``CircuitOps`` containing
        ``UnitaryGates`` or ``HamiltonianGates`` (if self.coeff is a ``ParameterExpression``)
        equalling the exponentiation of -i * operator. This is done by converting the
        ``EvolvedOp.primitive`` to a ``MatrixOp`` and simply calling ``.exp_i()`` on that.

        Args:
            operator: The Operator to convert.

        Returns:
            The converted operator.
        """
        if isinstance(operator, EvolvedOp):
            if not {"Matrix"} == operator.primitive_strings():
                logger.warning(
                    "Evolved Hamiltonian is not composed of only MatrixOps, converting "
                    "to Matrix representation, which can be expensive.")
                # Setting massive=False because this conversion is implicit. User can perform this
                # action on the Hamiltonian with massive=True explicitly if they so choose.
                # TODO explore performance to see whether we should avoid doing this repeatedly
                matrix_ham = operator.primitive.to_matrix_op(massive=False)
                operator = EvolvedOp(matrix_ham, coeff=operator.coeff)

            if isinstance(operator.primitive, ListOp):
                return operator.primitive.exp_i() * operator.coeff
            elif isinstance(operator.primitive, (MatrixOp, PauliOp)):
                return operator.primitive.exp_i()
        elif isinstance(operator, ListOp):
            return operator.traverse(self.convert).reduce()

        return operator