Beispiel #1
0
    def _format_qobj_str(self, qobj, backend_options, noise_model):
        """Format qobj string for qiskit aer controller"""
        # Save original qobj config so we can revert our modification
        # after execution
        original_config = qobj.config
        # Convert to dictionary and add new parameters
        # from noise model and backend options
        config = original_config.as_dict()
        if backend_options is not None:
            for key, val in backend_options.items():
                config[key] = val
        if not "available_memory" in config:
            available_mb = int(local_hardware_info()['memory'] * 1024)
            config['available_memory'] = available_mb
        # Add noise model
        if noise_model is not None:
            config["noise_model"] = noise_model

        # Add runtime config
        config['library_dir'] = self.configuration().library_dir
        qobj.config = QobjConfig.from_dict(config)
        # Get the JSON serialized string
        output = json.dumps(qobj, cls=AerJSONEncoder).encode('UTF-8')
        # Revert original qobj
        qobj.config = original_config
        # Return output
        return output
Beispiel #2
0
    def setUp(self):
        self.valid_qobj = Qobj(
            qobj_id='12345',
            header={},
            config=QobjConfig(shots=1024, memory_slots=2, max_credits=10),
            experiments=[
                QobjExperiment(instructions=[
                    QobjInstruction(name='u1', qubits=[1], params=[0.4]),
                    QobjInstruction(name='u2', qubits=[1], params=[0.4, 0.2])
                ])
            ]
        )

        self.valid_dict = {
            'qobj_id': '12345',
            'type': 'QASM',
            'schema_version': '1.0.0',
            'header': {},
            'config': {'max_credits': 10, 'memory_slots': 2, 'shots': 1024},
            'experiments': [
                {'instructions': [
                    {'name': 'u1', 'params': [0.4], 'qubits': [1]},
                    {'name': 'u2', 'params': [0.4, 0.2], 'qubits': [1]}
                ]}
            ],
        }

        self.bad_qobj = copy.deepcopy(self.valid_qobj)
        self.bad_qobj.experiments = None  # set experiments to None to cause the qobj to be invalid
Beispiel #3
0
    def test_from_dict_per_class(self):
        """Test Qobj and its subclass representations given a dictionary."""
        test_parameters = {
            Qobj: (self.valid_qobj, self.valid_dict),
            QobjConfig: (QobjConfig(shots=1, memory_slots=2), {
                'shots': 1,
                'memory_slots': 2
            }),
            QobjExperiment: (QobjExperiment(instructions=[
                QobjInstruction(name='u1', qubits=[1], params=[0.4])
            ]), {
                'instructions': {
                    'name': 'u1',
                    'qubits': [1],
                    'params': [0.4]
                }
            }),
            QobjInstruction: (QobjInstruction(name='u1',
                                              qubits=[1],
                                              params=[0.4]), {
                                                  'name': 'u1',
                                                  'qubits': [1],
                                                  'params': [0.4]
                                              })
        }

        for qobj_class, (qobj, expected_dict) in test_parameters.items():
            with self.subTest(msg=str(qobj_class)):
                self.assertEqual(qobj, qobj_class.from_dict(expected_dict))
    def setUp(self):
        qasm_filename = self._get_resource_path('qasm/example.qasm')
        qasm_ast = Qasm(filename=qasm_filename).parse()
        qasm_dag = Unroller(qasm_ast, DAGBackend()).execute()
        qasm_json = DagUnroller(qasm_dag,
                                JsonBackend(qasm_dag.basis)).execute()

        qr = QuantumRegister(2, 'q')
        cr = ClassicalRegister(2, 'c')
        qc = QuantumCircuit(qr, cr)
        qc.h(qr[0])
        qc.measure(qr[0], cr[0])
        qc_dag = DAGCircuit.fromQuantumCircuit(qc)
        qc_json = DagUnroller(qc_dag, JsonBackend(qc_dag.basis)).execute()

        # create qobj
        compiled_circuit1 = QobjExperiment.from_dict(qc_json)
        compiled_circuit2 = QobjExperiment.from_dict(qasm_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='qasm_simulator'))
        self.qobj.experiments[0].header.name = 'test_circuit1'
        self.qobj.experiments[1].header.name = 'test_circuit2'
        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.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_qobj_to_circuits_with_nothing(self):
     """Verify that qobj_to_circuits returns None without any data."""
     qobj = Qobj(qobj_id='abc123',
                 config=QobjConfig(),
                 header=QobjHeader(),
                 experiments=[],
                 type='QASM')
     self.assertIsNone(qobj_to_circuits(qobj))
Beispiel #8
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

    qobj.experiments = parallel_map(_dags_2_qobj_parallel, dags,
                                    task_kwargs={'basis_gates': basis_gates,
                                                 'config': config,
                                                 'coupling_map': coupling_map})

    # 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
Beispiel #9
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))
                ])
Beispiel #10
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))
                ])
Beispiel #11
0
    def load_qobj_from_cache(self, circuits, chunk, run_config=None):
        self.try_loading_cache_from_file()

        if self.try_reusing_qobjs and self.qobjs is not None and len(self.qobjs) <= chunk:
            self.mappings.insert(chunk, self.mappings[0])
            self.qobjs.insert(chunk, copy.deepcopy(self.qobjs[0]))

        for circ_num, input_circuit in enumerate(circuits):

            # If there are too few experiments in the cache, try reusing the first experiment.
            # Only do this for the first chunk. Subsequent chunks should rely on these copies
            # through the deepcopy above.
            if self.try_reusing_qobjs and chunk == 0 and circ_num > 0 and len(self.qobjs[chunk].experiments) <= \
                    circ_num:
                self.qobjs[0].experiments.insert(circ_num, copy.deepcopy(self.qobjs[0].experiments[0]))
                self.mappings[0].insert(circ_num, self.mappings[0][0])

            # Unroll circuit in case of composite gates
            raw_gates = []
            for gate in input_circuit.data:
                if isinstance(gate, CompositeGate): raw_gates += gate.instruction_list()
                else: raw_gates += [gate]
            self.qobjs[chunk].experiments[circ_num].header.name = input_circuit.name
            for gate_num, compiled_gate in enumerate(self.qobjs[chunk].experiments[circ_num].instructions):
                if not hasattr(compiled_gate, 'params') or len(compiled_gate.params) < 1: continue
                if compiled_gate.name == 'snapshot': continue
                cache_index = self.mappings[chunk][circ_num][gate_num]
                uncompiled_gate = raw_gates[cache_index]

                # Need the 'getattr' wrapper because measure has no 'params' field and breaks this.
                if not len(getattr(compiled_gate, 'params', [])) == len(getattr(uncompiled_gate, 'params', [])) or \
                    not compiled_gate.name == uncompiled_gate.name:
                    raise AquaError('Gate mismatch at gate {0} ({1}, {2} params) of circuit against gate {3} ({4}, '
                                    '{5} params) of cached qobj'.format(cache_index,
                                                                 uncompiled_gate.name,
                                                                 len(uncompiled_gate.params),
                                                                 gate_num,
                                                                 compiled_gate.name,
                                                                 len(compiled_gate.params)))
                compiled_gate.params = np.array(uncompiled_gate.params, dtype=float).tolist()
        exec_qobj = copy.copy(self.qobjs[chunk])
        if self.skip_qobj_deepcopy: exec_qobj.experiments = self.qobjs[chunk].experiments[0:len(circuits)]
        else: exec_qobj.experiments = copy.deepcopy(self.qobjs[chunk].experiments[0:len(circuits)])

        if run_config is None:
            run_config = RunConfig(shots=1024, max_credits=10, memory=False)
        exec_qobj.config = QobjConfig(**run_config.to_dict())
        exec_qobj.config.memory_slots = max(experiment.config.memory_slots for experiment in exec_qobj.experiments)
        exec_qobj.config.n_qubits = max(experiment.config.n_qubits for experiment in exec_qobj.experiments)
        return exec_qobj
Beispiel #12
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'))
Beispiel #13
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))
Beispiel #14
0
    def test_create_qobj(self):
        """Test creation of a Qobj based on the individual elements."""
        config = QobjConfig(max_credits=10, shots=1024, memory_slots=2)
        instruction_1 = QobjInstruction(name='u1', qubits=[1], params=[0.4])
        instruction_2 = QobjInstruction(name='u2',
                                        qubits=[1],
                                        params=[0.4, 0.2])
        instructions = [instruction_1, instruction_2]
        experiment_1 = QobjExperiment(instructions=instructions)
        experiments = [experiment_1]

        qobj = Qobj(id='12345',
                    config=config,
                    experiments=experiments,
                    header={})

        expected = {
            'id':
            '12345',
            'type':
            'QASM',
            'schema_version':
            '1.0.0',
            'header': {},
            'config': {
                'max_credits': 10,
                'memory_slots': 2,
                'shots': 1024
            },
            'experiments': [{
                'instructions': [{
                    'name': 'u1',
                    'params': [0.4],
                    'qubits': [1]
                }, {
                    'name': 'u2',
                    'params': [0.4, 0.2],
                    'qubits': [1]
                }]
            }],
        }

        self.assertEqual(qobj.as_dict(), expected)
Beispiel #15
0
 def _format_qobj_str(self, qobj, backend_options, noise_model):
     """Format qobj string for qiskit aer controller"""
     # Save original qobj config so we can revert our modification
     # after execution
     original_config = qobj.config
     # Convert to dictionary and add new parameters
     # from noise model and backend options
     config = original_config.as_dict()
     if backend_options is not None:
         for key, val in backend_options.items():
             config[key] = val
     # Add noise model
     if noise_model is not None:
         config["noise_model"] = noise_model
     qobj.config = QobjConfig.from_dict(config)
     # Get the JSON serialized string
     output = json.dumps(qobj, cls=AerJSONEncoder).encode('UTF-8')
     # Revert original qobj
     qobj.config = original_config
     # Return output
     return output
Beispiel #16
0
    def setUp(self):
        self.seed = 88
        self.backend = QasmSimulatorPy()
        backend_basis = self.backend.configuration().basis_gates
        qasm_filename = self._get_resource_path('qasm/example.qasm')
        qasm_ast = Qasm(filename=qasm_filename).parse()
        qasm_dag = Unroller(qasm_ast, DAGBackend()).execute()
        qasm_dag = DagUnroller(qasm_dag, DAGBackend(backend_basis)).expand_gates()
        qasm_json = DagUnroller(qasm_dag, JsonBackend(qasm_dag.basis)).execute()
        compiled_circuit = QobjExperiment.from_dict(qasm_json)
        compiled_circuit.header.name = 'test'

        self.qobj = Qobj(
            qobj_id='test_sim_single_shot',
            config=QobjConfig(
                shots=1024, memory_slots=6,
                max_credits=3, seed=self.seed
            ),
            experiments=[compiled_circuit],
            header=QobjHeader(backend_name='qasm_simulator_py')
        )
Beispiel #17
0
    def test_create_qobj(self):
        """Test creation of a Qobj based on the individual elements."""
        config = QobjConfig(max_credits=10, shots=1024, backend_name='backend')
        circuit_config = QobjExperimentConfig(
            seed=1234, basis_gates='u1,u2,u3,cx,id,snapshot',
            coupling_map=None, layout=None)
        circuit_config.seed = 1234

        instruction_1 = QobjInstruction(name='u1', qubits=[1], params=[0.4])
        instruction_2 = QobjInstruction(name='u2', qubits=[1], params=[0.4, 0.2])
        instructions = [instruction_1, instruction_2]
        compiled_circuit = QobjCompiledCircuit(header=None, operations=instructions)
        experiment_1 = QobjExperiment(name='circuit1', config=circuit_config,
                                      compiled_circuit=compiled_circuit,
                                      compiled_circuit_qasm='compiled_qasm')
        experiments = [experiment_1]

        qobj = Qobj(id='12345', config=config, circuits=experiments)

        expected = {'id': '12345',
                    'type': 'QASM',
                    'config': {'max_credits': 10, 'shots': 1024,
                               'backend_name': 'backend'},
                    'circuits': [
                        {
                            'name': 'circuit1',
                            'config': {
                                'seed': 1234, 'basis_gates': 'u1,u2,u3,cx,id,snapshot',
                                'coupling_map': None, 'layout': None},
                            'compiled_circuit': {
                                'header': None,
                                'operations': [
                                    {'name': 'u1', 'params': [0.4], 'qubits': [1]},
                                    {'name': 'u2', 'params': [0.4, 0.2],
                                     'qubits': [1]}]
                            },
                            'compiled_circuit_qasm': 'compiled_qasm'
                        }
                    ]}
        self.assertEqual(qobj.as_dict(), expected)
Beispiel #18
0
def circuits_to_qobj(circuits,
                     backend_name,
                     config=None,
                     shots=1024,
                     max_credits=10,
                     qobj_id=None,
                     basis_gates=None,
                     coupling_map=None,
                     seed=None,
                     memory=False):
    """Convert a list of circuits into a qobj.

    Args:
        circuits (list[QuantumCircuits] or QuantumCircuit): circuits 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
        memory (bool): if True, per-shot measurement bitstrings are returned as well

    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 {})
    qobj_config.update({
        'shots': shots,
        'max_credits': max_credits,
        'memory_slots': 0,
        'memory': memory
    })

    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

    if isinstance(circuits, QuantumCircuit):
        circuits = [circuits]

    for circuit in circuits:
        qobj.experiments.append(
            _circuit_to_experiment(circuit, config, basis_gates, coupling_map))

    # Update the global `memory_slots` and `n_qubits` values.
    qobj.config.memory_slots = max(experiment.config.memory_slots
                                   for experiment in qobj.experiments)

    qobj.config.n_qubits = max(experiment.config.n_qubits
                               for experiment in qobj.experiments)

    return qobj
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
Beispiel #20
0
def circuits_to_qobj(circuits,
                     user_qobj_header=None,
                     run_config=None,
                     qobj_id=None,
                     backend_name=None,
                     config=None,
                     shots=None,
                     max_credits=None,
                     basis_gates=None,
                     coupling_map=None,
                     seed=None,
                     memory=None):
    """Convert a list of circuits into a qobj.

    Args:
        circuits (list[QuantumCircuits] or QuantumCircuit): circuits to compile
        user_qobj_header (QobjHeader): header to pass to the results
        run_config (RunConfig): RunConfig object
        qobj_id (int): identifier for the generated qobj

        backend_name (str): TODO: delete after qiskit-terra 0.8
        config (dict): TODO: delete after qiskit-terra 0.8
        shots (int): TODO: delete after qiskit-terra 0.8
        max_credits (int): TODO: delete after qiskit-terra 0.8
        basis_gates (str): TODO: delete after qiskit-terra 0.8
        coupling_map (list): TODO: delete after qiskit-terra 0.8
        seed (int): TODO: delete after qiskit-terra 0.8
        memory (bool): TODO: delete after qiskit-terra 0.8

    Returns:
        Qobj: the Qobj to be run on the backends
    """
    user_qobj_header = user_qobj_header or QobjHeader()
    run_config = run_config or RunConfig()
    if isinstance(circuits, QuantumCircuit):
        circuits = [circuits]

    if backend_name:
        warnings.warn('backend_name is not required anymore',
                      DeprecationWarning)
        user_qobj_header.backend_name = backend_name
    if config:
        warnings.warn(
            'config is not used anymore. Set all configs in '
            'run_config.', DeprecationWarning)
    if shots:
        warnings.warn('shots is not used anymore. Set it via run_config.',
                      DeprecationWarning)
        run_config.shots = shots
    if basis_gates:
        warnings.warn('basis_gates was unused and will be removed.',
                      DeprecationWarning)
    if coupling_map:
        warnings.warn('coupling_map was unused and will be removed.',
                      DeprecationWarning)
    if seed:
        warnings.warn('seed is not used anymore. Set it via run_config',
                      DeprecationWarning)
        run_config.seed = seed
    if memory:
        warnings.warn('memory is not used anymore. Set it via run_config',
                      DeprecationWarning)
        run_config.memory = memory
    if max_credits:
        warnings.warn('max_credits is not used anymore. Set it via run_config',
                      DeprecationWarning)
        run_config.max_credits = max_credits

    userconfig = QobjConfig(**run_config.to_dict())
    experiments = []
    max_n_qubits = 0
    max_memory_slots = 0
    for circuit in circuits:
        # header stuff
        n_qubits = 0
        memory_slots = 0
        qubit_labels = []
        clbit_labels = []

        qreg_sizes = []
        creg_sizes = []
        for qreg in circuit.qregs:
            qreg_sizes.append([qreg.name, qreg.size])
            for j in range(qreg.size):
                qubit_labels.append([qreg.name, j])
            n_qubits += qreg.size
        for creg in circuit.cregs:
            creg_sizes.append([creg.name, creg.size])
            for j in range(creg.size):
                clbit_labels.append([creg.name, j])
            memory_slots += creg.size

        # TODO: why do we need creq_sizes and qreg_sizes in header
        # TODO: we need to rethink memory_slots as they are tied to classical bit
        # TODO: when no more backends use the compiled_circuit_qasm lets delete it form header
        experimentheader = QobjExperimentHeader(
            qubit_labels=qubit_labels,
            n_qubits=n_qubits,
            qreg_sizes=qreg_sizes,
            clbit_labels=clbit_labels,
            memory_slots=memory_slots,
            creg_sizes=creg_sizes,
            name=circuit.name,
            compiled_circuit_qasm=circuit.qasm())
        # TODO: why do we need n_qubits and memory_slots in both the header and the config
        experimentconfig = QobjExperimentConfig(n_qubits=n_qubits,
                                                memory_slots=memory_slots)

        instructions = []
        for opt in circuit.data:
            current_instruction = QobjInstruction(name=opt.name)
            if opt.qargs:
                qubit_indices = [
                    qubit_labels.index([qubit[0].name, qubit[1]])
                    for qubit in opt.qargs
                ]
                current_instruction.qubits = qubit_indices
            if opt.cargs:
                clbit_indices = [
                    clbit_labels.index([clbit[0].name, clbit[1]])
                    for clbit in opt.cargs
                ]
                current_instruction.memory = clbit_indices

            if opt.params:
                params = list(map(lambda x: x.evalf(), opt.params))
                current_instruction.params = params

            # TODO: I really dont like this for snapshot. I also think we should change
            # type to snap_type
            if opt.name == "snapshot":
                current_instruction.label = str(opt.params[0])
                current_instruction.type = str(opt.params[1])
            if opt.control:
                mask = 0
                for clbit in clbit_labels:
                    if clbit[0] == opt.control[0].name:
                        mask |= (1 << clbit_labels.index(clbit))

                current_instruction.conditional = QobjConditional(
                    mask="0x%X" % mask,
                    type='equals',
                    val="0x%X" % opt.control[1])

            instructions.append(current_instruction)
        experiments.append(
            QobjExperiment(instructions=instructions,
                           header=experimentheader,
                           config=experimentconfig))
        if n_qubits > max_n_qubits:
            max_n_qubits = n_qubits
        if memory_slots > max_memory_slots:
            max_memory_slots = memory_slots

    userconfig.memory_slots = max_memory_slots
    userconfig.n_qubits = max_n_qubits

    return Qobj(qobj_id=qobj_id or str(uuid.uuid4()),
                config=userconfig,
                experiments=experiments,
                header=user_qobj_header)
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: "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(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:
        experiment = _compile_single_circuit(circuit, backend, config,
                                             basis_gates, coupling_map,
                                             initial_layout, seed,
                                             pass_manager)
        # 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)

    return qobj
Beispiel #22
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
Beispiel #23
0
def assemble_circuits(circuits,
                      run_config=None,
                      qobj_header=None,
                      qobj_id=None):
    """Assembles a list of circuits into a qobj which can be run on the backend.

    Args:
        circuits (list[QuantumCircuits] or QuantumCircuit): circuits to assemble
        run_config (RunConfig): RunConfig object
        qobj_header (QobjHeader): header to pass to the results
        qobj_id (int): identifier for the generated qobj

    Returns:
        Qobj: the Qobj to be run on the backends
    """
    qobj_header = qobj_header or QobjHeader()
    run_config = run_config or RunConfig()
    if isinstance(circuits, QuantumCircuit):
        circuits = [circuits]

    userconfig = QobjConfig(**run_config.to_dict())
    experiments = []
    max_n_qubits = 0
    max_memory_slots = 0
    for circuit in circuits:
        # header stuff
        n_qubits = 0
        memory_slots = 0
        qubit_labels = []
        clbit_labels = []

        qreg_sizes = []
        creg_sizes = []
        for qreg in circuit.qregs:
            qreg_sizes.append([qreg.name, qreg.size])
            for j in range(qreg.size):
                qubit_labels.append([qreg.name, j])
            n_qubits += qreg.size
        for creg in circuit.cregs:
            creg_sizes.append([creg.name, creg.size])
            for j in range(creg.size):
                clbit_labels.append([creg.name, j])
            memory_slots += creg.size

        # TODO: why do we need creq_sizes and qreg_sizes in header
        # TODO: we need to rethink memory_slots as they are tied to classical bit
        experimentheader = QobjExperimentHeader(qubit_labels=qubit_labels,
                                                n_qubits=n_qubits,
                                                qreg_sizes=qreg_sizes,
                                                clbit_labels=clbit_labels,
                                                memory_slots=memory_slots,
                                                creg_sizes=creg_sizes,
                                                name=circuit.name)
        # TODO: why do we need n_qubits and memory_slots in both the header and the config
        experimentconfig = QobjExperimentConfig(n_qubits=n_qubits,
                                                memory_slots=memory_slots)

        instructions = []
        for opt in circuit.data:
            current_instruction = QobjInstruction(name=opt.name)
            if opt.qargs:
                qubit_indices = [
                    qubit_labels.index([qubit[0].name, qubit[1]])
                    for qubit in opt.qargs
                ]
                current_instruction.qubits = qubit_indices
            if opt.cargs:
                clbit_indices = [
                    clbit_labels.index([clbit[0].name, clbit[1]])
                    for clbit in opt.cargs
                ]
                current_instruction.memory = clbit_indices

            if opt.params:
                params = list(map(lambda x: x.evalf(), opt.params))
                params = [
                    sympy.matrix2numpy(x, dtype=complex) if isinstance(
                        x, sympy.Matrix) else x for x in params
                ]
                if len(params) == 1 and isinstance(params[0], numpy.ndarray):
                    # TODO: Aer expects list of rows for unitary instruction params;
                    # change to matrix in Aer.
                    params = params[0]
                current_instruction.params = params
            # TODO (jay): I really dont like this for snapshot. I also think we should change
            # type to snap_type
            if opt.name == "snapshot":
                current_instruction.label = str(opt.params[0])
                current_instruction.type = str(opt.params[1])
            if opt.control:
                mask = 0
                for clbit in clbit_labels:
                    if clbit[0] == opt.control[0].name:
                        mask |= (1 << clbit_labels.index(clbit))

                current_instruction.conditional = QobjConditional(
                    mask="0x%X" % mask,
                    type='equals',
                    val="0x%X" % opt.control[1])

            instructions.append(current_instruction)
        experiments.append(
            QobjExperiment(instructions=instructions,
                           header=experimentheader,
                           config=experimentconfig))
        if n_qubits > max_n_qubits:
            max_n_qubits = n_qubits
        if memory_slots > max_memory_slots:
            max_memory_slots = memory_slots

    userconfig.memory_slots = max_memory_slots
    userconfig.n_qubits = max_n_qubits

    return Qobj(qobj_id=qobj_id or str(uuid.uuid4()),
                config=userconfig,
                experiments=experiments,
                header=qobj_header,
                type=QobjType.QASM.value)
Beispiel #24
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)
Beispiel #25
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 circuits
    qobj = Qobj(id=qobj_id or str(uuid.uuid4()),
                config=QobjConfig(max_credits=max_credits,
                                  shots=shots,
                                  backend_name=backend_name),
                circuits=[])

    # 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']

    for circuit in circuits:
        # Step 1: create the experiment configuration.
        config = config or {}
        circuit_config = copy.deepcopy(config)

        # 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
        circuit_config["coupling_map"] = coupling_map
        circuit_config["basis_gates"] = basis_gates
        circuit_config["seed"] = seed
        circuit_config["layout"] = None  # set during step 3.

        # Step 2: create the QobjExperiment, with empty compiled circuits.
        experiment = QobjExperiment(
            name=circuit.name,
            config=QobjExperimentConfig(**circuit_config),
            compiled_circuit=None,
            compiled_circuit_qasm=None)

        # Step 3: populate the circuit `instructions` after compilation
        # Step 3a: 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 3b: 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 3c: 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
        experiment.config.layout = list_layout
        json_circuit = DagUnroller(dag_circuit,
                                   JsonBackend(dag_circuit.basis)).execute()
        experiment.compiled_circuit = QobjCompiledCircuit.from_dict(
            json_circuit)

        # set eval_symbols=True to evaluate each symbolic expression
        # TODO after transition to qobj, we can drop this
        experiment.compiled_circuit_qasm = dag_circuit.qasm(qeflag=True,
                                                            eval_symbols=True)

        # add job to the qobj
        qobj.circuits.append(experiment)

    return qobj