class FixedValueComparator(CircuitFactory):
    r"""Fixed Value Comparator.

    Operator compares basis states \|i>_n against a classically
    given fixed value L and flips a target qubit if i >= L (or < depending on parameters):

        \|i>_n\|0> --> \|i>_n\|1> if i >= L else \|i>\|0>

    Operator is based on two's complement implementation of binary
    subtraction but only uses carry bits and no actual result bits.
    If the most significant carry bit (= results bit) is 1, the ">="
    condition is True otherwise it is False.
    """

    def __init__(self, num_state_qubits, value, geq=True, i_state=None, i_target=None):
        """
        Args:
            num_state_qubits (int): number of state qubits, the target qubit comes on top of this
            value (int): fixed value to compare with
            geq (Optional(bool)): evaluate ">=" condition of "<" condition
            i_state (Optional(Union(list, numpy.ndarray))): indices of state qubits in
                given list of qubits / register,
                if None, i_state = list(range(num_state_qubits)) is used
            i_target (Optional(int)): index of target qubit in given list
                of qubits / register, if None, i_target = num_state_qubits is used
        """
        warnings.warn('The qiskit.aqua.circuits.FixedValueComparator object is deprecated and will '
                      'be removed no earlier than 3 months after the 0.7.0 release of Qiskit Aqua. '
                      'You should use qiskit.circuit.library.IntegerComparator instead.',
                      DeprecationWarning, stacklevel=2)

        super().__init__(num_state_qubits + 1)
        self._comparator_circuit = IntegerComparator(value=value,
                                                     num_state_qubits=num_state_qubits,
                                                     geq=geq)

        self.i_state = None
        if i_state is not None:
            self.i_state = i_state
        else:
            self.i_state = range(num_state_qubits)

        self.i_target = None
        if i_target is not None:
            self.i_target = i_target
        else:
            self.i_target = num_state_qubits

    @property
    def num_state_qubits(self):
        """ returns num state qubits """
        return self._comparator_circuit._num_state_qubits

    @property
    def value(self):
        """ returns value """
        return self._comparator_circuit._value

    def required_ancillas(self):
        return self.num_state_qubits - 1

    def required_ancillas_controlled(self):
        return self.num_state_qubits - 1

    def _get_twos_complement(self):
        """
        Returns the 2's complement of value as array

        Returns:
             list: two's complement
        """

        twos_complement = pow(2, self.num_state_qubits) - int(np.ceil(self.value))
        twos_complement = '{0:b}'.format(twos_complement).rjust(self.num_state_qubits, '0')
        twos_complement = \
            [1 if twos_complement[i] == '1' else 0 for i in reversed(range(len(twos_complement)))]
        return twos_complement

    def build(self, qc, q, q_ancillas=None, params=None):
        instr = self._comparator_circuit.to_instruction()
        qr = [q[i] for i in self.i_state] + [q[self.i_target]]
        if q_ancillas:
            # pylint:disable=unnecessary-comprehension
            qr += [qi for qi in q_ancillas[:self.required_ancillas()]]
        qc.append(instr, qr)
Esempio n. 2
0
class EuropeanCallExpectedValue(UncertaintyProblem):
    """The European Call Option Expected Value.

    Evaluates the expected payoff for a European call option given an uncertainty model.
    The payoff function is f(S, K) = max(0, S - K) for a spot price S and strike price K.
    """
    def __init__(self,
                 uncertainty_model: UnivariateDistribution,
                 strike_price: float,
                 c_approx: float,
                 i_state: Optional[Union[List[int], np.ndarray]] = None,
                 i_compare: Optional[int] = None,
                 i_objective: Optional[int] = None) -> None:
        """
        Constructor.

        Args:
            uncertainty_model: uncertainty model for spot price
            strike_price: strike price of the European option
            c_approx: approximation factor for linear payoff
            i_state: indices of qubits representing the uncertainty
            i_compare: index of qubit for comparing spot price to strike price
                            (enabling payoff or not)
            i_objective: index of qubit for objective function
        """
        super().__init__(uncertainty_model.num_target_qubits + 2)

        self._uncertainty_model = uncertainty_model
        self._strike_price = strike_price
        self._c_approx = c_approx

        if i_state is None:
            i_state = list(range(uncertainty_model.num_target_qubits))
        self.i_state = i_state
        if i_compare is None:
            i_compare = uncertainty_model.num_target_qubits
        self.i_compare = i_compare
        if i_objective is None:
            i_objective = uncertainty_model.num_target_qubits + 1
        self.i_objective = i_objective

        # map strike price to {0, ..., 2^n-1}
        lower = uncertainty_model.low
        upper = uncertainty_model.high
        self._mapped_strike_price = int(
            np.round((strike_price - lower) / (upper - lower) *
                     (uncertainty_model.num_values - 1)))

        # create comparator
        self._comparator = IntegerComparator(
            uncertainty_model.num_target_qubits, self._mapped_strike_price)

        self.offset_angle_zero = np.pi / 4 * (1 - self._c_approx)
        if self._mapped_strike_price < uncertainty_model.num_values - 1:
            self.offset_angle = -1 * np.pi / 2 * self._c_approx * self._mapped_strike_price / \
                (uncertainty_model.num_values - self._mapped_strike_price - 1)
            self.slope_angle = np.pi / 2 * self._c_approx / \
                (uncertainty_model.num_values - self._mapped_strike_price - 1)
        else:
            self.offset_angle = 0
            self.slope_angle = 0

    def value_to_estimation(self, value):
        estimator = value - 1 / 2 + np.pi / 4 * self._c_approx
        estimator *= 2 / np.pi / self._c_approx
        estimator *= (self._uncertainty_model.num_values -
                      self._mapped_strike_price - 1)
        estimator *= (self._uncertainty_model.high - self._uncertainty_model.low) / \
            (self._uncertainty_model.num_values - 1)
        return estimator

    def required_ancillas(self):
        num_uncertainty_ancillas = self._uncertainty_model.required_ancillas()
        num_comparator_ancillas = self._comparator.num_ancilla_qubits
        num_ancillas = int(
            np.maximum(num_uncertainty_ancillas, num_comparator_ancillas))
        return num_ancillas

    def build(self, qc, q, q_ancillas=None, params=None):

        # get qubits
        q_state = [q[i] for i in self.i_state]
        q_compare = q[self.i_compare]
        q_objective = q[self.i_objective]

        # apply uncertainty model
        self._uncertainty_model.build(qc, q_state, q_ancillas)

        # apply comparator to compare qubit
        qubits = q_state[:] + [q_compare]
        if q_ancillas:
            qubits += q_ancillas[:self._comparator.num_ancilla_qubits]
        qc.append(self._comparator.to_instruction(), qubits)

        # apply approximate payoff function
        qc.ry(2 * self.offset_angle_zero, q_objective)
        qc.cry(2 * self.offset_angle, q_compare, q_objective)
        for i, q_i in enumerate(q_state):
            qc.mcry(2 * self.slope_angle * 2**i, [q_compare, q_i], q_objective,
                    None)
class EuropeanCallDelta(UncertaintyProblem):
    """The European Call Option Delta.

    Evaluates the variance for a European call option given an uncertainty model.
    The payoff function is f(S, K) = max(0, S - K) for a spot price S and strike price K.
    """
    def __init__(self,
                 uncertainty_model: UnivariateDistribution,
                 strike_price: float,
                 i_state: Optional[Union[List[int], np.ndarray]] = None,
                 i_objective: Optional[int] = None) -> None:
        """
        Constructor.

        Args:
            uncertainty_model: uncertainty model for spot price
            strike_price: strike price of the European option
            i_state: indices of qubits representing the uncertainty
            i_objective: index of qubit for objective function
        """
        super().__init__(uncertainty_model.num_target_qubits + 1)

        self._uncertainty_model = uncertainty_model
        self._strike_price = strike_price

        if i_state is None:
            i_state = list(range(uncertainty_model.num_target_qubits))
        self.i_state = i_state
        if i_objective is None:
            i_objective = uncertainty_model.num_target_qubits
        self.i_objective = i_objective

        # map strike price to {0, ..., 2^n-1}
        lb = uncertainty_model.low
        ub = uncertainty_model.high
        self._mapped_strike_price = int(
            np.ceil((strike_price - lb) / (ub - lb) *
                    (uncertainty_model.num_values - 1)))

        # create comparator
        self._comparator = IntegerComparator(
            uncertainty_model.num_target_qubits, self._mapped_strike_price)

    def required_ancillas(self):
        num_uncertainty_ancillas = self._uncertainty_model.required_ancillas()
        num_comparator_ancillas = self._comparator.num_ancilla_qubits
        num_ancillas = num_uncertainty_ancillas + num_comparator_ancillas
        return num_ancillas

    def required_ancillas_controlled(self):
        num_uncertainty_ancillas = self._uncertainty_model.required_ancillas_controlled(
        )
        num_comparator_ancillas = self._comparator.num_ancilla_qubits
        num_ancillas_controlled = num_uncertainty_ancillas + num_comparator_ancillas
        return num_ancillas_controlled

    def build(self, qc, q, q_ancillas=None, params=None):
        # get qubit lists
        q_state = [q[i] for i in self.i_state]
        q_objective = q[self.i_objective]

        # apply uncertainty model
        self._uncertainty_model.build(qc, q_state, q_ancillas)

        # apply comparator to compare qubit
        qubits = q_state[:] + [q_objective]
        if q_ancillas:
            qubits += q_ancillas[:self.required_ancillas()]
        qc.append(self._comparator.to_instruction(), qubits)