Skip to content

Commit

Permalink
Revert "Update the develop branch."
Browse files Browse the repository at this point in the history
  • Loading branch information
thomashaener committed Jan 20, 2017
1 parent f2aba5f commit 419c4ba
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 117 deletions.
13 changes: 4 additions & 9 deletions examples/ibm.py
Expand Up @@ -3,7 +3,7 @@
from projectq import MainEngine


def run_entangle(eng, num_qubits=5):
def run_entangle(eng, num_qubits=3):
"""
Runs an entangling operation on the provided compiler engine.
Expand All @@ -16,7 +16,7 @@ def run_entangle(eng, num_qubits=5):
"""
# allocate the quantum register to entangle
qureg = eng.allocate_qureg(num_qubits)

# entangle the qureg
Entangle | qureg

Expand All @@ -26,17 +26,12 @@ def run_entangle(eng, num_qubits=5):
# run the circuit
eng.flush()

# access the probabilities via the back-end:
results = eng.backend.get_probabilities(qureg)
for state in results:
print("Measured {} with p = {}.".format(state, results[state]))

# return one (random) measurement outcome.
# return the list of measurements
return [int(q) for q in qureg]


if __name__ == "__main__":
# create main compiler engine for the IBM back-end
eng = MainEngine(IBMBackend(use_hardware=True, num_runs=1024, verbose=False))
eng = MainEngine(IBMBackend(use_hardware=True, num_runs=1024, verbose=True))
# run the circuit and print the result
print(run_entangle(eng))
2 changes: 1 addition & 1 deletion projectq/_version.py
Expand Up @@ -11,4 +11,4 @@
# limitations under the License.

"""Define version number here and read it from setup.py automatically"""
__version__ = "0.1.3"
__version__ = "0.1.2"
129 changes: 34 additions & 95 deletions projectq/backends/_ibm/_ibm.py
Expand Up @@ -67,15 +67,11 @@ def __init__(self, use_hardware=False, num_runs=1024, verbose=False,
if use_hardware:
self._device = 'real'
else:
self._device = 'sim_trivial_2'
self._device = 'sim_trivial'
self._num_runs = num_runs
self._verbose = verbose
self._user = user
self._password = password
self._mapping = dict()
self._inverse_mapping = dict()
self._mapped_qubits = 0
self._probabilities = dict()

def is_available(self, cmd):
"""
Expand Down Expand Up @@ -105,7 +101,6 @@ def _reset(self):
for _ in range(self._num_qubits):
self._cmds.append([""] * self._num_cols)
self._positions = [0] * self._num_qubits
self._mapped_qubits = 0

def _store(self, cmd):
"""
Expand All @@ -118,32 +113,14 @@ def _store(self, cmd):
"""
gate = cmd.gate
if gate == Allocate or gate == Deallocate:
return

if self._mapped_qubits == 0:
self._mapping = dict()
self._inverse_mapping = dict()
self._probabilities = dict()

for qr in cmd.qubits:
for qb in qr:
if not qb.id in self._mapping:
self._mapping[qb.id] = self._mapped_qubits
self._inverse_mapping[self._mapped_qubits] = qb.id
self._mapped_qubits += 1
for qb in cmd.control_qubits:
if not qb.id in self._mapping:
self._mapping[qb.id] = self._mapped_qubits
self._inverse_mapping[self._mapped_qubits] = qb.id
self._mapped_qubits += 1

if gate == Measure:
pass
elif gate == Measure:
for qr in cmd.qubits:
for qb in qr:
qb_pos = self._mapping[qb.id]
meas = _IBMGateCommand("measure", qb_pos)
self._cmds[qb_pos][self._positions[qb_pos]] = meas
self._positions[qb_pos] += 1
qb_id = qb.id
meas = _IBMGateCommand("measure", qb_id)
self._cmds[qb_id][self._positions[qb_id]] = meas
self._positions[qb_id] += 1

elif not (gate == NOT and get_control_count(cmd) == 1):
cls = gate.__class__.__name__
Expand All @@ -152,56 +129,20 @@ def _store(self, cmd):
else:
gate_str = str(gate).lower()

qb_pos = self._mapping[cmd.qubits[0][0].id]
ibm_cmd = _IBMGateCommand(gate_str, qb_pos)
self._cmds[qb_pos][self._positions[qb_pos]] = ibm_cmd
self._positions[qb_pos] += 1
qb_id = cmd.qubits[0][0].id
ibm_cmd = _IBMGateCommand(gate_str, qb_id)
self._cmds[qb_id][self._positions[qb_id]] = ibm_cmd
self._positions[qb_id] += 1
else:
ctrl_pos = self._mapping[cmd.control_qubits[0].id]
qb_pos = self._mapping[cmd.qubits[0][0].id]
pos = max(self._positions[qb_pos], self._positions[ctrl_pos])
self._positions[qb_pos] = pos
self._positions[ctrl_pos] = pos
ibm_cmd = _IBMGateCommand("cx", qb_pos, ctrl_pos)
self._cmds[qb_pos][self._positions[qb_pos]] = ibm_cmd
self._positions[qb_pos] += 1
self._positions[ctrl_pos] += 1

def get_probabilities(self, qureg):
"""
Return the list of basis states with corresponding probabilities.
The measured bits are ordered according to the supplied quantum register,
i.e., the left-most bit in the state-string corresponds to the first qubit
in the supplied quantum register.
Warning:
Only call this function after the circuit has been executed!
Args:
qureg (list<Qubit>): Quantum register determining the order of the
qubits.
Returns:
probability_dict (dict): Dictionary mapping n-bit strings to
probabilities.
Raises:
Exception: If no data is available (i.e., if the circuit has not been
executed).
"""
if len(self._probabilities) == 0:
raise RuntimeError("Please, run the circuit first!")

probability_dict = dict()

for state in self._probabilities:
mapped_state = ['0'] * len(qureg)
for i in range(len(qureg)):
mapped_state[i] = state[self._mapping[qureg[i].id]]
probability_dict["".join(mapped_state)] = self._probabilities[state]

return probability_dict
ctrl_id = cmd.control_qubits[0].id
qb_id = cmd.qubits[0][0].id
pos = max(self._positions[qb_id], self._positions[ctrl_id])
self._positions[qb_id] = pos
self._positions[ctrl_id] = pos
ibm_cmd = _IBMGateCommand("cx", qb_id, ctrl_id)
self._cmds[qb_id][self._positions[qb_id]] = ibm_cmd
self._positions[qb_id] += 1
self._positions[ctrl_id] += 1

def _run(self):
"""
Expand All @@ -225,7 +166,6 @@ def _run(self):
gate['position'] = j
try:
gate['name'] = cmd.gate
gate['qasm'] = cmd.gate
if not cmd.ctrl is None:
gate['to'] = cmd.ctrl
cnot_qubit_id = i
Expand Down Expand Up @@ -269,10 +209,8 @@ def _run(self):
for j in range(len(lines[i]['gates'])):
try:
name = lines[i]['gates'][j]['name']
qasm = lines[i]['gates'][j]['qasm']
gates += '{"position":' + str(j)
gates += ',"name":"' + name + '"'
gates += ',"qasm":"' + qasm + '"'
if name == "cx":
gates += ',"to":' + str(lines[i]['gates'][j]['to'])
gates += '},'
Expand All @@ -298,26 +236,27 @@ def _run(self):
p_sum = 0.
measured = ""
for state, probability in zip(data['labels'], data['values']):
state = list(reversed(state))
state[2], state[self._cnot_qubit_id] = state[self._cnot_qubit_id], state[2]
state = "".join(state)
if self._verbose and probability > 0:
print(str(state) + " with p = " + str(probability))
p_sum += probability
star = ""
if p_sum >= P and measured == "":
measured = state
star = "*"
self._probabilities[state] = probability
if self._verbose and probability > 0:
print(str(state) + " with p = " + str(probability) + star)


class QB():
def __init__(self, ID):
self.id = ID

# register measurement result
for ID in self._mapping:
location = self._mapping[ID]
self.main_engine.set_measurement_result(QB(ID), int(measured[location]))
for i in range(len(data['qubits'])):
ID = int(data['qubits'][i])
if ID == 2:
# we may have swapped these two qubits
# (cnot qubit is always #2 on the device)
# --> undo this transformation
ID = self._cnot_qubit_id
elif ID == self._cnot_qubit_id: # same here.
ID = 2
self.main_engine.set_measurement_result(QB(ID), int(measured[i]))
self._reset()
except TypeError:
raise Exception("Failed to run the circuit. Aborting.")
Expand Down
4 changes: 2 additions & 2 deletions projectq/backends/_ibm/_ibm_http_client.py
Expand Up @@ -27,7 +27,7 @@ class DeviceOfflineError(Exception):
pass


def send(json_qasm, name, device='sim_trivial_2', user=None, password=None,
def send(json_qasm, name, device='sim_trivial', user=None, password=None,
shots=1, verbose=False):
"""
Sends json QASM through the IBM API and runs the quantum circuit represented
Expand All @@ -36,7 +36,7 @@ def send(json_qasm, name, device='sim_trivial_2', user=None, password=None,
Args:
json_qasm: JSON QASM representation of the circuit to run.
name (str): Name of the experiment.
device (str): 'sim_trivial_2' or 'real' to run on simulator or on the real
device (str): 'sim_trivial' or 'real' to run on simulator or on the real
chip, respectively.
user (str): IBM quantum experience user.
password (str): IBM quantum experience user password.
Expand Down
12 changes: 5 additions & 7 deletions projectq/backends/_ibm/_ibm_test.py
Expand Up @@ -32,7 +32,7 @@ def no_requests(monkeypatch):
monkeypatch.delattr("requests.sessions.Session.request")


_api_url = 'https://quantumexperience.ng.bluemix.net/api/'
_api_url = 'https://qcwi-staging.mybluemix.net/api/'
_api_url_status = 'https://quantumexperience.ng.bluemix.net/api/'


Expand All @@ -54,9 +54,11 @@ def test_ibm_backend_is_available_control_not(num_ctrl_qubits, is_available):
eng = MainEngine(backend=DummyEngine(), engine_list=[DummyEngine()])
qubit1 = eng.allocate_qubit()
qureg = eng.allocate_qureg(num_ctrl_qubits)
print(len(qureg))
ibm_backend = _ibm.IBMBackend()
cmd = Command(eng, NOT , (qubit1,))
cmd.add_control_qubits(qureg)
print(cmd)
assert ibm_backend.is_available(cmd) == is_available


Expand All @@ -69,26 +71,22 @@ def test_ibm_backend_functional_test(monkeypatch):
toffoli2cnotandtgate,
entangle,
qft2crandhadamard)
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 = '{"playground":[{"line":0,"name":"q","gates":[{"position":0,"name":"h"},{"position":3,"name":"h"},{"position":4,"name":"measure"}]},{"line":1,"name":"q","gates":[{"position":0,"name":"h"},{"position":2,"name":"h"},{"position":3,"name":"measure"}]},{"line":2,"name":"q","gates":[{"position":1,"name":"cx","to":1},{"position":2,"name":"cx","to":0},{"position":3,"name":"h"},{"position":4,"name":"measure"}]},{"line":3,"name":"q","gates":[]},{"line":4,"name":"q","gates":[]}],"numberColumns":40,"numberLines":5,"numberGates":200,"hasMeasures":true,"topology":"250e969c6b9e68aa2a045ffbceb3ac33"}'
# patch send
def mock_send(*args, **kwargs):
assert args[0] == correct_info
return {'date': '2017-01-19T14:28:47.622Z', 'data': {'time': 14.429004907608032, 'serialNumberDevice': 'Real5Qv1', 'p': {'labels': ['00000', '00001', '00010', '00011', '00100', '00101', '00110', '00111'], 'values': [0.4521484375, 0.0419921875, 0.0185546875, 0.0146484375, 0.005859375, 0.0263671875, 0.0537109375, 0.38671875], 'qubits': [0, 1, 2]}, 'qasm': 'IBMQASM 2.0;\n\ninclude "qelib1.inc";\nqreg q[5];\ncreg c[5];\n\nh q[0];\nh q[1];\nCX q[0],q[2];\nh q[0];\nCX q[1],q[2];\nmeasure q[0] -> c[0];\nh q[1];\nh q[2];\nmeasure q[1] -> c[1];\nmeasure q[2] -> c[2];\n'}}
return {'data': {'qasm': 'qreg q,5;gate h, [[0.7071067811865476,0.7071067811865476],[0.7071067811865476,-0.7071067811865476]];gate measure, [[1,0],[0,0.7071067811865476+0.7071067811865476i]];gate cx, [[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]];\nh q[0];h q[1];cx q[1], q[2];h q[1];cx q[0], q[2];h q[0];measure q[1];h q[2];measure q[0];measure q[2];', 'p': {'values': [0.4580078125, 0.0068359375, 0.013671875, 0.064453125, 0.048828125, 0.0234375, 0.013671875, 0.37109375], 'qubits': [0, 1, 2], 'labels': ['000', '001', '010', '011', '100', '101', '110', '111']}, 'time': 16.12812304496765, 'serialNumberDevice': 'Real5Qv1'}, 'date': '2016-12-27T01:04:04.395Z'}
monkeypatch.setattr(_ibm, "send", mock_send)

backend = _ibm.IBMBackend()
engine_list = [TagRemover(), LocalOptimizer(10), AutoReplacer(),
TagRemover(), IBMCNOTMapper(), LocalOptimizer(10)]
eng = MainEngine(backend=backend, engine_list=engine_list)
unused_qubit = eng.allocate_qubit()
qureg = eng.allocate_qureg(3)
# entangle the qureg
Entangle | qureg
# measure; should be all-0 or all-1
Measure | qureg
# run the circuit
eng.flush()
prob_dict = eng.backend.get_probabilities([qureg[0],qureg[2],qureg[1]])
assert prob_dict['111'] == pytest.approx(0.38671875)
assert prob_dict['101'] == pytest.approx(0.0263671875)

4 changes: 1 addition & 3 deletions projectq/cengines/_main.py
Expand Up @@ -44,7 +44,6 @@ class MainEngine(BasicEngine):
main_engine (MainEngine): Self.
active_qubits (WeakSet): WeakSet containing all active qubits
dirty_qubits (Set): Containing all dirty qubit ids
backend (BasicEngine): Access the back-end.
"""
def __init__(self, backend=None, engine_list=None):
Expand Down Expand Up @@ -108,8 +107,7 @@ def __init__(self, backend=None, engine_list=None):
" MainEngine(engine_list=[AutoReplacer()])")

engine_list.append(backend)
self.backend = backend


# Test that user did not supply twice the same engine instance
num_different_engines = len(set([id(item) for item in engine_list]))
if len(engine_list) != num_different_engines:
Expand Down

0 comments on commit 419c4ba

Please sign in to comment.