From 419c4babf968e1d9085deb5caa71124c768bf8d9 Mon Sep 17 00:00:00 2001 From: Thomas Haener Date: Fri, 20 Jan 2017 13:28:36 +0100 Subject: [PATCH] Revert "Update the develop branch." --- examples/ibm.py | 13 +-- projectq/_version.py | 2 +- projectq/backends/_ibm/_ibm.py | 129 ++++++--------------- projectq/backends/_ibm/_ibm_http_client.py | 4 +- projectq/backends/_ibm/_ibm_test.py | 12 +- projectq/cengines/_main.py | 4 +- 6 files changed, 47 insertions(+), 117 deletions(-) diff --git a/examples/ibm.py b/examples/ibm.py index 0853097ae..3e2c077dd 100755 --- a/examples/ibm.py +++ b/examples/ibm.py @@ -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. @@ -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 @@ -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)) diff --git a/projectq/_version.py b/projectq/_version.py index 531d7887b..8460a4b98 100755 --- a/projectq/_version.py +++ b/projectq/_version.py @@ -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" diff --git a/projectq/backends/_ibm/_ibm.py b/projectq/backends/_ibm/_ibm.py index 8f3594adc..769fae828 100755 --- a/projectq/backends/_ibm/_ibm.py +++ b/projectq/backends/_ibm/_ibm.py @@ -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): """ @@ -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): """ @@ -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__ @@ -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): 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): """ @@ -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 @@ -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 += '},' @@ -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.") diff --git a/projectq/backends/_ibm/_ibm_http_client.py b/projectq/backends/_ibm/_ibm_http_client.py index 10e3b6c09..fa1d8d937 100755 --- a/projectq/backends/_ibm/_ibm_http_client.py +++ b/projectq/backends/_ibm/_ibm_http_client.py @@ -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 @@ -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. diff --git a/projectq/backends/_ibm/_ibm_test.py b/projectq/backends/_ibm/_ibm_test.py index af860301c..1fc5b755c 100755 --- a/projectq/backends/_ibm/_ibm_test.py +++ b/projectq/backends/_ibm/_ibm_test.py @@ -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/' @@ -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 @@ -69,18 +71,17 @@ 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 @@ -88,7 +89,4 @@ def mock_send(*args, **kwargs): 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) diff --git a/projectq/cengines/_main.py b/projectq/cengines/_main.py index b9bdc2809..f39a6c2c7 100755 --- a/projectq/cengines/_main.py +++ b/projectq/cengines/_main.py @@ -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): @@ -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: