Esempio n. 1
0
    def test_rescaling(self):
        """Test the rescaling."""
        amplitude = 0.8
        scaling = 0.25
        circuit = QuantumCircuit(1)
        circuit.ry(2 * np.arcsin(amplitude), 0)
        problem = EstimationProblem(circuit, objective_qubits=[0])

        rescaled = problem.rescale(scaling)
        rescaled_amplitude = Statevector.from_instruction(rescaled.state_preparation).data[3]

        self.assertAlmostEqual(scaling * amplitude, rescaled_amplitude)
Esempio n. 2
0
    def test_iqae_confidence_intervals(self):
        """End-to-end test for the IQAE confidence interval."""
        n = 3
        qae = IterativeAmplitudeEstimation(0.1,
                                           0.01,
                                           quantum_instance=self._statevector)
        expected_confint = (0.1984050, 0.3511015)
        estimation_problem = EstimationProblem(SineIntegral(n),
                                               objective_qubits=[n])

        # statevector simulator
        result = qae.estimate(estimation_problem)
        self.assertGreaterEqual(self._statevector.time_taken, 0.)
        self._statevector.reset_execution_results()
        confint = result.confidence_interval
        # confidence interval based on statevector should be empty, as we are sure of the result
        self.assertAlmostEqual(confint[1] - confint[0], 0.0)
        self.assertAlmostEqual(confint[0], result.estimation)

        # qasm simulator
        shots = 100
        qae.quantum_instance = self._qasm(shots)
        result = qae.estimate(estimation_problem)
        confint = result.confidence_interval
        np.testing.assert_array_almost_equal(confint, expected_confint)
        self.assertTrue(confint[0] <= result.estimation <= confint[1])
Esempio n. 3
0
    def test_iqae_circuits(self, efficient_circuit):
        """Test circuits resulting from iterative amplitude estimation.

        Build the circuit manually and from the algorithm and compare the resulting unitaries.
        """
        prob = 0.5
        problem = EstimationProblem(BernoulliStateIn(prob), objective_qubits=[0])

        for k in [2, 5]:
            qae = IterativeAmplitudeEstimation(0.01, 0.05)
            angle = 2 * np.arcsin(np.sqrt(prob))

            # manually set up the inefficient AE circuit
            q_objective = QuantumRegister(1, "q")
            circuit = QuantumCircuit(q_objective)

            # A operator
            circuit.ry(angle, q_objective)

            if efficient_circuit:
                qae.grover_operator = BernoulliGrover(prob)
                circuit.ry(2 * k * angle, q_objective[0])

            else:
                oracle = QuantumCircuit(1)
                oracle.z(0)
                state_preparation = QuantumCircuit(1)
                state_preparation.ry(angle, 0)
                grover_op = GroverOperator(oracle, state_preparation)
                grover_op.global_phase = np.pi
                for _ in range(k):
                    circuit.compose(grover_op, inplace=True)

            actual_circuit = qae.construct_circuit(problem, k, measurement=False)
            self.assertEqual(Operator(circuit), Operator(actual_circuit))
Esempio n. 4
0
    def test_confidence_intervals(self, qae, key, expect):
        """End-to-end test for all confidence intervals."""
        n = 3
        qae.quantum_instance = self._statevector
        estimation_problem = EstimationProblem(SineIntegral(n), objective_qubits=[n])

        # statevector simulator
        result = qae.estimate(estimation_problem)
        self.assertGreater(self._statevector.time_taken, 0.0)
        self._statevector.reset_execution_results()
        methods = ["lr", "fi", "oi"]  # short for likelihood_ratio, fisher, observed_fisher
        alphas = [0.1, 0.00001, 0.9]  # alpha shouldn't matter in statevector
        for alpha, method in zip(alphas, methods):
            confint = qae.compute_confidence_interval(result, alpha, method)
            # confidence interval based on statevector should be empty, as we are sure of the result
            self.assertAlmostEqual(confint[1] - confint[0], 0.0)
            self.assertAlmostEqual(confint[0], getattr(result, key))

        # qasm simulator
        shots = 100
        alpha = 0.01
        qae.quantum_instance = self._qasm(shots)
        result = qae.estimate(estimation_problem)
        for method, expected_confint in expect.items():
            confint = qae.compute_confidence_interval(result, alpha, method)
            np.testing.assert_array_almost_equal(confint, expected_confint)
            self.assertTrue(confint[0] <= getattr(result, key) <= confint[1])
Esempio n. 5
0
    def test_good_state(self, backend_str, expect):
        """Test with a good state function."""

        def is_good_state(bitstr):
            return bitstr[1] == "1"

        # construct the estimation problem where the second qubit is ignored
        a_op = QuantumCircuit(2)
        a_op.ry(2 * np.arcsin(np.sqrt(0.2)), 0)

        # oracle only affects first qubit
        oracle = QuantumCircuit(2)
        oracle.z(0)

        # reflect only on first qubit
        q_op = GroverOperator(oracle, a_op, reflection_qubits=[0])

        # but we measure both qubits (hence both are objective qubits)
        problem = EstimationProblem(
            a_op, objective_qubits=[0, 1], grover_operator=q_op, is_good_state=is_good_state
        )

        # construct algo
        backend = QuantumInstance(
            BasicAer.get_backend(backend_str), seed_simulator=2, seed_transpiler=2
        )
        # cannot use rescaling with a custom grover operator
        fae = FasterAmplitudeEstimation(0.01, 5, rescale=False, quantum_instance=backend)

        # run the algo
        result = fae.estimate(problem)

        # assert the result is correct
        self.assertAlmostEqual(result.estimation, expect, places=5)
Esempio n. 6
0
    def test_run_without_rescaling(self):
        """Run Faster AE without rescaling if the amplitude is in [0, 1/4]."""
        # construct estimation problem
        prob = 0.11
        a_op = QuantumCircuit(1)
        a_op.ry(2 * np.arcsin(np.sqrt(prob)), 0)
        problem = EstimationProblem(a_op, objective_qubits=[0])

        # construct algo without rescaling
        backend = BasicAer.get_backend('statevector_simulator')
        fae = FasterAmplitudeEstimation(0.1,
                                        1,
                                        rescale=False,
                                        quantum_instance=backend)

        # run the algo
        result = fae.estimate(problem)

        # assert the result is correct
        self.assertAlmostEqual(result.estimation, prob)

        # assert no rescaling was used
        theta = np.mean(result.theta_intervals[-1])
        value_without_scaling = np.sin(theta)**2
        self.assertAlmostEqual(result.estimation, value_without_scaling)
    def test_application(self):
        """Test an end-to-end application."""
        from qiskit import Aer

        num_qubits = 3

        # parameters for considered random distribution
        s_p = 2.0  # initial spot price
        vol = 0.4  # volatility of 40%
        r = 0.05  # annual interest rate of 4%
        t_m = 40 / 365  # 40 days to maturity

        # resulting parameters for log-normal distribution
        mu = (r - 0.5 * vol**2) * t_m + np.log(s_p)
        sigma = vol * np.sqrt(t_m)
        mean = np.exp(mu + sigma**2 / 2)
        variance = (np.exp(sigma**2) - 1) * np.exp(2 * mu + sigma**2)
        stddev = np.sqrt(variance)

        # lowest and highest value considered for the spot price;
        # in between, an equidistant discretization is considered.
        low = np.maximum(0, mean - 3 * stddev)
        high = mean + 3 * stddev
        bounds = (low, high)

        # construct circuit for uncertainty model
        uncertainty_model = LogNormalDistribution(num_qubits,
                                                  mu=mu,
                                                  sigma=sigma**2,
                                                  bounds=bounds).decompose()

        # set the strike price (should be within the low and the high value of the uncertainty)
        strike_price = 1.896

        # create amplitude function
        european_call_delta = EuropeanCallDeltaObjective(
            num_state_qubits=num_qubits,
            strike_price=strike_price,
            bounds=bounds)

        # create state preparation
        state_preparation = european_call_delta.compose(uncertainty_model,
                                                        front=True)

        problem = EstimationProblem(
            state_preparation=state_preparation,
            objective_qubits=[num_qubits],
            post_processing=european_call_delta.post_processing,
        )

        # run amplitude estimation
        q_i = QuantumInstance(Aer.get_backend("aer_simulator"),
                              seed_simulator=125,
                              seed_transpiler=80)
        iae = IterativeAmplitudeEstimation(epsilon_target=0.01,
                                           alpha=0.05,
                                           quantum_instance=q_i)
        result = iae.estimate(problem)
        self.assertAlmostEqual(result.estimation_processed, 0.8088790606143996)
    def test_qasm(self, prob, shots, qae, expect):
        """ qasm test """
        qae.quantum_instance = self._qasm(shots)
        problem = EstimationProblem(BernoulliStateIn(prob), [0], BernoulliGrover(prob))

        result = qae.estimate(problem)
        for key, value in expect.items():
            self.assertAlmostEqual(value, getattr(result, key), places=3,
                                   msg="estimate `{}` failed".format(key))
    def test_qasm(self, n, shots, qae, expect):
        """QASM simulator end-to-end test."""
        # construct factories for A and Q
        qae.quantum_instance = self._qasm(shots)
        estimation_problem = EstimationProblem(SineIntegral(n), objective_qubits=[n])

        result = qae.estimate(estimation_problem)
        for key, value in expect.items():
            self.assertAlmostEqual(value, getattr(result, key), places=3,
                                   msg="estimate `{}` failed".format(key))
    def test_statevector(self, prob, qae, expect):
        """statevector test"""
        qae.quantum_instance = self._statevector
        problem = EstimationProblem(BernoulliStateIn(prob), 0, BernoulliGrover(prob))

        result = qae.estimate(problem)
        self._statevector.reset_execution_results()
        for key, value in expect.items():
            self.assertAlmostEqual(
                value, getattr(result, key), places=3, msg=f"estimate `{key}` failed"
            )
    def test_application(self):
        """Test an end-to-end application."""
        try:
            from qiskit import (
                Aer, )  # pylint: disable=unused-import,import-outside-toplevel
        except ImportError as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return

        a_n = np.eye(2)
        b = np.zeros(2)

        num_qubits = [2, 2]

        # specify the lower and upper bounds for the different dimension
        bounds = [(0, 0.12), (0, 0.24)]
        mu = [0.12, 0.24]
        sigma = 0.01 * np.eye(2)

        # construct corresponding distribution
        dist = NormalDistribution(num_qubits, mu, sigma, bounds=bounds)

        # specify cash flow
        c_f = [1.0, 2.0]

        # specify approximation factor
        rescaling_factor = 0.125

        # get fixed income circuit appfactory
        fixed_income = FixedIncomePricingObjective(num_qubits, a_n, b, c_f,
                                                   rescaling_factor, bounds)

        # build state preparation operator
        state_preparation = fixed_income.compose(dist, front=True)

        problem = EstimationProblem(
            state_preparation=state_preparation,
            objective_qubits=[4],
            post_processing=fixed_income.post_processing,
        )

        # run simulation
        q_i = QuantumInstance(Aer.get_backend("qasm_simulator"),
                              seed_simulator=2,
                              seed_transpiler=2)
        iae = IterativeAmplitudeEstimation(epsilon_target=0.01,
                                           alpha=0.05,
                                           quantum_instance=q_i)
        result = iae.estimate(problem)

        # compare to precomputed solution
        self.assertAlmostEqual(result.estimation_processed, 2.3389012822103044)
Esempio n. 12
0
    def test_qae_circuit(self, efficient_circuit):
        """Test circuits resulting from canonical amplitude estimation.

        Build the circuit manually and from the algorithm and compare the resulting unitaries.
        """
        prob = 0.5

        problem = EstimationProblem(BernoulliStateIn(prob),
                                    objective_qubits=[0])
        for m in [2, 5]:
            qae = AmplitudeEstimation(m)
            angle = 2 * np.arcsin(np.sqrt(prob))

            # manually set up the inefficient AE circuit
            qr_eval = QuantumRegister(m, "a")
            qr_objective = QuantumRegister(1, "q")
            circuit = QuantumCircuit(qr_eval, qr_objective)

            # initial Hadamard gates
            for i in range(m):
                circuit.h(qr_eval[i])

            # A operator
            circuit.ry(angle, qr_objective)

            if efficient_circuit:
                qae.grover_operator = BernoulliGrover(prob)
                for power in range(m):
                    circuit.cry(2 * 2**power * angle, qr_eval[power],
                                qr_objective[0])
            else:
                oracle = QuantumCircuit(1)
                oracle.z(0)

                state_preparation = QuantumCircuit(1)
                state_preparation.ry(angle, 0)
                grover_op = GroverOperator(oracle, state_preparation)
                grover_op.global_phase = np.pi
                for power in range(m):
                    circuit.compose(
                        grover_op.power(2**power).control(),
                        qubits=[qr_eval[power], qr_objective[0]],
                        inplace=True,
                    )

            # fourier transform
            iqft = QFT(m, do_swaps=False).inverse().reverse_bits()
            circuit.append(iqft.to_instruction(), qr_eval)

            actual_circuit = qae.construct_circuit(problem, measurement=False)

            self.assertEqual(Operator(circuit), Operator(actual_circuit))
    def test_statevector(self, n, qae, expect):
        """Statevector end-to-end test"""
        # construct factories for A and Q
        # qae.state_preparation = SineIntegral(n)
        qae.quantum_instance = self._statevector
        estimation_problem = EstimationProblem(SineIntegral(n), objective_qubits=[n])

        # result = qae.run(self._statevector)
        result = qae.estimate(estimation_problem)
        self._statevector.reset_execution_results()
        for key, value in expect.items():
            self.assertAlmostEqual(
                value, getattr(result, key), places=3, msg=f"estimate `{key}` failed"
            )
Esempio n. 14
0
    def test_rescaling_with_custom_grover_raises(self):
        """Test that the rescaling option fails if a custom Grover operator is used."""
        prob = 0.8
        a_op = BernoulliStateIn(prob)
        q_op = BernoulliGrover(prob)
        problem = EstimationProblem(a_op, objective_qubits=[0], grover_operator=q_op)

        # construct algo without rescaling
        backend = BasicAer.get_backend("statevector_simulator")
        fae = FasterAmplitudeEstimation(0.1, 1, quantum_instance=backend)

        # run the algo
        with self.assertWarns(Warning):
            _ = fae.estimate(problem)
Esempio n. 15
0
    def test_mlae_circuits(self, efficient_circuit):
        """ Test the circuits constructed for MLAE """
        prob = 0.5
        problem = EstimationProblem(BernoulliStateIn(prob),
                                    objective_qubits=[0])

        for k in [2, 5]:
            qae = MaximumLikelihoodAmplitudeEstimation(k)
            angle = 2 * np.arcsin(np.sqrt(prob))

            # compute all the circuits used for MLAE
            circuits = []

            # 0th power
            q_objective = QuantumRegister(1, 'q')
            circuit = QuantumCircuit(q_objective)
            circuit.ry(angle, q_objective)
            circuits += [circuit]

            # powers of 2
            for power in range(k):
                q_objective = QuantumRegister(1, 'q')
                circuit = QuantumCircuit(q_objective)

                # A operator
                circuit.ry(angle, q_objective)

                # Q^(2^j) operator
                if efficient_circuit:
                    qae.grover_operator = BernoulliGrover(prob)
                    circuit.ry(2 * 2**power * angle, q_objective[0])

                else:
                    oracle = QuantumCircuit(1)
                    oracle.z(0)
                    state_preparation = QuantumCircuit(1)
                    state_preparation.ry(angle, 0)
                    grover_op = GroverOperator(oracle, state_preparation)
                    grover_op.global_phase = np.pi
                    for _ in range(2**power):
                        circuit.compose(grover_op, inplace=True)
                circuits += [circuit]

            actual_circuits = qae.construct_circuits(problem,
                                                     measurement=False)

            for actual, expected in zip(actual_circuits, circuits):
                self.assertEqual(Operator(actual), Operator(expected))
    def test_application(self):
        """Test an end-to-end application."""
        from qiskit import Aer

        bounds = np.array([0.0, 7.0])
        num_qubits = 3

        # the distribution circuit is a normal distribution plus a QGAN-trained ansatz circuit
        dist = NormalDistribution(num_qubits, mu=1, sigma=1, bounds=bounds)

        ansatz = TwoLocal(num_qubits, "ry", "cz", reps=1, entanglement="circular")
        trained_params = [
            0.29399714,
            0.38853322,
            0.9557694,
            0.07245791,
            6.02626428,
            0.13537225,
        ]
        ansatz.assign_parameters(trained_params, inplace=True)

        dist.compose(ansatz, inplace=True)

        # create the European call expected value
        strike_price = 2
        rescaling_factor = 0.25
        european_call = EuropeanCallPricingObjective(
            num_state_qubits=num_qubits,
            strike_price=strike_price,
            rescaling_factor=rescaling_factor,
            bounds=bounds,
        )

        # create the state preparation circuit
        state_preparation = european_call.compose(dist, front=True)

        problem = EstimationProblem(
            state_preparation=state_preparation,
            objective_qubits=[num_qubits],
            post_processing=european_call.post_processing,
        )

        q_i = QuantumInstance(
            Aer.get_backend("aer_simulator"), seed_simulator=125, seed_transpiler=80
        )
        iae = IterativeAmplitudeEstimation(epsilon_target=0.01, alpha=0.05, quantum_instance=q_i)
        result = iae.estimate(problem)
        self.assertAlmostEqual(result.estimation_processed, 1.0364776997977694)
Esempio n. 17
0
    def test_application(self):
        """Test an end-to-end application."""
        try:
            from qiskit import Aer  # pylint: disable=unused-import,import-outside-toplevel
        except ImportError as ex:  # pylint: disable=broad-except
            self.skipTest("Aer doesn't appear to be installed. Error: '{}'".format(str(ex)))
            return

        bounds = np.array([0., 7.])
        num_qubits = 3

        # the distribution circuit is a normal distribution plus a QGAN-trained ansatz circuit
        dist = NormalDistribution(num_qubits, mu=1, sigma=1, bounds=bounds)

        ansatz = TwoLocal(num_qubits, 'ry', 'cz', reps=1, entanglement='circular')
        trained_params = [0.29399714, 0.38853322, 0.9557694, 0.07245791, 6.02626428, 0.13537225]
        ansatz.assign_parameters(trained_params, inplace=True)

        dist.compose(ansatz, inplace=True)

        # create the European call expected value
        strike_price = 2
        rescaling_factor = 0.25
        european_call = EuropeanCallPricingObjective(num_state_qubits=num_qubits,
                                                     strike_price=strike_price,
                                                     rescaling_factor=rescaling_factor,
                                                     bounds=bounds)

        # create the state preparation circuit
        state_preparation = european_call.compose(dist, front=True)

        problem = EstimationProblem(state_preparation=state_preparation,
                                    objective_qubits=[num_qubits],
                                    post_processing=european_call.post_processing)

        q_i = QuantumInstance(Aer.get_backend('qasm_simulator'),
                              seed_simulator=125, seed_transpiler=80)
        iae = IterativeAmplitudeEstimation(epsilon_target=0.01,
                                           alpha=0.05,
                                           quantum_instance=q_i)
        result = iae.estimate(problem)
        self.assertAlmostEqual(result.estimation_processed, 1.0127253837345427)
Esempio n. 18
0
    def test_distribution_load(self):
        """ Test that calculates a cumulative probability from the P&L distribution."""

        correl = ft.get_correl("AAPL", "MSFT")

        bounds_std = 3.0
        num_qubits = [3, 3]
        sigma = correl
        bounds = [(-bounds_std, bounds_std), (-bounds_std, bounds_std)]
        mu = [0, 0]

        # starting point is a multi-variate normal distribution
        normal = NormalDistribution(num_qubits,
                                    mu=mu,
                                    sigma=sigma,
                                    bounds=bounds)

        pl_set = []
        coeff_set = []
        for ticker in ["MSFT", "AAPL"]:
            ((cdf_x, cdf_y), sigma) = ft.get_cdf_data(ticker)
            (x, y) = ft.get_fit_data(ticker, norm_to_rel=False)
            (pl, coeffs) = ft.fit_piecewise_linear(x, y)
            # scale, to apply an arbitrary delta (we happen to use the same value here, but could be different)
            coeffs = ft.scaled_coeffs(coeffs, 1.2)
            pl_set.append(lambda z: ft.piecewise_linear(z, *coeffs))
            coeff_set.append(coeffs)

        # calculate the max and min P&Ls
        p_max = max(pl_set[0](bounds_std), pl_set[1](bounds_std))
        p_min = min(pl_set[0](-bounds_std), pl_set[1](-bounds_std))

        # we discretise the transforms and create the circuits
        transforms = []
        i_to_js = []
        for i, ticker in enumerate(["MSFT", "AAPL"]):
            (i_0, i_1, a0, a1, a2, b0, b1, b2, i_to_j, i_to_x,
             j_to_y) = ft.integer_piecewise_linear_coeffs(coeff_set[i],
                                                          x_min=-bounds_std,
                                                          x_max=bounds_std,
                                                          y_min=p_min,
                                                          y_max=p_max)
            transforms.append(
                PiecewiseLinearTransform3(i_0, i_1, a0, a1, a2, b0, b1, b2))
            i_to_js.append(np.vectorize(i_to_j))

        i1, i2 = get_sims(normal)
        j1 = i_to_js[0](i1)
        j2 = i_to_js[1](i2)
        j_tot = j1 + j2

        num_ancillas = transforms[0].num_ancilla_qubits

        qr_input = QuantumRegister(6, 'input')  # 2 times 3 registers
        qr_objective = QuantumRegister(1, 'objective')
        qr_result = QuantumRegister(6, 'result')
        qr_ancilla = QuantumRegister(num_ancillas, 'ancilla')
        #output = ClassicalRegister(6, 'output')

        state_preparation = QuantumCircuit(qr_input, qr_objective, qr_result,
                                           qr_ancilla)  #, output)
        state_preparation.append(normal, qr_input)

        for i in range(2):
            offset = i * 3
            state_preparation.append(
                transforms[i],
                qr_input[offset:offset + 3] + qr_result[:] + qr_ancilla[:])

        # to calculate the cdf, we use an additional comparator
        x_eval = 4
        comparator = IntegerComparator(len(qr_result), x_eval + 1, geq=False)
        state_preparation.append(
            comparator, qr_result[:] + qr_objective[:] +
            qr_ancilla[0:comparator.num_ancillas])

        # now check
        check = False
        if check:
            job = execute(state_preparation,
                          backend=Aer.get_backend('statevector_simulator'))
            var_prob = 0
            for i, a in enumerate(job.result().get_statevector()):
                b = ('{0:0%sb}' %
                     (len(qr_input) + 1)).format(i)[-(len(qr_input) + 1):]
                prob = np.abs(a)**2
                if prob > 1e-6 and b[0] == '1':
                    var_prob += prob
            print('Operator CDF(%s)' % x_eval + ' = %.4f' % var_prob)

        # now do AE

        problem = EstimationProblem(state_preparation=state_preparation,
                                    objective_qubits=[len(qr_input)])

        # target precision and confidence level
        epsilon = 0.01
        alpha = 0.05
        qi = QuantumInstance(Aer.get_backend('aer_simulator'), shots=100)
        ae_cdf = IterativeAmplitudeEstimation(epsilon,
                                              alpha=alpha,
                                              quantum_instance=qi)
        result_cdf = ae_cdf.estimate(problem)

        conf_int = np.array(result_cdf.confidence_interval)
        print('Estimated value:\t%.4f' % result_cdf.estimation)
        print('Confidence interval: \t[%.4f, %.4f]' % tuple(conf_int))

        state_preparation.draw()
    def test_readme_sample(self):
        """ readme sample test """

        # pylint: disable=import-outside-toplevel,redefined-builtin

        def print(*args):
            """ overloads print to log values """
            if args:
                self.log.debug(args[0], *args[1:])

        # --- Exact copy of sample code ----------------------------------------

        import numpy as np
        from qiskit import BasicAer
        from qiskit.algorithms import AmplitudeEstimation, EstimationProblem
        from qiskit.circuit.library import NormalDistribution
        from qiskit_finance.applications import FixedIncomeExpectedValue

        # Create a suitable multivariate distribution
        num_qubits = [2, 2]
        bounds = [(0, 0.12), (0, 0.24)]
        mvnd = NormalDistribution(num_qubits,
                                  mu=[0.12, 0.24],
                                  sigma=0.01 * np.eye(2),
                                  bounds=bounds)

        # Create fixed income component
        fixed_income = FixedIncomeExpectedValue(num_qubits,
                                                np.eye(2),
                                                np.zeros(2),
                                                cash_flow=[1.0, 2.0],
                                                rescaling_factor=0.125,
                                                bounds=bounds)

        # the FixedIncomeExpectedValue provides us with the necessary rescalings

        # create the A operator for amplitude estimation by prepending the
        # normal distribution to the function mapping
        state_preparation = fixed_income.compose(mvnd, front=True)

        problem = EstimationProblem(
            state_preparation=state_preparation,
            objective_qubits=[4],
            post_processing=fixed_income.post_processing)

        # Set number of evaluation qubits (samples)
        num_eval_qubits = 5

        # Construct and run amplitude estimation
        q_i = BasicAer.get_backend('statevector_simulator')
        algo = AmplitudeEstimation(num_eval_qubits=num_eval_qubits,
                                   quantum_instance=q_i)
        result = algo.estimate(problem)

        print('Estimated value:\t%.4f' % result.estimation_processed)
        print('Probability:    \t%.4f' % result.max_probability)

        # ----------------------------------------------------------------------

        with self.subTest('test estimation'):
            self.assertAlmostEqual(result.estimation_processed, 2.46, places=4)
        with self.subTest('test max.probability'):
            self.assertAlmostEqual(result.max_probability, 0.8487, places=4)
    def test_application(self):
        """Test an end-to-end application."""
        try:
            from qiskit import Aer  # pylint: disable=unused-import,import-outside-toplevel
        except ImportError as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return

        num_qubits = 3

        # parameters for considered random distribution
        s_p = 2.0  # initial spot price
        vol = 0.4  # volatility of 40%
        r = 0.05  # annual interest rate of 4%
        t_m = 40 / 365  # 40 days to maturity

        # resulting parameters for log-normal distribution
        mu = ((r - 0.5 * vol**2) * t_m + np.log(s_p))
        sigma = vol * np.sqrt(t_m)
        mean = np.exp(mu + sigma**2 / 2)
        variance = (np.exp(sigma**2) - 1) * np.exp(2 * mu + sigma**2)
        stddev = np.sqrt(variance)

        # lowest and highest value considered for the spot price;
        # in between, an equidistant discretization is considered.
        low = np.maximum(0, mean - 3 * stddev)
        high = mean + 3 * stddev
        bounds = (low, high)

        # construct circuit factory for uncertainty model
        uncertainty_model = LogNormalDistribution(num_qubits,
                                                  mu=mu,
                                                  sigma=sigma**2,
                                                  bounds=bounds)

        # set the strike price (should be within the low and the high value of the uncertainty)
        strike_price = 1.896

        # create amplitude function
        european_call_delta = EuropeanCallDelta(num_state_qubits=num_qubits,
                                                strike_price=strike_price,
                                                bounds=bounds)

        # create state preparation
        state_preparation = european_call_delta.compose(uncertainty_model,
                                                        front=True)

        problem = EstimationProblem(
            state_preparation=state_preparation,
            objective_qubits=[num_qubits],
            post_processing=european_call_delta.post_processing)

        # run amplitude estimation
        q_i = QuantumInstance(Aer.get_backend('qasm_simulator'),
                              seed_simulator=125,
                              seed_transpiler=80)
        iae = IterativeAmplitudeEstimation(epsilon_target=0.01,
                                           alpha=0.05,
                                           quantum_instance=q_i)
        result = iae.estimate(problem)
        self.assertAlmostEqual(result.estimation_processed, 0.8079816552117238)