def run(self, q_job): """Run circuits in q_job""" # Generating a string id for the job result_list = [] qobj = q_job.qobj self._validate(qobj) self._sim = Simulator(gate_fusion=True) if 'seed' in qobj['config']: self._seed = qobj['config']['seed'] self._sim._simulator = CppSim(self._seed) else: self._seed = random.getrandbits(32) self._shots = qobj['config']['shots'] start = time.time() for circuit in qobj['circuits']: result_list.append(self.run_circuit(circuit)) end = time.time() result = { 'backend': self._configuration['name'], 'id': qobj['id'], 'result': result_list, 'status': 'COMPLETED', 'success': True, 'time_taken': (end - start) } return Result(result, qobj)
def sim(request): if request.param == "cpp_simulator": from projectq.backends._sim._cppsim import Simulator as CppSim sim = Simulator(gate_fusion=True) sim._simulator = CppSim(1) return sim if request.param == "py_simulator": from projectq.backends._sim._pysim import Simulator as PySim sim = Simulator() sim._simulator = PySim(1) return sim
def sim(request): if request.param == "cpp_simulator": from projectq.backends._sim._cppsim import Simulator as CppSim sim = Simulator(gate_fusion=True) sim._simulator = CppSim(1) # If an ImportError occurs, the C++ simulator was either not installed # or compiled for a different Python version. return sim if request.param == "py_simulator": from projectq.backends._sim._pysim import Simulator as PySim sim = Simulator() sim._simulator = PySim(1) return sim
def test_simulator_constant_math_emulation(): if "cpp_simulator" not in get_available_simulators(): pytest.skip("No C++ simulator") return results = [[[1, 1, 0, 0, 0]], [[0, 1, 0, 0, 0]], [[0, 1, 1, 1, 0]]] import projectq.backends._sim._simulator as _sim from projectq.backends._sim._pysim import Simulator as PySim from projectq.backends._sim._cppsim import Simulator as CppSim from projectq.libs.math import (AddConstant, AddConstantModN, MultiplyByConstantModN) def gate_filter(eng, cmd): g = cmd.gate if isinstance(g, BasicMathGate): return False return eng.next_engine.is_available(cmd) def run_simulation(sim): eng = MainEngine(sim, []) quint = eng.allocate_qureg(5) AddConstant(3) | quint All(Measure) | quint eng.flush() results[0].append([int(qb) for qb in quint]) AddConstantModN(4, 5) | quint All(Measure) | quint eng.flush() results[1].append([int(qb) for qb in quint]) MultiplyByConstantModN(15, 16) | quint All(Measure) | quint eng.flush() results[2].append([int(qb) for qb in quint]) cppsim = Simulator(gate_fusion=False) cppsim._simulator = CppSim(1) run_simulation(cppsim) _sim.FALLBACK_TO_PYSIM = True pysim = Simulator() pysim._simulator = PySim(1) # run_simulation(pysim) for result in results: ref = result[0] for res in result[1:]: assert ref == res
def _run_job(self, job_id, qobj): """Run circuits in qobj and return the result Args: qobj (Qobj): Qobj structure job_id (str): A job id Returns: qiskit.Result: Result is a class including the information to be returned to users. Specifically, result_list in the return contains the essential information, which looks like this:: [{'data': { 'counts': {'000': 40, '111': 60} }, 'status': 'DONE' }] """ result_list = [] self._validate(qobj) self._sim = Simulator(gate_fusion=True) if hasattr(qobj.config, 'seed'): self._seed = qobj.config.seed self._sim._simulator = CppSim(self._seed) else: self._seed = random.getrandbits(32) self._shots = qobj.config.shots start = time.time() for circuit in qobj.experiments: result_list.append(self.run_circuit(circuit)) end = time.time() job_id = str(uuid.uuid4()) result = { 'backend_name': self._configuration.backend_name, 'backend_version': '0.1.0', 'qobj_id': qobj.qobj_id, 'job_id': job_id, 'results': result_list, 'status': 'COMPLETED', 'success': True, 'time_taken': (end - start) } return Result.from_dict(result)
def run(self, q_job): """Run circuits in q_job""" # Generating a string id for the job job_id = str(uuid.uuid4()) result_list = [] qobj = q_job.qobj self._sim = Simulator(gate_fusion=True) if 'seed' in qobj['config']: self._seed = qobj['config']['seed'] self._sim._simulator = CppSim(self._seed) else: self._seed = random.getrandbits(32) self._shots = qobj['config']['shots'] for circuit in qobj['circuits']: result_list.append(self.run_circuit(circuit)) return Result({'job_id': job_id, 'result': result_list, 'status': 'COMPLETED'}, qobj)
def run_circuit(self, circuit): """Run a circuit and return a single Result. Args: circuit (dict): JSON circuit from qobj circuits list Returns: dict: A dictionary of results which looks something like:: { "data": { #### DATA CAN BE A DIFFERENT DICTIONARY FOR EACH BACKEND #### "counts": {'00000': XXXX, '00001': XXXXX}, "time" : xx.xxxxxxxx }, "status": --status (string)-- } Raises: SimulatorError: if an error occurred. """ # pylint: disable=expression-not-assigned,pointless-statement ccircuit = circuit['compiled_circuit'] self._number_of_qubits = ccircuit['header']['number_of_qubits'] self._number_of_clbits = ccircuit['header']['number_of_clbits'] self._statevector = 0 self._classical_state = 0 cl_reg_index = [] # starting bit index of classical register cl_reg_nbits = [] # number of bits in classical register clbit_index = 0 qobj_quregs = OrderedDict( _get_register_specs(ccircuit['header']['qubit_labels'])) eng = MainEngine(backend=self._sim) for cl_reg in ccircuit['header']['clbit_labels']: cl_reg_nbits.append(cl_reg[1]) cl_reg_index.append(clbit_index) clbit_index += cl_reg[1] # let circuit seed override qobj default if 'config' in circuit: if 'seed' in circuit['config']: if circuit['config']['seed'] is not None: self._sim._simulator = CppSim(circuit['config']['seed']) outcomes = [] start = time.time() for _ in range(self._shots): self._statevector = np.zeros(1 << self._number_of_qubits, dtype=complex) self._statevector[0] = 1 # initialize starting state self._classical_state = 0 unmeasured_qubits = list(range(self._number_of_qubits)) projq_qureg_dict = OrderedDict( ((key, eng.allocate_qureg(size)) for key, size in qobj_quregs.items())) qureg = [ qubit for sublist in projq_qureg_dict.values() for qubit in sublist ] # Do each operation in this shot for operation in ccircuit['operations']: if 'conditional' in operation: mask = int(operation['conditional']['mask'], 16) if mask > 0: value = self._classical_state & mask while (mask & 0x1) == 0: mask >>= 1 value >>= 1 if value != int(operation['conditional']['val'], 16): continue # Check if single gate if operation['name'] in ['U', 'u3']: params = operation['params'] qubit = qureg[operation['qubits'][0]] Rz(params[2]) | qubit Ry(params[0]) | qubit Rz(params[1]) | qubit elif operation['name'] in ['u1']: params = operation['params'] qubit = qureg[operation['qubits'][0]] Rz(params[0]) | qubit elif operation['name'] in ['u2']: params = operation['params'] qubit = qureg[operation['qubits'][0]] Rz(params[1] - np.pi / 2) | qubit Rx(np.pi / 2) | qubit Rz(params[0] + np.pi / 2) | qubit elif operation['name'] == 't': qubit = qureg[operation['qubits'][0]] T | qubit elif operation['name'] == 'h': qubit = qureg[operation['qubits'][0]] H | qubit elif operation['name'] == 's': qubit = qureg[operation['qubits'][0]] S | qubit elif operation['name'] in ['CX', 'cx']: qubit0 = qureg[operation['qubits'][0]] qubit1 = qureg[operation['qubits'][1]] CX | (qubit0, qubit1) elif operation['name'] in ['id', 'u0']: pass # Check if measure elif operation['name'] == 'measure': qubit_index = operation['qubits'][0] qubit = qureg[qubit_index] clbit = operation['clbits'][0] Measure | qubit bit = 1 << clbit self._classical_state = (self._classical_state & (~bit)) | (int(qubit) << clbit) # check whether we already measured this qubit if operation['qubits'][0] in unmeasured_qubits: unmeasured_qubits.remove(operation['qubits'][0]) # Check if reset elif operation['name'] == 'reset': qubit = operation['qubits'][0] raise SimulatorError('Reset operation not yet implemented ' 'for ProjectQ C++ backend') elif operation['name'] == 'barrier': pass else: backend = self._configuration['name'] err_msg = '{0} encountered unrecognized operation "{1}"' raise SimulatorError( err_msg.format(backend, operation['name'])) for ind in unmeasured_qubits: qubit = qureg[ind] Measure | qubit eng.flush() # Turn classical_state (int) into bit string state = format(self._classical_state, 'b') outcomes.append(state.zfill(self._number_of_clbits)) # Return the results counts = dict(Counter(outcomes)) data = {'counts': _format_result(counts, cl_reg_index, cl_reg_nbits)} if self._shots == 1: # TODO: deprecated -- remove in v0.6 data['statevector'] = self._statevector data['quantum_state'] = self._statevector data['classical_state'] = self._classical_state end = time.time() return { 'name': circuit['name'], 'seed': self._seed, 'shots': self._shots, 'data': data, 'status': 'DONE', 'success': True, 'time_taken': (end - start) }
def run_circuit(self, circuit): """Run a circuit and return a single Result. Args: circuit (QobjExperiment): Qobj experiment Returns: dict: A dictionary of results which looks something like: { "data": { #### DATA CAN BE A DIFFERENT DICTIONARY FOR EACH BACKEND #### "counts": {'00000': XXXX, '00001': XXXXX}, "time" : xx.xxxxxxxx }, "status": --status (string)-- } Raises: ProjectQSimulatorError: if an error occurred. """ # pylint: disable=expression-not-assigned,pointless-statement self._number_of_qubits = circuit.config.n_qubits self._number_of_clbits = circuit.config.memory_slots self._classical_state = 0 cl_reg_index = [] # starting bit index of classical register cl_reg_nbits = [] # number of bits in classical register clbit_index = 0 qobj_quregs = OrderedDict( _get_register_specs(circuit.header.qubit_labels)) eng = MainEngine(backend=self._sim) for cl_reg in circuit.header.clbit_labels: cl_reg_nbits.append(cl_reg[1]) cl_reg_index.append(clbit_index) clbit_index += cl_reg[1] # let circuit seed override qobj default if hasattr(circuit, 'config'): if hasattr(circuit.config, 'seed'): if circuit.config.seed is not None: self._sim._simulator = CppSim(circuit.config.seed) outcomes = [] snapshots = {} projq_qureg_dict = OrderedDict(((key, eng.allocate_qureg(size)) for key, size in qobj_quregs.items())) if self._shots > 1: ground_state = np.zeros(1 << self._number_of_qubits, dtype=complex) ground_state[0] = 1 start = time.time() for i in range(self._shots): # initialize starting state self._classical_state = 0 qureg = [ qubit for sublist in projq_qureg_dict.values() for qubit in sublist ] if i > 0: eng.flush() eng.backend.set_wavefunction(ground_state, qureg) # Do each operation in this shot for operation in circuit.instructions: if hasattr(operation, 'conditional'): mask = int(operation.conditional.mask, 16) if mask > 0: value = self._classical_state & mask while (mask & 0x1) == 0: mask >>= 1 value >>= 1 if value != int(operation.conditional.val, 16): continue # Check if single gate if operation.name in ['U', 'u3']: params = operation.params qubit = qureg[operation.qubits[0]] Rz(params[2]) | qubit Ry(params[0]) | qubit Rz(params[1]) | qubit elif operation.name in ['u1']: params = operation.params qubit = qureg[operation.qubits[0]] Rz(params[0]) | qubit elif operation.name in ['u2']: params = operation.params qubit = qureg[operation.qubits[0]] Rz(params[1] - np.pi / 2) | qubit Rx(np.pi / 2) | qubit Rz(params[0] + np.pi / 2) | qubit elif operation.name == 't': qubit = qureg[operation.qubits[0]] T | qubit elif operation.name == 'h': qubit = qureg[operation.qubits[0]] H | qubit elif operation.name == 's': qubit = qureg[operation.qubits[0]] S | qubit elif operation.name in ['CX', 'cx']: qubit0 = qureg[operation.qubits[0]] qubit1 = qureg[operation.qubits[1]] CX | (qubit0, qubit1) elif operation.name in ['id', 'u0']: pass # Check if measure elif operation.name == 'measure': qubit_index = operation.qubits[0] qubit = qureg[qubit_index] clbit = operation.memory[0] Measure | qubit bit = 1 << clbit self._classical_state = (self._classical_state & (~bit)) | (int(qubit) << clbit) # Check if reset elif operation.name == 'reset': qubit = operation.qubits[0] raise ProjectQSimulatorError( 'Reset operation not yet implemented ' 'for ProjectQ C++ backend') # Check if snapshot elif operation.name == 'snapshot': eng.flush() location = str(operation.params[0]) statevector = np.array(eng.backend.cheat()[1], dtype=complex) formatted_state = [[x.real, x.imag] for x in statevector] if location in snapshots: snapshots[location]['statevector'].append( formatted_state) else: snapshots[location] = { 'statevector': [formatted_state] } elif operation.name == 'barrier': pass else: backend = self._configuration.backend_name err_msg = '{0} encountered unrecognized operation "{1}"' raise ProjectQSimulatorError( err_msg.format(backend, operation.name)) # Before the program terminates, all the qubits must be measured, # including those that have not been measured by the circuit. # Otherwise ProjectQ throws an exception about qubits in superposition. for ind in list(range(self._number_of_qubits)): qubit = qureg[ind] Measure | qubit eng.flush() # Turn classical_state (int) into bit string state = format(self._classical_state, 'b') outcomes.append(state.zfill(self._number_of_clbits)) # Return the results counts = dict(Counter(outcomes)) data = {'counts': _format_result(counts, cl_reg_nbits)} if snapshots != {}: data['snapshots'] = snapshots if self._shots == 1: data['classical_state'] = self._classical_state end = time.time() # Calculate creg_sizes pre_creg_sizes = {} for clbit_label in circuit.header.clbit_labels: if clbit_label[0] in pre_creg_sizes: pre_creg_sizes[clbit_label[0]] += 1 else: pre_creg_sizes[clbit_label[0]] = 1 creg_sizes = [] for clbit_label in pre_creg_sizes: creg_sizes.append([clbit_label, pre_creg_sizes[clbit_label]]) return { 'header': { 'name': circuit.header.name, 'memory_slots': circuit.header.memory_slots, 'creg_sizes': creg_sizes }, 'seed': self._seed, 'shots': self._shots, 'data': data, 'status': 'DONE', 'success': True, 'time_taken': (end - start) }