def setUp(self): self.seed = 88 self.qasm_filename = self._get_resource_path('qasm/example.qasm') self.qasm_circ = QuantumCircuit.from_qasm_file(self.qasm_filename) qr = QuantumRegister(2, 'q') cr = ClassicalRegister(2, 'c') qc = QuantumCircuit(qr, cr) qc.h(qr[0]) qc.measure(qr[0], cr[0]) self.qc = qc # create qobj dag = DAGCircuit.fromQuantumCircuit(self.qc) json_circuit = DagUnroller(dag, JsonBackend(dag.basis)).execute() compiled_circuit1 = QobjExperiment.from_dict(json_circuit) dag = DAGCircuit.fromQuantumCircuit(self.qasm_circ) json_circuit = DagUnroller(dag, JsonBackend(dag.basis)).execute() compiled_circuit2 = QobjExperiment.from_dict(json_circuit) self.qobj = Qobj(qobj_id='test_qobj', config=QobjConfig(shots=2000, memory_slots=1, max_credits=3, seed=1111), experiments=[compiled_circuit1, compiled_circuit2], header=QobjHeader(backend_name='qasm_simulator')) self.qobj.experiments[0].header.name = 'test_circuit1' self.qobj.experiments[0].config = QobjItem( basis_gates='u1,u2,u3,cx,id') self.qobj.experiments[1].header.name = 'test_circuit2' self.qobj.experiments[1].config = QobjItem( basis_gates='u1,u2,u3,cx,id') self.backend = QasmSimulator()
def test_unitary_simulator(self): """test generation of circuit unitary""" unroller = unroll.Unroller( qasm.Qasm(filename=self.qasm_filename).parse(), unroll.JsonBackend([])) circuit = unroller.execute() # strip measurements from circuit to avoid warnings circuit['instructions'] = [ op for op in circuit['instructions'] if op['name'] != 'measure' ] circuit = QobjExperiment.from_dict(circuit) circuit.config = QobjItem(coupling_map=None, basis_gates=None, layout=None, seed=self.seed) circuit.header.name = 'test' qobj = Qobj( id='unitary', config=QobjConfig(shots=1, register_slots=6, max_credits=None), experiments=[circuit], header=QobjHeader(backend_name='local_unitary_simulator_py')) # numpy.savetxt currently prints complex numbers in a way # loadtxt can't read. To save file do, # fmtstr=['% .4g%+.4gj' for i in range(numCols)] # np.savetxt('example_unitary_matrix.dat', numpyMatrix, fmt=fmtstr, # delimiter=',') expected = np.loadtxt( self._get_resource_path('example_unitary_matrix.dat'), dtype='complex', delimiter=',') result = UnitarySimulatorPy().run(qobj).result() self.assertTrue( np.allclose(result.get_unitary('test'), expected, rtol=1e-3))
def setUp(self): self.seed = 88 self.qasm_filename = self._get_resource_path('qasm/example.qasm') self.qp = QuantumProgram() self.qp.load_qasm_file(self.qasm_filename, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm('example')).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() circuit_config = {'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': self.seed} resources = {'max_credits': 3} self.qobj = {'id': 'test_sim_single_shot', 'config': { 'max_credits': resources['max_credits'], 'shots': 1024, }, 'experiments': [circuit], 'header': {'backend_name': 'local_qasm_simulator_py'}} self.qobj = Qobj.from_dict(self.qobj) self.qobj.experiments[0].config = QobjItem.from_dict(circuit_config) self.qobj.experiments[0].header.name = 'test'
def _dags_2_qobj_parallel(dag, config=None, basis_gates=None, coupling_map=None): """Helper function for dags to qobj in parallel (if available). Args: dag (DAGCircuit): DAG to compile config (dict): dictionary of parameters (e.g. noise) used by runner basis_gates (list[str])): basis gates for the experiment coupling_map (list): coupling map (perhaps custom) to target in mapping Returns: Qobj: Qobj to be run on the backends """ json_circuit = DagUnroller(dag, JsonBackend(dag.basis)).execute() # Step 3a: create the Experiment based on json_circuit experiment = QobjExperiment.from_dict(json_circuit) # Step 3b: populate the Experiment configuration and header experiment.header.name = dag.name # TODO: place in header or config? experiment_config = deepcopy(config or {}) experiment_config.update({ 'coupling_map': coupling_map, 'basis_gates': basis_gates, 'layout': dag.layout, 'memory_slots': sum(dag.cregs.values()), # TODO: `n_qubits` is not part of the qobj spec, but needed for the simulator. 'n_qubits': sum(dag.qregs.values())}) experiment.config = QobjItem(**experiment_config) # set eval_symbols=True to evaluate each symbolic expression # TODO: after transition to qobj, we can drop this experiment.header.compiled_circuit_qasm = dag.qasm( qeflag=True, eval_symbols=True) # Step 3c: add the Experiment to the Qobj return experiment
def setUp(self): self.seed = 88 self.qasm_filename = self._get_resource_path('qasm/example.qasm') with open(self.qasm_filename, 'r') as qasm_file: self.qasm_text = qasm_file.read() self.qasm_ast = qiskit.qasm.Qasm(data=self.qasm_text).parse() self.qasm_be = qiskit.unroll.CircuitBackend(['u1', 'u2', 'u3', 'id', 'cx']) self.qasm_circ = qiskit.unroll.Unroller(self.qasm_ast, self.qasm_be).execute() qr = QuantumRegister(2, 'q') cr = ClassicalRegister(2, 'c') qc = QuantumCircuit(qr, cr) qc.h(qr[0]) qc.measure(qr[0], cr[0]) self.qc = qc # create qobj compiled_circuit1 = QobjExperiment.from_dict( transpile(DAGCircuit.fromQuantumCircuit(self.qc), format='json')) compiled_circuit2 = QobjExperiment.from_dict( transpile(DAGCircuit.fromQuantumCircuit(self.qasm_circ), format='json')) self.qobj = Qobj( qobj_id='test_qobj', config=QobjConfig( shots=2000, memory_slots=1, max_credits=3, seed=1111 ), experiments=[compiled_circuit1, compiled_circuit2], header=QobjHeader(backend_name='local_qasm_simulator_cpp') ) self.qobj.experiments[0].header.name = 'test_circuit1' self.qobj.experiments[0].config = QobjItem(basis_gates='u1,u2,u3,cx,id') self.qobj.experiments[1].header.name = 'test_circuit2' self.qobj.experiments[1].config = QobjItem(basis_gates='u1,u2,u3,cx,id') # Simulator backend try: self.backend = QasmSimulatorCpp() except FileNotFoundError as fnferr: raise unittest.SkipTest( 'cannot find {} in path'.format(fnferr))
def new_fake_qobj(): """Create fake `Qobj` and backend instances.""" backend = FakeBackend() return Qobj(id='test-id', config=QobjConfig(shots=1024, memory_slots=1, max_credits=100), header=QobjHeader(backend_name=backend.name), experiments=[ QobjExperiment(instructions=[], header=QobjExperimentHeader( compiled_circuit_qasm='fake-code'), config=QobjItem(seed=123456)) ])
def new_fake_qobj(): """Create fake `Qobj` and backend instances.""" backend = FakeQasmSimulator() return Qobj(qobj_id='test-id', config=QobjConfig(shots=1024, memory_slots=1, max_credits=100), header=QobjHeader(backend_name=backend.name()), experiments=[ QobjExperiment(instructions=[ QobjInstruction(name='barrier', qubits=[1]) ], header=QobjExperimentHeader(), config=QobjItem(seed=123456)) ])
def test_unitary_simulator(self): """test generation of circuit unitary""" self.qp.load_qasm_file(self.qasm_filename, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm('example')).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() # strip measurements from circuit to avoid warnings circuit['instructions'] = [ op for op in circuit['instructions'] if op['name'] != 'measure' ] # the simulator is expecting a JSON format, so we need to convert it # back to JSON qobj = { 'id': 'unitary', 'config': { 'max_credits': None, 'shots': 1 }, 'experiments': [circuit], 'header': { 'backend_name': 'local_unitary_simulator_py' } } qobj = Qobj.from_dict(qobj) qobj.experiments[0].header.name = 'test' qobj.experiments[0].header.compiled_circuit_qasm = self.qp.get_qasm( 'example') qobj.experiments[0].config = QobjItem(coupling_map=None, basis_gates=None, layout=None, seed=None) # numpy.savetxt currently prints complex numbers in a way # loadtxt can't read. To save file do, # fmtstr=['% .4g%+.4gj' for i in range(numCols)] # np.savetxt('example_unitary_matrix.dat', numpyMatrix, fmt=fmtstr, # delimiter=',') expected = np.loadtxt( self._get_resource_path('example_unitary_matrix.dat'), dtype='complex', delimiter=',') result = UnitarySimulatorPy().run(qobj).result() self.assertTrue( np.allclose(result.get_unitary('test'), expected, rtol=1e-3))
def setUp(self): self.qp = None self.seed = 88 qasm_filename = self._get_resource_path('qasm/example.qasm') unroller = unroll.Unroller( qasm.Qasm(filename=qasm_filename).parse(), unroll.JsonBackend([])) circuit = QobjExperiment.from_dict(unroller.execute()) circuit.config = QobjItem(coupling_map=None, basis_gates='u1,u2,u3,cx,id', layout=None, seed=self.seed) circuit.header.name = 'test' self.qobj = Qobj( id='test_sim_single_shot', config=QobjConfig(shots=1024, memory_slots=6, max_credits=3), experiments=[circuit], header=QobjHeader(backend_name='local_qasm_simulator_py'))
def _circuit_to_experiment(circuit, config=None, basis_gates=None, coupling_map=None): """Helper function for dags to qobj in parallel (if available). Args: circuit (QuantumCircuit): QuantumCircuit to convert into qobj experiment config (dict): dictionary of parameters (e.g. noise) used by runner basis_gates (list[str])): basis gates for the experiment coupling_map (list): coupling map (perhaps custom) to target in mapping Returns: Qobj: Qobj to be run on the backends """ # pylint: disable=unused-argument # TODO: if arguments are really unused, consider changing the signature # TODO: removed the DAG from this function from qiskit.converters import circuit_to_dag from qiskit.unroll import DagUnroller, JsonBackend dag = circuit_to_dag(circuit) json_circuit = DagUnroller(dag, JsonBackend(dag.basis)).execute() # Step 3a: create the Experiment based on json_circuit experiment = QobjExperiment.from_dict(json_circuit) # Step 3b: populate the Experiment configuration and header experiment.header.name = circuit.name experiment_config = deepcopy(config or {}) experiment_config.update({ 'memory_slots': sum([creg.size for creg in dag.cregs.values()]), 'n_qubits': sum([qreg.size for qreg in dag.qregs.values()]) }) experiment.config = QobjItem(**experiment_config) # set eval_symbols=True to evaluate each symbolic expression # TODO: after transition to qobj, we can drop this experiment.header.compiled_circuit_qasm = circuit.qasm() # Step 3c: add the Experiment to the Qobj return experiment
def test_if_statement(self): self.log.info('test_if_statement_x') shots = 100 max_qubits = 3 qr = QuantumRegister(max_qubits, 'qr') cr = ClassicalRegister(max_qubits, 'cr') circuit_if_true = QuantumCircuit(qr, cr, name='test_if_true') circuit_if_true.x(qr[0]) circuit_if_true.x(qr[1]) circuit_if_true.measure(qr[0], cr[0]) circuit_if_true.measure(qr[1], cr[1]) circuit_if_true.x(qr[2]).c_if(cr, 0x3) circuit_if_true.measure(qr[0], cr[0]) circuit_if_true.measure(qr[1], cr[1]) circuit_if_true.measure(qr[2], cr[2]) circuit_if_false = QuantumCircuit(qr, cr, name='test_if_false') circuit_if_false.x(qr[0]) circuit_if_false.measure(qr[0], cr[0]) circuit_if_false.measure(qr[1], cr[1]) circuit_if_false.x(qr[2]).c_if(cr, 0x3) circuit_if_false.measure(qr[0], cr[0]) circuit_if_false.measure(qr[1], cr[1]) circuit_if_false.measure(qr[2], cr[2]) basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=circuit_if_true.qasm()).parse(), unroll.JsonBackend(basis_gates)) ucircuit_true = QobjExperiment.from_dict(unroller.execute()) unroller = unroll.Unroller( qasm.Qasm(data=circuit_if_false.qasm()).parse(), unroll.JsonBackend(basis_gates)) ucircuit_false = QobjExperiment.from_dict(unroller.execute()) # Customize the experiments and create the qobj. ucircuit_true.config = QobjItem(coupling_map=None, basis_gates='u1,u2,u3,cx,id', layout=None, seed=None) ucircuit_true.header.name = 'test_if_true' ucircuit_false.config = QobjItem(coupling_map=None, basis_gates='u1,u2,u3,cx,id', layout=None, seed=None) ucircuit_false.header.name = 'test_if_false' qobj = Qobj(id='test_if_qobj', config=QobjConfig(max_credits=3, shots=shots, memory_slots=max_qubits), experiments=[ucircuit_true, ucircuit_false], header=QobjHeader(backend_name='local_qasm_simulator_py')) result = QasmSimulatorPy().run(qobj).result() result_if_true = result.get_data('test_if_true') self.log.info('result_if_true circuit:') self.log.info(circuit_if_true.qasm()) self.log.info('result_if_true=%s', result_if_true) result_if_false = result.get_data('test_if_false') self.log.info('result_if_false circuit:') self.log.info(circuit_if_false.qasm()) self.log.info('result_if_false=%s', result_if_false) self.assertTrue(result_if_true['counts']['111'] == 100) self.assertTrue(result_if_false['counts']['001'] == 100)
def _compile_single_circuit(circuit, backend, config=None, basis_gates=None, coupling_map=None, initial_layout=None, seed=None, pass_manager=None): """Compile a single circuit into a QobjExperiment. Args: circuit (QuantumCircuit): circuit to compile backend (BaseBackend): a backend to compile for config (dict): dictionary of parameters (e.g. noise) used by runner basis_gates (str): comma-separated basis gate set to compile to coupling_map (list): coupling map (perhaps custom) to target in mapping initial_layout (list): initial layout of qubits in mapping seed (int): random seed for simulators pass_manager (PassManager): a pass_manager for the transpiler stage Returns: QobjExperiment: the QobjExperiment to be run on the backends """ # TODO: A better solution is to have options to enable/disable optimizations num_qubits = sum((len(qreg) for qreg in circuit.get_qregs().values())) if num_qubits == 1 or coupling_map == "all-to-all": coupling_map = None # Step 2a: circuit -> dag dag_circuit = DAGCircuit.fromQuantumCircuit(circuit) # TODO: move this inside the mapper pass # pick a good initial layout if coupling_map is not already satisfied # otherwise keep it as q[i]->q[i] if (initial_layout is None and not backend.configuration['simulator'] and not _matches_coupling_map(circuit.data, coupling_map)): initial_layout = _pick_best_layout(backend, num_qubits, circuit.get_qregs()) # Step 2b: transpile (dag -> dag) dag_circuit, final_layout = transpile(dag_circuit, basis_gates=basis_gates, coupling_map=coupling_map, initial_layout=initial_layout, get_layout=True, seed=seed, pass_manager=pass_manager) # Step 2c: dag -> json # the compiled circuit to be run saved as a dag # we assume that transpile() has already expanded gates # to the target basis, so we just need to generate json list_layout = [[k, v] for k, v in final_layout.items()] if final_layout else None json_circuit = DagUnroller(dag_circuit, JsonBackend(dag_circuit.basis)).execute() # Step 3a: create the Experiment based on json_circuit experiment = QobjExperiment.from_dict(json_circuit) # Step 3b: populate the Experiment configuration and header experiment.header.name = circuit.name # TODO: place in header or config? experiment_config = deepcopy(config or {}) experiment_config.update({ 'coupling_map': coupling_map, 'basis_gates': basis_gates, 'layout': list_layout, 'memory_slots': sum(register.size for register in circuit.get_cregs().values()) }) experiment.config = QobjItem(**experiment_config) # set eval_symbols=True to evaluate each symbolic expression # TODO after transition to qobj, we can drop this experiment.header.compiled_circuit_qasm = dag_circuit.qasm( qeflag=True, eval_symbols=True) return experiment
def _dags_2_qobj(dags, backend_name, config=None, shots=None, max_credits=None, qobj_id=None, basis_gates=None, coupling_map=None, seed=None): """Convert a list of dags into a qobj. Args: dags (list[DAGCircuit]): dags to compile backend_name (str): name of runner backend config (dict): dictionary of parameters (e.g. noise) used by runner shots (int): number of repetitions of each circuit, for sampling max_credits (int): maximum credits to use qobj_id (int): identifier for the generated qobj basis_gates (list[str])): basis gates for the experiment coupling_map (list): coupling map (perhaps custom) to target in mapping seed (int): random seed for simulators Returns: Qobj: the Qobj to be run on the backends """ # TODO: the following will be removed from qobj and thus removed here: # `basis_gates`, `coupling_map` # Step 1: create the Qobj, with empty experiments. # Copy the configuration: the values in `config` have preference qobj_config = deepcopy(config or {}) # TODO: "memory_slots" is required by the qobj schema in the top-level # qobj.config, and is user-defined. At the moment is set to the maximum # number of *register* slots for the circuits, in order to have `measure` # behave properly until the transition is over; and each circuit stores # its memory_slots in its configuration. qobj_config.update({ 'shots': shots, 'max_credits': max_credits, 'memory_slots': 0 }) qobj = Qobj(qobj_id=qobj_id or str(uuid.uuid4()), config=QobjConfig(**qobj_config), experiments=[], header=QobjHeader(backend_name=backend_name)) if seed: qobj.config.seed = seed for dag in dags: json_circuit = DagUnroller(dag, JsonBackend(dag.basis)).execute() # Step 3a: create the Experiment based on json_circuit experiment = QobjExperiment.from_dict(json_circuit) # Step 3b: populate the Experiment configuration and header experiment.header.name = dag.name # TODO: place in header or config? experiment_config = deepcopy(config or {}) experiment_config.update({ 'coupling_map': coupling_map, 'basis_gates': basis_gates, 'layout': dag.layout, 'memory_slots': sum(dag.cregs.values()), # TODO: `n_qubits` is not part of the qobj spec, but needed for the simulator. 'n_qubits': sum(dag.qregs.values()) }) experiment.config = QobjItem(**experiment_config) # set eval_symbols=True to evaluate each symbolic expression # TODO: after transition to qobj, we can drop this experiment.header.compiled_circuit_qasm = dag.qasm(qeflag=True, eval_symbols=True) # Step 3c: add the Experiment to the Qobj qobj.experiments.append(experiment) # Update the `memory_slots` value. # TODO: remove when `memory_slots` can be provided by the user. qobj.config.memory_slots = max(experiment.config.memory_slots for experiment in qobj.experiments) # Update the `n_qubits` global value. # TODO: num_qubits is not part of the qobj specification, but needed # for the simulator. qobj.config.n_qubits = max(experiment.config.n_qubits for experiment in qobj.experiments) return qobj
def compile(circuits, backend, config=None, basis_gates=None, coupling_map=None, initial_layout=None, shots=1024, max_credits=10, seed=None, qobj_id=None, hpc=None, pass_manager=None): """Compile a list of circuits into a qobj. Args: circuits (QuantumCircuit or list[QuantumCircuit]): circuits to compile backend (BaseBackend): a backend to compile for config (dict): dictionary of parameters (e.g. noise) used by runner basis_gates (str): comma-separated basis gate set to compile to coupling_map (list): coupling map (perhaps custom) to target in mapping initial_layout (list): initial layout of qubits in mapping shots (int): number of repetitions of each circuit, for sampling max_credits (int): maximum credits to use seed (int): random seed for simulators qobj_id (int): identifier for the generated qobj hpc (dict): HPC simulator parameters pass_manager (PassManager): a pass_manager for the transpiler stage Returns: Qobj: the Qobj to be run on the backends Raises: TranspilerError: in case of bad compile options, e.g. the hpc options. """ if isinstance(circuits, QuantumCircuit): circuits = [circuits] backend_conf = backend.configuration backend_name = backend_conf['name'] # Step 1: create the Qobj, with empty experiments. # Copy the configuration: the values in `config` have prefern qobj_config = deepcopy(config or {}) # TODO: "register_slots" is required by the qobj schema in the top-level # qobj.config. In this implementation, is overridden by the individual # experiment.config entries (hence the 0 should never be used). qobj_config.update({ 'shots': shots, 'max_credits': max_credits, 'register_slots': 0 }) qobj = Qobj(id=qobj_id or str(uuid.uuid4()), config=QobjConfig(**qobj_config), experiments=[], header=QobjHeader(backend_name=backend_name)) if seed: qobj.config.seed = seed # Check for valid parameters for the experiments. if hpc is not None and \ not all(key in hpc for key in ('multi_shot_optimization', 'omp_num_threads')): raise TranspilerError('Unknown HPC parameter format!') basis_gates = basis_gates or backend_conf['basis_gates'] coupling_map = coupling_map or backend_conf['coupling_map'] # Step 2 and 3: transpile and populate the circuits for circuit in circuits: # TODO: A better solution is to have options to enable/disable optimizations num_qubits = sum((len(qreg) for qreg in circuit.get_qregs().values())) if num_qubits == 1 or coupling_map == "all-to-all": coupling_map = None # Step 2a: circuit -> dag dag_circuit = DAGCircuit.fromQuantumCircuit(circuit) # TODO: move this inside the mapper pass # pick a good initial layout if coupling_map is not already satisfied # otherwise keep it as q[i]->q[i] if (initial_layout is None and not backend_conf['simulator'] and not _matches_coupling_map(circuit.data, coupling_map)): initial_layout = _pick_best_layout(backend, num_qubits, circuit.get_qregs()) # Step 2b: transpile (dag -> dag) dag_circuit, final_layout = transpile(dag_circuit, basis_gates=basis_gates, coupling_map=coupling_map, initial_layout=initial_layout, get_layout=True, seed=seed, pass_manager=pass_manager) # Step 2c: dag -> json # the compiled circuit to be run saved as a dag # we assume that transpile() has already expanded gates # to the target basis, so we just need to generate json list_layout = [[k, v] for k, v in final_layout.items() ] if final_layout else None json_circuit = DagUnroller(dag_circuit, JsonBackend(dag_circuit.basis)).execute() # Step 3a: create the Experiment based on json_circuit experiment = QobjExperiment.from_dict(json_circuit) # Step 3b: populate the Experiment configuration and header experiment.header.name = circuit.name # TODO: place in header or config? experiment_config = deepcopy(config or {}) experiment_config.update({ 'coupling_map': coupling_map, 'basis_gates': basis_gates, 'layout': list_layout, 'register_slots': sum(register.size for register in circuit.get_cregs().values()) }) experiment.config = QobjItem(**experiment_config) # set eval_symbols=True to evaluate each symbolic expression # TODO after transition to qobj, we can drop this experiment.header.compiled_circuit_qasm = dag_circuit.qasm( qeflag=True, eval_symbols=True) # Step 3c: add the Experiment to the Qobj qobj.experiments.append(experiment) return qobj