def test_to_estimation_problem(self):
     """Test the expected circuit."""
     num_qubits = 3
     rescaling_factor = 0.1
     strike_price = 0.5
     bounds = (0, 2)
     # make an estimation problem
     uncertain_model = UniformDistribution(num_qubits)
     ecp = EuropeanCallPricing(num_qubits, strike_price, rescaling_factor,
                               bounds, uncertain_model)
     est_problem = ecp.to_estimation_problem()
     # make a state_preparation circuit manually
     breakpoints = [0, strike_price]
     slopes = [0, 1]
     offsets = [0, 0]
     image = (0, 2 - strike_price)
     domain = (0, 2)
     linear_function = LinearAmplitudeFunction(
         num_qubits,
         slopes,
         offsets,
         domain=domain,
         image=image,
         breakpoints=breakpoints,
         rescaling_factor=rescaling_factor,
     )
     expected_circ = linear_function.compose(uncertain_model, front=True)
     self.assertEqual(est_problem.objective_qubits, [num_qubits])
     self.assertTrue(
         Operator(est_problem.state_preparation).equiv(expected_circ))
     # pylint: disable=not-callable
     self.assertEqual(linear_function.post_processing(0.5),
                      est_problem.post_processing(0.5))
Example #2
0
    def __init__(
        self,
        num_state_qubits: int,
        strike_price: float,
        rescaling_factor: float,
        bounds: Tuple[float, float],
    ) -> None:
        """
        Args:
            num_state_qubits: The number of qubits used to represent the random variable.
            strike_price: strike price of the European option
            rescaling_factor: approximation factor for linear payoff
            bounds: The tuple of the bounds, (min, max), of the discretized random variable.
        """
        # create piecewise linear amplitude function
        breakpoints = [bounds[0], strike_price]
        slopes = [0, 1]
        offsets = [0, 0]
        f_min = 0
        f_max = bounds[1] - strike_price
        european_call = LinearAmplitudeFunction(
            num_state_qubits,
            slopes,
            offsets,
            domain=bounds,
            image=(f_min, f_max),
            breakpoints=breakpoints,
            rescaling_factor=rescaling_factor)

        super().__init__(*european_call.qregs, name='ECEV')
        self._data = european_call.data
        self._european_call = european_call
Example #3
0
    def test_ecev_circuit(self):
        """Test the expected circuit.

        If it equals the correct ``LinearAmplitudeFunction`` we know the circuit is correct.
        """
        num_qubits = 3
        rescaling_factor = 0.1
        strike_price = 0.5
        bounds = (0, 2)
        ecev = EuropeanCallExpectedValue(num_qubits, strike_price, rescaling_factor, bounds)

        breakpoints = [0, strike_price]
        slopes = [0, 1]
        offsets = [0, 0]
        image = (0, 2 - strike_price)
        domain = (0, 2)
        linear_function = LinearAmplitudeFunction(
            num_qubits,
            slopes,
            offsets,
            domain=domain,
            image=image,
            breakpoints=breakpoints,
            rescaling_factor=rescaling_factor)

        self.assertTrue(Operator(ecev).equiv(linear_function))
Example #4
0
    def test_not_including_start_in_breakpoints(self):
        """Test not including the start of the domain works."""
        num_state_qubits = 1
        slope = [0, 0]
        offset = [0, 0]
        domain = (0, 2)
        image = (0, 1)
        rescaling_factor = 0.1
        breakpoints = [1]

        reference = partial(
            self.evaluate_function,
            num_qubits=num_state_qubits,
            slope=slope,
            offset=offset,
            domain=domain,
            image=image,
            rescaling_factor=rescaling_factor,
            breakpoints=breakpoints,
        )

        linear_f = LinearAmplitudeFunction(num_state_qubits, slope, offset,
                                           domain, image, rescaling_factor,
                                           breakpoints)

        self.assertFunctionIsCorrect(linear_f, reference)
Example #5
0
    def test_invalid_inputs_raise(self):
        """Test passing invalid inputs to the LinearAmplitudeFunction raises an error."""
        # default values
        num_state_qubits = 1
        slope = [0, 0]
        offset = [0, 0]
        domain = (0, 2)
        image = (0, 1)
        rescaling_factor = 0.1
        breakpoints = [0, 1]

        with self.subTest('mismatching breakpoints size'):
            with self.assertRaises(ValueError):
                _ = LinearAmplitudeFunction(num_state_qubits, slope, offset,
                                            domain, image, rescaling_factor,
                                            [0])

        with self.subTest('mismatching offsets'):
            with self.assertRaises(ValueError):
                _ = LinearAmplitudeFunction(num_state_qubits, slope, [0],
                                            domain, image, rescaling_factor,
                                            breakpoints)

        with self.subTest('mismatching slopes'):
            with self.assertRaises(ValueError):
                _ = LinearAmplitudeFunction(num_state_qubits, [0], offset,
                                            domain, image, rescaling_factor,
                                            breakpoints)

        with self.subTest('breakpoints outside of domain'):
            with self.assertRaises(ValueError):
                _ = LinearAmplitudeFunction(num_state_qubits, slope, offset,
                                            (0, 0.2), image, rescaling_factor,
                                            breakpoints)

        with self.subTest('breakpoints not sorted'):
            with self.assertRaises(ValueError):
                _ = LinearAmplitudeFunction(num_state_qubits, slope, offset,
                                            domain, image, rescaling_factor,
                                            [1, 0])
    def test_post_processing(self):
        """Test the ``post_processing`` method."""
        num_state_qubits = 2
        slope = 1
        offset = -2
        domain = (0, 2)
        image = (-2, 0)
        rescaling_factor = 0.1

        circuit = LinearAmplitudeFunction(num_state_qubits, slope, offset,
                                          domain, image, rescaling_factor)

        values = [0, 0.2, 0.5, 0.9, 1]

        def reference_post_processing(x):
            x = 2 / np.pi / rescaling_factor * (x - 0.5) + 0.5
            return image[0] + (image[1] - image[0]) * x

        expected = [reference_post_processing(value) for value in values]
        actual = [circuit.post_processing(value) for value in values]

        self.assertListEqual(expected, actual)
Example #7
0
    def test_polynomial_function(self, num_state_qubits, slope, offset, domain,
                                 image, rescaling_factor, breakpoints):
        """Test the polynomial rotation."""
        reference = partial(self.evaluate_function,
                            num_qubits=num_state_qubits,
                            slope=slope,
                            offset=offset,
                            domain=domain,
                            image=image,
                            rescaling_factor=rescaling_factor,
                            breakpoints=breakpoints)

        linear_f = LinearAmplitudeFunction(num_state_qubits, slope, offset,
                                           domain, image, rescaling_factor,
                                           breakpoints)

        self.assertFunctionIsCorrect(linear_f, reference)
Example #8
0
import numpy as np

# define linear objective function
num_sum_qubits = 5
breakpoints = [0]
slopes = [1]
offsets = [0]
f_min = 0
f_max = 10
c_approx = 0.25

objective = LinearAmplitudeFunction(
    num_sum_qubits,
    slope=slopes,
    offset=offsets,
    # max value that can be reached by the qubit register (will not always be reached)
    domain=(0, 2**num_sum_qubits-1),
    image=(f_min, f_max),
    rescaling_factor=c_approx,
    breakpoints=breakpoints
)

qr_sum = QuantumRegister(5, "sum")
state_preparation = QuantumCircuit(qr_sum) # to complete

# set target precision and confidence level
epsilon = 0.01
alpha = 0.05

# construct amplitude estimation
ae_cdf = IterativeAmplitudeEstimation(state_preparation=state_preparation,
                                      epsilon=epsilon, alpha=alpha,