def test_fusion_default(self, method, device): """Test fusion threshsold""" shots = 100 num_qubits = 5 backend = self.backend(method=method, device=device) circuit = transpile(QFT(num_qubits), backend, optimization_level=0) if method == "unitary": circuit.save_unitary() elif method == "superop": circuit.save_superop() else: circuit.measure_all() backend.set_options(**self.fusion_options(enabled=True)) result = backend.run(circuit, shots=shots).result() expected_max_qubits = 5 expected_threshold = 14 if method == "density_matrix": expected_max_qubits = 2 expected_threshold = 7 elif method == "unitary": expected_max_qubits = 5 expected_threshold = 7 elif method == "superop": expected_max_qubits = 2 expected_threshold = 7 meta = result.results[0].metadata.get('fusion', None) self.assertEqual(meta.get('max_fused_qubits', None), expected_max_qubits) self.assertEqual(meta.get('threshold', None), expected_threshold)
def test_fusion_qft(self): """Test Fusion with qft""" shots = 100 num_qubits = 8 backend = self.backend(method="statevector") circuit = transpile(QFT(num_qubits), backend, optimization_level=0) circuit.measure_all() options_disabled = self.fusion_options(enabled=False, threshold=1) result_disabled = backend.run(circuit, shots=shots, **options_disabled).result() meta_disabled = self.fusion_metadata(result_disabled) options_enabled = self.fusion_options(enabled=True, threshold=1) result_enabled = backend.run(circuit, shots=shots, **options_enabled).result() meta_enabled = self.fusion_metadata(result_enabled) self.assertTrue(getattr(result_disabled, 'success', 'False')) self.assertTrue(getattr(result_enabled, 'success', 'False')) self.assertFalse(meta_disabled.get('enabled')) self.assertTrue(meta_enabled.get('enabled')) self.assertTrue(meta_enabled.get('applied')) self.assertDictAlmostEqual(result_enabled.get_counts(circuit), result_disabled.get_counts(circuit), delta=0.0, msg="fusion for qft was failed")
def __init__( self, num_eval_qubits: int, a_factory: Optional[CircuitFactory] = None, q_factory: Optional[CircuitFactory] = None, i_objective: Optional[int] = None, iqft: Optional[QuantumCircuit] = None, quantum_instance: Optional[Union[QuantumInstance, BaseBackend]] = None ) -> None: r""" Args: num_eval_qubits: Number of evaluation qubits, has a min. value of 1. a_factory: The CircuitFactory subclass object representing the problem unitary. q_factory: The CircuitFactory subclass object representing an amplitude estimation sample (based on a_factory). i_objective: The index of the objective qubit, i.e. the qubit marking 'good' solutions with the state \|1> and 'bad' solutions with the state \|0>. iqft: The Inverse Quantum Fourier Transform component, defaults to using a standard IQFT when None quantum_instance: Quantum Instance or Backend """ validate_min('num_eval_qubits', num_eval_qubits, 1) super().__init__(a_factory, q_factory, i_objective, quantum_instance) # get parameters self._m = num_eval_qubits self._M = 2**num_eval_qubits self._iqft = iqft or QFT(self._m).inverse() self._circuit = None self._ret = {} # type: Dict[str, Any]
def test_fusion_threshold(self, method, device): """Test fusion threshsold""" shots = 100 num_qubits = 5 backend = self.backend(method=method, device=device) circuit = transpile(QFT(num_qubits), backend, optimization_level=0) circuit.measure_all() with self.subTest(msg='at threshold'): backend.set_options( **self.fusion_options(enabled=True, threshold=num_qubits)) result = backend.run(circuit, shots=shots).result() self.assertSuccess(result) meta = self.fusion_metadata(result) self.assertTrue(meta.get('enabled')) self.assertFalse(meta.get('applied')) with self.subTest(msg='below threshold'): backend.set_options( **self.fusion_options(enabled=True, threshold=num_qubits + 1)) result = backend.run(circuit, shots=shots).result() self.assertSuccess(result) meta = self.fusion_metadata(result) self.assertTrue(meta.get('enabled')) self.assertFalse(meta.get('applied')) with self.subTest(msg='above threshold'): backend.set_options( **self.fusion_options(enabled=True, threshold=num_qubits - 1)) result = backend.run(circuit, shots=shots).result() self.assertSuccess(result) meta = self.fusion_metadata(result) self.assertTrue(meta.get('enabled')) self.assertTrue(meta.get('applied'))
def aqft(n_qubits, n_circuits): approximation_degree = int(math.log(n_qubits, 2) + 2) return [ QFT(num_qubits=n_qubits, approximation_degree=n_qubits - approximation_degree, do_swaps=False) for i in range(n_circuits) ], n_circuits
def create_eigs(matrix, num_ancillae, num_time_slices, negative_evals): ne_qfts = [None, None] if negative_evals: num_ancillae += 1 ne_qfts = [QFT(num_ancillae - 1), QFT(num_ancillae - 1).inverse()] ret = EigsQPE(MatrixOperator(matrix=matrix), QFT(num_ancillae).inverse(), num_time_slices=num_time_slices, num_ancillae=num_ancillae, expansion_mode='suzuki', expansion_order=2, evo_time=None, # This is t, can set to: np.pi*3/4 negative_evals=negative_evals, ne_qfts=ne_qfts) #print(ret.construct_circuit(mode='circuit')) return ret
def test_chunk_QFTWithFusion(self): """Test multi-chunk with fused QFT (testing multi-chunk diagonal matrix)""" shots = 100 num_qubits = 8 backend_options = self.BACKEND_OPTS.copy() backend_options['fusion_enable'] = True backend_options['fusion_threshold'] = 5 backend_options["blocking_qubits"] = 4 backend_options_no_chunk = self.BACKEND_OPTS.copy() backend_options_no_chunk.pop("blocking_enable") backend_options_no_chunk.pop("blocking_qubits") backend_options_no_chunk['fusion_enable'] = True backend_options_no_chunk['fusion_threshold'] = 5 circuit = transpile(QFT(num_qubits), backend=self.SIMULATOR, optimization_level=0) circuit.measure_all() qobj = assemble(circuit, shots=shots, memory=True) result = self.SIMULATOR.run(qobj, **backend_options_no_chunk).result() counts_no_chunk = result.get_counts(circuit) result = self.SIMULATOR.run(qobj, **backend_options).result() counts = result.get_counts(circuit) self.assertEqual(counts_no_chunk,counts)
def _construct_circuit(self, a: int, N: int, n: int, measurement: bool) -> QuantumCircuit: x_qreg = QuantumRegister(2 * n, 'x') y_qreg = QuantumRegister(n, 'y') aux_qreg = AncillaRegister(self._get_aux_register_size(n), 'aux') circuit = QuantumCircuit(x_qreg, y_qreg, aux_qreg, name=self._get_name(a, N)) circuit.h(x_qreg) circuit.x(y_qreg[0]) modular_exponentiation_gate = self._modular_exponentiation_gate( a, N, n) circuit.append(modular_exponentiation_gate, circuit.qubits) iqft = QFT(len(x_qreg)).inverse().to_gate() circuit.append(iqft, x_qreg) if measurement: x_creg = ClassicalRegister(2 * n, name='xValue') circuit.add_register(x_creg) circuit.measure(x_qreg, x_creg) return circuit
def test_fusion_qft(self): """Test Fusion with qft""" shots = 100 num_qubits = 8 circuit = transpile(QFT(num_qubits), backend=self.SIMULATOR, basis_gates=['u1', 'u2', 'u3', 'cx', 'cz'], optimization_level=0) circuit.measure_all() qobj = assemble([circuit], self.SIMULATOR, shots=shots, seed_simulator=1) backend_options = self.fusion_options(enabled=False, threshold=1) result_disabled = self.SIMULATOR.run(qobj, **backend_options).result() meta_disabled = self.fusion_metadata(result_disabled) backend_options = self.fusion_options(enabled=True, threshold=1) result_enabled = self.SIMULATOR.run(qobj, **backend_options).result() meta_enabled = self.fusion_metadata(result_enabled) self.assertTrue(getattr(result_disabled, 'success', 'False')) self.assertTrue(getattr(result_enabled, 'success', 'False')) self.assertFalse(meta_disabled.get('enabled')) self.assertTrue(meta_enabled.get('enabled')) self.assertTrue(meta_enabled.get('applied')) self.assertDictAlmostEqual(result_enabled.get_counts(circuit), result_disabled.get_counts(circuit), delta=0.0, msg="fusion for qft was failed")
class BeauregardShor(Shor): 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 _get_aux_register_size(self, n: int) -> int: return n + 2 @property def _prefix(self) -> str: return 'Beauregard' def _modular_exponentiation_gate(self, constant: int, N: int, n: int) -> Instruction: return modular_exponentiation_gate(constant, N, n) def _modular_multiplication_gate(self, constant: int, N: int, n: int) -> Instruction: return controlled_modular_multiplication_gate(constant, N, n, self._c_phi_add_N, self._iphi_add_N, self._qft, self._iqft)
def create_eigs(matrix, num_auxiliary, num_time_slices, negative_evals): ne_qfts = [None, None] if negative_evals: num_auxiliary += 1 ne_qfts = [QFT(num_auxiliary - 1), QFT(num_auxiliary - 1).inverse()] return EigsQPE( MatrixOperator(matrix=matrix), QFT(num_auxiliary).inverse(), num_time_slices=num_time_slices, num_ancillae=num_auxiliary, expansion_mode='suzuki', expansion_order=2, evo_time=None, # This is t, can set to: np.pi*3/4 negative_evals=negative_evals, ne_qfts=ne_qfts)
def test_initialize_qft(self): """Test that initialize with a complex statevector and qft work.""" k = 5 state = (1 / np.sqrt(8)) * np.array([ np.exp(-1j * 2 * np.pi * k * (0) / 8), np.exp(-1j * 2 * np.pi * k * (1) / 8), np.exp(-1j * 2 * np.pi * k * (2) / 8), np.exp(-1j * 2 * np.pi * k * 3 / 8), np.exp(-1j * 2 * np.pi * k * 4 / 8), np.exp(-1j * 2 * np.pi * k * 5 / 8), np.exp(-1j * 2 * np.pi * k * 6 / 8), np.exp(-1j * 2 * np.pi * k * 7 / 8), ]) qubits = 3 qc = QuantumCircuit(qubits, qubits) qc.initialize(state) qc.append(QFT(qubits), range(qubits)) qc.measure(range(qubits), range(qubits)) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ) self.assertEqual([x[0].label for x in qc.data], [x[0].label for x in new_circ.data])
def test_qft_num_gates(self, num_qubits, approximation_degree, insert_barriers): """Test the number of gates in the QFT and the approximated QFT.""" basis_gates = ['h', 'swap', 'cu1'] qft = QFT(num_qubits, approximation_degree=approximation_degree, insert_barriers=insert_barriers) ops = transpile(qft, basis_gates=basis_gates).count_ops() with self.subTest(msg='assert H count'): self.assertEqual(ops['h'], num_qubits) with self.subTest(msg='assert swap count'): self.assertEqual(ops['swap'], num_qubits // 2) with self.subTest(msg='assert CU1 count'): expected = sum( max( 0, min(num_qubits - 1 - k, num_qubits - 1 - approximation_degree)) for k in range(num_qubits)) self.assertEqual(ops.get('cu1', 0), expected) with self.subTest(msg='assert barrier count'): expected = qft.num_qubits if insert_barriers else 0 self.assertEqual(ops.get('barrier', 0), expected)
def test_qae_circuit(self, efficient_circuit): """Test circuits resulting from canonical amplitude estimation. Build the circuit manually and from the algorithm and compare the resulting unitaries. """ prob = 0.5 for m in [2, 5]: qae = AmplitudeEstimation(m, BernoulliStateIn(prob)) angle = 2 * np.arcsin(np.sqrt(prob)) # manually set up the inefficient AE circuit qr_eval = QuantumRegister(m, 'a') qr_objective = QuantumRegister(1, 'q') circuit = QuantumCircuit(qr_eval, qr_objective) # initial Hadamard gates for i in range(m): circuit.h(qr_eval[i]) # A operator circuit.ry(angle, qr_objective) if efficient_circuit: qae.grover_operator = BernoulliGrover(prob) for power in range(m): circuit.cry(2 * 2**power * angle, qr_eval[power], qr_objective[0]) else: oracle = QuantumCircuit(1) oracle.z(0) state_preparation = QuantumCircuit(1) state_preparation.ry(angle, 0) grover_op = GroverOperator(oracle, state_preparation) for power in range(m): circuit.compose(grover_op.power(2**power).control(), qubits=[qr_eval[power], qr_objective[0]], inplace=True) # fourier transform iqft = QFT(m, do_swaps=False).inverse().reverse_bits() circuit.append(iqft.to_instruction(), qr_eval) actual_circuit = qae.construct_circuit(measurement=False) self.assertEqual(Operator(circuit), Operator(actual_circuit))
def __init__(self, N: int = 15, a: int = 2, quantum_instance: Optional[Union[QuantumInstance, BaseBackend]] = None, job_id=None) -> None: """ Args: N: The integer to be factored, has a min. value of 3. a: A random integer that satisfies a < N and gcd(a, N) = 1, has a min. value of 2. quantum_instance: Quantum Instance or Backend Raises: ValueError: Invalid input """ validate_min('N', N, 3) validate_min('a', a, 2) super().__init__(quantum_instance) self.job_id = job_id self._n = None self._up_qreg = None self._down_qreg = None self._aux_qreg = None # check the input integer if N < 1 or N % 2 == 0: raise ValueError( 'The input needs to be an odd integer greater than 1.') self._N = N if a >= N or math.gcd(a, self._N) != 1: raise ValueError( 'The integer a needs to satisfy a < N and gcd(a, N) = 1.') self._a = a self._ret = {'factors': []} # check if the input integer is a power tf, b, p = is_power(N, return_decomposition=True) if tf: logger.info('The input integer is a power: %s=%s^%s.', N, b, p) self._ret['factors'].append(b) self._qft = QFT(do_swaps=False) self._iqft = self._qft.inverse()
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 self._qft_dag = circuit_to_dag(self._qft) self._iqft_dag = circuit_to_dag(self._iqft) # 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) # 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]) tdags = [] dag_self = circuit_to_dag(circuit) # Apply the multiplication gates as showed in # the report in order to create the exponentiation for i in range(0, 2 * self._n): tdags += self._controlled_multiple_mod_N_tdags( self._up_qreg[i], self._down_qreg, self._aux_qreg, int(pow(self._a, pow(2, i)))) for tdag in tdags: dag_compose_with_tagged(dag_self, tdag) composed_circuit = dag_to_circuit(dag_self) circuit.__dict__.update(composed_circuit.__dict__) # Apply inverse QFT iqft = QFT(len(self._up_qreg), inverse=True) circuit.compose(iqft, qubits=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 test_qae_circuit(self, efficient_circuit): """Test circuits resulting from canonical amplitude estimation. Build the circuit manually and from the algorithm and compare the resulting unitaries. """ prob = 0.5 for m in range(2, 7): qae = AmplitudeEstimation(m, a_factory=BernoulliAFactory(prob)) angle = 2 * np.arcsin(np.sqrt(prob)) # manually set up the inefficient AE circuit q_ancilla = QuantumRegister(m, 'a') q_objective = QuantumRegister(1, 'q') circuit = QuantumCircuit(q_ancilla, q_objective) # initial Hadamard gates for i in range(m): circuit.h(q_ancilla[i]) # A operator circuit.ry(angle, q_objective) if efficient_circuit: qae.q_factory = BernoulliQFactory(qae.a_factory) for power in range(m): circuit.cry(2 * 2 ** power * angle, q_ancilla[power], q_objective[0]) else: q_factory = QFactory(qae.a_factory, i_objective=0) for power in range(m): for _ in range(2**power): q_factory.build_controlled(circuit, q_objective, q_ancilla[power]) # fourier transform iqft = QFT(m, do_swaps=False).inverse() circuit.append(iqft.to_instruction(), q_ancilla) expected_unitary = self._unitary.execute(circuit).get_unitary() actual_circuit = qae.construct_circuit(measurement=False) actual_unitary = self._unitary.execute(actual_circuit).get_unitary() diff = np.sum(np.abs(actual_unitary - expected_unitary)) self.assertAlmostEqual(diff, 0)
def test_fusion_theshold(self): """Test fusion threhsold""" shots = 100 threshold = 6 backend_options = self.fusion_options(enabled=True, threshold=threshold) with self.subTest(msg='below fusion threshold'): circuit = transpile(QFT(threshold - 1), self.SIMULATOR, basis_gates=['u1', 'u2', 'u3', 'cx', 'cz'], optimization_level=0) circuit.measure_all() qobj = assemble(circuit, self.SIMULATOR, shots=shots) result = self.SIMULATOR.run(qobj, **backend_options).result() self.assertSuccess(result) meta = self.fusion_metadata(result) self.assertTrue(meta.get('enabled')) self.assertFalse(meta.get('applied')) with self.subTest(msg='at fusion threshold'): circuit = transpile(QFT(threshold), self.SIMULATOR, basis_gates=['u1', 'u2', 'u3', 'cx', 'cz'], optimization_level=0) circuit.measure_all() qobj = assemble(circuit, self.SIMULATOR, shots=shots) result = self.SIMULATOR.run(qobj, **backend_options).result() self.assertSuccess(result) meta = self.fusion_metadata(result) self.assertTrue(meta.get('enabled')) self.assertFalse(meta.get('applied')) with self.subTest(msg='above fusion threshold'): circuit = transpile(QFT(threshold + 1), self.SIMULATOR, basis_gates=['u1', 'u2', 'u3', 'cx', 'cz'], optimization_level=0) circuit.measure_all() qobj = assemble(circuit, self.SIMULATOR, shots=shots) result = self.SIMULATOR.run(qobj, **backend_options).result() self.assertSuccess(result) meta = self.fusion_metadata(result) self.assertTrue(meta.get('enabled')) self.assertTrue(meta.get('applied'))
def test_drawings(self): """Test draw method""" qc1 = QFT(5) sv = Statevector.from_instruction(qc1) with self.subTest(msg="str(statevector)"): str(sv) for drawtype in ["repr", "text", "latex", "latex_source", "qsphere", "hinton", "bloch"]: with self.subTest(msg=f"draw('{drawtype}')"): sv.draw(drawtype)
def test_drawings(self): """Test draw method""" qc1 = QFT(5) dm = DensityMatrix.from_instruction(qc1) with self.subTest(msg="str(density_matrix)"): str(dm) for drawtype in ["repr", "text", "latex", "latex_source", "qsphere", "hinton", "bloch"]: with self.subTest(msg=f"draw('{drawtype}')"): dm.draw(drawtype)
def test_save_amplitudes_cache_blocking(self, method, device, params): """Test save_amplitudes instruction""" self._test_save_amplitudes(QFT(3), params, False, method=method, device=device, blocking_qubits=2, max_parallel_threads=1)
def construct_circuit(circuit=None, qubits=None, inverse=False, approximation_degree=0, do_swaps=True): """Construct the circuit representing the desired state vector. Args: circuit (QuantumCircuit): The optional circuit to extend from. qubits (Union(QuantumRegister, list[Qubit])): The optional qubits to construct the circuit with. approximation_degree (int): degree of approximation for the desired circuit inverse (bool): Boolean flag to indicate Inverse Quantum Fourier Transform do_swaps (bool): Boolean flag to specify if swaps should be included to align the qubit order of input and output. The output qubits would be in reversed order without the swaps. Returns: QuantumCircuit: quantum circuit Raises: AquaError: invalid input """ warnings.warn( 'The class FourierTransformCircuits is deprecated and will be removed ' 'no earlier than 3 months after the release 0.7.0. You should use the ' 'qiskit.circuit.library.QFT class instead.', DeprecationWarning, stacklevel=2) if circuit is None: raise AquaError('Missing input QuantumCircuit.') if qubits is None: raise AquaError('Missing input qubits.') qft = QFT(len(qubits), approximation_degree=approximation_degree, do_swaps=do_swaps) if inverse: qft = qft.inverse() circuit.append(qft.to_instruction(), qubits) return circuit
def _build_operator( self, func_dict: Dict[Union[int, Tuple[int, int]], int]) -> QuantumCircuit: """Creates a circuit for the state preparation operator. Args: func_dict: Representation of the QUBO problem. The keys should be subscripts of the coefficients (e.g. x_1 -> 1), with the constant (if present) being represented with a key of -1 (i.e. d[-1] = constant). Quadratic coefficients should use a tuple for the key, with the corresponding subscripts inside (e.g. 2*x_1*x_2 -> d[(1,2)]=2). Returns: Circuit object describing the state preparation operator. """ # Build initial circuit. key_val = QuantumRegister(self._num_key + self._num_value, "key_value") circuit = QuantumCircuit(key_val) if self._measurement: measure = ClassicalRegister(self._num_key + self._num_value) circuit.add_register(measure) circuit.h(key_val) # Linear Coefficients. for i in range(self._num_value): if func_dict.get(-1, 0) != 0: circuit.u1( 1 / 2**self._num_value * 2 * np.pi * 2**i * func_dict[-1], key_val[self._num_key + i]) for j in range(self._num_key): if func_dict.get(j, 0) != 0: circuit.cu1( 1 / 2**self._num_value * 2 * np.pi * 2**i * func_dict[j], key_val[j], key_val[self._num_key + i]) # Quadratic Coefficients. for i in range(self._num_value): for k, v in func_dict.items(): if isinstance(k, tuple): a_v = [key_val[int(k[0])], key_val[int(k[1])]] b_v = key_val[self._num_key + i] circuit.mcu1(1 / 2**self._num_value * 2 * np.pi * 2**i * v, a_v, b_v) # Add IQFT. Adding swaps at the end of the IQFT, not the beginning. iqft = QFT(self._num_value, do_swaps=False).inverse() value = [ key_val[v] for v in range(self._num_key, self._num_key + self._num_value) ] circuit.compose(iqft, qubits=value, inplace=True) for i in range(len(value) // 2): circuit.swap(value[i], value[-(i + 1)]) return circuit
def test_drawings(self): """Test draw method""" qc1 = QFT(5) dm = DensityMatrix.from_instruction(qc1) with self.subTest(msg='str(density_matrix)'): str(dm) for drawtype in ['repr', 'text', 'latex', 'latex_source', 'qsphere', 'hinton', 'bloch']: with self.subTest(msg=f"draw('{drawtype}')"): dm.draw(drawtype)
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 test_qpe(self, qubit_op, simulator, num_time_slices, n_ancillae): """Test the QPE algorithm.""" self.log.debug('Testing QPE') qubit_op = self._dict[qubit_op] exact_eigensolver = NumPyMinimumEigensolver(qubit_op) results = exact_eigensolver.run() ref_eigenval = results.eigenvalue ref_eigenvec = results.eigenstate self.log.debug('The exact eigenvalue is: %s', ref_eigenval) self.log.debug('The corresponding eigenvector: %s', ref_eigenvec) state_in = Custom(qubit_op.num_qubits, state_vector=ref_eigenvec) iqft = QFT(n_ancillae).inverse() qpe = QPE(qubit_op, state_in, iqft, num_time_slices, n_ancillae, expansion_mode='suzuki', expansion_order=2, shallow_circuit_concat=True) backend = BasicAer.get_backend(simulator) quantum_instance = QuantumInstance(backend, shots=100, seed_transpiler=1, seed_simulator=1) # run qpe result = qpe.run(quantum_instance) # report result self.log.debug('top result str label: %s', result.top_measurement_label) self.log.debug('top result in decimal: %s', result.top_measurement_decimal) self.log.debug('stretch: %s', result.stretch) self.log.debug('translation: %s', result.translation) self.log.debug('final eigenvalue from QPE: %s', result.eigenvalue) self.log.debug('reference eigenvalue: %s', ref_eigenval) self.log.debug('ref eigenvalue (transformed): %s', (ref_eigenval + result.translation) * result.stretch) self.log.debug( 'reference binary str label: %s', decimal_to_binary( (ref_eigenval.real + result.translation) * result.stretch, max_num_digits=n_ancillae + 3, fractional_part_only=True)) self.assertAlmostEqual(result.eigenvalue.real, ref_eigenval.real, delta=2e-2)
def test_drawings(self): """Test draw method""" qc1 = QFT(5) sv = Statevector.from_instruction(qc1) with self.subTest(msg='str(statevector)'): str(sv) for drawtype in [ 'text', 'latex', 'latex_source', 'qsphere', 'hinton', 'bloch' ]: with self.subTest(msg=f"draw('{drawtype}')"): sv.draw(drawtype)
def _create_eigs(matrix, num_ancillae, negative_evals): # Adding an additional flag qubit for negative eigenvalues ne_qfts = [None, None] if negative_evals: num_ancillae += 1 ne_qfts = [QFT(num_ancillae - 1), QFT(num_ancillae - 1).inverse()] iqft = QFT(num_ancillae).inverse() eigs_qpe = EigsQPE(MatrixOperator(matrix=matrix), iqft, num_time_slices=1, num_ancillae=num_ancillae, expansion_mode='suzuki', expansion_order=2, evo_time=None, negative_evals=negative_evals, ne_qfts=ne_qfts) return eigs_qpe
def _create_eigs(matrix, num_ancillae, negative_evals, use_circuit_library=True): # Adding an additional flag qubit for negative eigenvalues ne_qfts = [None, None] if not use_circuit_library: warnings.filterwarnings('ignore', category=DeprecationWarning) if negative_evals: num_ancillae += 1 if use_circuit_library: ne_qfts = [ QFT(num_ancillae - 1), QFT(num_ancillae - 1).inverse() ] else: ne_qfts = [ StandardQFTS(num_ancillae - 1), StandardIQFTS(num_ancillae - 1) ] if use_circuit_library: iqft = QFT(num_ancillae).inverse() else: iqft = StandardIQFTS(num_ancillae) eigs_qpe = EigsQPE(MatrixOperator(matrix=matrix), iqft, num_time_slices=1, num_ancillae=num_ancillae, expansion_mode='suzuki', expansion_order=2, evo_time=None, negative_evals=negative_evals, ne_qfts=ne_qfts) if not use_circuit_library: warnings.filterwarnings('always', category=DeprecationWarning) return eigs_qpe
def modular_exponentiation_gate(constant: int, N: int, n: int) -> Gate: x_qreg = QuantumRegister(2 * n, name='x') y_qreg = QuantumRegister(n, name='y') aux_qreg = QuantumRegister(n + 1, name='aux') circuit = QuantumCircuit(x_qreg, y_qreg, aux_qreg, name=f'Exp({constant})_Mod_{N}') qft = QFT(n, do_swaps=False).to_gate() iqft = qft.inverse() for i in range(2 * n): partial_constant = pow(constant, pow(2, i), mod=N) circuit.append( controlled_modular_multiplication_gate(partial_constant, N, n, qft, iqft), list(chain([x_qreg[i]], y_qreg, aux_qreg)) ) return circuit.to_gate()