Example #1
0
    def _eval_aux_ops(
        self,
        parameters: np.ndarray,
        aux_operators: ListOrDict[OperatorBase],
        expectation: ExpectationBase,
        threshold: float = 1e-12,
    ) -> ListOrDict[Tuple[complex, complex]]:
        # Create new CircuitSampler to avoid breaking existing one's caches.
        sampler = CircuitSampler(self.quantum_instance)

        if isinstance(aux_operators, dict):
            list_op = ListOp(list(aux_operators.values()))
        else:
            list_op = ListOp(aux_operators)

        aux_op_meas = expectation.convert(StateFn(list_op,
                                                  is_measurement=True))
        aux_op_expect = aux_op_meas.compose(
            CircuitStateFn(self.ansatz.bind_parameters(parameters)))
        aux_op_expect_sampled = sampler.convert(aux_op_expect)

        # compute means
        values = np.real(aux_op_expect_sampled.eval())

        # compute standard deviations
        variances = np.real(
            expectation.compute_variance(aux_op_expect_sampled))
        if not isinstance(variances, np.ndarray) and variances == 0.0:
            # when `variances` is a single value equal to 0., our expectation value is exact and we
            # manually ensure the variances to be a list of the correct length
            variances = np.zeros(len(aux_operators), dtype=float)
        std_devs = np.sqrt(variances / self.quantum_instance.run_config.shots)

        # Discard values below threshold
        aux_op_means = values * (np.abs(values) > threshold)
        # zip means and standard deviations into tuples
        aux_op_results = zip(aux_op_means, std_devs)

        # Return None eigenvalues for None operators if aux_operators is a list.
        # None operators are already dropped in compute_minimum_eigenvalue if aux_operators is a dict.
        if isinstance(aux_operators, list):
            aux_operator_eigenvalues = [None] * len(aux_operators)
            key_value_iterator = enumerate(aux_op_results)
        else:
            aux_operator_eigenvalues = {}
            key_value_iterator = zip(aux_operators.keys(), aux_op_results)

        for key, value in key_value_iterator:
            if aux_operators[key] is not None:
                aux_operator_eigenvalues[key] = value

        return aux_operator_eigenvalues
Example #2
0
    def _eval_aux_ops(
        self,
        parameters: np.ndarray,
        aux_operators: List[OperatorBase],
        expectation: ExpectationBase,
        threshold: float = 1e-12,
    ) -> np.ndarray:
        # Create new CircuitSampler to avoid breaking existing one's caches.
        sampler = CircuitSampler(self.quantum_instance)

        aux_op_meas = expectation.convert(
            StateFn(ListOp(aux_operators), is_measurement=True))
        aux_op_expect = aux_op_meas.compose(
            CircuitStateFn(self.ansatz.bind_parameters(parameters)))
        values = np.real(sampler.convert(aux_op_expect).eval())

        # Discard values below threshold
        aux_op_results = values * (np.abs(values) > threshold)
        # Deal with the aux_op behavior where there can be Nones or Zero qubit Paulis in the list
        _aux_op_nones = [op is None for op in aux_operators]
        aux_operator_eigenvalues = [
            None if is_none else [result]
            for (is_none, result) in zip(_aux_op_nones, aux_op_results)
        ]
        # As this has mixed types, since it can included None, it needs to explicitly pass object
        # data type to avoid numpy 1.19 warning message about implicit conversion being deprecated
        aux_operator_eigenvalues = np.array([aux_operator_eigenvalues],
                                            dtype=object)
        return aux_operator_eigenvalues
Example #3
0
def _get_observable_evaluator(
    ansatz: QuantumCircuit,
    observables: Union[OperatorBase, List[OperatorBase]],
    expectation: ExpectationBase,
    sampler: CircuitSampler,
) -> Callable[[np.ndarray], Union[float, List[float]]]:
    """Get a callable to evaluate a (list of) observable(s) for given circuit parameters."""

    if isinstance(observables, list):
        observables = ListOp(observables)

    expectation_value = StateFn(observables,
                                is_measurement=True) @ StateFn(ansatz)
    converted = expectation.convert(expectation_value)

    ansatz_parameters = ansatz.parameters

    def evaluate_observables(theta: np.ndarray) -> Union[float, List[float]]:
        """Evaluate the observables for the ansatz parameters ``theta``.

        Args:
            theta: The ansatz parameters.

        Returns:
            The observables evaluated at the ansatz parameters.
        """
        value_dict = dict(zip(ansatz_parameters, theta))
        sampled = sampler.convert(converted, params=value_dict)
        return sampled.eval()

    return evaluate_observables
def _compute_std_devs(
    observables_expect_sampled: OperatorBase,
    observables: ListOrDict[OperatorBase],
    expectation: ExpectationBase,
    quantum_instance: Union[QuantumInstance, BaseBackend, Backend],
) -> List[complex]:
    """
    Calculates a list of standard deviations from expectation values of observables provided.

    Args:
        observables_expect_sampled: Expected values of observables.
        observables: A list or a dictionary of operators whose expectation values are to be
            calculated.
        expectation: An instance of ExpectationBase which defines a method for calculating
            expectation values.
        quantum_instance: A quantum instance used for calculations.

    Returns:
        A list of standard deviations.
    """
    variances = np.real(expectation.compute_variance(observables_expect_sampled))
    if not isinstance(variances, np.ndarray) and variances == 0.0:
        # when `variances` is a single value equal to 0., our expectation value is exact and we
        # manually ensure the variances to be a list of the correct length
        variances = np.zeros(len(observables), dtype=float)
    std_devs = np.sqrt(variances / quantum_instance.run_config.shots)
    return std_devs
Example #5
0
    def _eval_aux_ops(
        self,
        parameters: np.ndarray,
        aux_operators: ListOrDict[OperatorBase],
        expectation: ExpectationBase,
        threshold: float = 1e-12,
    ) -> ListOrDict[complex]:
        # Create new CircuitSampler to avoid breaking existing one's caches.
        sampler = CircuitSampler(self.quantum_instance)

        if isinstance(aux_operators, dict):
            list_op = ListOp(list(aux_operators.values()))
        else:
            list_op = ListOp(aux_operators)

        aux_op_meas = expectation.convert(StateFn(list_op,
                                                  is_measurement=True))
        aux_op_expect = aux_op_meas.compose(
            CircuitStateFn(self.ansatz.bind_parameters(parameters)))
        values = np.real(sampler.convert(aux_op_expect).eval())

        # Discard values below threshold
        aux_op_results = values * (np.abs(values) > threshold)

        # Return None eigenvalues for None operators if aux_operators is a list.
        # None operators are already dropped in compute_minimum_eigenvalue if aux_operators is a dict.
        if isinstance(aux_operators, list):
            aux_operator_eigenvalues = [None] * len(aux_operators)
            key_value_iterator = enumerate(aux_op_results)
        else:
            aux_operator_eigenvalues = {}
            key_value_iterator = zip(aux_operators.keys(), aux_op_results)

        for key, value in key_value_iterator:
            if aux_operators[key] is not None:
                aux_operator_eigenvalues[key] = value

        return aux_operator_eigenvalues
def eval_observables(
    quantum_instance: Union[QuantumInstance, BaseBackend, Backend],
    quantum_state: Union[
        Statevector,
        QuantumCircuit,
        OperatorBase,
    ],
    observables: ListOrDict[OperatorBase],
    expectation: ExpectationBase,
    threshold: float = 1e-12,
) -> ListOrDict[Tuple[complex, complex]]:
    """
    Accepts a list or a dictionary of operators and calculates their expectation values - means
    and standard deviations. They are calculated with respect to a quantum state provided. A user
    can optionally provide a threshold value which filters mean values falling below the threshold.

    Args:
        quantum_instance: A quantum instance used for calculations.
        quantum_state: An unparametrized quantum circuit representing a quantum state that
            expectation values are computed against.
        observables: A list or a dictionary of operators whose expectation values are to be
            calculated.
        expectation: An instance of ExpectationBase which defines a method for calculating
            expectation values.
        threshold: A threshold value that defines which mean values should be neglected (helpful for
            ignoring numerical instabilities close to 0).

    Returns:
        A list or a dictionary of tuples (mean, standard deviation).

    Raises:
        ValueError: If a ``quantum_state`` with free parameters is provided.
    """

    if (
        isinstance(
            quantum_state, (QuantumCircuit, OperatorBase)
        )  # Statevector cannot be parametrized
        and len(quantum_state.parameters) > 0
    ):
        raise ValueError(
            "A parametrized representation of a quantum_state was provided. It is not "
            "allowed - it cannot have free parameters."
        )

    # Create new CircuitSampler to avoid breaking existing one's caches.
    sampler = CircuitSampler(quantum_instance)

    list_op = _prepare_list_op(quantum_state, observables)
    observables_expect = expectation.convert(list_op)
    observables_expect_sampled = sampler.convert(observables_expect)

    # compute means
    values = np.real(observables_expect_sampled.eval())

    # compute standard deviations
    std_devs = _compute_std_devs(
        observables_expect_sampled, observables, expectation, quantum_instance
    )

    # Discard values below threshold
    observables_means = values * (np.abs(values) > threshold)
    # zip means and standard deviations into tuples
    observables_results = list(zip(observables_means, std_devs))

    # Return None eigenvalues for None operators if observables is a list.
    # None operators are already dropped in compute_minimum_eigenvalue if observables is a dict.

    return _prepare_result(observables_results, observables)