Exemplo n.º 1
0
    def evolution_for_pauli(self, pauli_op: PauliOp) -> PrimitiveOp:
        r"""
        Compute evolution Operator for a single Pauli using a ``PauliBasisChange``.

        Args:
            pauli_op: The ``PauliOp`` to evolve.

        Returns:
            A ``PrimitiveOp``, either the evolution ``CircuitOp`` or a ``PauliOp`` equal to the
            identity if pauli_op is the identity.
        """
        def replacement_fn(cob_instr_op, dest_pauli_op):
            z_evolution = dest_pauli_op.exp_i()
            # Remember, circuit composition order is mirrored operator composition order.
            return cob_instr_op.adjoint().compose(z_evolution).compose(
                cob_instr_op)

        # Note: PauliBasisChange will pad destination with identities
        # to produce correct CoB circuit
        sig_bits = np.logical_or(pauli_op.primitive.z, pauli_op.primitive.x)
        a_sig_bit = int(
            max(np.extract(sig_bits,
                           np.arange(pauli_op.num_qubits)[::-1])))
        destination = (I.tensorpower(a_sig_bit)) ^ (Z * pauli_op.coeff)
        cob = PauliBasisChange(destination_basis=destination,
                               replacement_fn=replacement_fn)
        return cast(PrimitiveOp, cob.convert(pauli_op))
Exemplo n.º 2
0
    def convert(self, operator: OperatorBase) -> OperatorBase:
        """Accepts an Operator and returns a new Operator with the Pauli measurements replaced by
        diagonal Pauli post-rotation based measurements so they can be evaluated by sampling and
        averaging.

        Args:
            operator: The operator to convert.

        Returns:
            The converted operator.
        """
        if isinstance(operator, ListOp):
            return operator.traverse(self.convert).reduce()

        if isinstance(operator, OperatorStateFn) and operator.is_measurement:
            # Change to Pauli representation if necessary
            if (isinstance(operator.primitive, (ListOp, PrimitiveOp))
                    and not isinstance(operator.primitive, PauliSumOp) and
                {"Pauli", "SparsePauliOp"} < 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.
                pauli_obsv = operator.primitive.to_pauli_op(massive=False)
                operator = StateFn(pauli_obsv,
                                   is_measurement=True,
                                   coeff=operator.coeff)

            if self._grouper and isinstance(operator.primitive,
                                            (ListOp, PauliSumOp)):
                grouped = self._grouper.convert(operator.primitive)
                operator = StateFn(grouped,
                                   is_measurement=True,
                                   coeff=operator.coeff)

            # Convert the measurement into diagonal basis (PauliBasisChange chooses
            # this basis by default).
            cob = PauliBasisChange(
                replacement_fn=PauliBasisChange.measurement_replacement_fn)
            return cob.convert(operator).reduce()

        return operator