diff --git a/README.rst b/README.rst index 614f23ad4..5b5dc5f66 100755 --- a/README.rst +++ b/README.rst @@ -106,9 +106,13 @@ To run a program on the IBM Quantum Experience chips, all one has to do is choos .. code-block:: python - compiler_engines = projectq.setups.ibm16.get_engine_list() + import projectq.setups.ibm + from projectq.backends import IBMBackend + + device='ibmq_16_melbourne' + compiler_engines = projectq.setups.ibm.get_engine_list(device=device) eng = MainEngine(IBMBackend(use_hardware=True, num_runs=1024, - verbose=False, device='ibmqx5'), + verbose=False, device=device), engine_list=compiler_engines) diff --git a/examples/ibm16.py b/examples/ibm16.py deleted file mode 100755 index 894c644ce..000000000 --- a/examples/ibm16.py +++ /dev/null @@ -1,43 +0,0 @@ -import projectq.setups.ibm16 -from projectq.backends import IBMBackend -from projectq.ops import All, Entangle, Measure -from projectq import MainEngine - - -def run_test(eng): - """ - Runs a test circuit on the provided compiler engine. - - Args: - eng (MainEngine): Main compiler engine to use. - - Returns: - measurement (list): List of measurement outcomes. - """ - # allocate the quantum register to entangle - qureg = eng.allocate_qureg(8) - - Entangle | qureg - - # measure; should be all-0 or all-1 - All(Measure) | qureg - - # run the circuit - eng.flush() - - # access the probabilities via the back-end: - results = eng.backend.get_probabilities(qureg) - for state, probability in sorted(list(results.items())): - print("Measured {} with p = {}.".format(state, probability)) - - # return one (random) measurement outcome. - return [int(q) for q in qureg] - - -if __name__ == "__main__": - # create main compiler engine for the 16-qubit IBM back-end - eng = MainEngine(IBMBackend(use_hardware=True, num_runs=1024, - verbose=False, device='ibmqx5'), - engine_list=projectq.setups.ibm16.get_engine_list()) - # run the circuit and print the result - print(run_test(eng)) diff --git a/projectq/backends/_ibm/_ibm_http_client.py b/projectq/backends/_ibm/_ibm_http_client.py index 98751bf90..a6d2ab54a 100755 --- a/projectq/backends/_ibm/_ibm_http_client.py +++ b/projectq/backends/_ibm/_ibm_http_client.py @@ -13,17 +13,20 @@ # limitations under the License. # helpers to run the jsonified gate sequence on ibm quantum experience server -# api documentation does not exist and has to be deduced from the qiskit code source -# at: https://github.com/Qiskit/qiskit-ibmq-provider +# api documentation does not exist and has to be deduced from the qiskit code +# source at: https://github.com/Qiskit/qiskit-ibmq-provider import getpass import time import signal +import uuid + import requests from requests.compat import urljoin from requests import Session -_AUTH_API_URL = 'https://auth.quantum-computing.ibm.com/api/users/loginWithToken' +_AUTH_API_URL = ('https://auth.quantum-computing.ibm.com/api/users/' + 'loginWithToken') _API_URL = 'https://api.quantum-computing.ibm.com/api/' # TODO: call to get the API version automatically @@ -34,7 +37,6 @@ class IBMQ(Session): """ Manage a session between ProjectQ and the IBMQ web API. """ - def __init__(self, **kwargs): super(IBMQ, self).__init__(**kwargs) # Python 2 compatibility self.backends = dict() @@ -59,11 +61,11 @@ def get_list_devices(self, verbose=False): request.raise_for_status() r_json = request.json() self.backends = dict() - for el in r_json: - self.backends[el['backend_name']] = { - 'nq': el['n_qubits'], - 'coupling_map': el['coupling_map'], - 'version': el['backend_version'] + for obj in r_json: + self.backends[obj['backend_name']] = { + 'nq': obj['n_qubits'], + 'coupling_map': obj['coupling_map'], + 'version': obj['backend_version'] } if verbose: @@ -125,69 +127,110 @@ def _authenticate(self, token=None): self.params.update({'access_token': r_json['id']}) def _run(self, info, device): - post_job_url = 'Network/ibm-q/Groups/open/Projects/main/Jobs' - shots = info['shots'] - n_classical_reg = info['nq'] - n_qubits = self.backends[device]['nq'] - version = self.backends[device]['version'] - instructions = info['json'] - maxcredit = info['maxCredits'] - c_label = [] - q_label = [] - for i in range(n_classical_reg): - c_label.append(['c', i]) - for i in range(n_qubits): - q_label.append(['q', i]) - experiment = [{ - 'header': { - 'qreg_sizes': [['q', n_qubits]], - 'n_qubits': n_qubits, - 'memory_slots': n_classical_reg, - 'creg_sizes': [['c', n_classical_reg]], - 'clbit_labels': c_label, - 'qubit_labels': q_label, - 'name': 'circuit0' - }, - 'config': { - 'n_qubits': n_qubits, - 'memory_slots': n_classical_reg - }, - 'instructions': instructions - }] - # Note: qobj_id is not necessary in projectQ, so fixed string for now - argument = { + """ + Run the quantum code to the IBMQ machine. + Update since March2020: only protocol available is what they call + 'object storage' where a job request via the POST method gets in + return a url link to which send the json data. A final http validates + the data communication. + + Args: + info (dict): dictionary sent by the backend containing the code to + run + device (str): name of the ibm device to use + + Returns: + (tuple): (str) Execution Id + + """ + + # STEP1: Obtain most of the URLs for handling communication with + # quantum device + json_step1 = { 'data': None, 'json': { - 'qObject': { - 'type': 'QASM', - 'schema_version': '1.1.0', - 'config': { - 'shots': shots, - 'max_credits': maxcredit, - 'n_qubits': n_qubits, - 'memory_slots': n_classical_reg, - 'memory': False, - 'parameter_binds': [] - }, - 'experiments': experiment, - 'header': { - 'backend_version': version, - 'backend_name': device - }, - 'qobj_id': 'e72443f5-7752-4e32-9ac8-156f1f3fee18' - }, 'backend': { 'name': device }, - 'shots': shots + 'allowObjectStorage': True, + 'shareLevel': 'none' }, 'timeout': (self.timeout, None) } - request = super(IBMQ, self).post(urljoin(_API_URL, post_job_url), - **argument) + request = super(IBMQ, self).post( + urljoin(_API_URL, 'Network/ibm-q/Groups/open/Projects/main/Jobs'), + **json_step1) + request.raise_for_status() + r_json = request.json() + download_endpoint_url = r_json['objectStorageInfo'][ + 'downloadQObjectUrlEndpoint'] + upload_endpoint_url = r_json['objectStorageInfo'][ + 'uploadQobjectUrlEndpoint'] + upload_url = r_json['objectStorageInfo']['uploadUrl'] + + # STEP2: WE USE THE ENDPOINT TO GET THE UPLOT LINK + json_step2 = {'allow_redirects': True, 'timeout': (5.0, None)} + request = super(IBMQ, self).get(upload_endpoint_url, **json_step2) request.raise_for_status() r_json = request.json() - execution_id = r_json["id"] + + # STEP3: WE USE THE ENDPOINT TO GET THE UPLOT LINK + n_classical_reg = info['nq'] + # hack: easier to restrict labels to measured qubits + n_qubits = n_classical_reg # self.backends[device]['nq'] + instructions = info['json'] + maxcredit = info['maxCredits'] + c_label = [["c", i] for i in range(n_classical_reg)] + q_label = [["q", i] for i in range(n_qubits)] + + # hack: the data value in the json quantum code is a string + instruction_str = str(instructions).replace('\'', '\"') + data = '{"qobj_id": "' + str(uuid.uuid4()) + '", ' + data += '"header": {"backend_name": "' + device + '", ' + data += ('"backend_version": "' + self.backends[device]['version'] + + '"}, ') + data += '"config": {"shots": ' + str(info['shots']) + ', ' + data += '"max_credits": ' + str(maxcredit) + ', "memory": false, ' + data += ('"parameter_binds": [], "memory_slots": ' + + str(n_classical_reg)) + data += (', "n_qubits": ' + str(n_qubits) + + '}, "schema_version": "1.1.0", ') + data += '"type": "QASM", "experiments": [{"config": ' + data += '{"n_qubits": ' + str(n_qubits) + ', ' + data += '"memory_slots": ' + str(n_classical_reg) + '}, ' + data += ('"header": {"qubit_labels": ' + + str(q_label).replace('\'', '\"') + ', ') + data += '"n_qubits": ' + str(n_classical_reg) + ', ' + data += '"qreg_sizes": [["q", ' + str(n_qubits) + ']], ' + data += '"clbit_labels": ' + str(c_label).replace('\'', '\"') + ', ' + data += '"memory_slots": ' + str(n_classical_reg) + ', ' + data += '"creg_sizes": [["c", ' + str(n_classical_reg) + ']], ' + data += ('"name": "circuit0"}, "instructions": ' + instruction_str + + '}]}') + + json_step3 = { + 'data': data, + 'params': { + 'access_token': None + }, + 'timeout': (5.0, None) + } + request = super(IBMQ, self).put(r_json['url'], **json_step3) + request.raise_for_status() + + # STEP4: CONFIRM UPLOAD + json_step4 = { + 'data': None, + 'json': None, + 'timeout': (self.timeout, None) + } + upload_data_url = upload_endpoint_url.replace('jobUploadUrl', + 'jobDataUploaded') + request = super(IBMQ, self).post(upload_data_url, **json_step4) + request.raise_for_status() + r_json = request.json() + execution_id = upload_endpoint_url.split('/')[-2] + return execution_id def _get_result(self, @@ -205,7 +248,7 @@ def _get_result(self, original_sigint_handler = signal.getsignal(signal.SIGINT) - def _handle_sigint_during_get_result(*_): + def _handle_sigint_during_get_result(*_): # pragma: no cover raise Exception( "Interrupted. The ID of your submitted job is {}.".format( execution_id)) @@ -214,20 +257,62 @@ def _handle_sigint_during_get_result(*_): signal.signal(signal.SIGINT, _handle_sigint_during_get_result) for retries in range(num_retries): - argument = { + # STEP5: WAIT FOR THE JOB TO BE RUN + json_step5 = { 'allow_redirects': True, 'timeout': (self.timeout, None) } request = super(IBMQ, self).get(urljoin(_API_URL, job_status_url), - **argument) + **json_step5) request.raise_for_status() r_json = request.json() + acceptable_status = ['VALIDATING', 'VALIDATED', 'RUNNING'] if r_json['status'] == 'COMPLETED': - return r_json['qObjectResult']['results'][0] - if r_json['status'] != 'RUNNING': - raise Exception("Error while running the code: {}.".format( - r_json['status'])) + # STEP6: Get the endpoint to get the result + json_step6 = { + 'allow_redirects': True, + 'timeout': (self.timeout, None) + } + request = super(IBMQ, self).get( + urljoin(_API_URL, + job_status_url + '/resultDownloadUrl'), + **json_step6) + request.raise_for_status() + r_json = request.json() + + # STEP7: Get the result + json_step7 = { + 'allow_redirects': True, + 'params': { + 'access_token': None + }, + 'timeout': (self.timeout, None) + } + request = super(IBMQ, self).get(r_json['url'], + **json_step7) + r_json = request.json() + result = r_json['results'][0] + + # STEP8: Confirm the data was downloaded + json_step8 = { + 'data': None, + 'json': None, + 'timeout': (5.0, None) + } + request = super(IBMQ, self).post( + urljoin(_API_URL, + job_status_url + '/resultDownloaded'), + **json_step8) + r_json = request.json() + return result + + # Note: if stays stuck if 'Validating' mode, then sthg went + # wrong in step 3 + if r_json['status'] not in acceptable_status: + raise Exception( + "Error while running the code. Last status: {}.". + format(r_json['status'])) time.sleep(interval) if self.is_online(device) and retries % 60 == 0: self.get_list_devices() diff --git a/projectq/backends/_ibm/_ibm_http_client_test.py b/projectq/backends/_ibm/_ibm_http_client_test.py index eb56b1ee4..5f43b5d28 100755 --- a/projectq/backends/_ibm/_ibm_http_client_test.py +++ b/projectq/backends/_ibm/_ibm_http_client_test.py @@ -74,11 +74,10 @@ def json(self): def raise_for_status(self): pass - # Accessing status of device. Return online. status_url = 'Network/ibm-q/Groups/open/Projects/main/devices/v/1' if (args[1] == urljoin(_API_URL, status_url) - and (request_num[0] == 1 or request_num[0] == 4)): + and (request_num[0] == 1 or request_num[0] == 7)): request_num[0] += 1 connections = set([(0, 1), (1, 0), (1, 2), (1, 3), (1, 4), (2, 1), (2, 3), (2, 4), (3, 1), (3, 4), (4, 3)]) @@ -88,12 +87,17 @@ def raise_for_status(self): 'backend_version': '0.1.547', 'n_qubits': 32 }], 200) - # Getting result + #STEP2 + elif (args[1] == "/"+execution_id+"/jobUploadUrl" + and request_num[0] == 3): + request_num[0] += 1 + return MockResponse({"url": "s3_url"}, 200) + #STEP5 elif (args[1] == urljoin( _API_URL, "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}". format(execution_id=execution_id)) and not result_ready[0] - and request_num[0] == 3): + and request_num[0] == 6): result_ready[0] = True request_num[0] += 1 return MockResponse({"status": "RUNNING"}, 200) @@ -101,14 +105,25 @@ def raise_for_status(self): _API_URL, "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}". format(execution_id=execution_id)) and result_ready[0] - and request_num[0] == 5): + and request_num[0] == 8): + request_num[0] += 1 return MockResponse( - { - 'qObjectResult': { - "results": [result] - }, - "status": "COMPLETED" - }, 200) + {"status": "COMPLETED"}, 200) + #STEP6 + elif (args[1] == urljoin( + _API_URL, + "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}/resultDownloadUrl". + format(execution_id=execution_id)) + and request_num[0] == 9): + request_num[0] += 1 + return MockResponse( + {"url": "result_download_url"}, 200) + #STEP7 + elif (args[1] == "result_download_url" + and request_num[0] == 10): + request_num[0] += 1 + return MockResponse( + {"results": [result]}, 200) def mocked_requests_post(*args, **kwargs): class MockRequest: @@ -134,16 +149,61 @@ def raise_for_status(self): and request_num[0] == 0): request_num[0] += 1 return MockPostResponse({"userId": user_id, "id": access_token}) - # Run code - elif (args[1] == urljoin(_API_URL, jobs_url) and kwargs["data"] is None - and kwargs["json"]["backend"]["name"] == device - and kwargs["json"]["qObject"]['config']['shots'] == shots + # STEP1 + elif (args[1] == urljoin(_API_URL, jobs_url) and request_num[0] == 2): request_num[0] += 1 - return MockPostResponse({"id": execution_id}) + answer1={'objectStorageInfo':{ + 'downloadQObjectUrlEndpoint':'url_dld_endpoint', + 'uploadQobjectUrlEndpoint':'/'+execution_id+'/jobUploadUrl', + 'uploadUrl':'url_upld'} + } + return MockPostResponse(answer1,200) + + # STEP4 + elif (args[1] == "/"+execution_id+"/jobDataUploaded" + and request_num[0] == 5): + request_num[0] += 1 + return MockPostResponse({}, 200) + + #STEP8 + elif (args[1] == urljoin( + _API_URL, + "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}/resultDownloaded". + format(execution_id=execution_id)) + and request_num[0] == 11): + request_num[0] += 1 + return MockPostResponse( + {}, 200) + + def mocked_requests_put(*args, **kwargs): + class MockRequest: + def __init__(self, url=""): + self.url = url + + class MockResponse: + def __init__(self, json_data, status_code): + self.json_data = json_data + self.status_code = status_code + self.request = MockRequest() + self.text = "" + + def json(self): + return self.json_data + + def raise_for_status(self): + pass + + # STEP3 + if (args[1] == "s3_url" + and request_num[0] == 4): + request_num[0] += 1 + return MockResponse({}, 200) + monkeypatch.setattr("requests.sessions.Session.get", mocked_requests_get) monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post) + monkeypatch.setattr("requests.sessions.Session.put", mocked_requests_put) def user_password_input(prompt): if prompt == "IBM QE token > ": @@ -157,6 +217,7 @@ def user_password_input(prompt): token=None, shots=shots, verbose=True) + assert res == result json_qasm['nq'] = 40 request_num[0] = 0 @@ -451,6 +512,7 @@ def test_timeout_exception(monkeypatch): } json_qasm = qasms tries = [0] + execution_id = '3' def mocked_requests_get(*args, **kwargs): class MockResponse: @@ -476,11 +538,21 @@ def raise_for_status(self): 'n_qubits': 32 }], 200) job_url = "Network/ibm-q/Groups/open/Projects/main/Jobs/{}".format( - "123e") + execution_id) if args[1] == urljoin(_API_URL, job_url): tries[0] += 1 return MockResponse({"status": "RUNNING"}, 200) + #STEP2 + elif (args[1] == "/"+execution_id+"/jobUploadUrl"): + return MockResponse({"url": "s3_url"}, 200) + #STEP5 + elif (args[1] == urljoin( + _API_URL, + "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}". + format(execution_id=execution_id))): + return MockResponse({"status": "RUNNING"}, 200) + def mocked_requests_post(*args, **kwargs): class MockRequest: def __init__(self, url=""): @@ -501,11 +573,45 @@ def raise_for_status(self): jobs_url = 'Network/ibm-q/Groups/open/Projects/main/Jobs' if args[1] == _AUTH_API_URL: return MockPostResponse({"userId": "1", "id": "12"}) - if args[1] == urljoin(_API_URL, jobs_url): - return MockPostResponse({"id": "123e"}) + + # STEP1 + elif (args[1] == urljoin(_API_URL, jobs_url)): + answer1={'objectStorageInfo':{ + 'downloadQObjectUrlEndpoint':'url_dld_endpoint', + 'uploadQobjectUrlEndpoint':'/'+execution_id+'/jobUploadUrl', + 'uploadUrl':'url_upld'} + } + return MockPostResponse(answer1,200) + + # STEP4 + elif (args[1] == "/"+execution_id+"/jobDataUploaded"): + return MockPostResponse({}, 200) + + def mocked_requests_put(*args, **kwargs): + class MockRequest: + def __init__(self, url=""): + self.url = url + + class MockResponse: + def __init__(self, json_data, status_code): + self.json_data = json_data + self.status_code = status_code + self.request = MockRequest() + self.text = "" + + def json(self): + return self.json_data + + def raise_for_status(self): + pass + + # STEP3 + if (args[1] == "s3_url"): + return MockResponse({}, 200) monkeypatch.setattr("requests.sessions.Session.get", mocked_requests_get) monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post) + monkeypatch.setattr("requests.sessions.Session.put", mocked_requests_put) _ibm_http_client.time.sleep = lambda x: x with pytest.raises(Exception) as excinfo: @@ -515,7 +621,7 @@ def raise_for_status(self): shots=1, num_retries=10, verbose=False) - assert "123e" in str(excinfo.value) # check that job id is in exception + assert execution_id in str(excinfo.value) # check that job id is in exception assert tries[0] > 0 @@ -609,6 +715,7 @@ def raise_for_status(self): def test_retrieve(monkeypatch): request_num = [0] + execution_id='3' def mocked_requests_get(*args, **kwargs): class MockResponse: @@ -631,20 +738,31 @@ def raise_for_status(self): 'backend_version': '0.1.547', 'n_qubits': 32 }], 200) - job_url = 'Network/ibm-q/Groups/open/Projects/main/Jobs/{}'.format( - "123e") - if args[1] == urljoin(_API_URL, job_url) and request_num[0] < 1: + + #STEP5 + elif (args[1] == urljoin( + _API_URL, + "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}". + format(execution_id=execution_id))and request_num[0] < 1): request_num[0] += 1 return MockResponse({"status": "RUNNING"}, 200) - elif args[1] == urljoin(_API_URL, job_url): + elif (args[1] == urljoin( + _API_URL, + "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}". + format(execution_id=execution_id))): return MockResponse( - { - "qObjectResult": { - 'qasm': 'qasm', - 'results': ['correct'] - }, - "status": "COMPLETED" - }, 200) + {"status": "COMPLETED"}, 200) + #STEP6 + elif (args[1] == urljoin( + _API_URL, + "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}/resultDownloadUrl". + format(execution_id=execution_id))): + return MockResponse( + {"url": "result_download_url"}, 200) + #STEP7 + elif (args[1] == "result_download_url"): + return MockResponse( + {"results": ['correct']}, 200) def mocked_requests_post(*args, **kwargs): class MockRequest: @@ -666,11 +784,19 @@ def raise_for_status(self): if args[1] == _AUTH_API_URL: return MockPostResponse({"userId": "1", "id": "12"}) + #STEP8 + elif (args[1] == urljoin( + _API_URL, + "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}/resultDownloaded". + format(execution_id=execution_id))): + return MockPostResponse( + {}, 200) + monkeypatch.setattr("requests.sessions.Session.get", mocked_requests_get) monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post) _ibm_http_client.time.sleep = lambda x: x res = _ibm_http_client.retrieve(device="ibmqx4", token="test", - jobid="123e") + jobid=execution_id) assert res == 'correct' diff --git a/projectq/setups/ibm16.py b/projectq/setups/ibm16.py deleted file mode 100755 index a00551a21..000000000 --- a/projectq/setups/ibm16.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2017 ProjectQ-Framework (www.projectq.ch) -# -# 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. - -""" -Defines a setup useful for the IBM QE chip with 16 qubits. - -It provides the `engine_list` for the `MainEngine`, and contains an -AutoReplacer with most of the gate decompositions of ProjectQ, among others -it includes: - - * Controlled z-rotations --> Controlled NOTs and single-qubit rotations - * Toffoli gate --> CNOT and single-qubit gates - * m-Controlled global phases --> (m-1)-controlled phase-shifts - * Global phases --> ignore - * (controlled) Swap gates --> CNOTs and Toffolis - * Arbitrary single qubit gates --> Rz and Ry - * Controlled arbitrary single qubit gates --> Rz, Ry, and CNOT gates - -Moreover, it contains `LocalOptimizers`. -""" - -import projectq -import projectq.libs.math -import projectq.setups.decompositions -from projectq.cengines import (AutoReplacer, - DecompositionRuleSet, - GridMapper, - InstructionFilter, - LocalOptimizer, - SwapAndCNOTFlipper, - TagRemover) -from projectq.setups.grid import high_level_gates - - -ibmqx5_connections = set([(1, 0), (1, 2), (2, 3), (3, 4), (3, 14), (5, 4), - (6, 5), (6, 7), (6, 11), (7, 10), (8, 7), (9, 8), - (9, 10), (11, 10), (12, 5), (12, 11), (12, 13), - (13, 4), (13, 14), (15, 0), (15, 2), (15, 14)]) - - -grid_to_physical = {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 0, - 9: 15, 10: 14, 11: 13, 12: 12, 13: 11, 14: 10, 15: 9} - - -def get_engine_list(): - rule_set = DecompositionRuleSet(modules=[projectq.libs.math, - projectq.setups.decompositions]) - return [TagRemover(), - LocalOptimizer(5), - AutoReplacer(rule_set), - InstructionFilter(high_level_gates), - TagRemover(), - LocalOptimizer(5), - AutoReplacer(rule_set), - TagRemover(), - GridMapper(2, 8, grid_to_physical), - LocalOptimizer(5), - SwapAndCNOTFlipper(ibmqx5_connections), - LocalOptimizer(5)] diff --git a/projectq/setups/ibm16_test.py b/projectq/setups/ibm16_test.py deleted file mode 100644 index cae50b168..000000000 --- a/projectq/setups/ibm16_test.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2017 ProjectQ-Framework (www.projectq.ch) -# -# 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. -"""Tests for projectq.setup.ibm16.""" - -import projectq -import projectq.setups.ibm16 -from projectq import MainEngine -from projectq.cengines import GridMapper, SwapAndCNOTFlipper, DummyEngine -from projectq.libs.math import AddConstant -from projectq.ops import QFT, get_inverse - - -def test_mappers_in_cengines(): - found = 0 - for engine in projectq.setups.ibm16.get_engine_list(): - if isinstance(engine, GridMapper): - found |= 1 - if isinstance(engine, SwapAndCNOTFlipper): - found |= 2 - assert found == 3 - - -def test_high_level_gate_set(): - mod_list = projectq.setups.ibm16.get_engine_list() - saving_engine = DummyEngine(save_commands=True) - mod_list = mod_list[:6] + [saving_engine] + mod_list[6:] - eng = MainEngine(DummyEngine(), - engine_list=mod_list) - qureg = eng.allocate_qureg(3) - AddConstant(3) | qureg - QFT | qureg - eng.flush() - received_gates = [cmd.gate for cmd in saving_engine.received_commands] - assert sum([1 for g in received_gates if g == QFT]) == 1 - assert get_inverse(QFT) not in received_gates - assert AddConstant(3) not in received_gates