From 845a841ec92e1fcf151a0849ea71691e8b70cfad Mon Sep 17 00:00:00 2001 From: Erick Winston Date: Fri, 23 Mar 2018 15:18:09 -0400 Subject: [PATCH 01/44] Resolves #262: add qiskit.backend methods... for getting parameter, calibration, and status. --- qiskit/_quantumprogram.py | 82 ++------------------- qiskit/backends/__init__.py | 5 +- qiskit/backends/_backendutils.py | 69 +++++++++++++++++- qiskit/backends/_basebackend.py | 19 +++++ qiskit/backends/_qeremote.py | 85 ++++++++++++++++++++++ test/performance/vqe.py | 2 +- test/python/test_projectq_cpp_simulator.py | 66 ++++++++--------- test/python/test_quantumprogram.py | 24 +++--- tools/random_qasm_generator.py | 2 +- 9 files changed, 228 insertions(+), 126 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index 4a0155ff2262..4969074492dc 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -824,19 +824,9 @@ def get_backend_status(self, backend): ConnectionError: if the API call failed. ValueError: if the backend is not available. """ + return qiskit.backends.status(backend) - if backend in self.__ONLINE_BACKENDS: - try: - return self.__api.backend_status(backend) - except Exception as ex: - raise ConnectionError("Couldn't get backend status: {0}" - .format(ex)) - elif backend in self.__LOCAL_BACKENDS: - return {'available': True} - else: - raise ValueError('the backend "{0}" is not available'.format(backend)) - - def get_backend_configuration(self, backend, list_format=False): + def configuration(self, backend, list_format=False): """Return the configuration of the backend. The return is via QX API call. @@ -854,36 +844,7 @@ def get_backend_configuration(self, backend, list_format=False): LookupError: if a configuration for the named backend can't be found. """ - if self.get_api(): - configuration_edit = {} - try: - backends = self.__api.available_backends() - except Exception as ex: - raise ConnectionError("Couldn't get available backend list: {0}" - .format(ex)) - for configuration in backends: - if configuration['name'] == backend: - for key in configuration: - new_key = convert(key) - # TODO: removed these from the API code - if new_key not in ['id', 'serial_number', 'topology_id', - 'status', 'coupling_map']: - configuration_edit[new_key] = configuration[key] - if new_key == 'coupling_map': - if configuration[key] == 'all-to-all': - configuration_edit[new_key] = \ - configuration[key] - else: - if not list_format: - cmap = mapper.coupling_list2dict(configuration[key]) - else: - cmap = configuration[key] - configuration_edit[new_key] = cmap - return configuration_edit - raise LookupError('Configuration for %s could not be found.' % - backend) - else: - return qiskit.backends.get_backend_configuration(backend) + return qiskit.backends.configuration(backend) def get_backend_calibration(self, backend): """Return the online backend calibrations. @@ -901,23 +862,9 @@ def get_backend_calibration(self, backend): LookupError: If a configuration for the named backend can't be found. """ - if backend in self.__ONLINE_BACKENDS: - try: - calibrations = self.__api.backend_calibration(backend) - except Exception as ex: - raise ConnectionError("Couldn't get backend calibration: {0}" - .format(ex)) - calibrations_edit = {} - for key, vals in calibrations.items(): - new_key = convert(key) - calibrations_edit[new_key] = vals - return calibrations_edit - elif backend in self.__LOCAL_BACKENDS: - return {'backend': backend, 'calibrations': None} - else: - raise LookupError( - 'backend calibration for "{0}" not found'.format(backend)) + return qiskit.backends.calibration(backend) + def get_backend_parameters(self, backend): """Return the online backend parameters. @@ -934,22 +881,7 @@ def get_backend_parameters(self, backend): LookupError: If a configuration for the named backend can't be found. """ - if backend in self.__ONLINE_BACKENDS: - try: - parameters = self.__api.backend_parameters(backend) - except Exception as ex: - raise ConnectionError("Couldn't get backend parameters: {0}" - .format(ex)) - parameters_edit = {} - for key, vals in parameters.items(): - new_key = convert(key) - parameters_edit[new_key] = vals - return parameters_edit - elif backend in self.__LOCAL_BACKENDS: - return {'backend': backend, 'parameters': None} - else: - raise LookupError( - 'backend parameters for "{0}" not found'.format(backend)) + return qiskit.backends.parameters(backend) ############################################################### # methods to compile quantum programs into qobj @@ -1083,7 +1015,7 @@ def compile(self, name_of_circuits=None, backend="local_qasm_simulator", hpc = None qobj['circuits'] = [] - backend_conf = qiskit.backends.get_backend_configuration(backend) + backend_conf = qiskit.backends.configuration(backend) if not basis_gates: if 'basis_gates' in backend_conf: basis_gates = backend_conf['basis_gates'] diff --git a/qiskit/backends/__init__.py b/qiskit/backends/__init__.py index e99ad49c7744..cf8ebac3108e 100644 --- a/qiskit/backends/__init__.py +++ b/qiskit/backends/__init__.py @@ -19,7 +19,10 @@ from ._basebackend import BaseBackend from ._backendutils import (get_backend_class, get_backend_instance, - get_backend_configuration, + configuration, + calibration, + parameters, + status, local_backends, remote_backends, register_backend, diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 450e75e66f1a..36c48158ec6e 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -25,6 +25,7 @@ import re from collections import namedtuple +import qiskit from qiskit import mapper from ._basebackend import BaseBackend from .. import QISKitError @@ -89,10 +90,10 @@ def discover_local_backends(directory=os.path.dirname(__file__)): def discover_remote_backends(api): - """Discover backends available on the Quantum Experience + """Discover backends available from IBM Q Args: - api (IBMQuantumExperience): Quantum Experience API + api (IBMQuantumExperience): IBM Q API Returns: list: list of discovered backend names """ @@ -253,7 +254,7 @@ def get_backend_instance(backend_name): configuration=registered_backend.configuration) -def get_backend_configuration(backend_name): +def configuration(backend_name): """Return the configuration for the named backend. Args: @@ -271,6 +272,68 @@ def get_backend_configuration(backend_name): raise LookupError('backend "{}" is not available'.format(backend_name)) +def calibration(backend_name): + """Return the calibration for the named backend. + + Args: + backend_name (str): the backend name + + Returns: + dict: calibration dict + + Raises: + LookupError: if backend is unavailable + """ + try: + backend = qiskit.backends.get_backend_instance(backend_name) + except KeyError: + raise LookupError('backend "{}" is not available'.format(backend_name)) + else: + return backend.calibration + + +def parameters(backend_name): + """Return the online backend parameters. + + Args: + backend (str): Name of the backend. + + Returns: + dict: The parameters of the named backend. + + Raises: + ConnectionError: if the API call failed. + LookupError: If parameters for the named backend can't be + found. + """ + try: + backend = qiskit.backends.get_backend_instance(backend_name) + except KeyError: + raise LookupError('backend "{}" is not available'.format(backend_name)) + else: + return backend.parameters + + +def status(backend_name): + """Return the status for the named backend. + + Args: + backend_name (str): the backend name + + Returns: + dict: status dict + + Raises: + LookupError: if backend is unavailable + """ + try: + backend = qiskit.backends.get_backend_instance(backend_name) + except KeyError: + raise LookupError('backend "{}" is not available'.format(backend_name)) + else: + return backend.status + + def local_backends(): """Get the local backends.""" return [backend.name for backend in _REGISTERED_BACKENDS.values() diff --git a/qiskit/backends/_basebackend.py b/qiskit/backends/_basebackend.py index 7a8ce5607704..67fafc707ceb 100644 --- a/qiskit/backends/_basebackend.py +++ b/qiskit/backends/_basebackend.py @@ -20,6 +20,7 @@ To create add-on backend modules subclass the Backend class in this module. Doing so requires that the required backend interface is implemented. """ +import abc from abc import ABC, abstractmethod @@ -50,3 +51,21 @@ def run(self, q_job): def configuration(self): """Return backend configuration""" return self._configuration + + @property + def calibration(self): + """Return backend calibration""" + backend_name = self.configuration['name'] + return {'backend': backend_name, 'calibrations': None} + + @property + def parameters(self): + """Return backend parameters""" + backend_name = self.configuration['name'] + return {'backend': backend_name, 'parameters': None} + + @property + def status(self): + """Return backend status""" + backend_name = self.configuration['name'] + return {'available': True} diff --git a/qiskit/backends/_qeremote.py b/qiskit/backends/_qeremote.py index 9906c0889885..c77e7d9a9bb9 100644 --- a/qiskit/backends/_qeremote.py +++ b/qiskit/backends/_qeremote.py @@ -22,6 +22,7 @@ import logging import pprint from qiskit.backends._basebackend import BaseBackend +from qiskit.backends._backendutils import _snake_case_to_camel_case from qiskit import _openquantumcompiler as openquantumcompiler from qiskit import QISKitError from qiskit._result import Result @@ -116,6 +117,88 @@ def set_api(cls, api): cls._api = api + @property + def calibration(self): + """Return the online backend calibrations. + + The return is via QX API call. + + Returns: + dict: The calibration of the backend. + + Raises: + ConnectionError: if the API call failed. + LookupError: If a configuration for the backend can't be + found. + """ + if self._api: + try: + backend_name = self.configuration['name'] + calibrations = self._api.backend_calibration(backend_name) + except Exception as ex: + raise ConnectionError("Couldn't get backend calibration: {0}" + .format(ex)) + else: + raise ConnectionError('API not set') + calibrations_edit = {} + for key, vals in calibrations.items(): + new_key = _snake_case_to_camel_case(key) + calibrations_edit[new_key] = vals + return calibrations_edit + + + @property + def parameters(self): + """Return the online backend parameters. + + Returns: + dict: The parameters of the backend. + + Raises: + ConnectionError: if the API call faled. + LookupError: If parameters for the backend can't be + found. + """ + if self._api: + try: + backend_name = self.configuration['name'] + parameters = self._api.backend_parameters(backend_name) + except Exception as ex: + raise ConnectionError("Couldn't get backend parameters: {0}" + .format(ex)) + parameters_edit = {} + for key, vals in parameters.items(): + new_key = _snake_case_to_camel_case(key) + parameters_edit[new_key] = vals + return parameters_edit + else: + raise ConnectionError('API not set') + + + @property + def status(self): + """Return the online backend status. + + Returns: + dict: The status of the backend. + + Raises: + ConnectionError: if the API call failed. + LookupError: If status for the backend can't be + found. + """ + if self._api: + try: + backend_name = self.configuration['name'] + status = self._api.backend_status(backend_name) + except Exception as ex: + raise ConnectionError("Couldn't get backend status: {0}" + .format(ex)) + else: + return status + else: + raise ConnectionError('API not set') + def _wait_for_job(jobid, api, wait=5, timeout=60): """Wait until all online ran circuits of a qobj are 'COMPLETED'. @@ -161,3 +244,5 @@ def _wait_for_job(jobid, api, wait=5, timeout=60): 'status': job_result['qasms'][index]['status']}) return {'job_id': jobid, 'status': job_result['status'], 'result': job_result_return} + + diff --git a/test/performance/vqe.py b/test/performance/vqe.py index 4cf5c09617cb..6bf4e5a76a6e 100644 --- a/test/performance/vqe.py +++ b/test/performance/vqe.py @@ -83,7 +83,7 @@ def vqe(molecule='H2', depth=6, max_trials=200, shots=1): if shots != 1: H = group_paulis(pauli_list) - entangler_map = qp.get_backend_configuration(device)['coupling_map'] + entangler_map = qp.configuration(device)['coupling_map'] if entangler_map == 'all-to-all': entangler_map = {i: [j for j in range(n_qubits) if j != i] for i in range(n_qubits)} diff --git a/test/python/test_projectq_cpp_simulator.py b/test/python/test_projectq_cpp_simulator.py index 163f7007fc15..76a875347325 100644 --- a/test/python/test_projectq_cpp_simulator.py +++ b/test/python/test_projectq_cpp_simulator.py @@ -143,39 +143,39 @@ def test_entangle(self): with self.subTest(key=key): self.assertTrue(key in ['0' * N, '1' * N]) - 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 = openquantumcompiler.compile(circuit.qasm()) - shots = 100 - 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)) - self.assertTrue(counts_pq.keys() == counts_py.keys()) - 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_random_circuits(self): + # local_simulator = qasm_simulator.QasmSimulator() + # for circuit in self.rqg.get_circuits(format_='QuantumCircuit'): + # self.log.info(circuit.qasm()) + # compiled_circuit = openquantumcompiler.compile(circuit.qasm()) + # shots = 100 + # 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)) + # self.assertTrue(counts_pq.keys() == counts_py.keys()) + # 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) if __name__ == '__main__': diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index e729b108b575..853ce3b8fa3d 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -637,7 +637,7 @@ def test_backend_status(self): If all correct should return dictionary with available: True/False. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - out = q_program.get_backend_status("local_qasm_simulator") + out = qiskit.backends.status("local_qasm_simulator") self.assertIn(out['available'], [True]) def test_backend_status_fail(self): @@ -646,10 +646,10 @@ def test_backend_status_fail(self): If all correct should return dictionary with available: True/False. """ qp = QuantumProgram(specs=self.QPS_SPECS) - self.assertRaises(ValueError, qp.get_backend_status, "fail") + self.assertRaises(LookupError, qp.get_backend_status, "fail") - def test_get_backend_configuration(self): - """Test get_backend_configuration. + def test_configuration(self): + """Test configuration. If all correct should return configuration for the local_qasm_simulator. @@ -657,17 +657,17 @@ def test_get_backend_configuration(self): qp = QuantumProgram(specs=self.QPS_SPECS) config_keys = {'name', 'simulator', 'local', 'description', 'coupling_map', 'basis_gates'} - backend_config = qp.get_backend_configuration("local_qasm_simulator") + backend_config = qp.configuration("local_qasm_simulator") self.assertTrue(config_keys < backend_config.keys()) - def test_get_backend_configuration_fail(self): - """Test get_backend_configuration fail. + def test_configuration_fail(self): + """Test configuration fail. If all correct should return LookupError. """ qp = QuantumProgram(specs=self.QPS_SPECS) - # qp.get_backend_configuration("fail") - self.assertRaises(LookupError, qp.get_backend_configuration, "fail") + # qp.configuration("fail") + self.assertRaises(LookupError, qp.configuration, "fail") @requires_qe_access def test_get_backend_calibration(self, QE_TOKEN, QE_URL): @@ -680,7 +680,7 @@ def test_get_backend_calibration(self, QE_TOKEN, QE_URL): backend_list = q_program.online_backends() if backend_list: backend = backend_list[0] - result = q_program.get_backend_calibration(backend) + result = qiskit.backends.calibration(backend) self.log.info(result) self.assertEqual(len(result), 4) @@ -695,7 +695,7 @@ def test_get_backend_parameters(self, QE_TOKEN, QE_URL): backend_list = q_program.online_backends() if backend_list: backend = backend_list[0] - result = q_program.get_backend_parameters(backend) + result = qiskit.backends.parameters(backend) self.log.info(result) self.assertEqual(len(result), 4) @@ -1391,7 +1391,7 @@ def test_execute_one_circuit_real_online(self, QE_TOKEN, QE_URL): q_program.set_api(QE_TOKEN, QE_URL) backend = 'ibmqx_qasm_simulator' shots = 1 # the number of shots in the experiment. - status = q_program.get_backend_status(backend) + status = qiskit.backends.status(backend) if not status.get('available', False): pass else: diff --git a/tools/random_qasm_generator.py b/tools/random_qasm_generator.py index 32631c6c3238..83e8177d661d 100755 --- a/tools/random_qasm_generator.py +++ b/tools/random_qasm_generator.py @@ -124,4 +124,4 @@ def create_circuit(self, do_measure=True): depth=args.depth, qubits=args.qubits) qasm = random_circuit.create_circuit(do_measure=args.measure) - print("%s" % qasm) \ No newline at end of file + print("%s" % qasm) From dde57404b3c4fc44dc3ff819fab626576534cfaf Mon Sep 17 00:00:00 2001 From: Ali Javadi-Abhari Date: Sun, 25 Mar 2018 13:04:22 -0400 Subject: [PATCH 02/44] linting quantumprogram --- qiskit/_quantumprogram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index 4969074492dc..974d709c6a51 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -864,7 +864,7 @@ def get_backend_calibration(self, backend): """ return qiskit.backends.calibration(backend) - + def get_backend_parameters(self, backend): """Return the online backend parameters. From e25b43a70a6bd0bb33d1911b8af1cd1f100bf48d Mon Sep 17 00:00:00 2001 From: Ali Javadi-Abhari Date: Sun, 25 Mar 2018 13:05:45 -0400 Subject: [PATCH 03/44] Update _backendutils.py --- qiskit/backends/_backendutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 36c48158ec6e..4146ae862607 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -290,7 +290,7 @@ def calibration(backend_name): raise LookupError('backend "{}" is not available'.format(backend_name)) else: return backend.calibration - + def parameters(backend_name): """Return the online backend parameters. From d2bdde202f72002a732eaef12302bea044c98325 Mon Sep 17 00:00:00 2001 From: Ali Javadi-Abhari Date: Sun, 25 Mar 2018 13:06:15 -0400 Subject: [PATCH 04/44] Update _backendutils.py --- qiskit/backends/_backendutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 4146ae862607..63fd0c4bd3ac 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -321,7 +321,7 @@ def status(backend_name): backend_name (str): the backend name Returns: - dict: status dict + dict: status dict Raises: LookupError: if backend is unavailable From b88a852363d4dbf53d6db19e64be6918de8d7c9f Mon Sep 17 00:00:00 2001 From: Ali Javadi-Abhari Date: Sun, 25 Mar 2018 13:06:41 -0400 Subject: [PATCH 05/44] Update _basebackend.py --- qiskit/backends/_basebackend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qiskit/backends/_basebackend.py b/qiskit/backends/_basebackend.py index 67fafc707ceb..d376f2e1a768 100644 --- a/qiskit/backends/_basebackend.py +++ b/qiskit/backends/_basebackend.py @@ -57,13 +57,13 @@ def calibration(self): """Return backend calibration""" backend_name = self.configuration['name'] return {'backend': backend_name, 'calibrations': None} - + @property def parameters(self): """Return backend parameters""" backend_name = self.configuration['name'] return {'backend': backend_name, 'parameters': None} - + @property def status(self): """Return backend status""" From 47aab7e9b097d6bff6f68adc64b7fff8a4ef97c0 Mon Sep 17 00:00:00 2001 From: Ali Javadi-Abhari Date: Sun, 25 Mar 2018 13:10:34 -0400 Subject: [PATCH 06/44] Update _qeremote.py --- qiskit/backends/_qeremote.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/qiskit/backends/_qeremote.py b/qiskit/backends/_qeremote.py index c77e7d9a9bb9..8418d41a1c1f 100644 --- a/qiskit/backends/_qeremote.py +++ b/qiskit/backends/_qeremote.py @@ -116,7 +116,6 @@ def set_api(cls, api): """Associate API with class""" cls._api = api - @property def calibration(self): """Return the online backend calibrations. @@ -133,11 +132,11 @@ def calibration(self): """ if self._api: try: - backend_name = self.configuration['name'] + backend_name = self.configuration['name'] calibrations = self._api.backend_calibration(backend_name) except Exception as ex: raise ConnectionError("Couldn't get backend calibration: {0}" - .format(ex)) + .format(ex)) else: raise ConnectionError('API not set') calibrations_edit = {} @@ -146,7 +145,6 @@ def calibration(self): calibrations_edit[new_key] = vals return calibrations_edit - @property def parameters(self): """Return the online backend parameters. @@ -174,7 +172,6 @@ def parameters(self): else: raise ConnectionError('API not set') - @property def status(self): """Return the online backend status. @@ -197,7 +194,8 @@ def status(self): else: return status else: - raise ConnectionError('API not set') + raise ConnectionError('API not set') + def _wait_for_job(jobid, api, wait=5, timeout=60): """Wait until all online ran circuits of a qobj are 'COMPLETED'. @@ -244,5 +242,3 @@ def _wait_for_job(jobid, api, wait=5, timeout=60): 'status': job_result['qasms'][index]['status']}) return {'job_id': jobid, 'status': job_result['status'], 'result': job_result_return} - - From cb078a6b85f646200cfd2647dc5270875f1d6061 Mon Sep 17 00:00:00 2001 From: Ali Javadi-Abhari Date: Sun, 25 Mar 2018 13:11:25 -0400 Subject: [PATCH 07/44] Update _basebackend.py --- qiskit/backends/_basebackend.py | 1 - 1 file changed, 1 deletion(-) diff --git a/qiskit/backends/_basebackend.py b/qiskit/backends/_basebackend.py index d376f2e1a768..27cd390427bf 100644 --- a/qiskit/backends/_basebackend.py +++ b/qiskit/backends/_basebackend.py @@ -20,7 +20,6 @@ To create add-on backend modules subclass the Backend class in this module. Doing so requires that the required backend interface is implemented. """ -import abc from abc import ABC, abstractmethod From 327435cf6061f82479d4f459edac553caf11b165 Mon Sep 17 00:00:00 2001 From: Ali Javadi-Abhari Date: Sun, 25 Mar 2018 13:22:07 -0400 Subject: [PATCH 08/44] Update _quantumprogram.py --- qiskit/_quantumprogram.py | 1 - 1 file changed, 1 deletion(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index 974d709c6a51..9c5299cd9dff 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -864,7 +864,6 @@ def get_backend_calibration(self, backend): """ return qiskit.backends.calibration(backend) - def get_backend_parameters(self, backend): """Return the online backend parameters. From 358e58b31c10a3a9733e97d7d2e183f3c3b310bd Mon Sep 17 00:00:00 2001 From: Ali Javadi-Abhari Date: Sun, 25 Mar 2018 13:22:28 -0400 Subject: [PATCH 09/44] Update _qeremote.py --- qiskit/backends/_qeremote.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/backends/_qeremote.py b/qiskit/backends/_qeremote.py index 8418d41a1c1f..6004b49c7964 100644 --- a/qiskit/backends/_qeremote.py +++ b/qiskit/backends/_qeremote.py @@ -170,7 +170,7 @@ def parameters(self): parameters_edit[new_key] = vals return parameters_edit else: - raise ConnectionError('API not set') + raise ConnectionError('API not set') @property def status(self): From db252f25371df7de50edffc43b00e1a8792fe041 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 13:31:48 -0400 Subject: [PATCH 10/44] Warning, updates to test, and backencs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added to the quantum program warnings — may of done this incorrect 2. Removed old versions 3. In the configuration we lost the rewrite of the mapping. I agree we want to update the API but first we need the backend configuration to work 4. Made the test use quantum program Still to be done — check why failing some test — add some test to backend that test the test_basebackends that test new methods --- qiskit/_quantumprogram.py | 200 ++++++++++++++--------------- qiskit/backends/_backendutils.py | 29 ++++- test/python/test_quantumprogram.py | 72 ++++++----- 3 files changed, 167 insertions(+), 134 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index 9c5299cd9dff..ddee499ab742 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -27,6 +27,7 @@ import re from threading import Event import copy +import warnings # use the external IBMQuantumExperience Library import itertools @@ -479,6 +480,76 @@ def load_qasm_text(self, qasm_string, name=None, self.add_circuit(name, circuit_unrolled) return name + def save(self, file_name=None, beauty=False): + """ Save Quantum Program in a Json file. + + Args: + file_name (str): file name and path. + beauty (boolean): save the text with indent 4 to make it readable. + + Returns: + dict: The dictionary with the status and result of the operation + + Raises: + LookupError: if the file_name is not correct, or writing to the + file resulted in an error. + """ + if file_name is None: + error = {"status": "Error", "result": "Not filename provided"} + raise LookupError(error['result']) + + if beauty: + indent = 4 + else: + indent = 0 + + elemements_to_save = self.__quantum_program + elements_saved = {} + + for circuit in elemements_to_save: + elements_saved[circuit] = {} + elements_saved[circuit]["qasm"] = elemements_to_save[circuit].qasm() + + try: + with open(file_name, 'w') as save_file: + json.dump(elements_saved, save_file, indent=indent) + return {'status': 'Done', 'result': elemements_to_save} + except ValueError: + error = {'status': 'Error', 'result': 'Some Problem happened to save the file'} + raise LookupError(error['result']) + + def load(self, file_name=None): + """ Load Quantum Program Json file into the Quantum Program object. + + Args: + file_name (str): file name and path. + + Returns: + dict: The dictionary with the status and result of the operation + + Raises: + LookupError: if the file_name is not correct, or reading from the + file resulted in an error. + """ + if file_name is None: + error = {"status": "Error", "result": "Not filename provided"} + raise LookupError(error['result']) + + try: + with open(file_name, 'r') as load_file: + elemements_loaded = json.load(load_file) + + for circuit in elemements_loaded: + circuit_qasm = elemements_loaded[circuit]["qasm"] + elemements_loaded[circuit] = qasm.Qasm(data=circuit_qasm).parse() + self.__quantum_program = elemements_loaded + + return {"status": 'Done', 'result': self.__quantum_program} + + except ValueError: + error = {'status': 'Error', 'result': 'Some Problem happened to load the file'} + raise LookupError(error['result']) + ############################################################### # methods to get elements from a QuantumProgram ############################################################### @@ -623,6 +694,7 @@ def set_api(self, token, url, hub=None, group=None, project=None, ConnectionError: if the API instantiation failed. QISKitError: if no hub, group or project were specified. """ + warnings.warn("get_api_config is going to be deprecated. Please use the api object", DeprecationWarning) try: config_dict = { 'url': url, @@ -653,6 +725,7 @@ def set_api_hubs_config(self, hub, group, project): group (str): The group used for online backend. project (str): The project used for online backend. """ + warnings.warn("get_api_config is going to be deprecated. Please use the api object", DeprecationWarning) config_dict = { 'hub': hub, 'group': group, @@ -665,85 +738,18 @@ def set_api_hubs_config(self, hub, group, project): def get_api_config(self): """Return the program specs.""" + warnings.warn("get_api_config is going to be deprecated. Please use the api object", DeprecationWarning) return self.__api_config def get_api(self): """Returns a function handle to the API.""" + warnings.warn("get_api is going to be deprecated. Please use the api object", DeprecationWarning) return self.__api - def save(self, file_name=None, beauty=False): - """ Save Quantum Program in a Json file. - - Args: - file_name (str): file name and path. - beauty (boolean): save the text with indent 4 to make it readable. - - Returns: - dict: The dictionary with the status and result of the operation - - Raises: - LookupError: if the file_name is not correct, or writing to the - file resulted in an error. - """ - if file_name is None: - error = {"status": "Error", "result": "Not filename provided"} - raise LookupError(error['result']) - - if beauty: - indent = 4 - else: - indent = 0 - - elemements_to_save = self.__quantum_program - elements_saved = {} - - for circuit in elemements_to_save: - elements_saved[circuit] = {} - elements_saved[circuit]["qasm"] = elemements_to_save[circuit].qasm() - - try: - with open(file_name, 'w') as save_file: - json.dump(elements_saved, save_file, indent=indent) - return {'status': 'Done', 'result': elemements_to_save} - except ValueError: - error = {'status': 'Error', 'result': 'Some Problem happened to save the file'} - raise LookupError(error['result']) - - def load(self, file_name=None): - """ Load Quantum Program Json file into the Quantum Program object. - - Args: - file_name (str): file name and path. - - Returns: - dict: The dictionary with the status and result of the operation - - Raises: - LookupError: if the file_name is not correct, or reading from the - file resulted in an error. - """ - if file_name is None: - error = {"status": "Error", "result": "Not filename provided"} - raise LookupError(error['result']) - - try: - with open(file_name, 'r') as load_file: - elemements_loaded = json.load(load_file) - - for circuit in elemements_loaded: - circuit_qasm = elemements_loaded[circuit]["qasm"] - elemements_loaded[circuit] = qasm.Qasm(data=circuit_qasm).parse() - self.__quantum_program = elemements_loaded - - return {"status": 'Done', 'result': self.__quantum_program} - - except ValueError: - error = {'status': 'Error', 'result': 'Some Problem happened to load the file'} - raise LookupError(error['result']) - def available_backends(self): """All the backends that are seen by QISKIT.""" - return self.__ONLINE_BACKENDS + self.__LOCAL_BACKENDS + warnings.warn("available_backends is going to be deprecated. Please use qiskit.backends.local_backends() + qiskit.backends.discover_remote_backends(api)", DeprecationWarning) + return qiskit.backends.local_backends() + qiskit.backends.discover_remote_backends(self.__api) def online_backends(self): """Get the online backends. @@ -757,14 +763,8 @@ def online_backends(self): Raises: ConnectionError: if the API call failed. """ - if self.get_api(): - try: - backends = self.__api.available_backends() - except Exception as ex: - raise ConnectionError("Couldn't get available backend list: {0}" - .format(ex)) - return [backend['name'] for backend in backends] - return [] + warnings.warn("online_backends is going to be deprecated. Please use qiskit.backends.discover_remote_backends(api)", DeprecationWarning) + return qiskit.backends.discover_remote_backends(self.__api) def online_simulators(self): """Gets online simulators via QX API calls. @@ -776,15 +776,12 @@ def online_simulators(self): ConnectionError: if the API call failed. """ online_simulators_list = [] - if self.get_api(): - try: - backends = self.__api.available_backends() - except Exception as ex: - raise ConnectionError("Couldn't get available backend list: {0}" - .format(ex)) - for backend in backends: - if backend['simulator']: - online_simulators_list.append(backend['name']) + online_backends = qiskit.backends.discover_remote_backends(self.__api) + warnings.warn("online_simulators is going to be deprecated. Do we actually need this function", DeprecationWarning) + for backend in online_backends: + config = qiskit.backends.configuration(backend) + if config['simulator']: + online_simulators_list.append(backend) return online_simulators_list def online_devices(self): @@ -796,17 +793,14 @@ def online_devices(self): Raises: ConnectionError: if the API call failed. """ - devices = [] - if self.get_api(): - try: - backends = self.__api.available_backends() - except Exception as ex: - raise ConnectionError("Couldn't get available backend list: {0}" - .format(ex)) - for backend in backends: - if not backend['simulator']: - devices.append(backend['name']) - return devices + online_device_list = [] + online_backends = qiskit.backends.discover_remote_backends(self.__api) + warnings.warn("online_devices is going to be deprecated. Do we actually need this function", DeprecationWarning) + for backend in online_backends: + config = qiskit.backends.configuration(backend) + if not config['simulator']: + online_device_list.append(backend) + return online_device_list def get_backend_status(self, backend): """Return the online backend status. @@ -824,9 +818,10 @@ def get_backend_status(self, backend): ConnectionError: if the API call failed. ValueError: if the backend is not available. """ + warnings.warn("get_backend_status('name') is going to be deprecated. Please use qiskit.backends.status('name')", DeprecationWarning) return qiskit.backends.status(backend) - def configuration(self, backend, list_format=False): + def get_backend_configuration(self, backend, list_format=True): """Return the configuration of the backend. The return is via QX API call. @@ -844,7 +839,8 @@ def configuration(self, backend, list_format=False): LookupError: if a configuration for the named backend can't be found. """ - return qiskit.backends.configuration(backend) + warnings.warn("get_backend_configuration('name') is going to be deprecated. Please use qiskit.backends.configuration('name')", DeprecationWarning) + return qiskit.backends.configuration(backend, list_format) def get_backend_calibration(self, backend): """Return the online backend calibrations. @@ -862,6 +858,7 @@ def get_backend_calibration(self, backend): LookupError: If a configuration for the named backend can't be found. """ + warnings.warn("get_backend_calibration('name') is going to be deprecated. Please use qiskit.backends.calibration('name')", DeprecationWarning) return qiskit.backends.calibration(backend) def get_backend_parameters(self, backend): @@ -880,6 +877,7 @@ def get_backend_parameters(self, backend): LookupError: If a configuration for the named backend can't be found. """ + warnings.warn("get_backend_parameters('name') is going to be deprecated. Please use qiskit.backends.parameters('name')", DeprecationWarning) return qiskit.backends.parameters(backend) ############################################################### diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 63fd0c4bd3ac..2e1d7b775bff 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -24,6 +24,7 @@ import pkgutil import re from collections import namedtuple +import warnings import qiskit from qiskit import mapper @@ -254,7 +255,7 @@ def get_backend_instance(backend_name): configuration=registered_backend.configuration) -def configuration(backend_name): +def configuration(backend_name, list_format=True): """Return the configuration for the named backend. Args: @@ -267,7 +268,27 @@ def configuration(backend_name): LookupError: if backend is unavailable """ try: - return _REGISTERED_BACKENDS[backend_name].configuration + config = _REGISTERED_BACKENDS[backend_name].configuration + if not config['local']: + ### THIS IS A HACK TO CONVERT THE BACKEND TO THE NEW FORMAT AND + ### WILL BE REMOVED WHEN THE API IS UPDATED. IT WILL BE SIMPLY A RETURN CONFIG + config_edit = config + if config['coupling_map'] == 'all-to-all': + config_edit['coupling_map'] = config['coupling_map'] + else: + cmap = config['coupling_map'] + cmap_new = [] + for key in cmap: + for i in cmap[key]: + cmap_new.append([key,i]) + if not list_format: + ### THIS IS KEEP AROUND FOR CODE THAT IS STILL USING THE DICTIONARY FORMAT OF THE COUPLING MAP + warnings.warn("dictionary format of coupling_map will be deprecated. Please rewrite code using a list for the coulping_map", DeprecationWarning) + cmap_new = mapper.coupling_list2dict(cmap_new) + config_edit['coupling_map'] = cmap_new + return config_edit + else: + return config except KeyError: raise LookupError('backend "{}" is not available'.format(backend_name)) @@ -290,7 +311,7 @@ def calibration(backend_name): raise LookupError('backend "{}" is not available'.format(backend_name)) else: return backend.calibration - + def parameters(backend_name): """Return the online backend parameters. @@ -321,7 +342,7 @@ def status(backend_name): backend_name (str): the backend name Returns: - dict: status dict + dict: status dict Raises: LookupError: if backend is unavailable diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index 853ce3b8fa3d..28e4e968894b 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -581,55 +581,47 @@ def test_available_backends_exist(self, QE_TOKEN, QE_URL): q_program = QuantumProgram(specs=self.QPS_SPECS) q_program.set_api(QE_TOKEN, QE_URL) available_backends = q_program.available_backends() + #print(available_backends) self.assertTrue(available_backends) - def test_local_backends_exist(self): - """Test if there are local backends. - - If all correct some should exists (even if ofline). - """ - _ = QuantumProgram(specs=self.QPS_SPECS) - local_backends = qiskit.backends.local_backends() - self.assertTrue(local_backends) - @requires_qe_access def test_online_backends_exist(self, QE_TOKEN, QE_URL): """Test if there are online backends. If all correct some should exists. """ - # TODO: Jay should we check if we the QX is online before runing. q_program = QuantumProgram(specs=self.QPS_SPECS) q_program.set_api(QE_TOKEN, QE_URL) online_backends = q_program.online_backends() + #print(online_backends) self.log.info(online_backends) self.assertTrue(online_backends) @requires_qe_access - def test_online_devices(self, QE_TOKEN, QE_URL): - """Test if there are online backends (which are devices). + def test_online_simulators(self, QE_TOKEN, QE_URL): + """Test if there are online backends (which are simulators). If all correct some should exists. NEED internet connection for this. """ - # TODO: Jay should we check if we the QX is online before runing. qp = QuantumProgram(specs=self.QPS_SPECS) qp.set_api(QE_TOKEN, QE_URL) - online_devices = qp.online_devices() - self.log.info(online_devices) - self.assertTrue(isinstance(online_devices, list)) + online_simulators = qp.online_simulators() + #print(online_simulators) + self.log.info(online_simulators) + self.assertTrue(isinstance(online_simulators, list)) @requires_qe_access - def test_online_simulators(self, QE_TOKEN, QE_URL): - """Test if there are online backends (which are simulators). + def test_online_devices(self, QE_TOKEN, QE_URL): + """Test if there are online backends (which are devices). If all correct some should exists. NEED internet connection for this. """ - # TODO: Jay should we check if we the QX is online before runing. qp = QuantumProgram(specs=self.QPS_SPECS) qp.set_api(QE_TOKEN, QE_URL) - online_simulators = qp.online_simulators() - self.log.info(online_simulators) - self.assertTrue(isinstance(online_simulators, list)) + online_devices = qp.online_devices() + #print(online_devices) + self.log.info(online_devices) + self.assertTrue(isinstance(online_devices, list)) def test_backend_status(self): """Test backend_status. @@ -637,7 +629,8 @@ def test_backend_status(self): If all correct should return dictionary with available: True/False. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - out = qiskit.backends.status("local_qasm_simulator") + out = q_program.get_backend_status("local_qasm_simulator") + #print(out) self.assertIn(out['available'], [True]) def test_backend_status_fail(self): @@ -648,7 +641,21 @@ def test_backend_status_fail(self): qp = QuantumProgram(specs=self.QPS_SPECS) self.assertRaises(LookupError, qp.get_backend_status, "fail") - def test_configuration(self): + def test_get_backend_configuration(self): + """Test configuration. + + If all correct should return configuration for the + local_qasm_simulator. + """ + qp = QuantumProgram(specs=self.QPS_SPECS) + config_keys = {'name', 'simulator', 'local', 'description', + 'coupling_map', 'basis_gates'} + backend_config = qp.get_backend_configuration("local_qasm_simulator") + #print(backend_config) + self.assertTrue(config_keys < backend_config.keys()) + + @requires_qe_access + def test_get_backend_configuration_online(self, QE_TOKEN, QE_URL): """Test configuration. If all correct should return configuration for the @@ -657,17 +664,22 @@ def test_configuration(self): qp = QuantumProgram(specs=self.QPS_SPECS) config_keys = {'name', 'simulator', 'local', 'description', 'coupling_map', 'basis_gates'} - backend_config = qp.configuration("local_qasm_simulator") + qp.set_api(QE_TOKEN, QE_URL) + backend_list = qp.online_backends() + if backend_list: + backend = backend_list[0] + backend_config = qp.get_backend_configuration(backend) + #print(backend_config) self.assertTrue(config_keys < backend_config.keys()) - def test_configuration_fail(self): + def test_get_backend_configuration_fail(self): """Test configuration fail. If all correct should return LookupError. """ qp = QuantumProgram(specs=self.QPS_SPECS) # qp.configuration("fail") - self.assertRaises(LookupError, qp.configuration, "fail") + self.assertRaises(LookupError, qp.get_backend_configuration, "fail") @requires_qe_access def test_get_backend_calibration(self, QE_TOKEN, QE_URL): @@ -680,7 +692,8 @@ def test_get_backend_calibration(self, QE_TOKEN, QE_URL): backend_list = q_program.online_backends() if backend_list: backend = backend_list[0] - result = qiskit.backends.calibration(backend) + result = q_program.get_backend_calibration(backend) + #print(result) self.log.info(result) self.assertEqual(len(result), 4) @@ -695,7 +708,8 @@ def test_get_backend_parameters(self, QE_TOKEN, QE_URL): backend_list = q_program.online_backends() if backend_list: backend = backend_list[0] - result = qiskit.backends.parameters(backend) + result = q_program.get_backend_parameters(backend) + #print(result) self.log.info(result) self.assertEqual(len(result), 4) From 8f868192465482ae6de80f0416be77a31b5f29fe Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 14:03:32 -0400 Subject: [PATCH 11/44] Fixing some spelling and linting --- qiskit/_quantumprogram.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index ddee499ab742..4c087076ad71 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -111,7 +111,7 @@ def __init__(self, specs=None): self.__quantum_registers = {} self.__classical_registers = {} self.__quantum_program = {} # stores all the quantum programs - self.__init_circuit = None # stores the intial quantum circuit of the program + self.__init_circuit = None # stores the initial quantum circuit of the program self.__ONLINE_BACKENDS = [] # pylint: disable=invalid-name self.__LOCAL_BACKENDS = qiskit.backends.local_backends() # pylint: disable=invalid-name self.__counter = itertools.count() @@ -175,16 +175,16 @@ def __init_specs(self, specs): }] }], """ - quantumr = [] - classicalr = [] + quantum_r = [] + classical_r = [] if "circuits" in specs: for circuit in specs["circuits"]: - quantumr = self.create_quantum_registers( + quantum_r = self.create_quantum_registers( circuit["quantum_registers"]) - classicalr = self.create_classical_registers( + classical_r = self.create_classical_registers( circuit["classical_registers"]) - self.create_circuit(name=circuit.get("name"), qregisters=quantumr, - cregisters=classicalr) + self.create_circuit(name=circuit.get("name"), qregisters=quantum_r, + cregisters=classical_r) # TODO: Jay: I think we should return function handles for the # registers and circuit. So that we dont need to get them after we # create them with get_quantum_register etc @@ -310,7 +310,7 @@ def create_classical_registers(self, registers_array): is not defined (or None) a random name wil be assigned. Returns: - list(ClassicalRegister): Array of clasical registers objects + list(ClassicalRegister): Array of classical registers objects """ new_registers = [] for register in registers_array: @@ -503,17 +503,17 @@ def save(self, file_name=None, beauty=False): else: indent = 0 - elemements_to_save = self.__quantum_program + elements_to_save = self.__quantum_program elements_saved = {} - for circuit in elemements_to_save: + for circuit in elements_to_save: elements_saved[circuit] = {} - elements_saved[circuit]["qasm"] = elemements_to_save[circuit].qasm() + elements_saved[circuit]["qasm"] = elements_to_save[circuit].qasm() try: with open(file_name, 'w') as save_file: json.dump(elements_saved, save_file, indent=indent) - return {'status': 'Done', 'result': elemements_to_save} + return {'status': 'Done', 'result': elements_to_save} except ValueError: error = {'status': 'Error', 'result': 'Some Problem happened to save the file'} raise LookupError(error['result']) @@ -537,12 +537,12 @@ def load(self, file_name=None): try: with open(file_name, 'r') as load_file: - elemements_loaded = json.load(load_file) + elements_loaded = json.load(load_file) - for circuit in elemements_loaded: - circuit_qasm = elemements_loaded[circuit]["qasm"] - elemements_loaded[circuit] = qasm.Qasm(data=circuit_qasm).parse() - self.__quantum_program = elemements_loaded + for circuit in elements_loaded: + circuit_qasm = elements_loaded[circuit]["qasm"] + elements_loaded[circuit] = qasm.Qasm(data=circuit_qasm).parse() + self.__quantum_program = elements_loaded return {"status": 'Done', 'result': self.__quantum_program} From ad19099832411515b63d219508fe556806f77a27 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 14:21:06 -0400 Subject: [PATCH 12/44] Spelling fixes --- qiskit/_quantumprogram.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index 4c087076ad71..09848987bdff 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -828,7 +828,7 @@ def get_backend_configuration(self, backend, list_format=True): Args: backend (str): Name of the backend. - list_format (bool): Struct used for the configuration coupling + list_format (bool): structure used for the configuration coupling map: dict (if False) or list (if True). Returns: @@ -918,7 +918,7 @@ def compile(self, name_of_circuits=None, backend="local_qasm_simulator", initial_layout (dict): A mapping of qubit to qubit:: { - ("q", strart(int)): ("q", final(int)), + ("q", start(int)): ("q", final(int)), ... } eg. From eef2617530296c7ef494a4c450c3f1430ca22f78 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 14:29:13 -0400 Subject: [PATCH 13/44] Lint and spelling --- qiskit/_quantumprogram.py | 44 ++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index 09848987bdff..c5147a2b53f2 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -694,7 +694,8 @@ def set_api(self, token, url, hub=None, group=None, project=None, ConnectionError: if the API instantiation failed. QISKitError: if no hub, group or project were specified. """ - warnings.warn("get_api_config is going to be deprecated. Please use the api object", DeprecationWarning) + warnings.warn("get_api_config is going to be deprecated. \ + Please use the api object", DeprecationWarning) try: config_dict = { 'url': url, @@ -725,7 +726,8 @@ def set_api_hubs_config(self, hub, group, project): group (str): The group used for online backend. project (str): The project used for online backend. """ - warnings.warn("get_api_config is going to be deprecated. Please use the api object", DeprecationWarning) + warnings.warn("get_api_config is going to be deprecated. \ + Please use the api object", DeprecationWarning) config_dict = { 'hub': hub, 'group': group, @@ -738,18 +740,23 @@ def set_api_hubs_config(self, hub, group, project): def get_api_config(self): """Return the program specs.""" - warnings.warn("get_api_config is going to be deprecated. Please use the api object", DeprecationWarning) + warnings.warn("get_api_config is going to be deprecated. \ + Please use the api object", DeprecationWarning) return self.__api_config def get_api(self): """Returns a function handle to the API.""" - warnings.warn("get_api is going to be deprecated. Please use the api object", DeprecationWarning) + warnings.warn("get_api is going to be deprecated. \ + Please use the api object", DeprecationWarning) return self.__api def available_backends(self): """All the backends that are seen by QISKIT.""" - warnings.warn("available_backends is going to be deprecated. Please use qiskit.backends.local_backends() + qiskit.backends.discover_remote_backends(api)", DeprecationWarning) - return qiskit.backends.local_backends() + qiskit.backends.discover_remote_backends(self.__api) + warnings.warn("available_backends is going to be deprecated. \ + Please use qiskit.backends.local_backends() + \ + qiskit.backends.discover_remote_backends(api)", DeprecationWarning) + return qiskit.backends.local_backends() + \ + qiskit.backends.discover_remote_backends(self.__api) def online_backends(self): """Get the online backends. @@ -763,7 +770,8 @@ def online_backends(self): Raises: ConnectionError: if the API call failed. """ - warnings.warn("online_backends is going to be deprecated. Please use qiskit.backends.discover_remote_backends(api)", DeprecationWarning) + warnings.warn("online_backends is going to be deprecated. \ + Please use qiskit.backends.discover_remote_backends(api)", DeprecationWarning) return qiskit.backends.discover_remote_backends(self.__api) def online_simulators(self): @@ -777,7 +785,8 @@ def online_simulators(self): """ online_simulators_list = [] online_backends = qiskit.backends.discover_remote_backends(self.__api) - warnings.warn("online_simulators is going to be deprecated. Do we actually need this function", DeprecationWarning) + warnings.warn("online_simulators is going to be deprecated. \ + Do we actually need this function", DeprecationWarning) for backend in online_backends: config = qiskit.backends.configuration(backend) if config['simulator']: @@ -795,7 +804,8 @@ def online_devices(self): """ online_device_list = [] online_backends = qiskit.backends.discover_remote_backends(self.__api) - warnings.warn("online_devices is going to be deprecated. Do we actually need this function", DeprecationWarning) + warnings.warn("online_devices is going to be deprecated. \ + Do we actually need this function", DeprecationWarning) for backend in online_backends: config = qiskit.backends.configuration(backend) if not config['simulator']: @@ -818,7 +828,8 @@ def get_backend_status(self, backend): ConnectionError: if the API call failed. ValueError: if the backend is not available. """ - warnings.warn("get_backend_status('name') is going to be deprecated. Please use qiskit.backends.status('name')", DeprecationWarning) + warnings.warn("get_backend_status('name') is going to be deprecated. \ + Please use qiskit.backends.status('name')", DeprecationWarning) return qiskit.backends.status(backend) def get_backend_configuration(self, backend, list_format=True): @@ -839,7 +850,8 @@ def get_backend_configuration(self, backend, list_format=True): LookupError: if a configuration for the named backend can't be found. """ - warnings.warn("get_backend_configuration('name') is going to be deprecated. Please use qiskit.backends.configuration('name')", DeprecationWarning) + warnings.warn("get_backend_configuration('name') is going to be deprecated. \ + Please use qiskit.backends.configuration('name')", DeprecationWarning) return qiskit.backends.configuration(backend, list_format) def get_backend_calibration(self, backend): @@ -858,7 +870,8 @@ def get_backend_calibration(self, backend): LookupError: If a configuration for the named backend can't be found. """ - warnings.warn("get_backend_calibration('name') is going to be deprecated. Please use qiskit.backends.calibration('name')", DeprecationWarning) + warnings.warn("get_backend_calibration('name') is going to be deprecated. \ + Please use qiskit.backends.calibration('name')", DeprecationWarning) return qiskit.backends.calibration(backend) def get_backend_parameters(self, backend): @@ -877,7 +890,8 @@ def get_backend_parameters(self, backend): LookupError: If a configuration for the named backend can't be found. """ - warnings.warn("get_backend_parameters('name') is going to be deprecated. Please use qiskit.backends.parameters('name')", DeprecationWarning) + warnings.warn("get_backend_parameters('name') is going to be deprecated. \ + Please use qiskit.backends.parameters('name')", DeprecationWarning) return qiskit.backends.parameters(backend) ############################################################### @@ -1174,7 +1188,7 @@ def get_compiled_configuration(self, qobj, name): raise QISKitError('No compiled configurations for circuit "{0}"'.format(name)) def get_compiled_qasm(self, qobj, name): - """Return the compiled cricuit in qasm format. + """Return the compiled circuit in qasm format. Args: qobj (dict): the qobj @@ -1393,7 +1407,7 @@ def execute(self, name_of_circuits=None, backend="local_qasm_simulator", Result: status done and populates the internal __quantum_program with the data """ - # TODO: Jay: currently basis_gates, coupling_map, intial_layout, shots, + # TODO: Jay: currently basis_gates, coupling_map, initial_layout, shots, # max_credits, and seed are extra inputs but I would like them to go # into the config qobj = self.compile(name_of_circuits=name_of_circuits, backend=backend, config=config, From 0a86e48924ec340be394c95a945578442b8a816f Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 14:47:32 -0400 Subject: [PATCH 14/44] Linter fixes and some spelling in backendutils --- qiskit/backends/_backendutils.py | 36 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 2e1d7b775bff..70f9f2e03664 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -113,8 +113,8 @@ def discover_remote_backends(api): configuration_edit[new_key] = configuration[key] if new_key == 'coupling_map': if isinstance(configuration[key], list): - cmap = mapper.coupling_list2dict(configuration[key]) - configuration_edit[new_key] = cmap + coupling_map = mapper.coupling_list2dict(configuration[key]) + configuration_edit[new_key] = coupling_map # online_qasm_simulator uses different name for basis_gates if 'gateSet' in configuration: configuration_edit['basis_gates'] = configuration['gateSet'] @@ -209,7 +209,7 @@ def deregister_backend(backend_name): """Remove backend from list of available backens Args: - backend_name (str): name of backend to unregister + backend_name (str): name of backend to deregister Raises: KeyError if backend_name is not registered. @@ -260,6 +260,7 @@ def configuration(backend_name, list_format=True): Args: backend_name (str): the backend name + list_format (bool): to use the old format or new format for coupling map Returns: dict: configuration dict @@ -270,23 +271,25 @@ def configuration(backend_name, list_format=True): try: config = _REGISTERED_BACKENDS[backend_name].configuration if not config['local']: - ### THIS IS A HACK TO CONVERT THE BACKEND TO THE NEW FORMAT AND + ### THIS IS A HACK TO CONVERT THE BACKEND TO THE NEW FORMAT AND ### WILL BE REMOVED WHEN THE API IS UPDATED. IT WILL BE SIMPLY A RETURN CONFIG config_edit = config if config['coupling_map'] == 'all-to-all': config_edit['coupling_map'] = config['coupling_map'] else: - cmap = config['coupling_map'] - cmap_new = [] - for key in cmap: - for i in cmap[key]: - cmap_new.append([key,i]) + coupling_map = config['coupling_map'] + coupling_map_new = [] + for key in coupling_map: + for i in coupling_map[key]: + coupling_map_new.append([key, i]) if not list_format: - ### THIS IS KEEP AROUND FOR CODE THAT IS STILL USING THE DICTIONARY FORMAT OF THE COUPLING MAP - warnings.warn("dictionary format of coupling_map will be deprecated. Please rewrite code using a list for the coulping_map", DeprecationWarning) - cmap_new = mapper.coupling_list2dict(cmap_new) - config_edit['coupling_map'] = cmap_new - return config_edit + ### THIS IS KEEP AROUND FOR CODE THAT IS STILL USING THE + ### DICTIONARY FORMAT OF THE COUPLING MAP + warnings.warn("dictionary format of coupling_map will be deprecated. \ + Please rewrite code using a list for the coupling_map", DeprecationWarning) + coupling_map_new = mapper.coupling_list2dict(coupling_map_new) + config_edit['coupling_map'] = coupling_map_new + return config_edit else: return config except KeyError: @@ -311,13 +314,12 @@ def calibration(backend_name): raise LookupError('backend "{}" is not available'.format(backend_name)) else: return backend.calibration - def parameters(backend_name): """Return the online backend parameters. Args: - backend (str): Name of the backend. + backend_name (str): Name of the backend. Returns: dict: The parameters of the named backend. @@ -342,7 +344,7 @@ def status(backend_name): backend_name (str): the backend name Returns: - dict: status dict + dict: status dict Raises: LookupError: if backend is unavailable From 9d9e56ea366d00f6fda8a683de839ed5ea470239 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 15:04:42 -0400 Subject: [PATCH 15/44] Cleaning up the coupling_map @ewinston we decided that all new code should use the new map and all old code the older one. I have remove the complicated identity map we inserted :-) --- qiskit/backends/_backendutils.py | 18 +++++------------- test/python/test_quantumprogram.py | 1 + 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 70f9f2e03664..d47c6a10c6fa 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -111,10 +111,6 @@ def discover_remote_backends(api): new_key = _snake_case_to_camel_case(key) if new_key not in ['id', 'serial_number', 'topology_id', 'status']: configuration_edit[new_key] = configuration[key] - if new_key == 'coupling_map': - if isinstance(configuration[key], list): - coupling_map = mapper.coupling_list2dict(configuration[key]) - configuration_edit[new_key] = coupling_map # online_qasm_simulator uses different name for basis_gates if 'gateSet' in configuration: configuration_edit['basis_gates'] = configuration['gateSet'] @@ -271,24 +267,20 @@ def configuration(backend_name, list_format=True): try: config = _REGISTERED_BACKENDS[backend_name].configuration if not config['local']: - ### THIS IS A HACK TO CONVERT THE BACKEND TO THE NEW FORMAT AND - ### WILL BE REMOVED WHEN THE API IS UPDATED. IT WILL BE SIMPLY A RETURN CONFIG + ### THIS IS A HACK TO CONVERT THE BACKEND TO THE OLD LIST FORMAT IF THE USER NEEDS IT config_edit = config if config['coupling_map'] == 'all-to-all': config_edit['coupling_map'] = config['coupling_map'] else: coupling_map = config['coupling_map'] - coupling_map_new = [] - for key in coupling_map: - for i in coupling_map[key]: - coupling_map_new.append([key, i]) if not list_format: ### THIS IS KEEP AROUND FOR CODE THAT IS STILL USING THE ### DICTIONARY FORMAT OF THE COUPLING MAP warnings.warn("dictionary format of coupling_map will be deprecated. \ - Please rewrite code using a list for the coupling_map", DeprecationWarning) - coupling_map_new = mapper.coupling_list2dict(coupling_map_new) - config_edit['coupling_map'] = coupling_map_new + Please rewrite code using a list format for the coupling_map", \ + DeprecationWarning) + coupling_map = mapper.coupling_list2dict(coupling_map) + config_edit['coupling_map'] = coupling_map return config_edit else: return config diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index 28e4e968894b..4e4dbb66c0d4 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -670,6 +670,7 @@ def test_get_backend_configuration_online(self, QE_TOKEN, QE_URL): backend = backend_list[0] backend_config = qp.get_backend_configuration(backend) #print(backend_config) + self.log.info(backend_config) self.assertTrue(config_keys < backend_config.keys()) def test_get_backend_configuration_fail(self): From 49507523eec2464f26ee5701e2b835dd8f64cd2d Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 15:12:06 -0400 Subject: [PATCH 16/44] Renaming configuration as config to fix scope error --- qiskit/backends/_backendutils.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index d47c6a10c6fa..80c801976965 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -100,28 +100,27 @@ def discover_remote_backends(api): """ from ._qeremote import QeRemote QeRemote.set_api(api) - configuration_list = api.available_backends() + config_list = api.available_backends() backend_name_list = [] - for configuration in configuration_list: - configuration_edit = {} - backend_name = configuration['name'] + for config in config_list: + config_edit = {} + backend_name = config['name'] backend_name_list.append(backend_name) - configuration_edit['local'] = False - for key in configuration.keys(): + config_edit['local'] = False + for key in config.keys(): new_key = _snake_case_to_camel_case(key) if new_key not in ['id', 'serial_number', 'topology_id', 'status']: - configuration_edit[new_key] = configuration[key] + config_edit[new_key] = config[key] # online_qasm_simulator uses different name for basis_gates - if 'gateSet' in configuration: - configuration_edit['basis_gates'] = configuration['gateSet'] - del configuration_edit['gate_set'] + if 'gateSet' in config: + config_edit['basis_gates'] = config['gateSet'] + del config_edit['gate_set'] # ibmqx_qasm_simulator doesn't report coupling_map - if ('coupling_map' not in configuration_edit.keys() and - configuration['simulator']): - configuration_edit['coupling_map'] = 'all-to-all' + if ('coupling_map' not in config_edit.keys() and config['simulator']): + config_edit['coupling_map'] = 'all-to-all' registered_backend = RegisteredBackend(backend_name, QeRemote, - configuration_edit) + config_edit) _REGISTERED_BACKENDS[backend_name] = registered_backend return backend_name_list From ad71fe1c750d4d942de44a516653efdbcf735f23 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 15:18:54 -0400 Subject: [PATCH 17/44] Linting in test --- test/python/test_quantumprogram.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index 4e4dbb66c0d4..f2620273bde9 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -581,7 +581,7 @@ def test_available_backends_exist(self, QE_TOKEN, QE_URL): q_program = QuantumProgram(specs=self.QPS_SPECS) q_program.set_api(QE_TOKEN, QE_URL) available_backends = q_program.available_backends() - #print(available_backends) + # print(available_backends) self.assertTrue(available_backends) @requires_qe_access @@ -593,7 +593,7 @@ def test_online_backends_exist(self, QE_TOKEN, QE_URL): q_program = QuantumProgram(specs=self.QPS_SPECS) q_program.set_api(QE_TOKEN, QE_URL) online_backends = q_program.online_backends() - #print(online_backends) + # print(online_backends) self.log.info(online_backends) self.assertTrue(online_backends) @@ -606,7 +606,7 @@ def test_online_simulators(self, QE_TOKEN, QE_URL): qp = QuantumProgram(specs=self.QPS_SPECS) qp.set_api(QE_TOKEN, QE_URL) online_simulators = qp.online_simulators() - #print(online_simulators) + # print(online_simulators) self.log.info(online_simulators) self.assertTrue(isinstance(online_simulators, list)) @@ -619,7 +619,7 @@ def test_online_devices(self, QE_TOKEN, QE_URL): qp = QuantumProgram(specs=self.QPS_SPECS) qp.set_api(QE_TOKEN, QE_URL) online_devices = qp.online_devices() - #print(online_devices) + # print(online_devices) self.log.info(online_devices) self.assertTrue(isinstance(online_devices, list)) @@ -630,7 +630,7 @@ def test_backend_status(self): """ q_program = QuantumProgram(specs=self.QPS_SPECS) out = q_program.get_backend_status("local_qasm_simulator") - #print(out) + # print(out) self.assertIn(out['available'], [True]) def test_backend_status_fail(self): @@ -651,7 +651,7 @@ def test_get_backend_configuration(self): config_keys = {'name', 'simulator', 'local', 'description', 'coupling_map', 'basis_gates'} backend_config = qp.get_backend_configuration("local_qasm_simulator") - #print(backend_config) + # print(backend_config) self.assertTrue(config_keys < backend_config.keys()) @requires_qe_access @@ -669,7 +669,7 @@ def test_get_backend_configuration_online(self, QE_TOKEN, QE_URL): if backend_list: backend = backend_list[0] backend_config = qp.get_backend_configuration(backend) - #print(backend_config) + # print(backend_config) self.log.info(backend_config) self.assertTrue(config_keys < backend_config.keys()) @@ -694,7 +694,7 @@ def test_get_backend_calibration(self, QE_TOKEN, QE_URL): if backend_list: backend = backend_list[0] result = q_program.get_backend_calibration(backend) - #print(result) + # print(result) self.log.info(result) self.assertEqual(len(result), 4) @@ -710,7 +710,7 @@ def test_get_backend_parameters(self, QE_TOKEN, QE_URL): if backend_list: backend = backend_list[0] result = q_program.get_backend_parameters(backend) - #print(result) + # print(result) self.log.info(result) self.assertEqual(len(result), 4) From 0fe296bb9e9309f399136c59141ccebe38cf6f2b Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 15:21:57 -0400 Subject: [PATCH 18/44] Linting more --- qiskit/backends/_backendutils.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 80c801976965..9804aceed0bb 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -266,18 +266,17 @@ def configuration(backend_name, list_format=True): try: config = _REGISTERED_BACKENDS[backend_name].configuration if not config['local']: - ### THIS IS A HACK TO CONVERT THE BACKEND TO THE OLD LIST FORMAT IF THE USER NEEDS IT + # THIS IS A HACK TO CONVERT THE BACKEND TO THE OLD LIST FORMAT IF THE USER NEEDS IT config_edit = config if config['coupling_map'] == 'all-to-all': config_edit['coupling_map'] = config['coupling_map'] else: coupling_map = config['coupling_map'] if not list_format: - ### THIS IS KEEP AROUND FOR CODE THAT IS STILL USING THE - ### DICTIONARY FORMAT OF THE COUPLING MAP - warnings.warn("dictionary format of coupling_map will be deprecated. \ - Please rewrite code using a list format for the coupling_map", \ - DeprecationWarning) + # THIS IS KEEP AROUND FOR CODE THAT IS STILL USING THE + # DICTIONARY FORMAT OF THE COUPLING MAP + warnings.warn("dictionary format of coupling_map will be deprecated. Please \ + rewrite code using a list format for the coupling_map", DeprecationWarning) coupling_map = mapper.coupling_list2dict(coupling_map) config_edit['coupling_map'] = coupling_map return config_edit @@ -306,6 +305,7 @@ def calibration(backend_name): else: return backend.calibration + def parameters(backend_name): """Return the online backend parameters. From f46c5a369fb81a5430a0b3127ba14ff7b95fcc4d Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 15:35:14 -0400 Subject: [PATCH 19/44] Fixing the vqe --- test/performance/vqe.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/performance/vqe.py b/test/performance/vqe.py index 6bf4e5a76a6e..e2b10e26ae20 100644 --- a/test/performance/vqe.py +++ b/test/performance/vqe.py @@ -25,11 +25,11 @@ import argparse import time import numpy as np -import time from scipy import linalg as la from functools import partial # import qiskit modules +from qiskit import mapper from qiskit import QuantumProgram from qiskit import QISKitError @@ -84,8 +84,11 @@ def vqe(molecule='H2', depth=6, max_trials=200, shots=1): H = group_paulis(pauli_list) entangler_map = qp.configuration(device)['coupling_map'] + if entangler_map == 'all-to-all': entangler_map = {i: [j for j in range(n_qubits) if j != i] for i in range(n_qubits)} + else: + entangler_map = mapper.coupling_list2dict(entangler_map) initial_theta = np.random.randn(2 * n_qubits * depth) # initial angles initial_c = 0.01 # first theta perturbations From a00a12d226405b489ceb5fcc6471e4f3daf648f5 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 15:40:25 -0400 Subject: [PATCH 20/44] More linting --- qiskit/_quantumprogram.py | 5 +++-- test/python/test_quantumprogram.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index c5147a2b53f2..ac054a815cb8 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -755,8 +755,9 @@ def available_backends(self): warnings.warn("available_backends is going to be deprecated. \ Please use qiskit.backends.local_backends() + \ qiskit.backends.discover_remote_backends(api)", DeprecationWarning) - return qiskit.backends.local_backends() + \ - qiskit.backends.discover_remote_backends(self.__api) + local = qiskit.backends.local_backends() + remote = qiskit.backends.discover_remote_backends(self.__api) + return local + remote def online_backends(self): """Get the online backends. diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index f2620273bde9..5fa5d3a2ae93 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -653,7 +653,7 @@ def test_get_backend_configuration(self): backend_config = qp.get_backend_configuration("local_qasm_simulator") # print(backend_config) self.assertTrue(config_keys < backend_config.keys()) - + @requires_qe_access def test_get_backend_configuration_online(self, QE_TOKEN, QE_URL): """Test configuration. From c989be4acada5166c2b02a0a2e94e8db0eff4ef1 Mon Sep 17 00:00:00 2001 From: Ali Javadi-Abhari Date: Sun, 25 Mar 2018 15:51:13 -0400 Subject: [PATCH 21/44] Update test_quantumprogram.py --- test/python/test_quantumprogram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index 5fa5d3a2ae93..29d1ddb4344b 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -653,7 +653,7 @@ def test_get_backend_configuration(self): backend_config = qp.get_backend_configuration("local_qasm_simulator") # print(backend_config) self.assertTrue(config_keys < backend_config.keys()) - + @requires_qe_access def test_get_backend_configuration_online(self, QE_TOKEN, QE_URL): """Test configuration. From 95eee8ee09b0ebe43265ea1dfda32732b2408d5a Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 16:51:17 -0400 Subject: [PATCH 22/44] lint errors I found trying to debug the error --- test/python/test_projectq_cpp_simulator.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/python/test_projectq_cpp_simulator.py b/test/python/test_projectq_cpp_simulator.py index 76a875347325..fb8505c9884b 100644 --- a/test/python/test_projectq_cpp_simulator.py +++ b/test/python/test_projectq_cpp_simulator.py @@ -20,11 +20,11 @@ import random import unittest -import numpy -from scipy.stats import chi2_contingency +# import numpy +# from scipy.stats import chi2_contingency import qiskit.backends._projectq_simulator as projectq_simulator -import qiskit.backends._qasmsimulator as qasm_simulator +# import qiskit.backends._qasmsimulator as qasm_simulator from qiskit import ClassicalRegister from qiskit import QuantumCircuit from qiskit import QuantumJob From e698686030f6e1091a6e8a3ff9db3af610f3ebea Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 20:11:39 -0400 Subject: [PATCH 23/44] Removing backend from quantum_program test --- test/python/test_quantumprogram.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index 29d1ddb4344b..7780c362dabf 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -24,7 +24,6 @@ import numpy as np -import qiskit.backends from qiskit import (ClassicalRegister, QISKitError, QuantumCircuit, QuantumRegister, QuantumProgram, Result, RegisterSizeError) @@ -1406,7 +1405,7 @@ def test_execute_one_circuit_real_online(self, QE_TOKEN, QE_URL): q_program.set_api(QE_TOKEN, QE_URL) backend = 'ibmqx_qasm_simulator' shots = 1 # the number of shots in the experiment. - status = qiskit.backends.status(backend) + status = q_program.get_backend_status(backend) if not status.get('available', False): pass else: From c4bd73ab6c02a129de7e2de81da02a1989f34bee Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 20:43:32 -0400 Subject: [PATCH 24/44] Making the backend object based --- qiskit/_quantumprogram.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index ac054a815cb8..b6458933bd03 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -830,8 +830,9 @@ def get_backend_status(self, backend): ValueError: if the backend is not available. """ warnings.warn("get_backend_status('name') is going to be deprecated. \ - Please use qiskit.backends.status('name')", DeprecationWarning) - return qiskit.backends.status(backend) + Please use qiskit.backends.get_backend_instance('name')", DeprecationWarning) + my_backend = qiskit.backends.get_backend_instance(backend) + return my_backend.status def get_backend_configuration(self, backend, list_format=True): """Return the configuration of the backend. @@ -872,8 +873,9 @@ def get_backend_calibration(self, backend): found. """ warnings.warn("get_backend_calibration('name') is going to be deprecated. \ - Please use qiskit.backends.calibration('name')", DeprecationWarning) - return qiskit.backends.calibration(backend) + Please use qiskit.backends.get_backend_instance('name')", DeprecationWarning) + my_backend = qiskit.backends.get_backend_instance(backend) + return my_backend.calibration def get_backend_parameters(self, backend): """Return the online backend parameters. @@ -892,8 +894,9 @@ def get_backend_parameters(self, backend): found. """ warnings.warn("get_backend_parameters('name') is going to be deprecated. \ - Please use qiskit.backends.parameters('name')", DeprecationWarning) - return qiskit.backends.parameters(backend) + Please use qiskit.backends.get_backend_instance('name')", DeprecationWarning) + my_backend = qiskit.backends.get_backend_instance(backend) + return my_backend.parameters ############################################################### # methods to compile quantum programs into qobj From a5577b6357153f2eadadcf959e25e211acced0aa Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 21:07:35 -0400 Subject: [PATCH 25/44] Adding tests for the backend object --- test/python/test_backends.py | 169 +++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 test/python/test_backends.py diff --git a/test/python/test_backends.py b/test/python/test_backends.py new file mode 100644 index 000000000000..cfe9ee0986bd --- /dev/null +++ b/test/python/test_backends.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +# pylint: disable=invalid-name,missing-docstring,broad-except + +# Copyright 2017 IBM RESEARCH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================= + +"""Quantum Program QISKit Test.""" + +import os +import unittest +from threading import Lock + +import numpy as np + +import qiskit.backends +from qiskit import (ClassicalRegister, QISKitError, QuantumCircuit, + QuantumRegister, RegisterSizeError) +from IBMQuantumExperience import IBMQuantumExperience +from .common import requires_qe_access, QiskitTestCase, Path + + +class TestBackends(QiskitTestCase): + """QISKit Backends (Object) Tests.""" + + def setUp(self): + # pylint: disable=redefined-outer-name,unused-variable + QiskitTestCase.setUp(self) + + def test_local_backends_discover(self): + """Test if there are local backends. + + If all correct some should exists. + """ + local = qiskit.backends.discover_local_backends() + # print(local) + self.log.info(local) + self.assertTrue(local) + + def test_local_backends_exist(self): + """Test if there are local backends. + + If all correct some should exists. + """ + local = qiskit.backends.local_backends() + # print(local) + self.log.info(local) + self.assertTrue(local) + + @requires_qe_access + def test_remote_backends_discover(self, QE_TOKEN, QE_URL): + """Test if there are remote backends to be discovered. + + If all correct some should exists. + """ + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + remote = qiskit.backends.discover_remote_backends(api) + # print(remote) + self.log.info(remote) + self.assertTrue(remote) + + @requires_qe_access + def test_remote_backends_exist(self, QE_TOKEN, QE_URL): + """Test if there are remote backends. + + If all correct some should exists. + """ + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) + remote = qiskit.backends.remote_backends() + # print(remote) + self.log.info(remote) + self.assertTrue(remote) + + def test_get_backend_instance(self): + """Test backend object. + + If all correct some should exists. + """ + my_backend = qiskit.backends.get_backend_instance('local_qasm_simulator') + # print(my_backend) + + def test_backend_status(self): + """Test backend_status. + + If all correct should return dictionary with available: True/False. + """ + my_backend = qiskit.backends.get_backend_instance('local_qasm_simulator') + out = my_backend.status + # print(out) + self.assertIn(out['available'], [True]) + + def test_get_backend_configuration(self): + """Test configuration. + + If all correct should return configuration for the + local_qasm_simulator. + """ + my_backend = qiskit.backends.get_backend_instance('local_qasm_simulator') + backend_config = my_backend.configuration + config_keys = {'name', 'simulator', 'local', 'description', + 'coupling_map', 'basis_gates'} + # print(backend_config) + self.assertTrue(config_keys < backend_config.keys()) + + @requires_qe_access + def test_get_backend_configuration_online(self, QE_TOKEN, QE_URL): + """Test configuration. + + If all correct should return configuration for the + local_qasm_simulator. + """ + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + backend_list = qiskit.backends.discover_remote_backends(api) + config_keys = {'name', 'simulator', 'local', 'description', + 'coupling_map', 'basis_gates'} + if backend_list: + backend = backend_list[0] + my_backend = qiskit.backends.get_backend_instance(backend) + backend_config = my_backend.configuration + # print(backend_config) + self.log.info(backend_config) + self.assertTrue(config_keys < backend_config.keys()) + + @requires_qe_access + def test_get_backend_calibration(self, QE_TOKEN, QE_URL): + """Test calibration. + + If all correct should return dictionay on length 4. + """ + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + backend_list = qiskit.backends.discover_remote_backends(api) + if backend_list: + backend = backend_list[0] + my_backend = qiskit.backends.get_backend_instance(backend) + result = my_backend.calibration + # print(result) + self.log.info(result) + self.assertEqual(len(result), 4) + + @requires_qe_access + def test_get_backend_parameters(self, QE_TOKEN, QE_URL): + """Test parameters. + + If all correct should return dictionay on length 4. + """ + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + backend_list = qiskit.backends.discover_remote_backends(api) + if backend_list: + backend = backend_list[0] + my_backend = qiskit.backends.get_backend_instance(backend) + result = my_backend.parameters + # print(result) + self.log.info(result) + self.assertEqual(len(result), 4) + +if __name__ == '__main__': + unittest.main(verbosity=2) From 28df243307e12d9f6c79f060fcc1f683b8c79fba Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 21:13:16 -0400 Subject: [PATCH 26/44] Linting tests --- test/python/test_backends.py | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/test/python/test_backends.py b/test/python/test_backends.py index cfe9ee0986bd..cf8f37f3902d 100644 --- a/test/python/test_backends.py +++ b/test/python/test_backends.py @@ -18,17 +18,11 @@ """Quantum Program QISKit Test.""" -import os import unittest -from threading import Lock - -import numpy as np import qiskit.backends -from qiskit import (ClassicalRegister, QISKitError, QuantumCircuit, - QuantumRegister, RegisterSizeError) from IBMQuantumExperience import IBMQuantumExperience -from .common import requires_qe_access, QiskitTestCase, Path +from .common import requires_qe_access, QiskitTestCase class TestBackends(QiskitTestCase): @@ -47,7 +41,7 @@ def test_local_backends_discover(self): # print(local) self.log.info(local) self.assertTrue(local) - + def test_local_backends_exist(self): """Test if there are local backends. @@ -69,7 +63,7 @@ def test_remote_backends_discover(self, QE_TOKEN, QE_URL): # print(remote) self.log.info(remote) self.assertTrue(remote) - + @requires_qe_access def test_remote_backends_exist(self, QE_TOKEN, QE_URL): """Test if there are remote backends. @@ -83,14 +77,6 @@ def test_remote_backends_exist(self, QE_TOKEN, QE_URL): self.log.info(remote) self.assertTrue(remote) - def test_get_backend_instance(self): - """Test backend object. - - If all correct some should exists. - """ - my_backend = qiskit.backends.get_backend_instance('local_qasm_simulator') - # print(my_backend) - def test_backend_status(self): """Test backend_status. @@ -137,7 +123,7 @@ def test_get_backend_configuration_online(self, QE_TOKEN, QE_URL): def test_get_backend_calibration(self, QE_TOKEN, QE_URL): """Test calibration. - If all correct should return dictionay on length 4. + If all correct should return dictionary on length 4. """ api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) backend_list = qiskit.backends.discover_remote_backends(api) @@ -153,7 +139,7 @@ def test_get_backend_calibration(self, QE_TOKEN, QE_URL): def test_get_backend_parameters(self, QE_TOKEN, QE_URL): """Test parameters. - If all correct should return dictionay on length 4. + If all correct should return dictionary on length 4. """ api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) backend_list = qiskit.backends.discover_remote_backends(api) From d6fa6cf47d70d850b159450ef980536e5a04aef5 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 21:20:53 -0400 Subject: [PATCH 27/44] Spelling and linting --- test/python/test_quantumprogram.py | 124 ++++++++++++++--------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index 7780c362dabf..c9a10cb7a862 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -44,10 +44,10 @@ def setUp(self): "circuits": [{ "name": "circuitName", "quantum_registers": [{ - "name": "qname", + "name": "q_name", "size": 3}], "classical_registers": [{ - "name": "cname", + "name": "c_name", "size": 3}] }] } @@ -373,8 +373,8 @@ def test_get_register_and_circuit(self): """ q_program = QuantumProgram(specs=self.QPS_SPECS) qc = q_program.get_circuit("circuitName") - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") self.assertIsInstance(qc, QuantumCircuit) self.assertIsInstance(qr, QuantumRegister) self.assertIsInstance(cr, ClassicalRegister) @@ -406,7 +406,7 @@ def test_get_register_and_circuit_names(self): def test_get_qasm(self): """Test the get_qasm. - If all correct the qasm output should be of a certain lenght + If all correct the qasm output should be of a certain length Previously: Libraries: @@ -414,8 +414,8 @@ def test_get_qasm(self): """ q_program = QuantumProgram(specs=self.QPS_SPECS) qc = q_program.get_circuit("circuitName") - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc.h(qr[0]) qc.cx(qr[0], qr[1]) qc.cx(qr[1], qr[2]) @@ -429,7 +429,7 @@ def test_get_qasms(self): """Test the get_qasms. If all correct the qasm output for each circuit should be of a certain - lenght + length Previously: Libraries: @@ -457,7 +457,7 @@ def test_get_qasms(self): def test_get_qasm_all_gates(self): """Test the get_qasm for more gates. - If all correct the qasm output should be of a certain lenght + If all correct the qasm output should be of a certain length Previously: Libraries: @@ -465,8 +465,8 @@ def test_get_qasm_all_gates(self): """ q_program = QuantumProgram(specs=self.QPS_SPECS) qc = q_program.get_circuit("circuitName") - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc.u1(0.3, qr[0]) qc.u2(0.2, 0.1, qr[1]) qc.u3(0.3, 0.2, 0.1, qr[2]) @@ -507,8 +507,8 @@ def test_save(self): q_program = QuantumProgram(specs=self.QPS_SPECS) qc = q_program.get_circuit("circuitName") - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc.u3(0.3, 0.2, 0.1, qr[0]) qc.h(qr[1]) @@ -685,7 +685,7 @@ def test_get_backend_configuration_fail(self): def test_get_backend_calibration(self, QE_TOKEN, QE_URL): """Test get_backend_calibration. - If all correct should return dictionay on length 4. + If all correct should return dictionary on length 4. """ q_program = QuantumProgram(specs=self.QPS_SPECS) q_program.set_api(QE_TOKEN, QE_URL) @@ -701,7 +701,7 @@ def test_get_backend_calibration(self, QE_TOKEN, QE_URL): def test_get_backend_parameters(self, QE_TOKEN, QE_URL): """Test get_backend_parameters. - If all correct should return dictionay on length 4. + If all correct should return dictionary on length 4. """ q_program = QuantumProgram(specs=self.QPS_SPECS) q_program.set_api(QE_TOKEN, QE_URL) @@ -724,8 +724,8 @@ def test_compile_program(self): """ q_program = QuantumProgram(specs=self.QPS_SPECS) qc = q_program.get_circuit("circuitName") - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc.h(qr[0]) qc.cx(qr[0], qr[1]) qc.measure(qr[0], cr[0]) @@ -740,12 +740,12 @@ def test_compile_program(self): def test_get_compiled_configuration(self): """Test compiled_configuration. - If all correct should return lenght 6 dictionary. + If all correct should return length 6 dictionary. """ q_program = QuantumProgram(specs=self.QPS_SPECS) qc = q_program.get_circuit("circuitName") - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc.h(qr[0]) qc.cx(qr[0], qr[1]) qc.measure(qr[0], cr[0]) @@ -761,12 +761,12 @@ def test_get_compiled_configuration(self): def test_get_compiled_qasm(self): """Test get_compiled_qasm. - If all correct should return lenght dictionary. + If all correct should return length dictionary. """ q_program = QuantumProgram(specs=self.QPS_SPECS) qc = q_program.get_circuit("circuitName") - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc.h(qr[0]) qc.cx(qr[0], qr[1]) qc.measure(qr[0], cr[0]) @@ -786,8 +786,8 @@ def test_get_execution_list(self): """ q_program = QuantumProgram(specs=self.QPS_SPECS) qc = q_program.get_circuit("circuitName") - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc.h(qr[0]) qc.cx(qr[0], qr[1]) qc.measure(qr[0], cr[0]) @@ -833,8 +833,8 @@ def test_compile_coupling_map(self): def test_change_circuit_qobj_after_compile(self): q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc3 = q_program.create_circuit("qc3", [qr], [cr]) qc2.h(qr[0]) @@ -890,8 +890,8 @@ def test_gate_after_measure(self, QE_TOKEN, QE_URL): qc.measure(qr[j], cr[j]) q_program.set_api(QE_TOKEN, QE_URL) backend = 'ibmqx5' - cmap = {1: [0, 2], 2: [3], 3: [4, 14], 5: [4], 6: [5, 7, 11], 7: [10], 8: [7], - 9: [8, 10], 11: [10], 12: [5, 11, 13], 13: [4, 14], 15: [0, 2, 14]} + coupling_map = {1: [0, 2], 2: [3], 3: [4, 14], 5: [4], 6: [5, 7, 11], 7: [10], 8: [7], + 9: [8, 10], 11: [10], 12: [5, 11, 13], 13: [4, 14], 15: [0, 2, 14]} initial_layout = {('qr', 0): ('q', 1), ('qr', 1): ('q', 0), ('qr', 2): ('q', 2), ('qr', 3): ('q', 3), ('qr', 4): ('q', 4), ('qr', 5): ('q', 14), @@ -901,7 +901,7 @@ def test_gate_after_measure(self, QE_TOKEN, QE_URL): ('qr', 12): ('q', 9), ('qr', 13): ('q', 12), ('qr', 14): ('q', 13), ('qr', 15): ('q', 15)} qobj = q_program.compile(["emoticon"], backend=backend, - initial_layout=initial_layout, coupling_map=cmap) + initial_layout=initial_layout, coupling_map=coupling_map) measured_qubits = set() has_gate_after_measure = False for x in qobj["circuits"][0]["compiled_circuit"]["operations"]: @@ -921,8 +921,8 @@ def test_run_program(self): If all correct should the data. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc3 = q_program.create_circuit("qc3", [qr], [cr]) qc2.h(qr[0]) @@ -963,8 +963,8 @@ def _job_done_callback(result): self.qp_program_finished = True q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc3 = q_program.create_circuit("qc3", [qr], [cr]) qc2.h(qr[0]) @@ -1017,8 +1017,8 @@ def _job_done_callback(result): qp_programs_finished += 1 q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc3 = q_program.create_circuit("qc3", [qr], [cr]) qc2.h(qr[0]) @@ -1050,8 +1050,8 @@ def test_run_batch(self): If all correct should the data. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc3 = q_program.create_circuit("qc3", [qr], [cr]) qc2.h(qr[0]) @@ -1099,8 +1099,8 @@ def _jobs_done_callback(results): self.qp_program_finished = True q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc3 = q_program.create_circuit("qc3", [qr], [cr]) qc2.h(qr[0]) @@ -1158,8 +1158,8 @@ def test_local_qasm_simulator(self): If all correct should the data. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc3 = q_program.create_circuit("qc3", [qr], [cr]) qc2.h(qr[0]) @@ -1186,13 +1186,13 @@ def test_local_qasm_simulator(self): '010': 145, '011': 134}) def test_local_qasm_simulator_one_shot(self): - """Test sinlge shot of local simulator . + """Test single shot of local simulator . If all correct should the quantum state. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc3 = q_program.create_circuit("qc3", [qr], [cr]) qc2.h(qr[0]) @@ -1222,7 +1222,7 @@ def test_local_qasm_simulator_one_shot(self): def test_local_unitary_simulator(self): """Test unitary simulator. - If all correct should the h otimes h and cx. + If all correct should the hxh and cx. """ q_program = QuantumProgram() q = q_program.create_quantum_register("q", 2) @@ -1307,14 +1307,14 @@ def test_average_data(self): backend = 'local_qasm_simulator' results = q_program.execute(circuits, backend=backend, shots=shots) observable = {"00": 1, "11": 1, "01": -1, "10": -1} - meanzz = results.average_data("qc", observable) + mean_zz = results.average_data("qc", observable) observable = {"00": 1, "11": -1, "01": 1, "10": -1} - meanzi = results.average_data("qc", observable) + mean_zi = results.average_data("qc", observable) observable = {"00": 1, "11": -1, "01": -1, "10": 1} - meaniz = results.average_data("qc", observable) - self.assertAlmostEqual(meanzz, 1, places=1) - self.assertAlmostEqual(meanzi, 0, places=1) - self.assertAlmostEqual(meaniz, 0, places=1) + mean_iz = results.average_data("qc", observable) + self.assertAlmostEqual(mean_zz, 1, places=1) + self.assertAlmostEqual(mean_zi, 0, places=1) + self.assertAlmostEqual(mean_iz, 0, places=1) @requires_qe_access def test_execute_one_circuit_simulator_online(self, QE_TOKEN, QE_URL): @@ -1675,7 +1675,7 @@ def test_offline(self): import string import random qp = QuantumProgram() - FAKE_TOKEN = 'thistokenisnotgoingtobesentnowhere' + FAKE_TOKEN = 'this_token_is_not_going_to_be_sent_nowhere' FAKE_URL = 'http://{0}.com'.format( ''.join(random.choice(string.ascii_lowercase) for _ in range(63)) ) @@ -1746,7 +1746,7 @@ def test_qubitpol(self): self.assertTrue(np.array_equal(xvals, [0, 1])) def test_ccx(self): - """Checks a CCNOT gate. + """Checks a Toffoli gate. Based on https://github.com/QISKit/qiskit-sdk-py/pull/172. """ @@ -1778,8 +1778,8 @@ def test_reconfig(self): reconfig instead of recompile """ q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc2.measure(qr[0], cr[0]) qc2.measure(qr[1], cr[1]) @@ -1830,8 +1830,8 @@ def test_timeout(self): register_backend(DummySimulator) q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc2.h(qr[0]) qc2.cx(qr[0], qr[1]) @@ -1859,8 +1859,8 @@ def test_hpc_parameter_is_correct(self, QE_TOKEN, QE_URL): backend is not ibmqx_hpc_qasm_simulator. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc2.h(qr[0]) qc2.cx(qr[0], qr[1]) @@ -1883,8 +1883,8 @@ def test_hpc_parameter_is_incorrect(self, QE_TOKEN, QE_URL): If the parameter format is incorrect, it will raise a QISKitError. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - qr = q_program.get_quantum_register("qname") - cr = q_program.get_classical_register("cname") + qr = q_program.get_quantum_register("q_name") + cr = q_program.get_classical_register("c_name") qc2 = q_program.create_circuit("qc2", [qr], [cr]) qc2.h(qr[0]) qc2.cx(qr[0], qr[1]) From 9e2dd299d426f8e673ab88097fbac9ff671a6304 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 22:06:38 -0400 Subject: [PATCH 28/44] Removing some set_api that are not needed --- test/python/test_quantumprogram.py | 45 +++++++++++++++++++----------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index c9a10cb7a862..c220a1c0a003 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -28,7 +28,9 @@ QuantumRegister, QuantumProgram, Result, RegisterSizeError) from qiskit.tools import file_io +import qiskit.backends from .common import requires_qe_access, QiskitTestCase, Path +from IBMQuantumExperience import IBMQuantumExperience class TestQuantumProgram(QiskitTestCase): @@ -873,6 +875,9 @@ def test_gate_after_measure(self, QE_TOKEN, QE_URL): for real backends. NEED internet connection for this. See: https://github.com/QISKit/qiskit-sdk-py/issues/342 + + TODO: (JAY) THIS IS VERY SYSTEM DEPENDENT AND NOT A GOOD TEST. I WOULD LIKE + TO DELETE THIS """ q_program = QuantumProgram() qr = q_program.create_quantum_register('qr', 16) @@ -888,7 +893,8 @@ def test_gate_after_measure(self, QE_TOKEN, QE_URL): qc.x(qr[13]) for j in range(16): qc.measure(qr[j], cr[j]) - q_program.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) backend = 'ibmqx5' coupling_map = {1: [0, 2], 2: [3], 3: [4, 14], 5: [4], 6: [5, 7, 11], 7: [10], 8: [7], 9: [8, 10], 11: [10], 12: [5, 11, 13], 13: [4, 14], 15: [0, 2, 14]} @@ -1329,8 +1335,9 @@ def test_execute_one_circuit_simulator_online(self, QE_TOKEN, QE_URL): qc.h(qr[0]) qc.measure(qr[0], cr[0]) shots = 1024 # the number of shots in the experiment. - q_program.set_api(QE_TOKEN, QE_URL) - backend = q_program.online_simulators()[0] + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) + backend = 'ibmqx_qasm_simulator' # print(backend) result = q_program.execute(['qc'], backend=backend, shots=shots, max_credits=3, @@ -1351,7 +1358,8 @@ def test_simulator_online_size(self, QE_TOKEN, QE_URL): qc.h(qr) qc.measure(qr, cr) shots = 1 # the number of shots in the experiment. - q_program.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) backend = 'ibmqx_qasm_simulator' with self.assertLogs('IBMQuantumExperience', level='WARNING') as cm: result = q_program.execute(['qc'], backend=backend, shots=shots, max_credits=3, @@ -1380,8 +1388,9 @@ def test_execute_several_circuits_simulator_online(self, QE_TOKEN, QE_URL): qc2.measure(qr[1], cr[1]) circuits = ['qc1', 'qc2'] shots = 1024 # the number of shots in the experiment. - q_program.set_api(QE_TOKEN, QE_URL) - backend = q_program.online_simulators()[0] + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) + backend = 'ibmqx_qasm_simulator' result = q_program.execute(circuits, backend=backend, shots=shots, max_credits=3, seed=1287126141) counts1 = result.get_counts('qc1') @@ -1402,10 +1411,12 @@ def test_execute_one_circuit_real_online(self, QE_TOKEN, QE_URL): qc = q_program.create_circuit("circuitName", [qr], [cr]) qc.h(qr) qc.measure(qr[0], cr[0]) - q_program.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) backend = 'ibmqx_qasm_simulator' shots = 1 # the number of shots in the experiment. - status = q_program.get_backend_status(backend) + my_backend = qiskit.backends.get_backend_instance(backend) + status = my_backend.status if not status.get('available', False): pass else: @@ -1472,8 +1483,9 @@ def test_online_qasm_simulator_two_registers(self, QE_TOKEN, QE_URL): qc2.measure(q2[1], c2[1]) circuits = ['qc1', 'qc2'] shots = 1024 # the number of shots in the experiment. - q_program.set_api(QE_TOKEN, QE_URL) - backend = q_program.online_simulators()[0] + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) + backend = 'ibmqx_qasm_simulator' result = q_program.execute(circuits, backend=backend, shots=shots, seed=8458) result1 = result.get_counts('qc1') @@ -1596,8 +1608,7 @@ def test_example_multiple_compile(self): self.assertEqual(ghzresult.get_counts("ghz"), {'00000': 1047, '11111': 1001}) - @requires_qe_access - def test_example_swap_bits(self, QE_TOKEN, QE_URL): + def test_example_swap_bits(self): """Test a toy example swapping a set bit around. Uses the mapper. Pass if results are correct. @@ -1638,9 +1649,7 @@ def swap(qc, q0, q1): ] } qp = QuantumProgram(specs=QPS_SPECS) - qp.set_api(QE_TOKEN, QE_URL) - if backend not in qp.online_simulators(): - unittest.skip('backend "{}" not available'.format(backend)) + backend = 'local_qasm_simulator' qc = qp.get_circuit("swapping") q = qp.get_quantum_register("q") r = qp.get_quantum_register("r") @@ -1869,7 +1878,8 @@ def test_hpc_parameter_is_correct(self, QE_TOKEN, QE_URL): circuits = ['qc2'] shots = 1 # the number of shots in the experiment. backend = 'ibmqx_hpc_qasm_simulator' - q_program.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) qobj = q_program.compile(circuits, backend=backend, shots=shots, seed=88, hpc={'multi_shot_optimization': True, @@ -1893,7 +1903,8 @@ def test_hpc_parameter_is_incorrect(self, QE_TOKEN, QE_URL): circuits = ['qc2'] shots = 1 # the number of shots in the experiment. backend = 'ibmqx_hpc_qasm_simulator' - q_program.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) self.assertRaises(QISKitError, q_program.compile, circuits, backend=backend, shots=shots, seed=88, hpc={'invalid_key': None}) From e6dec7a141f69632927b780437398d79d78716bc Mon Sep 17 00:00:00 2001 From: Erick Winston Date: Sun, 25 Mar 2018 22:06:08 -0400 Subject: [PATCH 29/44] set log level to debug --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4cc42b20caea..2d562f3a4ed8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,7 +51,9 @@ stage_linux: &stage_linux dist: trusty language: python python: 3.5 - env: CMAKE_FLAGS="-D CMAKE_CXX_COMPILER=g++-5 -D ENABLE_TARGETS_QA=False" + env: + CMAKE_FLAGS="-D CMAKE_CXX_COMPILER=g++-5 -D ENABLE_TARGETS_QA=False" + LOG_LEVEL=10 addons: apt: sources: From 72800cccb88465c013817c979841f082f847bed4 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 22:28:47 -0400 Subject: [PATCH 30/44] Removing the api from the tests and needed by the program --- qiskit/_quantumprogram.py | 8 ++++---- test/python/test_job_processor.py | 3 ++- test/python/test_quantumprogram.py | 21 ++++++++++++++------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index b6458933bd03..d39a16f4012c 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -756,7 +756,7 @@ def available_backends(self): Please use qiskit.backends.local_backends() + \ qiskit.backends.discover_remote_backends(api)", DeprecationWarning) local = qiskit.backends.local_backends() - remote = qiskit.backends.discover_remote_backends(self.__api) + remote = qiskit.backends.remote_backends() return local + remote def online_backends(self): @@ -773,7 +773,7 @@ def online_backends(self): """ warnings.warn("online_backends is going to be deprecated. \ Please use qiskit.backends.discover_remote_backends(api)", DeprecationWarning) - return qiskit.backends.discover_remote_backends(self.__api) + return qiskit.backends.remote_backends() def online_simulators(self): """Gets online simulators via QX API calls. @@ -785,7 +785,7 @@ def online_simulators(self): ConnectionError: if the API call failed. """ online_simulators_list = [] - online_backends = qiskit.backends.discover_remote_backends(self.__api) + online_backends = qiskit.backends.remote_backends() warnings.warn("online_simulators is going to be deprecated. \ Do we actually need this function", DeprecationWarning) for backend in online_backends: @@ -804,7 +804,7 @@ def online_devices(self): ConnectionError: if the API call failed. """ online_device_list = [] - online_backends = qiskit.backends.discover_remote_backends(self.__api) + online_backends = qiskit.backends.remote_backends() warnings.warn("online_devices is going to be deprecated. \ Do we actually need this function", DeprecationWarning) for backend in online_backends: diff --git a/test/python/test_job_processor.py b/test/python/test_job_processor.py index eb6a5f6ce03a..fdb9b468b2f0 100644 --- a/test/python/test_job_processor.py +++ b/test/python/test_job_processor.py @@ -212,7 +212,8 @@ def test_quantum_program_online(self, QE_TOKEN, QE_URL): qc.measure(qr[0], cr[0]) backend = 'ibmqx_qasm_simulator' # the backend to run on shots = 1024 # the number of shots in the experiment. - qp.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) _ = qp.execute(['qc'], backend=backend, shots=shots, seed=78) def test_run_job_processor_local_parallel(self): diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index c220a1c0a003..cbaca28a6a24 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -580,7 +580,8 @@ def test_available_backends_exist(self, QE_TOKEN, QE_URL): If all correct some should exists (even if offline). """ q_program = QuantumProgram(specs=self.QPS_SPECS) - q_program.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) available_backends = q_program.available_backends() # print(available_backends) self.assertTrue(available_backends) @@ -592,7 +593,8 @@ def test_online_backends_exist(self, QE_TOKEN, QE_URL): If all correct some should exists. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - q_program.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) online_backends = q_program.online_backends() # print(online_backends) self.log.info(online_backends) @@ -605,7 +607,8 @@ def test_online_simulators(self, QE_TOKEN, QE_URL): If all correct some should exists. NEED internet connection for this. """ qp = QuantumProgram(specs=self.QPS_SPECS) - qp.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) online_simulators = qp.online_simulators() # print(online_simulators) self.log.info(online_simulators) @@ -618,7 +621,8 @@ def test_online_devices(self, QE_TOKEN, QE_URL): If all correct some should exists. NEED internet connection for this. """ qp = QuantumProgram(specs=self.QPS_SPECS) - qp.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) online_devices = qp.online_devices() # print(online_devices) self.log.info(online_devices) @@ -665,7 +669,8 @@ def test_get_backend_configuration_online(self, QE_TOKEN, QE_URL): qp = QuantumProgram(specs=self.QPS_SPECS) config_keys = {'name', 'simulator', 'local', 'description', 'coupling_map', 'basis_gates'} - qp.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) backend_list = qp.online_backends() if backend_list: backend = backend_list[0] @@ -690,7 +695,8 @@ def test_get_backend_calibration(self, QE_TOKEN, QE_URL): If all correct should return dictionary on length 4. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - q_program.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) backend_list = q_program.online_backends() if backend_list: backend = backend_list[0] @@ -706,7 +712,8 @@ def test_get_backend_parameters(self, QE_TOKEN, QE_URL): If all correct should return dictionary on length 4. """ q_program = QuantumProgram(specs=self.QPS_SPECS) - q_program.set_api(QE_TOKEN, QE_URL) + api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) + qiskit.backends.discover_remote_backends(api) backend_list = q_program.online_backends() if backend_list: backend = backend_list[0] From ace23ec7094a770fe567f9402e49e7cf86e75d24 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 22:52:27 -0400 Subject: [PATCH 31/44] Cleaning up and adding a discover --- qiskit/_quantumprogram.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index d39a16f4012c..c9a2896bb53f 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -97,8 +97,6 @@ class QuantumProgram(object): } __init_circuit (obj): A quantum circuit object for the initial quantum circuit - __ONLINE_BACKENDS (list[str]): A list of online backends - __LOCAL_BACKENDS (list[str]): A list of local backends """ # -- FUTURE IMPROVEMENTS -- # TODO: for status results make ALL_CAPS (check) or some unified method @@ -112,8 +110,6 @@ def __init__(self, specs=None): self.__classical_registers = {} self.__quantum_program = {} # stores all the quantum programs self.__init_circuit = None # stores the initial quantum circuit of the program - self.__ONLINE_BACKENDS = [] # pylint: disable=invalid-name - self.__LOCAL_BACKENDS = qiskit.backends.local_backends() # pylint: disable=invalid-name self.__counter = itertools.count() self.mapper = mapper if specs: @@ -676,7 +672,7 @@ def set_api(self, token, url, hub=None, group=None, project=None, proxies=None, verify=True): """ Setup the API. - Fills the __ONLINE_BACKENDS, __api, and __api_config variables. + Fills the __api, and __api_config variables. Does not catch exceptions from IBMQuantumExperience. Args: @@ -714,8 +710,6 @@ def set_api(self, token, url, hub=None, group=None, project=None, root_exception = None raise ConnectionError("Couldn't connect to IBMQuantumExperience server: {0}" .format(ex)) from root_exception - qiskit.backends.discover_remote_backends(self.__api) - self.__ONLINE_BACKENDS = self.online_backends() self.__api_config["token"] = token self.__api_config["config"] = config_dict.copy() @@ -756,6 +750,8 @@ def available_backends(self): Please use qiskit.backends.local_backends() + \ qiskit.backends.discover_remote_backends(api)", DeprecationWarning) local = qiskit.backends.local_backends() + if self.__api: + qiskit.backends.discover_remote_backends(self.__api) remote = qiskit.backends.remote_backends() return local + remote @@ -773,6 +769,8 @@ def online_backends(self): """ warnings.warn("online_backends is going to be deprecated. \ Please use qiskit.backends.discover_remote_backends(api)", DeprecationWarning) + if self.__api: + qiskit.backends.discover_remote_backends(self.__api) return qiskit.backends.remote_backends() def online_simulators(self): @@ -785,6 +783,8 @@ def online_simulators(self): ConnectionError: if the API call failed. """ online_simulators_list = [] + if self.__api: + qiskit.backends.discover_remote_backends(self.__api) online_backends = qiskit.backends.remote_backends() warnings.warn("online_simulators is going to be deprecated. \ Do we actually need this function", DeprecationWarning) @@ -804,6 +804,8 @@ def online_devices(self): ConnectionError: if the API call failed. """ online_device_list = [] + if self.__api: + qiskit.backends.discover_remote_backends(self.__api) online_backends = qiskit.backends.remote_backends() warnings.warn("online_devices is going to be deprecated. \ Do we actually need this function", DeprecationWarning) @@ -831,6 +833,8 @@ def get_backend_status(self, backend): """ warnings.warn("get_backend_status('name') is going to be deprecated. \ Please use qiskit.backends.get_backend_instance('name')", DeprecationWarning) + if self.__api: + qiskit.backends.discover_remote_backends(self.__api) my_backend = qiskit.backends.get_backend_instance(backend) return my_backend.status @@ -854,6 +858,8 @@ def get_backend_configuration(self, backend, list_format=True): """ warnings.warn("get_backend_configuration('name') is going to be deprecated. \ Please use qiskit.backends.configuration('name')", DeprecationWarning) + if self.__api: + qiskit.backends.discover_remote_backends(self.__api) return qiskit.backends.configuration(backend, list_format) def get_backend_calibration(self, backend): @@ -875,6 +881,8 @@ def get_backend_calibration(self, backend): warnings.warn("get_backend_calibration('name') is going to be deprecated. \ Please use qiskit.backends.get_backend_instance('name')", DeprecationWarning) my_backend = qiskit.backends.get_backend_instance(backend) + if self.__api: + qiskit.backends.discover_remote_backends(self.__api) return my_backend.calibration def get_backend_parameters(self, backend): @@ -896,6 +904,8 @@ def get_backend_parameters(self, backend): warnings.warn("get_backend_parameters('name') is going to be deprecated. \ Please use qiskit.backends.get_backend_instance('name')", DeprecationWarning) my_backend = qiskit.backends.get_backend_instance(backend) + if self.__api: + qiskit.backends.discover_remote_backends(self.__api) return my_backend.parameters ############################################################### From c4adaa8336da9d19c580d5cc21b69a90634f110b Mon Sep 17 00:00:00 2001 From: Erick Winston Date: Sun, 25 Mar 2018 23:21:24 -0400 Subject: [PATCH 32/44] correct travis.yml env variable specification --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2d562f3a4ed8..33cd332aab82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,8 +52,8 @@ stage_linux: &stage_linux language: python python: 3.5 env: - CMAKE_FLAGS="-D CMAKE_CXX_COMPILER=g++-5 -D ENABLE_TARGETS_QA=False" - LOG_LEVEL=10 + - CMAKE_FLAGS="-D CMAKE_CXX_COMPILER=g++-5 -D ENABLE_TARGETS_QA=False" + - LOG_LEVEL=10 addons: apt: sources: From a24bcdba0520c8f2ab30f9d81f97581a7936496f Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Sun, 25 Mar 2018 23:08:32 -0400 Subject: [PATCH 33/44] Removing more old code --- test/python/test_quantumprogram.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index cbaca28a6a24..b07a1e5c6f27 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -670,8 +670,7 @@ def test_get_backend_configuration_online(self, QE_TOKEN, QE_URL): config_keys = {'name', 'simulator', 'local', 'description', 'coupling_map', 'basis_gates'} api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) - qiskit.backends.discover_remote_backends(api) - backend_list = qp.online_backends() + backend_list = qiskit.backends.discover_remote_backends(api) if backend_list: backend = backend_list[0] backend_config = qp.get_backend_configuration(backend) @@ -696,8 +695,7 @@ def test_get_backend_calibration(self, QE_TOKEN, QE_URL): """ q_program = QuantumProgram(specs=self.QPS_SPECS) api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) - qiskit.backends.discover_remote_backends(api) - backend_list = q_program.online_backends() + backend_list = qiskit.backends.discover_remote_backends(api) if backend_list: backend = backend_list[0] result = q_program.get_backend_calibration(backend) @@ -713,8 +711,7 @@ def test_get_backend_parameters(self, QE_TOKEN, QE_URL): """ q_program = QuantumProgram(specs=self.QPS_SPECS) api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) - qiskit.backends.discover_remote_backends(api) - backend_list = q_program.online_backends() + backend_list = qiskit.backends.discover_remote_backends(api) if backend_list: backend = backend_list[0] result = q_program.get_backend_parameters(backend) From 6cd78107b30beaccd5bf77b07467bea0ed5e5926 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Mon, 26 Mar 2018 07:06:00 -0400 Subject: [PATCH 34/44] Updated lengths with rename of q_name and c_name --- test/python/test_quantumprogram.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index b07a1e5c6f27..4ca83a67daf4 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -425,7 +425,7 @@ def test_get_qasm(self): qc.measure(qr[1], cr[1]) qc.measure(qr[2], cr[2]) result = q_program.get_qasm("circuitName") - self.assertEqual(len(result), 212) + self.assertEqual(len(result), 225) def test_get_qasms(self): """Test the get_qasms. @@ -486,7 +486,7 @@ def test_get_qasm_all_gates(self): qc.measure(qr[1], cr[1]) qc.measure(qr[2], cr[2]) result = q_program.get_qasm('circuitName') - self.assertEqual(len(result), 535) + self.assertEqual(len(result), 565) def test_get_initial_circuit(self): """Test get_initial_circuit. @@ -783,7 +783,7 @@ def test_get_compiled_qasm(self): coupling_map=coupling_map) result = q_program.get_compiled_qasm(qobj, 'circuitName',) self.log.info(result) - self.assertEqual(len(result), 181) + self.assertEqual(len(result), 190) def test_get_execution_list(self): """Test get_execution_list. From 9028eb3f60f84b7d4dd5518d060141f6e39ab376 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Mon, 26 Mar 2018 07:18:08 -0400 Subject: [PATCH 35/44] Lint errors found from travis fixed --- test/python/test_backends.py | 1 + test/python/test_quantumprogram.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/python/test_backends.py b/test/python/test_backends.py index cf8f37f3902d..961fe9dfd36d 100644 --- a/test/python/test_backends.py +++ b/test/python/test_backends.py @@ -151,5 +151,6 @@ def test_get_backend_parameters(self, QE_TOKEN, QE_URL): self.log.info(result) self.assertEqual(len(result), 4) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index 4ca83a67daf4..687ca2face04 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -880,7 +880,7 @@ def test_gate_after_measure(self, QE_TOKEN, QE_URL): See: https://github.com/QISKit/qiskit-sdk-py/issues/342 - TODO: (JAY) THIS IS VERY SYSTEM DEPENDENT AND NOT A GOOD TEST. I WOULD LIKE + TODO: (JAY) THIS IS VERY SYSTEM DEPENDENT AND NOT A GOOD TEST. I WOULD LIKE TO DELETE THIS """ q_program = QuantumProgram() From 1b22e458ca3c1cae86f589f5f91b8d6d274db5d6 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Mon, 26 Mar 2018 07:27:56 -0400 Subject: [PATCH 36/44] Moving import order to help travis linter --- test/python/test_backends.py | 2 +- test/python/test_quantumprogram.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/python/test_backends.py b/test/python/test_backends.py index 961fe9dfd36d..e90d70dfd464 100644 --- a/test/python/test_backends.py +++ b/test/python/test_backends.py @@ -19,9 +19,9 @@ """Quantum Program QISKit Test.""" import unittest +from IBMQuantumExperience import IBMQuantumExperience import qiskit.backends -from IBMQuantumExperience import IBMQuantumExperience from .common import requires_qe_access, QiskitTestCase diff --git a/test/python/test_quantumprogram.py b/test/python/test_quantumprogram.py index 687ca2face04..a203e4bc2951 100644 --- a/test/python/test_quantumprogram.py +++ b/test/python/test_quantumprogram.py @@ -23,6 +23,7 @@ from threading import Lock import numpy as np +from IBMQuantumExperience import IBMQuantumExperience from qiskit import (ClassicalRegister, QISKitError, QuantumCircuit, QuantumRegister, QuantumProgram, Result, @@ -30,7 +31,6 @@ from qiskit.tools import file_io import qiskit.backends from .common import requires_qe_access, QiskitTestCase, Path -from IBMQuantumExperience import IBMQuantumExperience class TestQuantumProgram(QiskitTestCase): From 0baac1a26fbe9f1e1749ce80e67879a88a063106 Mon Sep 17 00:00:00 2001 From: "Diego M. Rodriguez" Date: Mon, 26 Mar 2018 16:32:55 +0200 Subject: [PATCH 37/44] Revise DeprecationWarnings, add note to docstrings Add a context manager for ensuring the DeprecationWarnings are shown regardless of the user configuration, as by default they are hidden for end users (ie. when not on an interpreter). Revise the strings for the warnings and add entries to the docstrings for visually showing them on the online docs. --- .travis.yml | 4 +- qiskit/_quantumprogram.py | 152 +++++++++++++++++++++++++------ qiskit/_util.py | 31 ++++++- qiskit/backends/_backendutils.py | 12 ++- 4 files changed, 165 insertions(+), 34 deletions(-) diff --git a/.travis.yml b/.travis.yml index 33cd332aab82..4cc42b20caea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,9 +51,7 @@ stage_linux: &stage_linux dist: trusty language: python python: 3.5 - env: - - CMAKE_FLAGS="-D CMAKE_CXX_COMPILER=g++-5 -D ENABLE_TARGETS_QA=False" - - LOG_LEVEL=10 + env: CMAKE_FLAGS="-D CMAKE_CXX_COMPILER=g++-5 -D ENABLE_TARGETS_QA=False" addons: apt: sources: diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index c9a2896bb53f..6ecc1527a65d 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -47,6 +47,7 @@ from . import Gate from .extensions.standard.barrier import Barrier from ._logging import set_qiskit_logger, unset_qiskit_logger +from ._util import show_deprecation_warnings # Beta Modules from . import unroll @@ -689,9 +690,15 @@ def set_api(self, token, url, hub=None, group=None, project=None, Raises: ConnectionError: if the API instantiation failed. QISKitError: if no hub, group or project were specified. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + API object instead is recommended. """ - warnings.warn("get_api_config is going to be deprecated. \ - Please use the api object", DeprecationWarning) + with show_deprecation_warnings: + warnings.warn( + "set_api() will be deprecated in upcoming versions (>0.5.0). " + "Using the API object instead is recommended.", DeprecationWarning) try: config_dict = { 'url': url, @@ -719,9 +726,15 @@ def set_api_hubs_config(self, hub, group, project): hub (str): The hub used for online backend. group (str): The group used for online backend. project (str): The project used for online backend. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + API object instead is recommended. """ - warnings.warn("get_api_config is going to be deprecated. \ - Please use the api object", DeprecationWarning) + with show_deprecation_warnings: + warnings.warn( + "set_api_hubs_config() will be deprecated in upcoming versions (>0.5.0). " + "Using the API object instead is recommended.", DeprecationWarning) config_dict = { 'hub': hub, 'group': group, @@ -733,22 +746,47 @@ def set_api_hubs_config(self, hub, group, project): self.__api_config['config'][key] = value def get_api_config(self): - """Return the program specs.""" - warnings.warn("get_api_config is going to be deprecated. \ - Please use the api object", DeprecationWarning) + """Return the program specs. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + API object instead is recommended. + """ + with show_deprecation_warnings: + warnings.warn( + "get_api_config() will be deprecated in upcoming versions (>0.5.0). " + "Using the API object instead is recommended.", DeprecationWarning) + return self.__api_config def get_api(self): - """Returns a function handle to the API.""" - warnings.warn("get_api is going to be deprecated. \ - Please use the api object", DeprecationWarning) + """Returns a function handle to the API. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + API object instead is recommended. + """ + with show_deprecation_warnings: + warnings.warn( + "get_api() will be deprecated in upcoming versions (>0.5.0). " + "Using the API object instead is recommended.", DeprecationWarning) + return self.__api def available_backends(self): - """All the backends that are seen by QISKIT.""" - warnings.warn("available_backends is going to be deprecated. \ - Please use qiskit.backends.local_backends() + \ - qiskit.backends.discover_remote_backends(api)", DeprecationWarning) + """All the backends that are seen by QISKIT. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + qiskit.backends family of functions instead is recommended. + """ + with show_deprecation_warnings: + warnings.warn( + "available_backends() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.local_backends() and " + "qiskit.backends.remote_backends() instead is recommended.", + DeprecationWarning) + local = qiskit.backends.local_backends() if self.__api: qiskit.backends.discover_remote_backends(self.__api) @@ -766,9 +804,17 @@ def online_backends(self): Raises: ConnectionError: if the API call failed. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + qiskit.backends family of functions instead is recommended. """ - warnings.warn("online_backends is going to be deprecated. \ - Please use qiskit.backends.discover_remote_backends(api)", DeprecationWarning) + with show_deprecation_warnings: + warnings.warn( + "online_backends() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.remote_backends() object instead is recommended.", + DeprecationWarning) + if self.__api: qiskit.backends.discover_remote_backends(self.__api) return qiskit.backends.remote_backends() @@ -781,13 +827,22 @@ def online_simulators(self): Raises: ConnectionError: if the API call failed. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + qiskit.backends family of functions instead is recommended. """ + with show_deprecation_warnings: + warnings.warn( + "online_simulators() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.remote_backends() instead is recommended.", + DeprecationWarning) + online_simulators_list = [] if self.__api: qiskit.backends.discover_remote_backends(self.__api) online_backends = qiskit.backends.remote_backends() - warnings.warn("online_simulators is going to be deprecated. \ - Do we actually need this function", DeprecationWarning) + for backend in online_backends: config = qiskit.backends.configuration(backend) if config['simulator']: @@ -802,13 +857,22 @@ def online_devices(self): Raises: ConnectionError: if the API call failed. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + qiskit.backends family of functions instead is recommended. """ + with show_deprecation_warnings: + warnings.warn( + "online_devices() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.remote_backends() instead is recommended.", + DeprecationWarning) + online_device_list = [] if self.__api: qiskit.backends.discover_remote_backends(self.__api) online_backends = qiskit.backends.remote_backends() - warnings.warn("online_devices is going to be deprecated. \ - Do we actually need this function", DeprecationWarning) + for backend in online_backends: config = qiskit.backends.configuration(backend) if not config['simulator']: @@ -830,9 +894,17 @@ def get_backend_status(self, backend): Raises: ConnectionError: if the API call failed. ValueError: if the backend is not available. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + qiskit.backends family of functions instead is recommended. """ - warnings.warn("get_backend_status('name') is going to be deprecated. \ - Please use qiskit.backends.get_backend_instance('name')", DeprecationWarning) + with show_deprecation_warnings: + warnings.warn( + "get_backend_status() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.get_backend_instance('name').status " + "instead is recommended.", DeprecationWarning) + if self.__api: qiskit.backends.discover_remote_backends(self.__api) my_backend = qiskit.backends.get_backend_instance(backend) @@ -855,9 +927,17 @@ def get_backend_configuration(self, backend, list_format=True): ConnectionError: if the API call failed. LookupError: if a configuration for the named backend can't be found. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + qiskit.backends family of functions instead is recommended. """ - warnings.warn("get_backend_configuration('name') is going to be deprecated. \ - Please use qiskit.backends.configuration('name')", DeprecationWarning) + with show_deprecation_warnings: + warnings.warn( + "get_backend_configuration() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.get_backend_instance('name').configuration " + "instead is recommended.", DeprecationWarning) + if self.__api: qiskit.backends.discover_remote_backends(self.__api) return qiskit.backends.configuration(backend, list_format) @@ -877,9 +957,17 @@ def get_backend_calibration(self, backend): ConnectionError: if the API call failed. LookupError: If a configuration for the named backend can't be found. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + qiskit.backends family of functions instead is recommended. """ - warnings.warn("get_backend_calibration('name') is going to be deprecated. \ - Please use qiskit.backends.get_backend_instance('name')", DeprecationWarning) + with show_deprecation_warnings: + warnings.warn( + "get_backend_calibration() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.get_backend_instance('name').calibration " + "instead is recommended.", DeprecationWarning) + my_backend = qiskit.backends.get_backend_instance(backend) if self.__api: qiskit.backends.discover_remote_backends(self.__api) @@ -900,9 +988,17 @@ def get_backend_parameters(self, backend): ConnectionError: if the API call failed. LookupError: If a configuration for the named backend can't be found. + + .. deprecated:: 0.5 + This method will be deprecated in upcoming versions. Using the + qiskit.backends family of functions instead is recommended. """ - warnings.warn("get_backend_parameters('name') is going to be deprecated. \ - Please use qiskit.backends.get_backend_instance('name')", DeprecationWarning) + with show_deprecation_warnings: + warnings.warn( + "get_backend_parameters() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.get_backend_instance('name').parameters" + "instead is recommended.", DeprecationWarning) + my_backend = qiskit.backends.get_backend_instance(backend) if self.__api: qiskit.backends.discover_remote_backends(self.__api) diff --git a/qiskit/_util.py b/qiskit/_util.py index ac04149867da..ae9101df227b 100644 --- a/qiskit/_util.py +++ b/qiskit/_util.py @@ -16,8 +16,10 @@ # ============================================================================= """Common utilities for QISKit.""" -import sys import logging +import re +import sys +import warnings API_NAME = 'IBMQuantumExperience' logger = logging.getLogger(__name__) @@ -85,5 +87,32 @@ def _check_ibmqx_version(): str(ibmqx_require)) +class show_deprecation_warnings(object): + """ + Context manager that forces the `DeprecationWarning` warnings to be + displayed for the qiskit module, overriding the system configuration as + they are ignored by default [1] for end-users. + + TODO: on Python 3.7, this might not be needed due to PEP-0565. + + [1] https://docs.python.org/3/library/warnings.html#default-warning-filters + [2] https://www.python.org/dev/peps/pep-0565/ + """ + # pylint: disable=invalid-name + deprecation_filter = ('always', None, DeprecationWarning, + re.compile(r'^qiskit\.*', re.UNICODE), 0) + + def __enter__(self): + # Instead of using warnings.simple_filter() directly, the internal + # _add_filter() function is used for being able to match agains the + # module. + warnings._add_filter(*self.deprecation_filter, append=False) + + def __exit__(self, *exc_info): + # Remove the filter added during __enter__, cleaning up afterwards. + warnings.filters.remove(self.deprecation_filter) + warnings._filters_mutated() + + _check_python_version() _check_ibmqx_version() diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 9804aceed0bb..04a52bfa185b 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -28,6 +28,7 @@ import qiskit from qiskit import mapper +from qiskit._util import show_deprecation_warnings from ._basebackend import BaseBackend from .. import QISKitError @@ -262,6 +263,10 @@ def configuration(backend_name, list_format=True): Raises: LookupError: if backend is unavailable + + .. versionchanged:: 0.5 + Since version 0.5, the dictionary format of coupling_map is deprecated. + Please use a list format for the coupling_map. """ try: config = _REGISTERED_BACKENDS[backend_name].configuration @@ -275,8 +280,11 @@ def configuration(backend_name, list_format=True): if not list_format: # THIS IS KEEP AROUND FOR CODE THAT IS STILL USING THE # DICTIONARY FORMAT OF THE COUPLING MAP - warnings.warn("dictionary format of coupling_map will be deprecated. Please \ - rewrite code using a list format for the coupling_map", DeprecationWarning) + with show_deprecation_warnings: + warnings.warn( + "The dictionary format of coupling_map will be deprecated in upcoming " + "versions (>0.5.0). Please use a list format for the coupling_map", + DeprecationWarning) coupling_map = mapper.coupling_list2dict(coupling_map) config_edit['coupling_map'] = coupling_map return config_edit From 91ed3e8c2ed12d29baeee8bd209c65763cac440a Mon Sep 17 00:00:00 2001 From: "Diego M. Rodriguez" Date: Mon, 26 Mar 2018 16:46:02 +0200 Subject: [PATCH 38/44] Enable deprecation warnings during __init__ Enable the display of deprecation warnings during qiskit.__init__ instead of via a context manager, for simplifying the deprecated calls and help providing visual aids for the editors. --- qiskit/_quantumprogram.py | 103 ++++++++++++++----------------- qiskit/_util.py | 25 +++----- qiskit/backends/_backendutils.py | 10 ++- 3 files changed, 59 insertions(+), 79 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index 6ecc1527a65d..8296a0217f89 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -47,7 +47,6 @@ from . import Gate from .extensions.standard.barrier import Barrier from ._logging import set_qiskit_logger, unset_qiskit_logger -from ._util import show_deprecation_warnings # Beta Modules from . import unroll @@ -695,10 +694,9 @@ def set_api(self, token, url, hub=None, group=None, project=None, This method will be deprecated in upcoming versions. Using the API object instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "set_api() will be deprecated in upcoming versions (>0.5.0). " - "Using the API object instead is recommended.", DeprecationWarning) + warnings.warn( + "set_api() will be deprecated in upcoming versions (>0.5.0). " + "Using the API object instead is recommended.", DeprecationWarning) try: config_dict = { 'url': url, @@ -731,10 +729,9 @@ def set_api_hubs_config(self, hub, group, project): This method will be deprecated in upcoming versions. Using the API object instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "set_api_hubs_config() will be deprecated in upcoming versions (>0.5.0). " - "Using the API object instead is recommended.", DeprecationWarning) + warnings.warn( + "set_api_hubs_config() will be deprecated in upcoming versions (>0.5.0). " + "Using the API object instead is recommended.", DeprecationWarning) config_dict = { 'hub': hub, 'group': group, @@ -752,10 +749,9 @@ def get_api_config(self): This method will be deprecated in upcoming versions. Using the API object instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "get_api_config() will be deprecated in upcoming versions (>0.5.0). " - "Using the API object instead is recommended.", DeprecationWarning) + warnings.warn( + "get_api_config() will be deprecated in upcoming versions (>0.5.0). " + "Using the API object instead is recommended.", DeprecationWarning) return self.__api_config @@ -766,10 +762,9 @@ def get_api(self): This method will be deprecated in upcoming versions. Using the API object instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "get_api() will be deprecated in upcoming versions (>0.5.0). " - "Using the API object instead is recommended.", DeprecationWarning) + warnings.warn( + "get_api() will be deprecated in upcoming versions (>0.5.0). " + "Using the API object instead is recommended.", DeprecationWarning) return self.__api @@ -780,12 +775,11 @@ def available_backends(self): This method will be deprecated in upcoming versions. Using the qiskit.backends family of functions instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "available_backends() will be deprecated in upcoming versions (>0.5.0). " - "Using qiskit.backends.local_backends() and " - "qiskit.backends.remote_backends() instead is recommended.", - DeprecationWarning) + warnings.warn( + "available_backends() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.local_backends() and " + "qiskit.backends.remote_backends() instead is recommended.", + DeprecationWarning) local = qiskit.backends.local_backends() if self.__api: @@ -809,11 +803,10 @@ def online_backends(self): This method will be deprecated in upcoming versions. Using the qiskit.backends family of functions instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "online_backends() will be deprecated in upcoming versions (>0.5.0). " - "Using qiskit.backends.remote_backends() object instead is recommended.", - DeprecationWarning) + warnings.warn( + "online_backends() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.remote_backends() object instead is recommended.", + DeprecationWarning) if self.__api: qiskit.backends.discover_remote_backends(self.__api) @@ -832,11 +825,10 @@ def online_simulators(self): This method will be deprecated in upcoming versions. Using the qiskit.backends family of functions instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "online_simulators() will be deprecated in upcoming versions (>0.5.0). " - "Using qiskit.backends.remote_backends() instead is recommended.", - DeprecationWarning) + warnings.warn( + "online_simulators() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.remote_backends() instead is recommended.", + DeprecationWarning) online_simulators_list = [] if self.__api: @@ -862,11 +854,10 @@ def online_devices(self): This method will be deprecated in upcoming versions. Using the qiskit.backends family of functions instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "online_devices() will be deprecated in upcoming versions (>0.5.0). " - "Using qiskit.backends.remote_backends() instead is recommended.", - DeprecationWarning) + warnings.warn( + "online_devices() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.remote_backends() instead is recommended.", + DeprecationWarning) online_device_list = [] if self.__api: @@ -899,11 +890,10 @@ def get_backend_status(self, backend): This method will be deprecated in upcoming versions. Using the qiskit.backends family of functions instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "get_backend_status() will be deprecated in upcoming versions (>0.5.0). " - "Using qiskit.backends.get_backend_instance('name').status " - "instead is recommended.", DeprecationWarning) + warnings.warn( + "get_backend_status() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.get_backend_instance('name').status " + "instead is recommended.", DeprecationWarning) if self.__api: qiskit.backends.discover_remote_backends(self.__api) @@ -932,11 +922,10 @@ def get_backend_configuration(self, backend, list_format=True): This method will be deprecated in upcoming versions. Using the qiskit.backends family of functions instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "get_backend_configuration() will be deprecated in upcoming versions (>0.5.0). " - "Using qiskit.backends.get_backend_instance('name').configuration " - "instead is recommended.", DeprecationWarning) + warnings.warn( + "get_backend_configuration() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.get_backend_instance('name').configuration " + "instead is recommended.", DeprecationWarning) if self.__api: qiskit.backends.discover_remote_backends(self.__api) @@ -962,11 +951,10 @@ def get_backend_calibration(self, backend): This method will be deprecated in upcoming versions. Using the qiskit.backends family of functions instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "get_backend_calibration() will be deprecated in upcoming versions (>0.5.0). " - "Using qiskit.backends.get_backend_instance('name').calibration " - "instead is recommended.", DeprecationWarning) + warnings.warn( + "get_backend_calibration() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.get_backend_instance('name').calibration " + "instead is recommended.", DeprecationWarning) my_backend = qiskit.backends.get_backend_instance(backend) if self.__api: @@ -993,11 +981,10 @@ def get_backend_parameters(self, backend): This method will be deprecated in upcoming versions. Using the qiskit.backends family of functions instead is recommended. """ - with show_deprecation_warnings: - warnings.warn( - "get_backend_parameters() will be deprecated in upcoming versions (>0.5.0). " - "Using qiskit.backends.get_backend_instance('name').parameters" - "instead is recommended.", DeprecationWarning) + warnings.warn( + "get_backend_parameters() will be deprecated in upcoming versions (>0.5.0). " + "Using qiskit.backends.get_backend_instance('name').parameters" + "instead is recommended.", DeprecationWarning) my_backend = qiskit.backends.get_backend_instance(backend) if self.__api: diff --git a/qiskit/_util.py b/qiskit/_util.py index ae9101df227b..d1e9e10d42f8 100644 --- a/qiskit/_util.py +++ b/qiskit/_util.py @@ -87,13 +87,13 @@ def _check_ibmqx_version(): str(ibmqx_require)) -class show_deprecation_warnings(object): +def _enable_deprecation_warnings(): """ - Context manager that forces the `DeprecationWarning` warnings to be - displayed for the qiskit module, overriding the system configuration as - they are ignored by default [1] for end-users. + Force the `DeprecationWarning` warnings to be displayed for the qiskit + module, overriding the system configuration as they are ignored by default + [1] for end-users. - TODO: on Python 3.7, this might not be needed due to PEP-0565. + TODO: on Python 3.7, this might not be needed due to PEP-0565 [2]. [1] https://docs.python.org/3/library/warnings.html#default-warning-filters [2] https://www.python.org/dev/peps/pep-0565/ @@ -102,17 +102,12 @@ class show_deprecation_warnings(object): deprecation_filter = ('always', None, DeprecationWarning, re.compile(r'^qiskit\.*', re.UNICODE), 0) - def __enter__(self): - # Instead of using warnings.simple_filter() directly, the internal - # _add_filter() function is used for being able to match agains the - # module. - warnings._add_filter(*self.deprecation_filter, append=False) - - def __exit__(self, *exc_info): - # Remove the filter added during __enter__, cleaning up afterwards. - warnings.filters.remove(self.deprecation_filter) - warnings._filters_mutated() + # Instead of using warnings.simple_filter() directly, the internal + # _add_filter() function is used for being able to match against the + # module. + warnings._add_filter(*deprecation_filter, append=False) _check_python_version() _check_ibmqx_version() +_enable_deprecation_warnings() diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 04a52bfa185b..07dabbe2efc3 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -28,7 +28,6 @@ import qiskit from qiskit import mapper -from qiskit._util import show_deprecation_warnings from ._basebackend import BaseBackend from .. import QISKitError @@ -280,11 +279,10 @@ def configuration(backend_name, list_format=True): if not list_format: # THIS IS KEEP AROUND FOR CODE THAT IS STILL USING THE # DICTIONARY FORMAT OF THE COUPLING MAP - with show_deprecation_warnings: - warnings.warn( - "The dictionary format of coupling_map will be deprecated in upcoming " - "versions (>0.5.0). Please use a list format for the coupling_map", - DeprecationWarning) + warnings.warn( + "The dictionary format of coupling_map will be deprecated in upcoming " + "versions (>0.5.0). Please use a list format for the coupling_map", + DeprecationWarning) coupling_map = mapper.coupling_list2dict(coupling_map) config_edit['coupling_map'] = coupling_map return config_edit From cce3be08a3c7a363a584ababb9dd227463d6234a Mon Sep 17 00:00:00 2001 From: Erick Winston Date: Mon, 26 Mar 2018 12:31:19 -0400 Subject: [PATCH 39/44] fix cyclic import and scope of configuration These were pylint warnings. The configuration one was due to having a function of of the same name as a parameter in _backendutils.py. --- qiskit/backends/_backendutils.py | 8 ++++---- qiskit/backends/_basebackend.py | 1 - qiskit/backends/_qeremote.py | 11 ++++++++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 07dabbe2efc3..62c0bc0a805e 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -116,7 +116,7 @@ def discover_remote_backends(api): config_edit['basis_gates'] = config['gateSet'] del config_edit['gate_set'] # ibmqx_qasm_simulator doesn't report coupling_map - if ('coupling_map' not in config_edit.keys() and config['simulator']): + if 'coupling_map' not in config_edit.keys() and config['simulator']: config_edit['coupling_map'] = 'all-to-all' registered_backend = RegisteredBackend(backend_name, QeRemote, @@ -150,7 +150,7 @@ def update_backends(api=None): return backend_name_list -def register_backend(cls, configuration=None): +def register_backend(cls, configuration_=None): """Register a backend in the list of available backends. Register a `cls` backend in the `_REGISTERED_BACKENDS` dict, validating @@ -161,7 +161,7 @@ def register_backend(cls, configuration=None): Args: cls (class): a subclass of BaseBackend that contains a backend - configuration (dict): backend configuration to use instead of class' + configuration_ (dict): backend configuration to use instead of class' default. Returns: @@ -181,7 +181,7 @@ def register_backend(cls, configuration=None): raise QISKitError('Could not register backend: %s is not a subclass ' 'of BaseBackend' % cls) try: - backend_instance = cls(configuration=configuration) + backend_instance = cls(configuration=configuration_) except Exception as err: raise QISKitError('Could not register backend: %s could not be ' 'instantiated: %s' % (cls, err)) diff --git a/qiskit/backends/_basebackend.py b/qiskit/backends/_basebackend.py index 27cd390427bf..084d0c9e728b 100644 --- a/qiskit/backends/_basebackend.py +++ b/qiskit/backends/_basebackend.py @@ -66,5 +66,4 @@ def parameters(self): @property def status(self): """Return backend status""" - backend_name = self.configuration['name'] return {'available': True} diff --git a/qiskit/backends/_qeremote.py b/qiskit/backends/_qeremote.py index 6004b49c7964..97e62545853e 100644 --- a/qiskit/backends/_qeremote.py +++ b/qiskit/backends/_qeremote.py @@ -21,8 +21,8 @@ import time import logging import pprint +import re from qiskit.backends._basebackend import BaseBackend -from qiskit.backends._backendutils import _snake_case_to_camel_case from qiskit import _openquantumcompiler as openquantumcompiler from qiskit import QISKitError from qiskit._result import Result @@ -30,6 +30,9 @@ logger = logging.getLogger(__name__) +FIRST_CAP_RE = re.compile('(.)([A-Z][a-z]+)') +ALL_CAP_RE = re.compile('([a-z0-9])([A-Z])') + class QeRemote(BaseBackend): """Backend class interfacing with the Quantum Experience remotely. @@ -242,3 +245,9 @@ def _wait_for_job(jobid, api, wait=5, timeout=60): 'status': job_result['qasms'][index]['status']}) return {'job_id': jobid, 'status': job_result['status'], 'result': job_result_return} + +# this is also in _backendutils but using that was creating cyclic import. +def _snake_case_to_camel_case(name): + """Return a snake case string from a camelcase string.""" + string_1 = FIRST_CAP_RE.sub(r'\1_\2', name) + return ALL_CAP_RE.sub(r'\1_\2', string_1).lower() From a71f67ebfebc180302667f7c05244d12a733b612 Mon Sep 17 00:00:00 2001 From: Erick Winston Date: Mon, 26 Mar 2018 12:45:10 -0400 Subject: [PATCH 40/44] fix linter --- qiskit/backends/_qeremote.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qiskit/backends/_qeremote.py b/qiskit/backends/_qeremote.py index 97e62545853e..6f6248e0ace6 100644 --- a/qiskit/backends/_qeremote.py +++ b/qiskit/backends/_qeremote.py @@ -246,6 +246,7 @@ def _wait_for_job(jobid, api, wait=5, timeout=60): return {'job_id': jobid, 'status': job_result['status'], 'result': job_result_return} + # this is also in _backendutils but using that was creating cyclic import. def _snake_case_to_camel_case(name): """Return a snake case string from a camelcase string.""" From 9cc3adf9833a4b1c2c223054ec1bcbc0d46a5a7f Mon Sep 17 00:00:00 2001 From: Erick Winston Date: Mon, 26 Mar 2018 14:01:24 -0400 Subject: [PATCH 41/44] remove converting coupling_map to dict --- qiskit/_quantumprogram.py | 6 ++---- qiskit/backends/_backendutils.py | 31 +++---------------------------- 2 files changed, 5 insertions(+), 32 deletions(-) diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index 8296a0217f89..dfbbc7da3957 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -900,15 +900,13 @@ def get_backend_status(self, backend): my_backend = qiskit.backends.get_backend_instance(backend) return my_backend.status - def get_backend_configuration(self, backend, list_format=True): + def get_backend_configuration(self, backend): """Return the configuration of the backend. The return is via QX API call. Args: backend (str): Name of the backend. - list_format (bool): structure used for the configuration coupling - map: dict (if False) or list (if True). Returns: dict: The configuration of the named backend. @@ -929,7 +927,7 @@ def get_backend_configuration(self, backend, list_format=True): if self.__api: qiskit.backends.discover_remote_backends(self.__api) - return qiskit.backends.configuration(backend, list_format) + return qiskit.backends.configuration(backend) def get_backend_calibration(self, backend): """Return the online backend calibrations. diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 62c0bc0a805e..d0abe8bbb00d 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -24,10 +24,8 @@ import pkgutil import re from collections import namedtuple -import warnings import qiskit -from qiskit import mapper from ._basebackend import BaseBackend from .. import QISKitError @@ -250,47 +248,24 @@ def get_backend_instance(backend_name): configuration=registered_backend.configuration) -def configuration(backend_name, list_format=True): +def configuration(backend_name): """Return the configuration for the named backend. Args: backend_name (str): the backend name - list_format (bool): to use the old format or new format for coupling map Returns: dict: configuration dict Raises: LookupError: if backend is unavailable - - .. versionchanged:: 0.5 - Since version 0.5, the dictionary format of coupling_map is deprecated. - Please use a list format for the coupling_map. """ try: config = _REGISTERED_BACKENDS[backend_name].configuration - if not config['local']: - # THIS IS A HACK TO CONVERT THE BACKEND TO THE OLD LIST FORMAT IF THE USER NEEDS IT - config_edit = config - if config['coupling_map'] == 'all-to-all': - config_edit['coupling_map'] = config['coupling_map'] - else: - coupling_map = config['coupling_map'] - if not list_format: - # THIS IS KEEP AROUND FOR CODE THAT IS STILL USING THE - # DICTIONARY FORMAT OF THE COUPLING MAP - warnings.warn( - "The dictionary format of coupling_map will be deprecated in upcoming " - "versions (>0.5.0). Please use a list format for the coupling_map", - DeprecationWarning) - coupling_map = mapper.coupling_list2dict(coupling_map) - config_edit['coupling_map'] = coupling_map - return config_edit - else: - return config except KeyError: raise LookupError('backend "{}" is not available'.format(backend_name)) - + else: + return config def calibration(backend_name): """Return the calibration for the named backend. From 9ef34b3caed3d4281dfb7fd987e056f508319ad0 Mon Sep 17 00:00:00 2001 From: Erick Winston Date: Mon, 26 Mar 2018 14:09:06 -0400 Subject: [PATCH 42/44] minor lint fix --- qiskit/backends/_backendutils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index d0abe8bbb00d..e1a4884c171a 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -267,6 +267,7 @@ def configuration(backend_name): else: return config + def calibration(backend_name): """Return the calibration for the named backend. From 83ec75cc1f357fc0cf5e6ff34b3db8285199ae24 Mon Sep 17 00:00:00 2001 From: Jay Gambetta Date: Mon, 26 Mar 2018 15:37:41 -0400 Subject: [PATCH 43/44] Small fix to the backends. --- qiskit/backends/_backendutils.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index e1a4884c171a..66759720784c 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -261,11 +261,9 @@ def configuration(backend_name): LookupError: if backend is unavailable """ try: - config = _REGISTERED_BACKENDS[backend_name].configuration + return _REGISTERED_BACKENDS[backend_name].configuration except KeyError: raise LookupError('backend "{}" is not available'.format(backend_name)) - else: - return config def calibration(backend_name): From 864a06803ec8592f18d839bba7073fbb4e4c45a8 Mon Sep 17 00:00:00 2001 From: "Diego M. Rodriguez" Date: Tue, 27 Mar 2018 12:05:35 +0200 Subject: [PATCH 44/44] Fix LookupErrors, style, comments Fix several backendutils methods raising ConnectionError instead of LookupError when the entities were not found. Update the structure of those methods for simplicity and consistency. Fix commented out code on tests. --- qiskit/__init__.py | 2 + qiskit/_quantumprogram.py | 2 + qiskit/backends/_backendutils.py | 13 ++-- qiskit/backends/_qeremote.py | 75 +++++++++++----------- test/python/test_backends.py | 15 +---- test/python/test_projectq_cpp_simulator.py | 72 ++++++++++----------- 6 files changed, 84 insertions(+), 95 deletions(-) diff --git a/qiskit/__init__.py b/qiskit/__init__.py index 87db2ffff8c5..2b690af6b749 100644 --- a/qiskit/__init__.py +++ b/qiskit/__init__.py @@ -45,4 +45,6 @@ from ._quantumprogram import QuantumProgram from ._result import Result +from . import backends + __version__ = '0.5.0' diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py index dfbbc7da3957..40c40d56002e 100644 --- a/qiskit/_quantumprogram.py +++ b/qiskit/_quantumprogram.py @@ -694,6 +694,8 @@ def set_api(self, token, url, hub=None, group=None, project=None, This method will be deprecated in upcoming versions. Using the API object instead is recommended. """ + # TODO: remove the tests as well when the deprecation is completed + warnings.warn( "set_api() will be deprecated in upcoming versions (>0.5.0). " "Using the API object instead is recommended.", DeprecationWarning) diff --git a/qiskit/backends/_backendutils.py b/qiskit/backends/_backendutils.py index 66759720784c..699df09452ac 100644 --- a/qiskit/backends/_backendutils.py +++ b/qiskit/backends/_backendutils.py @@ -242,10 +242,10 @@ def get_backend_instance(backend_name): """ try: registered_backend = _REGISTERED_BACKENDS[backend_name] + return registered_backend.cls( + configuration=registered_backend.configuration) except KeyError: raise LookupError('backend "{}" is not available'.format(backend_name)) - return registered_backend.cls( - configuration=registered_backend.configuration) def configuration(backend_name): @@ -280,10 +280,9 @@ def calibration(backend_name): """ try: backend = qiskit.backends.get_backend_instance(backend_name) + return backend.calibration except KeyError: raise LookupError('backend "{}" is not available'.format(backend_name)) - else: - return backend.calibration def parameters(backend_name): @@ -302,10 +301,9 @@ def parameters(backend_name): """ try: backend = qiskit.backends.get_backend_instance(backend_name) + return backend.parameters except KeyError: raise LookupError('backend "{}" is not available'.format(backend_name)) - else: - return backend.parameters def status(backend_name): @@ -322,10 +320,9 @@ def status(backend_name): """ try: backend = qiskit.backends.get_backend_instance(backend_name) + return backend.status except KeyError: raise LookupError('backend "{}" is not available'.format(backend_name)) - else: - return backend.status def local_backends(): diff --git a/qiskit/backends/_qeremote.py b/qiskit/backends/_qeremote.py index 6f6248e0ace6..dfd9047e986a 100644 --- a/qiskit/backends/_qeremote.py +++ b/qiskit/backends/_qeremote.py @@ -130,22 +130,23 @@ def calibration(self): Raises: ConnectionError: if the API call failed. - LookupError: If a configuration for the backend can't be - found. + LookupError: If a configuration for the backend can't be found. """ - if self._api: - try: - backend_name = self.configuration['name'] - calibrations = self._api.backend_calibration(backend_name) - except Exception as ex: - raise ConnectionError("Couldn't get backend calibration: {0}" - .format(ex)) - else: + if not self._api: raise ConnectionError('API not set') + + try: + backend_name = self.configuration['name'] + calibrations = self._api.backend_calibration(backend_name) + except Exception as ex: + raise LookupError( + "Couldn't get backend calibration: {0}".format(ex)) + calibrations_edit = {} for key, vals in calibrations.items(): new_key = _snake_case_to_camel_case(key) calibrations_edit[new_key] = vals + return calibrations_edit @property @@ -157,24 +158,25 @@ def parameters(self): Raises: ConnectionError: if the API call faled. - LookupError: If parameters for the backend can't be - found. + LookupError: If parameters for the backend can't be found. """ - if self._api: - try: - backend_name = self.configuration['name'] - parameters = self._api.backend_parameters(backend_name) - except Exception as ex: - raise ConnectionError("Couldn't get backend parameters: {0}" - .format(ex)) - parameters_edit = {} - for key, vals in parameters.items(): - new_key = _snake_case_to_camel_case(key) - parameters_edit[new_key] = vals - return parameters_edit - else: + if not self._api: raise ConnectionError('API not set') + try: + backend_name = self.configuration['name'] + parameters = self._api.backend_parameters(backend_name) + except Exception as ex: + raise LookupError( + "Couldn't get backend parameters: {0}".format(ex)) + + parameters_edit = {} + for key, vals in parameters.items(): + new_key = _snake_case_to_camel_case(key) + parameters_edit[new_key] = vals + + return parameters_edit + @property def status(self): """Return the online backend status. @@ -184,21 +186,20 @@ def status(self): Raises: ConnectionError: if the API call failed. - LookupError: If status for the backend can't be - found. + LookupError: If status for the backend can't be found. """ - if self._api: - try: - backend_name = self.configuration['name'] - status = self._api.backend_status(backend_name) - except Exception as ex: - raise ConnectionError("Couldn't get backend status: {0}" - .format(ex)) - else: - return status - else: + if not self._api: raise ConnectionError('API not set') + try: + backend_name = self.configuration['name'] + status = self._api.backend_status(backend_name) + except Exception as ex: + raise LookupError( + "Couldn't get backend status: {0}".format(ex)) + + return status + def _wait_for_job(jobid, api, wait=5, timeout=60): """Wait until all online ran circuits of a qobj are 'COMPLETED'. diff --git a/test/python/test_backends.py b/test/python/test_backends.py index e90d70dfd464..8a113966e2c0 100644 --- a/test/python/test_backends.py +++ b/test/python/test_backends.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=invalid-name,missing-docstring,broad-except +# pylint: disable=invalid-name # Copyright 2017 IBM RESEARCH. All Rights Reserved. # @@ -28,17 +28,12 @@ class TestBackends(QiskitTestCase): """QISKit Backends (Object) Tests.""" - def setUp(self): - # pylint: disable=redefined-outer-name,unused-variable - QiskitTestCase.setUp(self) - def test_local_backends_discover(self): """Test if there are local backends. If all correct some should exists. """ local = qiskit.backends.discover_local_backends() - # print(local) self.log.info(local) self.assertTrue(local) @@ -48,7 +43,6 @@ def test_local_backends_exist(self): If all correct some should exists. """ local = qiskit.backends.local_backends() - # print(local) self.log.info(local) self.assertTrue(local) @@ -60,7 +54,6 @@ def test_remote_backends_discover(self, QE_TOKEN, QE_URL): """ api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) remote = qiskit.backends.discover_remote_backends(api) - # print(remote) self.log.info(remote) self.assertTrue(remote) @@ -73,7 +66,6 @@ def test_remote_backends_exist(self, QE_TOKEN, QE_URL): api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL}) qiskit.backends.discover_remote_backends(api) remote = qiskit.backends.remote_backends() - # print(remote) self.log.info(remote) self.assertTrue(remote) @@ -84,7 +76,6 @@ def test_backend_status(self): """ my_backend = qiskit.backends.get_backend_instance('local_qasm_simulator') out = my_backend.status - # print(out) self.assertIn(out['available'], [True]) def test_get_backend_configuration(self): @@ -97,7 +88,6 @@ def test_get_backend_configuration(self): backend_config = my_backend.configuration config_keys = {'name', 'simulator', 'local', 'description', 'coupling_map', 'basis_gates'} - # print(backend_config) self.assertTrue(config_keys < backend_config.keys()) @requires_qe_access @@ -115,7 +105,6 @@ def test_get_backend_configuration_online(self, QE_TOKEN, QE_URL): backend = backend_list[0] my_backend = qiskit.backends.get_backend_instance(backend) backend_config = my_backend.configuration - # print(backend_config) self.log.info(backend_config) self.assertTrue(config_keys < backend_config.keys()) @@ -131,7 +120,6 @@ def test_get_backend_calibration(self, QE_TOKEN, QE_URL): backend = backend_list[0] my_backend = qiskit.backends.get_backend_instance(backend) result = my_backend.calibration - # print(result) self.log.info(result) self.assertEqual(len(result), 4) @@ -147,7 +135,6 @@ def test_get_backend_parameters(self, QE_TOKEN, QE_URL): backend = backend_list[0] my_backend = qiskit.backends.get_backend_instance(backend) result = my_backend.parameters - # print(result) self.log.info(result) self.assertEqual(len(result), 4) diff --git a/test/python/test_projectq_cpp_simulator.py b/test/python/test_projectq_cpp_simulator.py index fb8505c9884b..163f7007fc15 100644 --- a/test/python/test_projectq_cpp_simulator.py +++ b/test/python/test_projectq_cpp_simulator.py @@ -20,11 +20,11 @@ import random import unittest -# import numpy -# from scipy.stats import chi2_contingency +import numpy +from scipy.stats import chi2_contingency import qiskit.backends._projectq_simulator as projectq_simulator -# import qiskit.backends._qasmsimulator as qasm_simulator +import qiskit.backends._qasmsimulator as qasm_simulator from qiskit import ClassicalRegister from qiskit import QuantumCircuit from qiskit import QuantumJob @@ -143,39 +143,39 @@ def test_entangle(self): with self.subTest(key=key): self.assertTrue(key in ['0' * N, '1' * N]) - # 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 = openquantumcompiler.compile(circuit.qasm()) - # shots = 100 - # 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)) - # self.assertTrue(counts_pq.keys() == counts_py.keys()) - # 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_random_circuits(self): + local_simulator = qasm_simulator.QasmSimulator() + for circuit in self.rqg.get_circuits(format_='QuantumCircuit'): + self.log.info(circuit.qasm()) + compiled_circuit = openquantumcompiler.compile(circuit.qasm()) + shots = 100 + 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)) + self.assertTrue(counts_pq.keys() == counts_py.keys()) + 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) if __name__ == '__main__':