def construct_circuit(self, measurement=False): """Construct circuit. Args: measurement (bool): Boolean flag to indicate if measurement should be included in the circuit. Returns: QuantumCircuit: quantum circuit. """ breakpoints = [] # Get n value used in Shor's algorithm, to know how many qubits are used self._n = math.ceil(math.log(self._N, 2)) # quantum register where the sequential QFT is performed self._up_qreg = QuantumRegister(2 * self._n, name='up') # quantum register where the multiplications are made self._down_qreg = QuantumRegister(self._n, name='down') # auxilliary quantum register used in addition and multiplication self._aux_qreg = QuantumRegister(self._n + 2, name='aux') up_cqreg = ClassicalRegister(2 * self._n, name='m_up') down_cqreg = ClassicalRegister(self._n, name='m_down') # Create Quantum Circuit circuit = QuantumCircuit(self._up_qreg, self._down_qreg, self._aux_qreg, up_cqreg, down_cqreg) # Initialize down register to 1 and create maximal superposition in top register circuit.u2(0, np.pi, self._up_qreg) circuit.u3(np.pi, 0, np.pi, self._down_qreg[0]) # validate maximal superposition in top register breakpoints.append(circuit.get_breakpoint_uniform(self._up_qreg, up_cqreg, 0.05)) # validate initialize down register to 1 breakpoints.append(circuit.get_breakpoint_classical(self._down_qreg, down_cqreg, 0.05, 1)) # Apply the multiplication gates as showed in the report in order to create the exponentiation for i in range(0, 2 * self._n): self._controlled_multiple_mod_N( circuit, self._up_qreg[i], self._down_qreg, self._aux_qreg, int(pow(self._a, pow(2, i))) ) # Apply inverse QFT ftc.construct_circuit(circuit=circuit, qubits=self._up_qreg, do_swaps=True, inverse=True) # validate uncomputation is complete and registers are in product state breakpoints.append(circuit.get_breakpoint_product(self._up_qreg[:], up_cqreg[:], self._down_qreg[:], down_cqreg[:], .05)) if measurement: circuit.measure(self._up_qreg, up_cqreg) logger.info(summarize_circuits(circuit)) return breakpoints, circuit
def construct_circuit(self, mode, qubits=None, circuit=None): if mode == 'vector': # note the difference between QFT and DFT in the phase definition: # QFT: \omega = exp(2*pi*i/N) ; DFT: \omega = exp(-2*pi*i/N) # so linalg.inv(linalg.dft()) is correct for QFT return linalg.inv(linalg.dft(2 ** self._num_qubits, scale='sqrtn')) elif mode == 'circuit': ftc = FourierTransformCircuits(self._num_qubits, approximation_degree=0, inverse=False) return ftc.construct_circuit(qubits, circuit) else: raise ValueError('Mode should be either "vector" or "circuit"')
def construct_circuit(self, mode, qubits=None, circuit=None): if mode == 'vector': # TODO: implement vector mode for approximate iqft raise NotImplementedError() elif mode == 'circuit': ftc = FourierTransformCircuits(self._num_qubits, approximation_degree=self._degree, inverse=True) return ftc.construct_circuit(qubits, circuit) else: raise ValueError('Mode should be either "vector" or "circuit"')
def _controlled_controlled_phi_add_mod_N_inv(self, circuit, q, ctl1, ctl2, aux, a): """ Circuit that implements the inverse of doubly controlled modular addition by a """ self._controlled_controlled_phi_add(circuit, q, ctl1, ctl2, a, inverse=True) ftc.construct_circuit( circuit=circuit, qubits=[q[i] for i in reversed(range(self._n + 1))], do_swaps=False, inverse=True ) circuit.u3(np.pi, 0, np.pi, q[self._n]) circuit.cx(q[self._n], aux) circuit.u3(np.pi, 0, np.pi, q[self._n]) ftc.construct_circuit( circuit=circuit, qubits=[q[i] for i in reversed(range(self._n + 1))], do_swaps=False ) self._controlled_controlled_phi_add(circuit, q, ctl1, ctl2, a) self._controlled_phi_add(circuit, q, aux, inverse=True) ftc.construct_circuit( circuit=circuit, qubits=[q[i] for i in reversed(range(self._n + 1))], do_swaps=False, inverse=True ) circuit.cx(q[self._n], aux) ftc.construct_circuit( circuit=circuit, qubits=[q[i] for i in reversed(range(self._n + 1))], do_swaps=False ) self._phi_add(circuit, q) self._controlled_controlled_phi_add(circuit, q, ctl1, ctl2, a, inverse=True)
def _build_circuit(self, qubits=None, circuit=None, do_swaps=True): return ftc.construct_circuit( circuit=circuit, qubits=qubits, inverse=True, approximation_degree=self._degree, do_swaps=do_swaps )
def _controlled_multiple_mod_N(self, circuit, ctl, q, aux, a): """ Circuit that implements single controlled modular multiplication by a """ ftc.construct_circuit( circuit=circuit, qubits=[aux[i] for i in reversed(range(self._n + 1))], do_swaps=False) for i in range(0, self._n): self._controlled_controlled_phi_add_mod_N(circuit, aux, q[i], ctl, aux[self._n + 1], (2**i) * a % self._N) ftc.construct_circuit( circuit=circuit, qubits=[aux[i] for i in reversed(range(self._n + 1))], do_swaps=False, inverse=True) for i in range(0, self._n): circuit.cswap(ctl, q[i], aux[i]) def modinv(a, m): def egcd(a, b): if a == 0: return (b, 0, 1) else: g, y, x = egcd(b % a, a) return (g, x - (b // a) * y, y) g, x, _ = egcd(a, m) if g != 1: raise Exception('modular inverse does not exist') return x % m a_inv = modinv(a, self._N) ftc.construct_circuit( circuit=circuit, qubits=[aux[i] for i in reversed(range(self._n + 1))], do_swaps=False) for i in reversed(range(self._n)): self._controlled_controlled_phi_add_mod_N_inv( circuit, aux, q[i], ctl, aux[self._n + 1], math.pow(2, i) * a_inv % self._N) ftc.construct_circuit( circuit=circuit, qubits=[aux[i] for i in reversed(range(self._n + 1))], do_swaps=False, inverse=True)
def construct_circuit(self): """Construct circuit. Returns: QuantumCircuit: quantum circuit. """ # Get n value used in Shor's algorithm, to know how many qubits are used self._n = math.ceil(math.log(self._N, 2)) # quantum register where the sequential QFT is performed self._up_qreg = QuantumRegister(2 * self._n, name='up') # quantum register where the multiplications are made self._down_qreg = QuantumRegister(self._n, name='down') # auxilliary quantum register used in addition and multiplication self._aux_qreg = QuantumRegister(self._n + 2, name='aux') # Create Quantum Circuit circuit = QuantumCircuit(self._up_qreg, self._down_qreg, self._aux_qreg) # Initialize down register to 1 and create maximal superposition in top register circuit.u2(0, np.pi, self._up_qreg) circuit.u3(np.pi, 0, np.pi, self._down_qreg[0]) # Apply the multiplication gates as showed in the report in order to create the exponentiation for i in range(0, 2 * self._n): self._controlled_multiple_mod_N(circuit, self._up_qreg[i], self._down_qreg, self._aux_qreg, int(pow(self._a, pow(2, i)))) # Apply inverse QFT ftc.construct_circuit(circuit=circuit, qubits=self._up_qreg, do_swaps=True, inverse=True) logger.info(summarize_circuits(circuit)) return circuit
def applyIQFT_circuit(L: int, current_state: np.ndarray) -> np.ndarray: """ Apply IQFT on control register of current state and returns final state using qiskit circuit :param L: number of qubits in target register :param current_state: state to apply IQFT on :return: state after IQFT """ circuit = QuantumCircuit(3 * L) circuit.initialize(current_state.reshape(2**(3 * L)), circuit.qubits) circuit = QFT.construct_circuit(circuit=circuit, qubits=circuit.qubits[L:3 * L], inverse=True, do_swaps=True) backend = qt.Aer.get_backend('statevector_simulator') # backend = QCGPUProvider().get_backend('statevector_simulator') final_state = execute(circuit, backend, shots=1).result().get_statevector() return final_state