def test_mutability(self): """Test changing the arguments of the comparator.""" comp = IntegerComparator() with self.subTest(msg='missing num state qubits and value'): with self.assertRaises(AttributeError): print(comp.draw()) comp.num_state_qubits = 2 with self.subTest(msg='missing value'): with self.assertRaises(AttributeError): print(comp.draw()) comp.value = 0 comp.geq = True with self.subTest(msg='updating num state qubits'): comp.num_state_qubits = 1 self.assertComparisonIsCorrect(comp, 1, 0, True) with self.subTest(msg='updating the value'): comp.num_state_qubits = 3 comp.value = 2 self.assertComparisonIsCorrect(comp, 3, 2, True) with self.subTest(msg='updating geq'): comp.geq = False self.assertComparisonIsCorrect(comp, 3, 2, False)
def integercomparator(relative_numbers): from qiskit.circuit.library import IntegerComparator from unqomp.examples.intergercomparator import makeIntegerComparator n = 12 v = 40 circuit1 = makeIntegerComparator(n, v).circuitWithUncomputation() qcirc = IntegerComparator(n, v) print('IntegerComparator ; ', end = '') #qiskit nb_qb_qi = qcirc.num_qubits nb_gates_qi = qcirc.decompose().decompose().decompose().decompose().decompose().count_ops() if not relative_numbers: print(str(nb_qb_qi) + ' ; ' + str(nb_gates_qi['cx'] + nb_gates_qi['u3']) + ' ; ' + str(nb_gates_qi['cx']) + ' ; ', end = '') #qiskit++ nb_qb_mi = circuit1.num_qubits nb_gates_mi = circuit1.decompose().decompose().decompose().decompose().decompose().count_ops() if not relative_numbers: print(str(nb_qb_mi) + ' ; ' + str(nb_gates_mi['cx'] + nb_gates_mi['u3']) + ' ; ' + str(nb_gates_mi['cx'])) if relative_numbers: print_relative_vals(nb_qb_qi, nb_gates_qi['cx'], nb_gates_qi['u3'], nb_qb_mi, nb_gates_mi['cx'], nb_gates_mi['u3'])
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
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 __init__(self, x0, x1, a0, a1, a2, b0, b1, b2, nbits = 3): qr_input = QuantumRegister(nbits, 'input') num_result_qubits = nbits * 2 qr_result = QuantumRegister(num_result_qubits, 'result') self.num_ancilla_qubits = 2 + num_result_qubits + 3 qr_ancilla = QuantumRegister(self.num_ancilla_qubits, 'ancilla') qr_comp_anc = qr_ancilla[0:2] qr_arith_anc = qr_ancilla[2:2 + num_result_qubits] qr_range_anc = qr_ancilla[2 + num_result_qubits:2 + num_result_qubits + 3] super().__init__(qr_input, qr_result, qr_ancilla, name='pwise_lin_trans') comp0 = IntegerComparator(num_state_qubits=nbits, value=x0, name = "comparator0") # true if i >= point comp1 = IntegerComparator(num_state_qubits=nbits, value=x1, name = "comparator1") # true if i >= point trans0 = multiply_add.cond_classical_add_mult(a0, b0, qr_input, qr_result, qr_arith_anc) trans1 = multiply_add.cond_classical_add_mult(a1, b1, qr_input, qr_result, qr_arith_anc) trans2 = multiply_add.cond_classical_add_mult(a2, b2, qr_input, qr_result, qr_arith_anc) self.append(comp0.to_gate(), qr_input[:] + [qr_comp_anc[0]] + qr_arith_anc[0:comp0.num_ancillas]) self.append(comp1.to_gate(), qr_input[:] + [qr_comp_anc[1]] + qr_arith_anc[0:comp1.num_ancillas]) # use three additional ancillas to define the ranges self.cx(qr_comp_anc[0], qr_range_anc[0]) self.x(qr_range_anc[0]) self.cx(qr_comp_anc[1], qr_range_anc[2]) self.x(qr_range_anc[2]) self.ccx(qr_comp_anc[0], qr_range_anc[2], qr_range_anc[1]) self.append(trans0, [qr_range_anc[0]] + qr_input[:] + qr_result[:] + qr_arith_anc[:]) self.append(trans1, [qr_range_anc[1]] + qr_input[:] + qr_result[:] + qr_arith_anc[:]) self.append(trans2, [qr_comp_anc[1]] + qr_input[:] + qr_result[:] + qr_arith_anc[:]) # uncompute range ancillas self.ccx(qr_comp_anc[0], qr_range_anc[2], qr_range_anc[1]) self.x(qr_range_anc[2]) self.cx(qr_comp_anc[1], qr_range_anc[2]) self.x(qr_range_anc[0]) self.cx(qr_comp_anc[0], qr_range_anc[0]) # uncompute comparator ancillas self.append(comp1.to_gate().inverse(), qr_input[:] + [qr_comp_anc[1]] + qr_arith_anc[0:comp1.num_ancillas]) self.append(comp0.to_gate().inverse(), qr_input[:] + [qr_comp_anc[0]] + qr_arith_anc[0:comp0.num_ancillas])
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 test_circuit(self): """Test the expected circuit. If it equals the correct ``IntegerComparator`` we know the circuit is correct. """ num_qubits = 3 strike_price = 0.5 bounds = (0, 2) ecd = EuropeanCallDelta(num_qubits, strike_price, bounds) # map strike_price to a basis state x = (strike_price - bounds[0]) / (bounds[1] - bounds[0]) * (2 ** num_qubits - 1) comparator = IntegerComparator(num_qubits, x) self.assertTrue(Operator(ecd).equiv(comparator))
def test_to_estimation_problem(self): """Test the expected circuit.""" num_qubits = 3 strike_price = 0.5 bounds = (0, 2) # make an estimation problem uncertain_model = UniformDistribution(num_qubits) ecd = EuropeanCallDelta(num_qubits, strike_price, bounds, uncertain_model) est_problem = ecd.to_estimation_problem() # make a state_preparation circuit manually x = (strike_price - bounds[0]) / (bounds[1] - bounds[0]) * (2**num_qubits - 1) comparator = IntegerComparator(num_qubits, x) expected_circ = comparator.compose(uncertain_model, front=True) self.assertEqual(est_problem.objective_qubits, [num_qubits]) self.assertTrue( Operator(est_problem.state_preparation).equiv(expected_circ)) self.assertEqual(0.5, est_problem.post_processing(0.5)) # pylint: disable=not-callable
def __init__(self, num_state_qubits: int, strike_price: float, bounds: Tuple[float, float] ) -> None: """ Args: num_state_qubits: The number of qubits used to encode the random variable. strike_price: strike price of the European option bounds: The tuple of the bounds, (min, max), of the discretized random variable. """ # map strike price to {0, ..., 2^n-1} num_values = 2 ** num_state_qubits strike_price = (strike_price - bounds[0]) / (bounds[1] - bounds[0]) * (num_values - 1) strike_price = int(np.ceil(strike_price)) # create comparator comparator = IntegerComparator(num_state_qubits, strike_price) # initialize circuit qr_state = QuantumRegister(comparator.num_qubits - comparator.num_ancillas, 'state') qr_work = QuantumRegister(comparator.num_ancillas, 'work') super().__init__(qr_state, qr_work, name='ECD') self.append(comparator.to_gate(), self.qubits)
def test_fixed_value_comparator(self, num_state_qubits, value, geq): """Test the fixed value comparator circuit.""" # build the circuit with the comparator comp = IntegerComparator(num_state_qubits, value, geq=geq) self.assertComparisonIsCorrect(comp, num_state_qubits, value, geq)
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 in_progress_test_piecewise_transform(self): """Simple end-to-end test of the (semi-classical) multiply and add building block.""" import numpy as np import matplotlib.pyplot as plt from qiskit import execute, Aer, QuantumCircuit, QuantumRegister, ClassicalRegister, AncillaRegister from qiskit.aqua.algorithms import IterativeAmplitudeEstimation from qiskit.circuit.library import NormalDistribution, LogNormalDistribution, LinearAmplitudeFunction, IntegerComparator, WeightedAdder from qiskit.visualization import plot_histogram from quantum_mc.arithmetic import multiply_add qr_input = QuantumRegister(3, 'input') qr_result = QuantumRegister(6, 'result') qr_comp = QuantumRegister(2, 'comparisons') qr_ancilla = QuantumRegister(6, 'ancilla') qr_comp_anc = QuantumRegister(3, 'cond_ancilla') output = ClassicalRegister(6, 'output') circ = QuantumCircuit(qr_input, qr_result, qr_comp, qr_ancilla, qr_comp_anc, output) # our test piece-wise transforms: # trans0 if x <= 2, x => 6*x + 7 # trans1 if 2 < x <= 5, x => x + 17 # trans2 if x > 5, x => 3*x + 7 sigma = 1 low = -3 high = 3 mu = 0 normal = NormalDistribution(3, mu=mu, sigma=sigma**2, bounds=(low, high)) circ.append(normal, qr_input) comp0 = IntegerComparator(num_state_qubits=3, value=3, name="comparator0") # true if i >= point comp1 = IntegerComparator(num_state_qubits=3, value=6, name="comparator1") # true if i >= point trans0 = multiply_add.cond_classical_add_mult(6, 7, qr_input, qr_result, qr_ancilla) trans1 = multiply_add.cond_classical_add_mult(1, 17, qr_input, qr_result, qr_ancilla) trans2 = multiply_add.cond_classical_add_mult(3, 7, qr_input, qr_result, qr_ancilla) circ.append( comp0, qr_input[:] + [qr_comp[0]] + qr_ancilla[0:comp0.num_ancillas]) circ.append( comp1, qr_input[:] + [qr_comp[1]] + qr_ancilla[0:comp0.num_ancillas]) # use three additional ancillas to define the ranges circ.cx(qr_comp[0], qr_comp_anc[0]) circ.x(qr_comp_anc[0]) circ.cx(qr_comp[1], qr_comp_anc[2]) circ.x(qr_comp_anc[2]) circ.ccx(qr_comp[0], qr_comp_anc[2], qr_comp_anc[1]) circ.append(trans0, [qr_comp_anc[0]] + qr_input[:] + qr_result[:] + qr_ancilla[:]) circ.append(trans1, [qr_comp_anc[1]] + qr_input[:] + qr_result[:] + qr_ancilla[:]) circ.append(trans2, [qr_comp[1]] + qr_input[:] + qr_result[:] + qr_ancilla[:]) # can uncompute qr_comp_anc # then uncompute the comparators circ.measure(qr_result, output)