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)
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)