Skip to content

Commit

Permalink
Adapting tests to new mapper.
Browse files Browse the repository at this point in the history
  • Loading branch information
thomashaener committed Apr 19, 2017
1 parent 4da3ae4 commit d7e1861
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 61 deletions.
8 changes: 0 additions & 8 deletions projectq/backends/_ibm/_ibm_http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
# api documentation is at https://qcwi-staging.mybluemix.net/explorer/
import requests
import getpass
import logging
import sys
import time
from requests.compat import urljoin
Expand Down Expand Up @@ -65,7 +64,6 @@ def send(qasm, device='sim_trivial_2', user=None, password=None,
if verbose:
print("Waiting for results...")
res = _get_result(execution_id, access_token)
logging.info(res)
if verbose:
print("Done.")
return res
Expand Down Expand Up @@ -97,7 +95,6 @@ def _authenticate(email=None, password=None):

r = requests.post(urljoin(_api_url, 'users/login'),
data={"email": email, "password": password})
logging.info(r.text)
r.raise_for_status()

json_data = r.json()
Expand All @@ -117,9 +114,6 @@ def _run(qasm, device, user_id, access_token, shots):
"fromCache": "false",
"shots": shots},
headers={"Content-Type": "application/json"})
logging.info(r.request.body)
logging.info(r.request.url)
logging.info(r.text)
r.raise_for_status()

r_json = r.json()
Expand All @@ -133,8 +127,6 @@ def _get_result(execution_id, access_token, num_retries=100, interval=1):
for _ in range(num_retries):
r = requests.get(urljoin(_api_url, suffix),
params={"access_token": access_token})
logging.info(r.request.url)
logging.info(r.text)
r.raise_for_status()

r_json = r.json()
Expand Down
37 changes: 14 additions & 23 deletions projectq/backends/_ibm/_ibm_http_client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def test_send_real_device_online_verbose(monkeypatch):
json_data = ''.join(['{', json_body, '}'])
shots = 1
device = "real"
json_data_run = ''.join(['{"jsonQasm":', json_qasm, '}'])
json_data_run = ''.join(['{"qasm":', json_qasm, '}'])
execution_id = 3
result_ready = [False]
result = "my_result"
Expand Down Expand Up @@ -75,13 +75,13 @@ def raise_for_status(self):
elif (args[0] == urljoin(_api_url,
"Executions/{execution_id}".format(execution_id=execution_id))
and kwargs["params"]["access_token"] == access_token and
not result_ready[0] and request_num[0] == 4):
not result_ready[0] and request_num[0] == 3):
result_ready[0] = True
return MockResponse({"status": {"id": "NotDone"}}, 200)
elif (args[0] == urljoin(_api_url,
"Executions/{execution_id}".format(execution_id=execution_id))
and kwargs["params"]["access_token"] == access_token and
result_ready[0] and request_num[0] == 4):
result_ready[0] and request_num[0] == 3):
return MockResponse({"status": {"id": "DONE"},
"result": result}, 200)

Expand Down Expand Up @@ -110,28 +110,19 @@ def raise_for_status(self):
request_num[0] == 1):
request_num[0] += 1
return MockPostResponse({"userId": user_id, "id": access_token})
# Save code
elif (args[0] == urljoin(_api_url,
"users/{}/codes".format(user_id)) and
kwargs["data"] == json_data and
kwargs["params"]["access_token"] == access_token and
kwargs["headers"]["Content-Type"] == "application/json" and
request_num[0] == 2):
request_num[0] += 1
return MockPostResponse({"idCode": code_id})
# Run code
elif (args[0] == urljoin(_api_url, "users/{user_id}/codes/{code_id}"
"/executions".format(user_id=user_id,
code_id=code_id)) and
kwargs["data"] == json_data_run and
elif (args[0] == urljoin(_api_url, "codes/execute") and
kwargs["data"] == json_qasm and
kwargs["params"]["access_token"] == access_token and
kwargs["params"]["deviceRunType"] == device and
kwargs["params"]["fromCache"] == "false" and
kwargs["params"]["shots"] == shots and
kwargs["headers"]["Content-Type"] == "application/json" and
request_num[0] == 3):
request_num[0] == 2):
request_num[0] += 1
return MockPostResponse({"execution": {"id": execution_id}})
return MockPostResponse({"id": execution_id})
else:
print(kwargs)

monkeypatch.setattr("requests.get", mocked_requests_get)
monkeypatch.setattr("requests.post", mocked_requests_post)
Expand All @@ -148,7 +139,7 @@ def user_password_input(prompt):
monkeypatch.setattr("getpass.getpass", user_password_input)

# Code to test:
res = _ibm_http_client.send(json_qasm, name=name,
res = _ibm_http_client.send(json_qasm,
device="real",
user=None, password=None,
shots=shots, verbose=True)
Expand All @@ -175,7 +166,7 @@ def json(self):
json_qasm = "my_json_qasm"
name = 'projectq_test'
with pytest.raises(_ibm_http_client.DeviceOfflineError):
_ibm_http_client.send(json_qasm, name=name,
_ibm_http_client.send(json_qasm,
device="real",
user=None, password=None,
shots=shots, verbose=True)
Expand Down Expand Up @@ -216,7 +207,7 @@ def user_password_input(prompt):
shots = 1
json_qasm = "my_json_qasm"
name = 'projectq_test'
_ibm_http_client.send(json_qasm, name=name,
_ibm_http_client.send(json_qasm,
device="real",
user=None, password=None,
shots=shots, verbose=True)
Expand Down Expand Up @@ -257,7 +248,7 @@ def user_password_input(prompt):
shots = 1
json_qasm = "my_json_qasm"
name = 'projectq_test'
_ibm_http_client.send(json_qasm, name=name,
_ibm_http_client.send(json_qasm,
device="real",
user=None, password=None,
shots=shots, verbose=True)
Expand Down Expand Up @@ -298,7 +289,7 @@ def user_password_input(prompt):
shots = 1
json_qasm = "my_json_qasm"
name = 'projectq_test'
_ibm_http_client.send(json_qasm, name=name,
_ibm_http_client.send(json_qasm,
device="real",
user=None, password=None,
shots=shots, verbose=True)
18 changes: 3 additions & 15 deletions projectq/backends/_ibm/_ibm_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"""Tests for projectq.backends._ibm._ibm.py."""

import pytest
import json

import projectq.setups.decompositions
from projectq import MainEngine
Expand Down Expand Up @@ -62,24 +63,11 @@ def test_ibm_backend_is_available_control_not(num_ctrl_qubits, is_available):


def test_ibm_backend_functional_test(monkeypatch):
correct_info = ('{"playground":[{"line":0,"name":"q","gates":[{"position"'
':0,"name":"h","qasm":"h"},{"position":2,"name":"h","qasm'
'":"h"},{"position":3,"name":"measure","qasm":"measure"}]'
'},{"line":1,"name":"q","gates":[{"position":0,"name":"h"'
',"qasm":"h"},{"position":3,"name":"h","qasm":"h"},{'
'"position":4,"name":"measure","qasm":"measure"}]},{'
'"line":2,"name":"q","gates":[{"position":1,"name":"cx"'
',"qasm":"cx","to":0},{"position":2,"name":"cx","qasm":'
'"cx","to":1},{"position":3,"name":"h","qasm":"h"},{'
'"position":4,"name":"measure","qasm":"measure"}]},{'
'"line":3,"name":"q","gates":[]},{"line":4,"name":"q",'
'"gates":[]}],"numberColumns":40,"numberLines":5,'
'"numberGates":200,"hasMeasures":true,"topology":'
'"250e969c6b9e68aa2a045ffbceb3ac33"}')
correct_info = ('{"name": "ProjectQ Experiment", "qasm": "\\ninclude \\"qelib1.inc\\";\\nqreg q[5];\\ncreg c[5];\\nh q[0];\\ncx q[0], q[2];\\ncx q[0], q[1];\\nmeasure q[0] -> c[0];\\nmeasure q[2] -> c[2];\\nmeasure q[1] -> c[1];", "codeType": "QASM2"}')

# patch send
def mock_send(*args, **kwargs):
assert args[0] == correct_info
assert json.loads(args[0]) == json.loads(correct_info)
return {'date': '2017-01-19T14:28:47.622Z',
'data': {'time': 14.429004907608032, 'serialNumberDevice':
'Real5Qv1', 'p': {'labels': ['00000', '00001',
Expand Down
14 changes: 6 additions & 8 deletions projectq/cengines/_ibmcnotmapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,14 @@ class IBMCNOTMapper(BasicEngine):
"""
CNOT mapper for the IBM backend.
Transforms CNOTs such that all CNOTs within the circuit have the same
target qubit (required by IBM backend). If necessary, it will flip
around the CNOT gate by first applying Hadamard gates to both qubits, then
CNOT with swapped control and target qubit, and finally Hadamard gates to
both qubits.
Maps a given circuit to the IBM Quantum Experience chip.
If necessary, it will flip around the CNOT gate by first applying Hadamard
gates to both qubits, then CNOT with swapped control and target qubit, and
finally Hadamard gates to both qubits.
Furthermore, it adds QubitPlacementTags to Allocate gate commands.
Note:
The mapper has to be run once on the entire circuit. Else, an
Exception will be raised (if, e.g., several measurements are performed
without re-initializing the mapper).
The mapper has to be run once on the entire circuit.
Warning:
If the provided circuit cannot be mapped to the hardware layout
Expand Down
40 changes: 33 additions & 7 deletions projectq/cengines/_ibmcnotmapper_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,49 @@ def test_ibmcnotmapper_invalid_circuit():
qb3 = eng.allocate_qubit()
CNOT | (qb1, qb2)
CNOT | (qb0, qb1)
CNOT | (qb0, qb2)
CNOT | (qb3, qb1)
with pytest.raises(Exception):
CNOT | (qb3, qb2)
eng.flush()


def test_ibmcnotmapper_nointermediate_measurements():
backend = DummyEngine()
def test_ibmcnotmapper_valid_circuit1():
backend = DummyEngine(save_commands=True)
eng = MainEngine(backend=backend,
engine_list=[_ibmcnotmapper.IBMCNOTMapper()])
qb0 = eng.allocate_qubit()
qb1 = eng.allocate_qubit()

qb2 = eng.allocate_qubit()
qb3 = eng.allocate_qubit()
qb4 = eng.allocate_qubit()
CNOT | (qb0, qb1)
Measure | qb0
CNOT | (qb1, qb0)
with pytest.raises(Exception):
Measure | qb0
CNOT | (qb0, qb2)
CNOT | (qb0, qb3)
CNOT | (qb0, qb4)
CNOT | (qb1, qb2)
CNOT | (qb3, qb4)
CNOT | (qb4, qb3)
eng.flush()


def test_ibmcnotmapper_valid_circuit2():
backend = DummyEngine(save_commands=True)
eng = MainEngine(backend=backend,
engine_list=[_ibmcnotmapper.IBMCNOTMapper()])
qb0 = eng.allocate_qubit()
qb1 = eng.allocate_qubit()
qb2 = eng.allocate_qubit()
qb3 = eng.allocate_qubit()
qb4 = eng.allocate_qubit()
CNOT | (qb3, qb1)
CNOT | (qb3, qb2)
CNOT | (qb3, qb0)
CNOT | (qb3, qb4)
CNOT | (qb1, qb2)
CNOT | (qb0, qb4)
CNOT | (qb2, qb1)
eng.flush()


def test_ibmcnotmapper_optimizeifpossible():
Expand Down

0 comments on commit d7e1861

Please sign in to comment.