Example #1
0
 def _try_set_expectation_value_from_factory(
         self, operator: OperatorBase) -> None:
     if operator is not None and self.quantum_instance is not None:
         self._set_expectation(
             ExpectationFactory.build(operator=operator,
                                      backend=self.quantum_instance,
                                      include_custom=self._include_custom))
    def test_aer_simulator_pauli_sum(self):
        """Test expectation selection with Aer's qasm_simulator."""
        backend = Aer.get_backend("aer_simulator")
        op = 0.2 * (X ^ X) + 0.1 * (Z ^ I)

        with self.subTest("Defaults"):
            expectation = ExpectationFactory.build(op,
                                                   backend,
                                                   include_custom=False)
            self.assertIsInstance(expectation, PauliExpectation)

        with self.subTest("Include custom"):
            expectation = ExpectationFactory.build(op,
                                                   backend,
                                                   include_custom=True)
            self.assertIsInstance(expectation, AerPauliExpectation)
Example #3
0
    def construct_expectation(
        self,
        parameter: Union[List[float], List[Parameter], np.ndarray],
        operator: OperatorBase,
        return_expectation: bool = False,
    ) -> Union[OperatorBase, Tuple[OperatorBase, ExpectationBase]]:
        r"""
        Generate the ansatz circuit and expectation value measurement, and return their
        runnable composition.

        Args:
            parameter: Parameters for the ansatz circuit.
            operator: Qubit operator of the Observable
            return_expectation: If True, return the ``ExpectationBase`` expectation converter used
                in the construction of the expectation value. Useful e.g. to compute the standard
                deviation of the expectation value.

        Returns:
            The Operator equalling the measurement of the ansatz :class:`StateFn` by the
            Observable's expectation :class:`StateFn`, and, optionally, the expectation converter.

        Raises:
            AlgorithmError: If no operator has been provided.
            AlgorithmError: If no expectation is passed and None could be inferred via the
                ExpectationFactory.
        """
        if operator is None:
            raise AlgorithmError("The operator was never provided.")

        self._check_operator_ansatz(operator)

        # if expectation was never created, try to create one
        if self.expectation is None:
            expectation = ExpectationFactory.build(
                operator=operator,
                backend=self.quantum_instance,
                include_custom=self._include_custom,
            )
        else:
            expectation = self.expectation

        param_dict = dict(zip(self._ansatz_params, parameter))  # type: Dict
        wave_function = self.ansatz.assign_parameters(param_dict)

        observable_meas = expectation.convert(
            StateFn(operator, is_measurement=True))
        ansatz_circuit_op = CircuitStateFn(wave_function)
        expect_op = observable_meas.compose(ansatz_circuit_op).reduce()

        if return_expectation:
            return expect_op, expectation

        return expect_op
    def test_eval_observables(self, observables: ListOrDict[OperatorBase]):
        """Tests evaluator of auxiliary operators for algorithms."""

        ansatz = EfficientSU2(2)
        parameters = np.array(
            [
                1.2, 4.2, 1.4, 2.0, 1.2, 4.2, 1.4, 2.0, 1.2, 4.2, 1.4, 2.0,
                1.2, 4.2, 1.4, 2.0
            ],
            dtype=float,
        )

        bound_ansatz = ansatz.bind_parameters(parameters)
        expected_result = self.get_exact_expectation(bound_ansatz, observables)

        for backend_name in self.backend_names:
            shots = 4096 if backend_name == "qasm_simulator" else 1
            decimal = (1 if backend_name == "qasm_simulator" else 6
                       )  # to accommodate for qasm being imperfect
            with self.subTest(msg=f"Test {backend_name} backend."):
                backend = BasicAer.get_backend(backend_name)
                quantum_instance = QuantumInstance(
                    backend=backend,
                    shots=shots,
                    seed_simulator=self.seed,
                    seed_transpiler=self.seed,
                )
                expectation = ExpectationFactory.build(
                    operator=self.h2_op,
                    backend=quantum_instance,
                )

                with self.subTest(msg="Test QuantumCircuit."):
                    self._run_test(
                        expected_result,
                        bound_ansatz,
                        decimal,
                        expectation,
                        observables,
                        quantum_instance,
                    )

                with self.subTest(msg="Test Statevector."):
                    statevector = Statevector(bound_ansatz)
                    self._run_test(
                        expected_result,
                        statevector,
                        decimal,
                        expectation,
                        observables,
                        quantum_instance,
                    )
    def test_trotter_qrte_trotter_single_qubit_aux_ops(self):
        """Test for default TrotterQRTE on a single qubit with auxiliary operators."""
        operator = SummedOp([X, Z])
        # LieTrotter with 1 rep
        aux_ops = [X, Y]

        initial_state = Zero
        time = 3
        evolution_problem = EvolutionProblem(operator, time, initial_state, aux_ops)

        expected_evolved_state = VectorStateFn(
            Statevector([0.98008514 + 0.13970775j, 0.01991486 + 0.13970775j], dims=(2,))
        )
        expected_aux_ops_evaluated = [(0.078073, 0.0), (0.268286, 0.0)]
        expected_aux_ops_evaluated_qasm = [
            (0.05799999999999995, 0.011161518713866855),
            (0.2495, 0.010826759383582883),
        ]

        for backend_name in self.backends_names_not_none:
            with self.subTest(msg=f"Test {backend_name} backend."):
                algorithm_globals.random_seed = 0
                backend = self.backends_dict[backend_name]
                expectation = ExpectationFactory.build(
                    operator=operator,
                    backend=backend,
                )
                trotter_qrte = TrotterQRTE(quantum_instance=backend, expectation=expectation)
                evolution_result = trotter_qrte.evolve(evolution_problem)

                np.testing.assert_equal(
                    evolution_result.evolved_state.eval(), expected_evolved_state
                )
                if backend_name == "qi_qasm":
                    expected_aux_ops_evaluated = expected_aux_ops_evaluated_qasm
                np.testing.assert_array_almost_equal(
                    evolution_result.aux_ops_evaluated, expected_aux_ops_evaluated
                )
Example #6
0
    def _calculate_observable(
        self,
        solution: QuantumCircuit,
        observable: Optional[Union[LinearSystemObservable,
                                   BaseOperator]] = None,
        observable_circuit: Optional[QuantumCircuit] = None,
        post_processing: Optional[Callable[[Union[float, List[float]]],
                                           Union[float, List[float]]]] = None
    ) -> Tuple[Union[float, List[float]], Union[float, List[float]]]:
        """Calculates the value of the observable(s) given.

        Args:
            solution: The quantum circuit preparing the solution x to the system.
            observable: Information to be extracted from the solution.
            observable_circuit: Circuit to be applied to the solution to extract information.
            post_processing: Function to compute the value of the observable.

        Returns:
            The value of the observable(s) and the circuit results before post-processing as a
             tuple.
        """
        # Get the number of qubits
        nb = solution.qregs[0].size
        nl = solution.qregs[1].size
        na = solution.num_ancillas

        # if the observable is given construct post_processing and observable_circuit
        if observable is not None:
            observable_circuit = observable.observable_circuit(nb)
            post_processing = observable.post_processing

            if isinstance(observable, LinearSystemObservable):
                observable = observable.observable(nb)

        # in the other case use the identity as observable
        else:
            observable = I ^ nb

        # Create the Operators Zero and One
        zero_op = (I + Z) / 2
        one_op = (I - Z) / 2

        is_list = True
        if not isinstance(observable_circuit, list):
            is_list = False
            observable_circuit = [observable_circuit]
            observable = [observable]

        expectations = []
        for circ, obs in zip(observable_circuit, observable):
            circuit = QuantumCircuit(solution.num_qubits)
            circuit.append(solution, circuit.qubits)
            circuit.append(circ, range(nb))

            ob = one_op ^ TensoredOp((nl + na) * [zero_op]) ^ obs
            expectations.append(~StateFn(ob) @ StateFn(circuit))

        if is_list:
            # execute all in a list op to send circuits in batches
            expectations = ListOp(expectations)
        else:
            expectations = expectations[0]

        # check if an expectation converter is given
        if self._expectation is not None:
            expectations = self._expectation.convert(expectations)
        # if otherwise a backend was specified, try to set the best expectation value
        elif self._sampler is not None:
            if is_list:
                op = expectations.oplist[0]
            else:
                op = expectations
            self._expectation = ExpectationFactory.build(
                op, self._sampler.quantum_instance)

        if self._sampler is not None:
            expectations = self._sampler.convert(expectations)

        # evaluate
        expectation_results = expectations.eval()

        # apply post_processing
        result = post_processing(expectation_results, nb, self.scaling)

        return result, expectation_results