def test_run_job_processor_local_parallel(self): def job_done_callback(results): try: self.log.info(pprint.pformat(results)) for result in results: self.assertTrue(result.get_status() == 'COMPLETED') except Exception as e: self.job_processor_exception = e finally: self.job_processor_finished = True njobs = 20 job_list = [] # TODO: make this run on `local_qasm_simulator` after `do_compile` # is fixed in _quantumjob. backend = get_backend('local_qasm_simulator_py') for _ in range(njobs): compiled_circuit = compile_circuit(self.qc) quantum_job = QuantumJob(compiled_circuit, backend=backend) job_list.append(quantum_job) self.job_processor_finished = False self.job_processor_exception = None jp = jobprocessor.JobProcessor(job_list, max_workers=None, callback=job_done_callback) jp.submit() while not self.job_processor_finished: # Wait until the job_done_callback is invoked and completed. pass if self.job_processor_exception: raise self.job_processor_exception
def test_random_circuits(self): qk_simulator = get_backend('local_qasm_simulator') for circuit in self.rqg.get_circuits(format_='QuantumCircuit'): self.log.info(circuit.qasm()) compiled_circuit = compile_circuit(circuit) shots = 100 job_pq = QuantumJob(compiled_circuit, backend=pq_simulator, seed=1, shots=shots) job_qk = QuantumJob(compiled_circuit, backend=qk_simulator, seed=1, shots=shots) result_pq = pq_simulator.run(job_pq).result() result_qk = qk_simulator.run(job_qk).result() counts_pq = result_pq.get_counts(result_pq.get_names()[0]) counts_qk = result_qk.get_counts(result_qk.get_names()[0]) self.log.info('local_qasm_simulator_projectq: %s', str(counts_pq)) self.log.info('local_qasm_simulator: %s', str(counts_qk)) states = counts_qk.keys() | counts_pq.keys() # contingency table ctable = numpy.array([[counts_pq.get(key, 0) for key in states], [counts_qk.get(key, 0) for key in states]]) result = chi2_contingency(ctable) self.log.info('chi2_contingency: %s', str(result)) with self.subTest(circuit=circuit): self.assertGreater(result[1], 0.01)
def test_mix_local_remote_jobs(self, QE_TOKEN, QE_URL): """test mixing local and remote jobs Internally local jobs execute in seperate processes since they are CPU bound and remote jobs execute in seperate threads since they are I/O bound. The module gets results from potentially both kinds in one list. Test that this works. """ provider = IBMQProvider(QE_TOKEN, QE_URL) remote_backend = provider.available_backends({'simulator': True})[0] local_backend = get_backend('local_qasm_simulator') njobs = 6 job_list = [] backend_type = [local_backend, remote_backend] i = 0 for circuit in self.rqg.get_circuits(format_='QuantumCircuit')[:njobs]: compiled_circuit = compile_circuit(circuit) backend = backend_type[i % len(backend_type)] self.log.info(backend) quantum_job = QuantumJob(compiled_circuit, backend=backend) job_list.append(quantum_job) i += 1 jp = jobprocessor.JobProcessor(job_list, max_workers=None, callback=None) jp.submit()
def test_run_local_backend_qasm(self): backend = QasmSimulator() dag_circuit = compile_circuit(self.qc) quantum_job = QuantumJob(dag_circuit, do_compile=False, backend=backend) jobprocessor.run_backend(quantum_job)
def test_random_circuits(self): local_simulator = qasm_simulator.QasmSimulator() for circuit in self.rqg.get_circuits(format_='QuantumCircuit'): self.log.info(circuit.qasm()) compiled_circuit = compile_circuit(circuit) shots = 1000 min_cnts = int(shots / 10) job_pq = QuantumJob(compiled_circuit, backend='local_projectq_simulator', seed=1, shots=shots) job_py = QuantumJob(compiled_circuit, backend='local_qasm_simulator', seed=1, shots=shots) result_pq = pq_simulator.run(job_pq) result_py = local_simulator.run(job_py) counts_pq = result_pq.get_counts(result_pq.get_names()[0]) counts_py = result_py.get_counts(result_py.get_names()[0]) # filter states with few counts counts_pq = {key: cnt for key, cnt in counts_pq.items() if cnt > min_cnts} counts_py = {key: cnt for key, cnt in counts_py.items() if cnt > min_cnts} self.log.info('local_projectq_simulator: %s', str(counts_pq)) self.log.info('local_qasm_simulator: %s', str(counts_py)) threshold = 0.05 * shots self.assertDictAlmostEqual(counts_pq, counts_py, threshold) states = counts_py.keys() # contingency table ctable = numpy.array([[counts_pq[key] for key in states], [counts_py[key] for key in states]]) result = chi2_contingency(ctable) self.log.info('chi2_contingency: %s', str(result)) with self.subTest(circuit=circuit): self.assertGreater(result[1], 0.01)
def test_run_local_backend_unitary(self): backend = get_backend('local_unitary_simulator') compiled_circuit = compile_circuit(self.qc) quantum_job = QuantumJob(compiled_circuit, do_compile=False, backend=backend) jobprocessor.run_backend(quantum_job)
def test_random_circuits(self): qk_simulator = get_backend('local_qasm_simulator') for circuit in self.rqg.get_circuits(format_='QuantumCircuit'): self.log.info(circuit.qasm()) compiled_circuit = compile_circuit(circuit) shots = 100 job_pq = QuantumJob(compiled_circuit, backend=pq_simulator, seed=1, shots=shots) job_qk = QuantumJob(compiled_circuit, backend=qk_simulator, seed=1, shots=shots) result_pq = pq_simulator.run(job_pq).result() result_qk = qk_simulator.run(job_qk).result() counts_pq = result_pq.get_counts(result_pq.get_names()[0]) counts_qk = result_qk.get_counts(result_qk.get_names()[0]) self.log.info('local_qasm_simulator_projectq: %s', str(counts_pq)) self.log.info('local_qasm_simulator: %s', str(counts_qk)) states = counts_qk.keys() | counts_pq.keys() # contingency table ctable = numpy.array([[counts_pq.get(key, 0) for key in states], [counts_qk.get(key, 0) for key in states]]) result = chi2_contingency(ctable) self.log.info('chi2_contingency: %s', str(result)) with self.subTest(circuit=circuit): self.assertGreater(result[1], 0.01)
def _submit(self): """Submit job to IBM Q. Returns: dict: submission info including job id from server Raises: QISKitError: The backend name in the job doesn't match this backend. ResultError: If the API reported an error with the submitted job. RegisterSizeError: If the requested register size exceeded device capability. """ qobj = self._qobj api_jobs = [] for circuit in qobj['circuits']: if (('compiled_circuit_qasm' not in circuit) or (circuit['compiled_circuit_qasm'] is None)): compiled_circuit = compile_circuit(circuit['circuit']) circuit['compiled_circuit_qasm'] = compiled_circuit.qasm(qeflag=True) if isinstance(circuit['compiled_circuit_qasm'], bytes): api_jobs.append({'qasm': circuit['compiled_circuit_qasm'].decode()}) else: api_jobs.append({'qasm': circuit['compiled_circuit_qasm']}) seed0 = qobj['circuits'][0]['config']['seed'] hpc = None if 'hpc' in qobj['config']: try: # Use CamelCase when passing the hpc parameters to the API. hpc = { 'multiShotOptimization': qobj['config']['hpc']['multi_shot_optimization'], 'ompNumThreads': qobj['config']['hpc']['omp_num_threads'] } except (KeyError, TypeError): hpc = None backend_name = qobj['config']['backend_name'] if backend_name != self._backend_name: raise QISKitError("inconsistent qobj backend " "name ({0} != {1})".format(backend_name, self._backend_name)) submit_info = {} try: submit_info = self._api.run_job(api_jobs, backend_name, shots=qobj['config']['shots'], max_credits=qobj['config']['max_credits'], seed=seed0, hpc=hpc) except ApiError as err: self._status = JobStatus.ERROR self._exception = err if 'error' in submit_info: self._status = JobStatus.ERROR self._exception = IBMQJobError(str(submit_info['error'])) self._job_id = submit_info.get('id') self._status = JobStatus.QUEUED return submit_info
def test_run_remote_simulator(self, QE_TOKEN, QE_URL): provider = IBMQProvider(QE_TOKEN, QE_URL) backend = provider.get_backend('ibmqx_qasm_simulator') compiled_circuit = compile_circuit(self.qc) quantum_job = QuantumJob(compiled_circuit, do_compile=False, backend=backend) jobprocessor.run_backend(quantum_job)
def test_run_remote_simulator(self, QE_TOKEN, QE_URL): provider = IBMQProvider(QE_TOKEN, QE_URL) backend = provider.available_backends({'simulator': True})[0] compiled_circuit = compile_circuit(self.qc) quantum_job = QuantumJob(compiled_circuit, do_compile=False, backend=backend) jobprocessor.run_backend(quantum_job)
def test_run_local_backend_qasm(self): # TODO: make this run on `local_qasm_simulator` after `do_compile` # is fixed in _quantumjob. backend = get_backend('local_qasm_simulator_py') dag_circuit = compile_circuit(self.qc) quantum_job = QuantumJob(dag_circuit, do_compile=False, backend=backend) jobprocessor.run_backend(quantum_job)
def setUp(self): self.seed = 88 self.qasm_filename = self._get_resource_path('qasm/example.qasm') with open(self.qasm_filename, 'r') as qasm_file: self.qasm_text = qasm_file.read() self.qasm_ast = qiskit.qasm.Qasm(data=self.qasm_text).parse() self.qasm_be = qiskit.unroll.CircuitBackend( ['u1', 'u2', 'u3', 'id', 'cx']) self.qasm_circ = qiskit.unroll.Unroller(self.qasm_ast, self.qasm_be).execute() # create QuantumCircuit qr = QuantumRegister(2, 'q') cr = ClassicalRegister(2, 'c') qc = QuantumCircuit(qr, cr) qc.h(qr[0]) qc.measure(qr[0], cr[0]) self.qc = qc # create qobj compiled_circuit1 = compile_circuit(self.qc) compiled_circuit2 = compile_circuit(self.qasm_circ) self.qobj = { 'id': 'test_qobj', 'config': { 'max_credits': 3, 'shots': 100, 'backend': 'local_qasm_simulator', }, 'circuits': [{ 'name': 'test_circuit1', 'compiled_circuit': compiled_circuit1, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': None }, { 'name': 'test_circuit2', 'compiled_circuit': compiled_circuit2, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': None }] } self.job_processor_exception = Exception() self.job_processor_finished = False
def test_random_local(self): """test randomly generated circuits on local_qasm_simulator""" njobs = 5 job_list = [] backend = get_backend('local_qasm_simulator') for circuit in self.rqg.get_circuits(format_='QuantumCircuit')[:njobs]: compiled_circuit = compile_circuit(circuit) quantum_job = QuantumJob(compiled_circuit, backend=backend) job_list.append(quantum_job) jp = jobprocessor.JobProcessor(job_list, max_workers=1, callback=None) jp.submit()
def test_run_job_processor_local(self): njobs = 5 job_list = [] backend = get_backend('local_qasm_simulator') for _ in range(njobs): compiled_circuit = compile_circuit(self.qc) quantum_job = QuantumJob(compiled_circuit, backend=backend, do_compile=False) job_list.append(quantum_job) jp = jobprocessor.JobProcessor(job_list, callback=None) jp.submit()
def test_run_job_processor_online(self, QE_TOKEN, QE_URL): provider = IBMQProvider(QE_TOKEN, QE_URL) backend = provider.available_backends({'simulator': True})[0] njobs = 1 job_list = [] for _ in range(njobs): compiled_circuit = compile_circuit(self.qc) quantum_job = QuantumJob(compiled_circuit, backend=backend) job_list.append(quantum_job) jp = jobprocessor.JobProcessor(job_list, callback=None) jp.submit()
def test_error_in_job(self): def job_done_callback(results): try: for result in results: self.log.info(pprint.pformat(result)) self.assertTrue(result.get_status() == 'ERROR') except Exception as e: self.job_processor_exception = e finally: self.job_processor_finished = True njobs = 5 job_list = [] backend = get_backend('local_qasm_simulator') for _ in range(njobs): compiled_circuit = compile_circuit(self.qc) quantum_job = QuantumJob(compiled_circuit, backend=backend) job_list.append(quantum_job) self.job_processor_finished = False self.job_processor_exception = None jp = jobprocessor.JobProcessor(job_list, max_workers=None, callback=job_done_callback) tmp = jobprocessor.run_backend jobprocessor.run_backend = mock_run_local_backend jp.submit() jobprocessor.run_backend = tmp while not self.job_processor_finished: # Wait until the job_done_callback is invoked and completed. pass if self.job_processor_exception: raise self.job_processor_exception
def _submit(self): """Submit job to IBM Q. Returns: dict: submission info including job id from server Raises: QISKitError: The backend name in the job doesn't match this backend. ResultError: If the API reported an error with the submitted job. RegisterSizeError: If the requested register size exceeded device capability. """ qobj = self._qobj api_jobs = [] for circuit in qobj['circuits']: job = {} if (('compiled_circuit_qasm' not in circuit) or (circuit['compiled_circuit_qasm'] is None)): compiled_circuit = compile_circuit(circuit['circuit']) circuit['compiled_circuit_qasm'] = compiled_circuit.qasm( qeflag=True) if isinstance(circuit['compiled_circuit_qasm'], bytes): job['qasm'] = circuit['compiled_circuit_qasm'].decode() else: job['qasm'] = circuit['compiled_circuit_qasm'] if 'name' in circuit: job['name'] = circuit['name'] # convert numpy types for json serialization compiled_circuit = json.loads( json.dumps(circuit['compiled_circuit'], default=_numpy_type_converter)) job['metadata'] = {'compiled_circuit': compiled_circuit} api_jobs.append(job) seed0 = qobj['circuits'][0]['config']['seed'] hpc = None if 'hpc' in qobj['config']: try: # Use CamelCase when passing the hpc parameters to the API. hpc = { 'multiShotOptimization': qobj['config']['hpc']['multi_shot_optimization'], 'ompNumThreads': qobj['config']['hpc']['omp_num_threads'] } except (KeyError, TypeError): hpc = None backend_name = qobj['config']['backend_name'] if backend_name != self._backend_name: raise QISKitError("inconsistent qobj backend " "name ({0} != {1})".format( backend_name, self._backend_name)) submit_info = {} try: submit_info = self._api.run_job( api_jobs, backend=backend_name, shots=qobj['config']['shots'], max_credits=qobj['config']['max_credits'], seed=seed0, hpc=hpc) # pylint: disable=broad-except except Exception as err: self._status = JobStatus.ERROR self._status_msg = str(err) self._exception = err return None if 'error' in submit_info: self._status = JobStatus.ERROR self._status_msg = str(submit_info['error']) self._exception = IBMQJobError(self._status_msg) return submit_info self._id = submit_info.get('id') self.creation_date = submit_info.get('creationDate') self._status = JobStatus.QUEUED return submit_info
def _submit(self): """Submit job to IBM Q. Returns: dict: submission info including job id from server Raises: QISKitError: The backend name in the job doesn't match this backend. ResultError: If the API reported an error with the submitted job. RegisterSizeError: If the requested register size exceeded device capability. """ qobj = self._qobj api_jobs = [] for circuit in qobj['circuits']: if (('compiled_circuit_qasm' not in circuit) or (circuit['compiled_circuit_qasm'] is None)): compiled_circuit = compile_circuit(circuit['circuit']) circuit['compiled_circuit_qasm'] = compiled_circuit.qasm( qeflag=True) if isinstance(circuit['compiled_circuit_qasm'], bytes): api_jobs.append( {'qasm': circuit['compiled_circuit_qasm'].decode()}) else: api_jobs.append({'qasm': circuit['compiled_circuit_qasm']}) seed0 = qobj['circuits'][0]['config']['seed'] hpc = None if (qobj['config']['backend_name'] == 'ibmq_qasm_simulator_hpc' and 'hpc' in qobj['config']): try: # Use CamelCase when passing the hpc parameters to the API. hpc = { 'multiShotOptimization': qobj['config']['hpc']['multi_shot_optimization'], 'ompNumThreads': qobj['config']['hpc']['omp_num_threads'] } except (KeyError, TypeError): hpc = None backend_name = qobj['config']['backend_name'] if backend_name != self._backend_name: raise QISKitError("inconsistent qobj backend " "name ({0} != {1})".format( backend_name, self._backend_name)) submit_info = {} try: submit_info = self._api.run_job( api_jobs, backend_name, shots=qobj['config']['shots'], max_credits=qobj['config']['max_credits'], seed=seed0, hpc=hpc) except ApiError as err: self._status = JobStatus.ERROR self._exception = err if 'error' in submit_info: self._status = JobStatus.ERROR self._exception = IBMQJobError(str(submit_info['error'])) self._job_id = submit_info.get('id') self._status = JobStatus.QUEUED return submit_info
def run(self, q_job): """Run jobs Args: q_job (QuantumJob): job to run Returns: Result: Result object. Raises: QISKitError: if there are inconsistencies between qobj data and backend data ResultError: if the api put 'error' in its output """ qobj = q_job.qobj wait = q_job.wait timeout = q_job.timeout api_jobs = [] for circuit in qobj['circuits']: if (('compiled_circuit_qasm' not in circuit) or (circuit['compiled_circuit_qasm'] is None)): compiled_circuit = compile_circuit(circuit['circuit']) circuit['compiled_circuit_qasm'] = compiled_circuit.qasm( qeflag=True) if isinstance(circuit['compiled_circuit_qasm'], bytes): api_jobs.append( {'qasm': circuit['compiled_circuit_qasm'].decode()}) else: api_jobs.append({'qasm': circuit['compiled_circuit_qasm']}) seed0 = qobj['circuits'][0]['config']['seed'] hpc = None if (qobj['config']['backend_name'] == 'ibmq_qasm_simulator_hpc' and 'hpc' in qobj['config']): try: # Use CamelCase when passing the hpc parameters to the API. hpc = { 'multiShotOptimization': qobj['config']['hpc']['multi_shot_optimization'], 'ompNumThreads': qobj['config']['hpc']['omp_num_threads'] } except (KeyError, TypeError): hpc = None backend_name = qobj['config']['backend_name'] if backend_name != self.name: raise QISKitError("inconsistent qobj backend " "name ({0} != {1})".format( backend_name, self.name)) output = self._api.run_job(api_jobs, backend_name, shots=qobj['config']['shots'], max_credits=qobj['config']['max_credits'], seed=seed0, hpc=hpc) if 'error' in output: raise ResultError(output['error']) logger.info('Running qobj: %s on remote backend %s with job id: %s', qobj["id"], qobj['config']['backend_name'], output['id']) job_result = _wait_for_job(output['id'], self._api, wait=wait, timeout=timeout) logger.info( 'Got a result for qobj: %s from remote backend %s with job id: %s', qobj["id"], qobj['config']['backend_name'], output['id']) job_result['name'] = qobj['id'] job_result['backend'] = qobj['config']['backend_name'] this_result = Result(job_result, qobj) return this_result