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