def construct_circuit(self, N: int, a: int = 2, measurement: bool = False) -> QuantumCircuit: """Construct quantum part of the algorithm. Args: N: The odd integer to be factored, has a min. value of 3. a: Any integer that satisfies 1 < a < N and gcd(a, N) = 1. measurement: Boolean flag to indicate if measurement should be included in the circuit. Returns: Quantum circuit. """ self._validate_input(N, a) # Get n value used in Shor's algorithm, to know how many qubits are used n = N.bit_length() # quantum register where the sequential QFT is performed up_qreg = QuantumRegister(2 * n, name="up") # quantum register where the multiplications are made down_qreg = QuantumRegister(n, name="down") # auxiliary quantum register used in addition and multiplication aux_qreg = QuantumRegister(n + 2, name="aux") # Create Quantum Circuit circuit = QuantumCircuit(up_qreg, down_qreg, aux_qreg, name=f"Shor(N={N}, a={a})") # Create maximal superposition in top register circuit.h(up_qreg) # Initialize down register to 1 circuit.x(down_qreg[0]) # Apply modulo exponentiation modulo_power = self._power_mod_N(n, N, a) circuit.append(modulo_power, circuit.qubits) # Apply inverse QFT iqft = QFT(len(up_qreg)).inverse().to_gate() circuit.append(iqft, up_qreg) if measurement: up_cqreg = ClassicalRegister(2 * n, name="m") circuit.add_register(up_cqreg) circuit.measure(up_qreg, up_cqreg) logger.info(summarize_circuits(circuit)) return circuit
def construct_circuit(self, N: int, a: int = 2, measurement: bool = False) -> QuantumCircuit: """Construct circuit. Args: N: The integer to be factored, has a min. value of 3. a: Any integer that satisfies 1 < a < N and gcd(a, N) = 1. measurement: Boolean flag to indicate if measurement should be included in the circuit. Returns: Quantum circuit. Raises: ValueError: Invalid N """ validate_min('N', N, 3) validate_min('a', a, 2) # check the input integer if N < 1 or N % 2 == 0: raise ValueError( 'The input needs to be an odd integer greater than 1.') if a >= N or math.gcd(a, N) != 1: raise ValueError( 'The integer a needs to satisfy a < N and gcd(a, N) = 1.') # Get n value used in Shor's algorithm, to know how many qubits are used self._n = math.ceil(math.log(N, 2)) self._qft.num_qubits = self._n + 1 self._iqft.num_qubits = self._n + 1 # 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') # auxiliary 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, name="Shor(N={}, a={})".format(N, a)) # Create gates to perform addition/subtraction by N in Fourier Space self._phi_add_N = self._phi_add_gate(self._aux_qreg.size - 1, self._get_angles(N)) self._iphi_add_N = self._phi_add_N.inverse() # Create maximal superposition in top register circuit.h(self._up_qreg) # Initialize down register to 1 circuit.x(self._down_qreg[0]) # Apply the multiplication gates as showed in # the report in order to create the exponentiation for i, ctl_up in enumerate(self._up_qreg): # type: ignore a = int(pow(a, pow(2, i))) controlled_multiple_mod_N = self._controlled_multiple_mod_N( len(self._down_qreg) + len(self._aux_qreg) + 1, N, a, ) circuit.append(controlled_multiple_mod_N, [ctl_up, *self._down_qreg, *self._aux_qreg]) # Apply inverse QFT iqft = QFT(len(self._up_qreg)).inverse().to_instruction() circuit.append(iqft, self._up_qreg) if measurement: up_cqreg = ClassicalRegister(2 * self._n, name='m') circuit.add_register(up_cqreg) circuit.measure(self._up_qreg, up_cqreg) logger.info(summarize_circuits(circuit)) return circuit
def construct_circuit(self, measurement: bool = False) -> QuantumCircuit: """Construct circuit. Args: measurement: Boolean flag to indicate if measurement should be included in the circuit. Returns: 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)) self._qft.num_qubits = self._n + 1 self._iqft.num_qubits = self._n + 1 # 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') # auxiliary 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, name="Shor(N={}, a={})".format( self._N, self._a)) # Create gates to perform addition/subtraction by N in Fourier Space self._phi_add_N = self._phi_add_gate(self._aux_qreg.size - 1, self._get_angles(self._N)) self._iphi_add_N = self._phi_add_N.inverse() # Create maximal superposition in top register circuit.h(self._up_qreg) # Initialize down register to 1 circuit.x(self._down_qreg[0]) # Apply the multiplication gates as showed in # the report in order to create the exponentiation for i, ctl_up in enumerate(self._up_qreg): # type: ignore a = int(pow(self._a, pow(2, i))) controlled_multiple_mod_N = self._controlled_multiple_mod_N( len(self._down_qreg) + len(self._aux_qreg) + 1, a, ) circuit.append(controlled_multiple_mod_N, [ctl_up, *self._down_qreg, *self._aux_qreg]) # Apply inverse QFT iqft = QFT(len(self._up_qreg)).inverse().to_instruction() circuit.append(iqft, self._up_qreg) if measurement: up_cqreg = ClassicalRegister(2 * self._n, name='m') circuit.add_register(up_cqreg) circuit.measure(self._up_qreg, up_cqreg) logger.info(summarize_circuits(circuit)) return circuit