def test_recognize_incorrect_gates(): saving_backend = DummyEngine(save_commands=True) eng = MainEngine(backend=saving_backend) qubit = eng.allocate_qubit() ctrl_qubit = eng.allocate_qubit() ctrl_qureg = eng.allocate_qureg(2) eng.flush() with Control(eng, ctrl_qubit): Rx(0.3) | qubit X | qubit with Control(eng, ctrl_qureg): X | qubit eng.flush(deallocate_qubits=True) for cmd in saving_backend.received_commands: assert not cnu2toffoliandcu._recognize_CnU(cmd)
def test_unitary_functional_measurement(): eng = MainEngine(UnitarySimulator()) qubits = eng.allocate_qureg(5) # entangle all qubits: H | qubits[0] for qb in qubits[1:]: CNOT | (qubits[0], qb) eng.flush() All(Measure) | qubits bit_value_sum = sum([int(qubit) for qubit in qubits]) assert bit_value_sum == 0 or bit_value_sum == 5 qb1 = WeakQubitRef(engine=eng, idx=qubits[0].id) qb2 = WeakQubitRef(engine=eng, idx=qubits[1].id) with pytest.raises(ValueError): eng.backend._handle(Command(engine=eng, gate=Measure, qubits=([qb1],), controls=[qb2]))
def _initialize_register(num_bit, mode='simulator'): ''' use an engine instead of current one. ''' import projectq.setups.default # create a main compiler engine with a specific backend: if mode == 'graphical': backend = CircuitDrawer() elif mode == 'simulator': backend = Simulator() else: raise eng = MainEngine(backend) # initialize register qureg = eng.allocate_qureg(num_bit) return qureg
def test_flush_deallocates_all_qubits(): mapper = BoundedQubitMapper(10) engine = MainEngine( Simulator(), engine_list=[mapper], verbose=True, ) # needed to prevent GC from removing qubit refs qureg = engine.allocate_qureg(10) assert len(mapper.current_mapping.keys()) == 10 assert len(engine.active_qubits) == 10 engine.flush() # Should still be around after flush assert len(engine.active_qubits) == 10 assert len(mapper.current_mapping.keys()) == 10 # GC will clean things up del qureg assert len(engine.active_qubits) == 0 assert len(mapper.current_mapping.keys()) == 0
def test_recognize_incorrect_gates(): saving_backend = DummyEngine(save_commands=True) eng = MainEngine(backend=saving_backend) qubit = eng.allocate_qubit() ctrl_qubit = eng.allocate_qubit() ctrl_qureg = eng.allocate_qureg(2) eng.flush() with Control(eng, ctrl_qubit): # Does not have matrix attribute: BasicGate() | qubit # Two qubit gate: two_qubit_gate = BasicGate() two_qubit_gate.matrix = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]] two_qubit_gate | qubit with Control(eng, ctrl_qureg): # Too many Control qubits: Rx(0.3) | qubit eng.flush(deallocate_qubits=True) for cmd in saving_backend.received_commands: assert not carb1q._recognize_carb1qubit(cmd)
def run_qft(a=11, param = "draw"): # Initialisation if param == "draw": drawing_engine = CircuitDrawer() eng = MainEngine(drawing_engine) else: eng = MainEngine() [La, n] = int2bit(a) xa = eng.allocate_qureg(n) # initialisation de a et b for i in range(n): if La[i]: X | xa[i] # On passe de a a phi(a) : QTF eng.flush() for i in range(n): N = n - i - 1 H | xa[N] for k in range(2, N + 2): with Control(eng, xa[N - k + 1]): R((2*math.pi) / (1 << k)) | xa[N] eng.flush() if param != "draw": amp_xa = [] for i in range(1 << n): phase_reel = phase(eng.backend.get_amplitude(adapt_binary(bin(i), n), xa)) / (2 * math.pi) amp_xa.append(Fraction(phase_reel).limit_denominator(10)) print(amp_xa) All(Measure) | xa eng.flush() if param == "draw": print(drawing_engine.get_latex())
def test_unitary_after_deallocation_or_measurement(): eng = MainEngine(backend=UnitarySimulator(), engine_list=[]) qubit = eng.allocate_qubit() X | qubit assert not eng.backend.history eng.flush() Measure | qubit # FlushGate and MeasureGate do not append to the history assert not eng.backend.history assert np.allclose(eng.backend.unitary, X.matrix) with pytest.warns(UserWarning): Y | qubit # YGate after FlushGate and MeasureGate does not append current unitary (identity) to the history assert len(eng.backend.history) == 1 assert np.allclose(eng.backend.unitary, Y.matrix) # Reset of unitary when applying Y above assert np.allclose(eng.backend.history[0], X.matrix) # Still ok eng.flush() Measure | qubit # FlushGate and MeasureGate do not append to the history assert len(eng.backend.history) == 1 assert np.allclose(eng.backend.unitary, Y.matrix) assert np.allclose(eng.backend.history[0], X.matrix) # Make sure that the new gate will trigger appending to the history and modify the current unitary with pytest.warns(UserWarning): Rx(1) | qubit assert len(eng.backend.history) == 2 assert np.allclose(eng.backend.unitary, Rx(1).matrix) assert np.allclose(eng.backend.history[0], X.matrix) assert np.allclose(eng.backend.history[1], Y.matrix) # -------------------------------------------------------------------------- eng = MainEngine(backend=UnitarySimulator(), engine_list=[]) qureg = eng.allocate_qureg(2) All(X) | qureg XX_matrix = np.kron(X.matrix, X.matrix) assert not eng.backend.history assert np.allclose(eng.backend.unitary, XX_matrix) eng.deallocate_qubit(qureg[0]) assert not eng.backend.history with pytest.warns(UserWarning): Y | qureg[1] # An internal call to flush() happens automatically since the X # gate occurs as the simulator is in an invalid state (after qubit # deallocation) assert len(eng.backend.history) == 1 assert np.allclose(eng.backend.history[0], XX_matrix) assert np.allclose(eng.backend.unitary, Y.matrix) # Still ok eng.flush() Measure | qureg[1] # Nothing should have changed assert len(eng.backend.history) == 1 assert np.allclose(eng.backend.history[0], XX_matrix) assert np.allclose(eng.backend.unitary, Y.matrix)
def test_openqasm_allocate_deallocate(qubit_id_redux): qc_list = [] def _process(circuit): qc_list.append(circuit) backend = OpenQASMEngine(_process, qubit_id_mapping_redux=qubit_id_redux) assert backend._qubit_id_mapping_redux == qubit_id_redux eng = MainEngine(backend) qubit = eng.allocate_qubit() eng.flush() assert len(backend._qreg_dict) == 1 assert len(backend._creg_dict) == 1 assert backend._reg_index == 1 assert not backend._available_indices assert len(qc_list) == 1 qasm = qc_list[0].qasm() assert re.search(r'qreg\s+q0\[1\]', qasm) assert re.search(r'creg\s+c0\[1\]', qasm) qureg = eng.allocate_qureg(5) eng.flush() assert len(backend._qreg_dict) == 6 assert len(backend._creg_dict) == 6 assert backend._reg_index == 6 assert not backend._available_indices assert len(qc_list) == 2 qasm = qc_list[1].qasm() for i in range(1, 6): assert re.search(r'qreg\s+q{}\[1\]'.format(i), qasm) assert re.search(r'creg\s+c{}\[1\]'.format(i), qasm) del qubit eng.flush() if qubit_id_redux: assert len(backend._qreg_dict) == 5 assert len(backend._creg_dict) == 5 assert backend._reg_index == 6 assert backend._available_indices == [0] else: assert len(backend._qreg_dict) == 6 assert len(backend._creg_dict) == 6 assert backend._reg_index == 6 assert not backend._available_indices qubit = eng.allocate_qubit() eng.flush() if qubit_id_redux: assert len(backend._qreg_dict) == 6 assert len(backend._creg_dict) == 6 assert backend._reg_index == 6 assert not backend._available_indices else: assert len(backend._qreg_dict) == 7 assert len(backend._creg_dict) == 7 assert backend._reg_index == 7 assert not backend._available_indices
SqrtY | x[8] SqrtX | x[10] SqrtX | x[11] SqrtY | x[17] SqrtY | x[18] SqrtX | x[20] SqrtY | x[21] start = datetime.datetime.now() print(start) x = eng.allocate_qureg(nqubits) # Alice creates a nice state to send eng.flush() run(eng) result = eng.backend.cheat() All(Measure) | x print(result) end = datetime.datetime.now() print(end) print("time used:", (end - start))
class ProjectQContext(object): ''' Context for running circuits. Args: num_bit (int): number of bits in register. task ('ibm'|'draw'|'simulate'): task that decide the environment type. ibm_config (dict): extra arguments for IBM backend. ''' def __init__(self, num_bit, task, ibm_config=None): self.task = task self.num_bit = num_bit self.ibm_config = ibm_config def __enter__(self): ''' Enter context, Attributes: eng (MainEngine): main engine. backend ('graphical' or 'simulate'): backend used. qureg (Qureg): quantum register. ''' if self.task=='ibm': import projectq.setups.ibm else: import projectq.setups.default # create a main compiler engine with a specific backend: if self.task == 'draw': self.backend = CircuitDrawer() # locations = {0: 0, 1: 1, 2: 2, 3:3} # swap order of lines 0-1-2. # self.backend.set_qubit_locations(locations) elif self.task == 'simulate': print('ProjecQ simulation in training can be slow, since in scipy context, we cached a lot gates.') self.backend = Simulator() elif self.task == 'ibm': # choose device device = self.ibm_config.get('device', 'ibmqx2' if self.num_bit<=5 else 'ibmqx5') # check data if self.ibm_config is None: raise if device == 'ibmqx5': device_num_bit = 16 else: device_num_bit = 5 if device_num_bit < self.num_bit: raise AttributeError('device %s has not enough qubits for %d bit simulation!'%(device, self.num_bit)) self.backend = IBMBackend(use_hardware=True, num_runs=self.ibm_config['num_runs'], user=self.ibm_config['user'], password=self.ibm_config['password'], device=device, verbose=True) else: raise ValueError('engine %s not defined' % self.task) self.eng = MainEngine(self.backend) # initialize register self.qureg = self.eng.allocate_qureg(self.num_bit) return self def __exit__(self, exc_type, exc_val, traceback): ''' exit, meanwhile cheat and get wave function. Attributes: wf (1darray): for 'simulate' task, the wave function vector. res (1darray): for 'ibm' task, the measurements output. ''' if traceback is not None: return False if self.task == 'draw': self._viz_circuit() elif self.task == 'simulate': self.eng.flush() order, qvec = self.backend.cheat() self.wf = np.array(qvec) order = [order[i] for i in range(len(self.qureg))] self.wf = np.transpose(self.wf.reshape([2]*len(self.qureg), order='F'), axes=order).ravel(order='F') Measure | self.qureg self.eng.flush() elif self.task == 'ibm': Measure | self.qureg self.eng.flush() self.res = self.backend.get_probabilities(self.qureg) else: raise return self def _viz_circuit(self): Measure | self.qureg self.eng.flush() # print latex code to draw the circuit: s = self.backend.get_latex() # save graph to latex file os.chdir(TEX_FOLDER) with open(TEX_FILENAME, 'w') as f: f.write(s) # texfile = os.path.join(folder, 'circuit-%d.tex'%bench_id) pdffile = TEX_FILENAME[:-3]+'pdf' os.system('pdflatex %s'%TEX_FILENAME) openfile(pdffile)
from projectq.libs.revkit import PermutationOracle, PhaseOracle from projectq.meta import Compute, Dagger, Uncompute from projectq.ops import All, H, Measure, X # phase function def f(a, b, c, d, e, f): """Phase function.""" return (a and b) ^ (c and d) ^ (e and f) # permutation pi = [0, 2, 3, 5, 7, 1, 4, 6] eng = MainEngine() qubits = eng.allocate_qureg(6) x = qubits[::2] # qubits on odd lines y = qubits[1::2] # qubits on even lines # circuit with Compute(eng): All(H) | qubits All(X) | [x[0], x[1]] PermutationOracle(pi) | y PhaseOracle(f) | qubits Uncompute(eng) with Compute(eng): with Dagger(eng): PermutationOracle(pi, synth=revkit.dbs) | x PhaseOracle(f) | qubits
def test_ibm_backend_functional_test(monkeypatch): correct_info = { 'json': [ {'qubits': [1], 'name': 'u2', 'params': [0, 3.141592653589793]}, {'qubits': [1, 2], 'name': 'cx'}, {'qubits': [1, 3], 'name': 'cx'}, {'qubits': [1], 'name': 'u3', 'params': [6.28318530718, 0, 0]}, {'qubits': [1], 'name': 'u1', 'params': [11.780972450962]}, {'qubits': [1], 'name': 'u3', 'params': [6.28318530718, 0, 0]}, {'qubits': [1], 'name': 'u1', 'params': [10.995574287564]}, {'qubits': [1, 2, 3], 'name': 'barrier'}, { 'qubits': [1], 'name': 'u3', 'params': [0.2, -1.5707963267948966, 1.5707963267948966], }, {'qubits': [1], 'name': 'measure', 'memory': [1]}, {'qubits': [2], 'name': 'measure', 'memory': [2]}, {'qubits': [3], 'name': 'measure', 'memory': [3]}, ], 'nq': 4, 'shots': 1000, 'maxCredits': 10, 'backend': {'name': 'ibmq_qasm_simulator'}, } def mock_send(*args, **kwargs): assert args[0] == correct_info return { 'data': {'counts': {'0x0': 504, '0x2': 8, '0xc': 6, '0xe': 482}}, 'header': { 'clbit_labels': [['c', 0], ['c', 1], ['c', 2], ['c', 3]], 'creg_sizes': [['c', 4]], 'memory_slots': 4, 'n_qubits': 32, 'name': 'circuit0', 'qreg_sizes': [['q', 32]], 'qubit_labels': [ ['q', 0], ['q', 1], ['q', 2], ['q', 3], ['q', 4], ['q', 5], ['q', 6], ['q', 7], ['q', 8], ['q', 9], ['q', 10], ['q', 11], ['q', 12], ['q', 13], ['q', 14], ['q', 15], ['q', 16], ['q', 17], ['q', 18], ['q', 19], ['q', 20], ['q', 21], ['q', 22], ['q', 23], ['q', 24], ['q', 25], ['q', 26], ['q', 27], ['q', 28], ['q', 29], ['q', 30], ['q', 31], ], }, 'metadata': { 'measure_sampling': True, 'method': 'statevector', 'parallel_shots': 1, 'parallel_state_update': 16, }, 'seed_simulator': 465435780, 'shots': 1000, 'status': 'DONE', 'success': True, 'time_taken': 0.0045786460000000005, } monkeypatch.setattr(_ibm, "send", mock_send) backend = _ibm.IBMBackend(verbose=True, num_runs=1000) import sys # no circuit has been executed -> raises exception with pytest.raises(RuntimeError): backend.get_probabilities([]) mapper = BasicMapperEngine() res = {} for i in range(4): res[i] = i mapper.current_mapping = res ibm_setup = [mapper] setup = restrictedgateset.get_engine_list( one_qubit_gates=(Rx, Ry, Rz, H), two_qubit_gates=(CNOT,), other_gates=(Barrier,) ) setup.extend(ibm_setup) eng = MainEngine(backend=backend, engine_list=setup) # 4 qubits circuit is run, but first is unused to test ability for # get_probability to return the correct values for a subset of the total # register unused_qubit = eng.allocate_qubit() qureg = eng.allocate_qureg(3) # entangle the qureg Entangle | qureg Tdag | qureg[0] Sdag | qureg[0] Barrier | qureg Rx(0.2) | qureg[0] del unused_qubit # measure; should be all-0 or all-1 All(Measure) | qureg # run the circuit eng.flush() prob_dict = eng.backend.get_probabilities([qureg[2], qureg[1]]) assert prob_dict['00'] == pytest.approx(0.512) assert prob_dict['11'] == pytest.approx(0.488) result = "\nu2(0,pi/2) q[1];\ncx q[1], q[2];\ncx q[1], q[3];" if sys.version_info.major == 3: result += "\nu3(6.28318530718, 0, 0) q[1];\nu1(11.780972450962) q[1];" result += "\nu3(6.28318530718, 0, 0) q[1];\nu1(10.995574287564) q[1];" else: result += "\nu3(6.28318530718, 0, 0) q[1];\nu1(11.780972451) q[1];" result += "\nu3(6.28318530718, 0, 0) q[1];\nu1(10.9955742876) q[1];" result += "\nbarrier q[1], q[2], q[3];" result += "\nu3(0.2, -pi/2, pi/2) q[1];\nmeasure q[1] -> c[1];" result += "\nmeasure q[2] -> c[2];\nmeasure q[3] -> c[3];" assert eng.backend.get_qasm() == result with pytest.raises(RuntimeError): eng.backend.get_probabilities(eng.allocate_qubit())
def test_ibm_retrieve(monkeypatch): # patch send def mock_retrieve(*args, **kwargs): return { 'data': {'counts': {'0x0': 504, '0x2': 8, '0xc': 6, '0xe': 482}}, 'header': { 'clbit_labels': [['c', 0], ['c', 1], ['c', 2], ['c', 3]], 'creg_sizes': [['c', 4]], 'memory_slots': 4, 'n_qubits': 32, 'name': 'circuit0', 'qreg_sizes': [['q', 32]], 'qubit_labels': [ ['q', 0], ['q', 1], ['q', 2], ['q', 3], ['q', 4], ['q', 5], ['q', 6], ['q', 7], ['q', 8], ['q', 9], ['q', 10], ['q', 11], ['q', 12], ['q', 13], ['q', 14], ['q', 15], ['q', 16], ['q', 17], ['q', 18], ['q', 19], ['q', 20], ['q', 21], ['q', 22], ['q', 23], ['q', 24], ['q', 25], ['q', 26], ['q', 27], ['q', 28], ['q', 29], ['q', 30], ['q', 31], ], }, 'metadata': { 'measure_sampling': True, 'method': 'statevector', 'parallel_shots': 1, 'parallel_state_update': 16, }, 'seed_simulator': 465435780, 'shots': 1000, 'status': 'DONE', 'success': True, 'time_taken': 0.0045786460000000005, } monkeypatch.setattr(_ibm, "retrieve", mock_retrieve) backend = _ibm.IBMBackend(retrieve_execution="ab1s2", num_runs=1000) mapper = BasicMapperEngine() res = {} for i in range(4): res[i] = i mapper.current_mapping = res ibm_setup = [mapper] setup = restrictedgateset.get_engine_list(one_qubit_gates=(Rx, Ry, Rz, H), two_qubit_gates=(CNOT,)) setup.extend(ibm_setup) eng = MainEngine(backend=backend, engine_list=setup) unused_qubit = eng.allocate_qubit() qureg = eng.allocate_qureg(3) # entangle the qureg Entangle | qureg Tdag | qureg[0] Sdag | qureg[0] Barrier | qureg Rx(0.2) | qureg[0] del unused_qubit # measure; should be all-0 or all-1 All(Measure) | qureg # run the circuit eng.flush() prob_dict = eng.backend.get_probabilities([qureg[0], qureg[2], qureg[1]]) assert prob_dict['000'] == pytest.approx(0.504) assert prob_dict['111'] == pytest.approx(0.482) assert prob_dict['011'] == pytest.approx(0.006)
"""Example of a 4-qubit phase function.""" from projectq.cengines import MainEngine from projectq.libs.revkit import PhaseOracle from projectq.meta import Compute, Uncompute from projectq.ops import All, H, Measure, X # phase function def f(a, b, c, d): """Phase function.""" return (a and b) ^ (c and d) eng = MainEngine() x1, x2, x3, x4 = qubits = eng.allocate_qureg(4) with Compute(eng): All(H) | qubits X | x1 PhaseOracle(f) | qubits Uncompute(eng) PhaseOracle(f) | qubits All(H) | qubits All(Measure) | qubits eng.flush() print("Shift is {}".format(8 * int(x4) + 4 * int(x3) + 2 * int(x2) + int(x1)))