def _double_controlled_modular_adder(constant: int, N: int, n: int, qft: Gate, iqft: Gate) -> Gate: ctrl_qreg = QuantumRegister(2, name='ctrl') x_qreg = QuantumRegister(n, name='x') g_qreg = QuantumRegister(n - 1 if n >= 2 else 1, name='g') flag_qreg = QuantumRegister(1, name='flag') circuit = QuantumCircuit(ctrl_qreg, x_qreg, g_qreg, flag_qreg, name=f'CC-MA_({constant})_Mod_{N}') adder_regs = list(chain(flag_qreg, x_qreg)) circuit.append(double_controlled_comparator(N - constant, n), circuit.qubits) circuit.append(qft, x_qreg) circuit.append( phi_constant_adder(get_angles(constant, n)).control(1), adder_regs) circuit.ccx(ctrl_qreg[0], ctrl_qreg[1], flag_qreg[0]) circuit.append( phi_constant_adder(get_angles(N - constant, n)).control(1).inverse(), adder_regs) circuit.append(iqft, x_qreg) circuit.append(double_controlled_comparator(constant, n), circuit.qubits) return circuit.to_gate()
def _construct_circuit_with_semiclassical_QFT(self, a: int, N: int, n: int) -> QuantumCircuit: self._qft = QFT(n + 1, do_swaps=False).to_gate() self._iqft = self._qft.inverse() phi_add_N = phi_constant_adder(get_angles(N, n + 1)) self._iphi_add_N = phi_add_N.inverse() self._c_phi_add_N = phi_add_N.control(1) return super()._construct_circuit_with_semiclassical_QFT(a, N, n)
def modular_exponentiation_gate(constant: int, N: int, n: int) -> Instruction: up_qreg = QuantumRegister(2 * n, name='up') down_qreg = QuantumRegister(n, name='down') aux_qreg = QuantumRegister(n + 2, name='aux') circuit = QuantumCircuit(up_qreg, down_qreg, aux_qreg, name=f'{constant}^x mod {N}') qft = QFT(n + 1, do_swaps=False).to_gate() iqft = qft.inverse() phi_add_N = phi_constant_adder(get_angles(N, n + 1)) iphi_add_N = phi_add_N.inverse() c_phi_add_N = phi_add_N.control(1) for i in range(2 * n): partial_constant = pow(constant, pow(2, i), mod=N) modulo_multiplier = controlled_modular_multiplication_gate( partial_constant, N, n, c_phi_add_N, iphi_add_N, qft, iqft) circuit.append(modulo_multiplier, [up_qreg[i], *down_qreg, *aux_qreg]) return circuit.to_instruction()
def append_adder(adder: QuantumCircuit, constant: int, idx: int): partial_constant = (pow(2, idx, mod=N) * constant) % N angles = get_angles(partial_constant, n + 1) bound = adder.assign_parameters({angle_params: angles}) circuit.append(bound, [*ctrl_qreg, x_qreg[idx], *b_qreg, *flag_qreg])