Ejemplo n.º 1
0
    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'
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
    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))
Ejemplo n.º 6
0
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))
                ])
Ejemplo n.º 7
0
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))
Ejemplo n.º 9
0
    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'))
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
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
Ejemplo n.º 13
0
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
Ejemplo n.º 14
0
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