def test_mcu1(self, num_controls): c = QuantumRegister(num_controls, name='c') o = QuantumRegister(1, name='o') allsubsets = list( chain(*[ combinations(range(num_controls), ni) for ni in range(num_controls + 1) ])) for subset in allsubsets: qc = QuantumCircuit(o, c) for idx in subset: qc.x(c[idx]) qc.h(o[0]) qc.mcu1(pi, [c[i] for i in range(num_controls)], o[0]) qc.h(o[0]) for idx in subset: qc.x(c[idx]) vec = np.asarray( q_execute(qc, BasicAer.get_backend( 'statevector_simulator')).result().get_statevector( qc, decimals=16)) vec_o = [0, 1] if len(subset) == num_controls else [1, 0] # print(vec, np.array(vec_o + [0] * (2 ** (num_controls + num_ancillae + 1) - 2))) f = state_fidelity( vec, np.array(vec_o + [0] * (2**(num_controls + 1) - 2))) self.assertAlmostEqual(f, 1)
def execute(self, circuits): """ A wrapper for all algorithms to interface with quantum backend. Args: circuits (QuantumCircuit or list[QuantumCircuit]): circuits to execute Returns: Result or [Result]: Result objects it will be a list if number of circuits exceed the maximum number (300) """ if not isinstance(circuits, list): circuits = [circuits] jobs = [] chunks = int(np.ceil(len(circuits) / self.MAX_CIRCUITS_PER_JOB)) for i in range(chunks): sub_circuits = circuits[i * self.MAX_CIRCUITS_PER_JOB:(i + 1) * self.MAX_CIRCUITS_PER_JOB] jobs.append( q_execute(sub_circuits, self._backend, **self._execute_config)) if logger.isEnabledFor(logging.DEBUG): logger.debug(summarize_circuits(circuits)) results = [] for job in jobs: results.append(job.result(**self._qjob_config)) result = functools.reduce(lambda x, y: x + y, results) return result
def test_logic_expr_oracle(self, dimacs_str, sols, mct_mode, optimization): """ Logic Expr oracle test """ num_shots = 1024 leo = LogicalExpressionOracle(dimacs_str, optimization=optimization, mct_mode=mct_mode) leo_circuit = leo.circuit m = ClassicalRegister(1, name='m') for assignment in itertools.product([True, False], repeat=len(leo.variable_register)): qc = QuantumCircuit(m, leo.variable_register) for idx, t_f in enumerate(assignment): if t_f: qc.x(leo.variable_register[idx]) qc += leo_circuit qc.barrier(leo.output_register) qc.measure(leo.output_register, m) # print(qc.draw(line_length=10000)) counts = q_execute(qc, BasicAer.get_backend('qasm_simulator'), shots=num_shots).result().get_counts(qc) if assignment in sols: self.assertEqual(counts['1'], num_shots) else: self.assertEqual(counts['0'], num_shots)
def test_cnx(self, num_controls, num_ancillae): c = QuantumRegister(num_controls, name='c') o = QuantumRegister(1, name='o') a = QuantumRegister(num_ancillae, name='a') allsubsets = list(chain( *[combinations(range(num_controls), ni) for ni in range(num_controls + 1)])) for subset in allsubsets: qc = QuantumCircuit(o, c, a) for idx in subset: qc.x(c[idx]) qc.cnx( [c[i] for i in range(num_controls)], [a[i] for i in range(num_ancillae)], o[0] ) for idx in subset: qc.x(c[idx]) vec = np.asarray(q_execute(qc, qiskit.Aer.get_backend( 'statevector_simulator')).result().get_statevector(qc, decimals=16)) vec_o = [0, 1] if len(subset) == num_controls else [1, 0] np.testing.assert_almost_equal( vec, np.array(vec_o + [0] * (2 ** (num_controls + num_ancillae + 1) - 2)) )
def construct_circuit(self, mode, register=None): """ Construct the statevector of desired initial state. Args: mode (string): `vector` or `circuit`. The `vector` mode produces the vector. While the `circuit` constructs the quantum circuit corresponding that vector. register (QuantumRegister): register for circuit construction. Returns: QuantumCircuit or numpy.ndarray: statevector. Raises: AquaError: when mode is not 'vector' or 'circuit'. """ if mode == 'vector': if self._state_vector is None: if self._circuit is not None: self._state_vector = np.asarray( q_execute( self._circuit, BasicAer.get_backend('statevector_simulator')). result().get_statevector(self._circuit)) return self._state_vector elif mode == 'circuit': if self._circuit is None: if register is None: register = QuantumRegister(self._num_qubits, name='q') # create emtpy quantum circuit circuit = QuantumCircuit() # if register is actually a list of qubits if type(register) is list: # loop over all qubits and add the required registers for q in register: if not circuit.has_register(q[0]): circuit.add_register(q[0]) else: # if an actual register is given, add it circuit.add_register(register) if self._state is None or self._state == 'random': svc = StateVectorCircuit(self._state_vector) svc.construct_circuit(circuit, register) elif self._state == 'zero': pass elif self._state == 'uniform': for i in range(self._num_qubits): circuit.u2(0.0, np.pi, register[i]) else: pass self._circuit = circuit return self._circuit.copy() else: raise AquaError('Mode should be either "vector" or "circuit"')
def construct_circuit(self, mode='circuit', register=None): # pylint: disable=import-outside-toplevel from qiskit import BasicAer if mode == 'vector': if self._state_vector is None: if self._circuit is not None: self._state_vector = np.asarray( q_execute( self._circuit, BasicAer.get_backend('statevector_simulator')). result().get_statevector(self._circuit)) return self._state_vector elif mode == 'circuit': if self._circuit is None: # create empty quantum circuit circuit = QuantumCircuit() if register is None: register = QuantumRegister(self._num_qubits, name='q') if isinstance(register, QuantumRegister): circuit.add_register(register) elif isinstance(register, list): for q in register: if isinstance(q, Qubit): if not circuit.has_register(q.register): circuit.add_register(q.register) else: raise AquaError('Unexpected qubit type {}.'.format( type(q))) else: raise AquaError('Unexpected register type {}.'.format( type(register))) if self._state is None or self._state == 'random': svc = StateVectorCircuit(self._state_vector) svc.construct_circuit(circuit=circuit, register=register) elif self._state == 'uniform': for i in range(self._num_qubits): circuit.u(np.pi / 2, 0.0, np.pi, register[i]) elif self._state == 'zero': pass else: AquaError('Unexpected state mode {}.'.format(self._state)) self._circuit = circuit return self._circuit.copy() else: raise AquaError('Mode should be either "vector" or "circuit"')
def test_mct(self, num_controls): c = QuantumRegister(num_controls, name='c') o = QuantumRegister(1, name='o') allsubsets = list( chain(*[ combinations(range(num_controls), ni) for ni in range(num_controls + 1) ])) for subset in allsubsets: for mode in ['basic', 'advanced', 'noancilla']: qc = QuantumCircuit(o, c) if mode == 'basic': if num_controls <= 2: num_ancillae = 0 else: num_ancillae = num_controls - 2 elif mode == 'noancilla': num_ancillae = 0 else: if num_controls <= 4: num_ancillae = 0 else: num_ancillae = 1 if num_ancillae > 0: a = QuantumRegister(num_ancillae, name='a') qc.add_register(a) for idx in subset: qc.x(c[idx]) qc.mct([c[i] for i in range(num_controls)], o[0], [a[i] for i in range(num_ancillae)], mode=mode) for idx in subset: qc.x(c[idx]) vec = np.asarray( q_execute(qc, get_aer_backend( 'statevector_simulator')).result().get_statevector( qc, decimals=16)) vec_o = [0, 1] if len(subset) == num_controls else [1, 0] # print(vec, np.array(vec_o + [0] * (2 ** (num_controls + num_ancillae + 1) - 2))) f = state_fidelity( vec, np.array(vec_o + [0] * (2**(num_controls + num_ancillae + 1) - 2))) self.assertAlmostEqual(f, 1) return
def construct_circuit(self, mode, register=None): """ Construct the statevector of desired initial state. Args: mode (string): `vector` or `circuit`. The `vector` mode produces the vector. While the `circuit` constructs the quantum circuit corresponding that vector. register (QuantumRegister): register for circuit construction. Returns: QuantumCircuit or numpy.ndarray: statevector. Raises: ValueError: when mode is not 'vector' or 'circuit'. """ if mode == 'vector': if self._state_vector is None: if self._circuit is not None: self._state_vector = np.asarray( q_execute(self._circuit, get_aer_backend('statevector_simulator')). result().get_statevector(self._circuit)) return self._state_vector elif mode == 'circuit': if self._circuit is None: if register is None: register = QuantumRegister(self._num_qubits, name='q') circuit = QuantumCircuit(register) if self._state is None or self._state == 'random': circuit.initialize( self._state_vector, [register[i] for i in range(self._num_qubits)]) circuit = Custom._convert_to_basis_gates(circuit) elif self._state == 'zero': pass elif self._state == 'uniform': for i in range(self._num_qubits): circuit.u2(0.0, np.pi, register[i]) else: pass self._circuit = circuit return self._circuit else: raise ValueError('Mode should be either "vector" or "circuit"')
def test_sat_oracle(self, cnf_str, sols): num_shots = 1024 for cnx_mode in ['basic', 'advanced']: sat = SAT(cnf_str, cnx_mode=cnx_mode) sat_circuit = sat.construct_circuit() m = ClassicalRegister(1, name='m') for assignment in itertools.product([True, False], repeat=len(sat.variable_register())): qc = QuantumCircuit(m, sat.variable_register()) for idx, tf in enumerate(assignment): if tf: qc.x(sat.variable_register()[idx]) qc += sat_circuit qc.barrier(sat._qr_outcome) qc.measure(sat._qr_outcome, m) counts = q_execute(qc, get_aer_backend( 'qasm_simulator'), shots=num_shots).result().get_counts(qc) if assignment in sols: assert(counts['1'] == num_shots) else: assert(counts['0'] == num_shots)
def test_sat_oracle(self, cnf_str, sols): num_shots = 1024 sat = get_oracle_instance('SAT') sat.init_args(cnf_str) sat_circuit = sat.construct_circuit() m = ClassicalRegister(1, name='m') for assignment in itertools.product([True, False], repeat=len( sat.variable_register())): qc = QuantumCircuit(m, sat.variable_register()) for idx, tf in enumerate(assignment): if tf: qc.x(sat.variable_register()[idx]) qc += sat_circuit qc.measure(sat._qr_outcome, m) counts = q_execute(qc, 'local_qasm_simulator', shots=num_shots).result().get_counts(qc) if assignment in sols: assert (counts['1'] == num_shots) else: assert (counts['0'] == num_shots)
def test_mct(self, num_controls, mode): c = QuantumRegister(num_controls, name='c') o = QuantumRegister(1, name='o') subsets = [tuple(range(i)) for i in range(num_controls + 1)] for subset in subsets: qc = QuantumCircuit(o, c) if mode == 'basic': if num_controls <= 2: num_ancillae = 0 else: num_ancillae = num_controls - 2 elif mode == 'noancilla': num_ancillae = 0 else: if num_controls <= 4: num_ancillae = 0 else: num_ancillae = 1 if num_ancillae > 0: a = QuantumRegister(num_ancillae, name='a') qc.add_register(a) for idx in subset: qc.x(c[idx]) qc.mct( [c[i] for i in range(num_controls)], o[0], [a[i] for i in range(num_ancillae)], mode=mode ) for idx in subset: qc.x(c[idx]) vec = np.asarray(q_execute(qc, BasicAer.get_backend( 'statevector_simulator')).result().get_statevector(qc, decimals=16)) vec_o = [0, 1] if len(subset) == num_controls else [1, 0] f = state_fidelity(vec, np.array(vec_o + [0] * (2 ** (num_controls + num_ancillae + 1) - 2))) self.assertAlmostEqual(f, 1)
def test_mcmt(self, num_controls, num_targets, single_control_gate_function): c = QuantumRegister(num_controls, name='c') o = QuantumRegister(num_targets, name='o') subsets = [tuple(range(i)) for i in range(num_controls + 1)] for subset in subsets: # Expecting some other modes for mode in ['basic']: self.log.debug("Subset is {0}".format(subset)) self.log.debug("Num controls = {0}".format(num_controls)) self.log.debug("Num targets = {0}".format(num_targets)) self.log.debug("Gate function is {0}".format( single_control_gate_function.__name__)) self.log.debug("Mode is {0}".format(mode)) qc = QuantumCircuit(o, c) # Initialize all targets to 1, just to be sure that # the generic gate has some effect (f.e. Z gate has no effect # on a 0 state) qc.x(o) if mode == 'basic': if num_controls <= 1: num_ancillae = 0 else: num_ancillae = num_controls - 1 self.log.debug("Num ancillae is {0} ".format(num_ancillae)) if num_ancillae > 0: a = QuantumRegister(num_ancillae, name='a') qc.add_register(a) for idx in subset: qc.x(c[idx]) qc.mcmt([c[i] for i in range(num_controls)], [a[i] for i in range(num_ancillae)], single_control_gate_function, o, mode=mode) for idx in subset: qc.x(c[idx]) vec = np.asarray( q_execute(qc, get_aer_backend('statevector_simulator')). result().get_statevector(qc, decimals=16)) # target register is initially |11...1>, with length equal to 2**(n_targets) vec_exp = np.array([0] * (2**(num_targets) - 1) + [1]) if (single_control_gate_function.__name__ == "cz"): # Z gate flips the last qubit only if it's applied an odd # number of times if (len(subset) == num_controls and (num_controls % 2) == 1): vec_exp[-1] = -1 elif (single_control_gate_function.__name__ == "ch"): # if all the control qubits have been activated, # we repeatedly apply the kronecker product of the Hadamard # with itself and then multiply the results for the original # state of the target qubits if (len(subset) == num_controls): h = 1 / np.sqrt(2) * np.array([[1, 1], [1, -1]]) h_tot = np.array([1]) for i in range(num_targets): h_tot = np.kron(h_tot, h) vec_exp = np.dot(h_tot, vec_exp) else: raise ValueError("Gate {0} not implementend yet".format( single_control_gate_function.__name__)) # append the remaining part of the state vec_exp = np.concatenate( (vec_exp, [0] * (2**(num_controls + num_ancillae + num_targets) - vec_exp.size))) f = state_fidelity(vec, vec_exp) self.assertAlmostEqual(f, 1)
def test_evolution(self): SIZE = 2 # SPARSITY = 0 # X = [[0, 1], [1, 0]] # Y = [[0, -1j], [1j, 0]] Z = [[1, 0], [0, -1]] _I = [[1, 0], [0, 1]] # + 0.5 * np.kron(Y, X)# + 0.3 * np.kron(Z, X) + 0.4 * np.kron(Z, Y) h1 = np.kron(_I, Z) # np.random.seed(2) temp = np.random.random((2**SIZE, 2**SIZE)) h1 = temp + temp.T qubit_op = Operator(matrix=h1) # qubit_op_jw.chop_by_threshold(10 ** -10) if qubit_op.grouped_paulis is None: qubit_op._matrix_to_paulis() qubit_op._paulis_to_grouped_paulis() for ps in qubit_op.grouped_paulis: for p1 in ps: for p2 in ps: if p1 != p2: np.testing.assert_almost_equal( p1[1].to_matrix() @ p2[1].to_matrix(), p2[1].to_matrix() @ p1[1].to_matrix()) state_in = Custom(SIZE, state='random') evo_time = 1 num_time_slices = 3 # announces params self.log.debug('evo time: {}'.format(evo_time)) self.log.debug('num time slices: {}'.format(num_time_slices)) self.log.debug('state_in: {}'.format(state_in._state_vector)) # get the exact state_out from raw matrix multiplication state_out_exact = qubit_op.evolve( state_in=state_in.construct_circuit('vector'), evo_time=evo_time, evo_mode='matrix', num_time_slices=0) # self.log.debug('exact:\n{}'.format(state_out_exact)) qubit_op_temp = copy.deepcopy(qubit_op) for expansion_mode in ['trotter', 'suzuki']: self.log.debug('Under {} expansion mode:'.format(expansion_mode)) for expansion_order in [1, 2, 3, 4 ] if expansion_mode == 'suzuki' else [1]: # assure every time the operator from the original one qubit_op = copy.deepcopy(qubit_op_temp) if expansion_mode == 'suzuki': self.log.debug( 'With expansion order {}:'.format(expansion_order)) state_out_matrix = qubit_op.evolve( state_in=state_in.construct_circuit('vector'), evo_time=evo_time, evo_mode='matrix', num_time_slices=num_time_slices, expansion_mode=expansion_mode, expansion_order=expansion_order) quantum_registers = QuantumRegister(qubit_op.num_qubits, name='q') qc = QuantumCircuit(quantum_registers) qc += state_in.construct_circuit('circuit', quantum_registers) qc += qubit_op.evolve( evo_time=evo_time, evo_mode='circuit', num_time_slices=num_time_slices, quantum_registers=quantum_registers, expansion_mode=expansion_mode, expansion_order=expansion_order, ) job = q_execute(qc, BasicAer.get_backend('statevector_simulator')) state_out_circuit = np.asarray(job.result().get_statevector( qc, decimals=16)) self.log.debug( 'The fidelity between exact and matrix: {}'.format( state_fidelity(state_out_exact, state_out_matrix))) self.log.debug( 'The fidelity between exact and circuit: {}'.format( state_fidelity(state_out_exact, state_out_circuit))) f_mc = state_fidelity(state_out_matrix, state_out_circuit) self.log.debug( 'The fidelity between matrix and circuit: {}'.format(f_mc)) self.assertAlmostEqual(f_mc, 1)
def test_evolution(self): SIZE = 2 #SPARSITY = 0 #X = [[0, 1], [1, 0]] #Y = [[0, -1j], [1j, 0]] Z = [[1, 0], [0, -1]] I = [[1, 0], [0, 1]] # + 0.5 * np.kron(Y, X)# + 0.3 * np.kron(Z, X) + 0.4 * np.kron(Z, Y) h1 = np.kron(I, Z) # np.random.seed(2) temp = np.random.random((2 ** SIZE, 2 ** SIZE)) h1 = temp + temp.T qubitOp = Operator(matrix=h1) # qubitOp_jw.chop_by_threshold(10 ** -10) # self.log.debug('matrix:\n{}\n'.format(qubitOp.matrix)) # self.log.debug('paulis:') # self.log.debug(qubitOp.print_operators('paulis')) if qubitOp.grouped_paulis is None: qubitOp._matrix_to_paulis() qubitOp._paulis_to_grouped_paulis() for ps in qubitOp.grouped_paulis: for p1 in ps: for p2 in ps: if p1 != p2: np.testing.assert_almost_equal( p1[1].to_matrix() @ p2[1].to_matrix(), p2[1].to_matrix() @ p1[1].to_matrix() ) flattened_grouped_paulis = [ pauli for group in qubitOp.grouped_paulis for pauli in group[1:]] state_in = get_initial_state_instance('CUSTOM') state_in.init_args(SIZE, state='random') evo_time = 1 num_time_slices = 1 # announces params self.log.debug('evo time: {}'.format(evo_time)) self.log.debug('num time slices: {}'.format(num_time_slices)) self.log.debug('state_in: {}'.format(state_in._state_vector)) # get the exact state_out from raw matrix multiplication state_out_exact = qubitOp.evolve( state_in.construct_circuit('vector'), evo_time, 'matrix', 0) # self.log.debug('exact:\n{}'.format(state_out_exact)) qubitOp_temp = copy.deepcopy(qubitOp) for grouping in ['default', 'random']: self.log.debug('Under {} paulis grouping:'.format(grouping)) for expansion_mode in ['trotter', 'suzuki']: self.log.debug( 'Under {} expansion mode:'.format(expansion_mode)) for expansion_order in [1, 2, 3, 4] if expansion_mode == 'suzuki' else [1]: # assure every time the operator from the original one qubitOp = copy.deepcopy(qubitOp_temp) if expansion_mode == 'suzuki': self.log.debug( 'With expansion order {}:'.format(expansion_order)) state_out_matrix = qubitOp.evolve( state_in.construct_circuit( 'vector'), evo_time, 'matrix', num_time_slices, paulis_grouping=grouping, expansion_mode=expansion_mode, expansion_order=expansion_order ) quantum_registers = QuantumRegister(qubitOp.num_qubits) qc = state_in.construct_circuit( 'circuit', quantum_registers) qc += qubitOp.evolve( None, evo_time, 'circuit', num_time_slices, quantum_registers=quantum_registers, paulis_grouping=grouping, expansion_mode=expansion_mode, expansion_order=expansion_order, ) job = q_execute(qc, qiskit.Aer.get_backend( 'statevector_simulator'), skip_transpiler=True) state_out_circuit = np.asarray( job.result().get_statevector(qc)) self.log.debug('The fidelity between exact and matrix: {}'.format( state_fidelity(state_out_exact, state_out_matrix) )) self.log.debug('The fidelity between exact and circuit: {}'.format( state_fidelity(state_out_exact, state_out_circuit) )) f_mc = state_fidelity(state_out_matrix, state_out_circuit) self.log.debug( 'The fidelity between matrix and circuit: {}'.format(f_mc)) self.assertAlmostEqual(f_mc, 1)
def run_exp(num_reps=1): # choice of Hi basis H_basis = [Pauli.from_label(p) for p in ['II', 'ZI', 'IZ', 'ZZ', 'YY', 'XX']] num_qubits = 2 evo_time = 1 epsilon = 0.1 L = 32 ## number of local hamiltonian terms ############################################################ # Generate a random Hamiltonian H as the sum of m basis Hi operators ############################################################ hs = np.random.random(L) indexes = np.random.randint(low=0, high=6, size=L) ## H in matrix form H_matrix = np.zeros((2 ** num_qubits, 2 ** num_qubits)) ## H as a list of pauli operators (unweighted) H_list = [] for i in range(L): H_matrix = H_matrix + hs[i] * H_basis[indexes[i]].to_matrix() H_list.append(H_basis[indexes[i]]) print('matrix H: \n', H_matrix) # H as a pauli operator H_qubitOp = op_converter.to_weighted_pauli_operator(MatrixOperator(matrix=H_matrix)) # Generate an initial state state_in = Custom(num_qubits, state='random') ############################################################ # Ground truth and benchmarks ############################################################ # Ground truth state_in_vec = state_in.construct_circuit('vector') groundtruth = expm(-1.j * H_matrix * evo_time) @ state_in_vec print('The directly computed groundtruth evolution result state is') print('{}\n.'.format(groundtruth)) # Build circuit using Qiskit's evolve algorithm, which based on Trotter-Suzuki. quantum_registers = QuantumRegister(num_qubits) circuit = state_in.construct_circuit('circuit', quantum_registers) circuit += H_qubitOp.evolve( None, evo_time, num_time_slices=10, quantum_registers=quantum_registers, expansion_mode='suzuki', expansion_order=1 ) # Simulate Trotter-Suzuki circuit and print it backend = BasicAer.get_backend('statevector_simulator') job = q_execute(circuit, backend) circuit_execution_result = np.asarray(job.result().get_statevector(circuit)) print('The simulated (suzuki) evolution result state is') print('{}\n'.format(circuit_execution_result)) # The difference between the ground truth and the simulated state # measured by "Fidelity" fidelity_suzuki = state_fidelity(groundtruth, circuit_execution_result) print('Fidelity between the groundtruth and the circuit result states is {}.'.format(fidelity_suzuki)) print('\n') ############################################################ # Our qdrift implementation ############################################################ quantum_registers = QuantumRegister(num_qubits) circuit = state_in.construct_circuit('circuit', quantum_registers) # Contruct the circuit which implements qdrift circuit = time_evolve_qubits(quantum_registers, circuit, num_qubits, H_list, hs, evo_time, epsilon, num_reps) # Simulate circuit and print it backend = BasicAer.get_backend('statevector_simulator') job = q_execute(circuit, backend) circuit_execution_result = np.asarray(job.result().get_statevector(circuit)) print('The simulated (qdrift) evolution result state is\n{}.'.format(circuit_execution_result)) print('\n') # Measure the fidelity fidelity_qdrift = state_fidelity(groundtruth, circuit_execution_result) print('Fidelity between the groundtruth and the circuit result states is {}.'.format(fidelity_qdrift)) print('\n') print('benchmark, suzuki:', fidelity_suzuki) print('qdrift:', fidelity_qdrift) return fidelity_qdrift, fidelity_suzuki