Repository: Qiskit/qiskit

Issue:
Update local Python simulators to use Qobj internally
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues to confirm this idea does not exist. -->

### What is the expected enhancement?

After #655, the local Python simulators accept a `Qobj` instance (with the new schema) during `.run()`, but internally they still use the old schema (for example, in `.run_circuit()`). Ideally they should also make use of the new schema and the instances directly instead of performing that conversion.



Discussion:

Resolving patch:
diff --git a/qiskit/backends/local/qasm_simulator_py.py b/qiskit/backends/local/qasm_simulator_py.py
--- a/qiskit/backends/local/qasm_simulator_py.py
+++ b/qiskit/backends/local/qasm_simulator_py.py
@@ -82,7 +82,6 @@
 from qiskit._result import Result
 from qiskit.backends import BaseBackend
 from qiskit.backends.local.localjob import LocalJob
-from qiskit.qobj import qobj_to_dict
 from ._simulatorerror import SimulatorError
 from ._simulatortools import single_gate_matrix
 logger = logging.getLogger(__name__)
@@ -117,7 +116,7 @@ def __init__(self, configuration=None):
         self._number_of_cbits = 0
         self._number_of_qubits = 0
         self._shots = 0
-        self._seed = 1
+        self._qobj_config = None
 
     @staticmethod
     def _index1(b, i, k):
@@ -278,10 +277,10 @@ def _run_job(self, qobj):
         self._validate(qobj)
         result_list = []
         self._shots = qobj.config.shots
+        self._qobj_config = qobj.config
         start = time.time()
 
-        qobj_prev = qobj_to_dict(qobj, version='0.0.1')
-        for circuit in qobj_prev['circuits']:
+        for circuit in qobj.experiments:
             result_list.append(self.run_circuit(circuit))
         end = time.time()
         job_id = str(uuid.uuid4())
@@ -298,7 +297,7 @@ def run_circuit(self, circuit):
         """Run a circuit and return a single Result.
 
         Args:
-            circuit (dict): JSON circuit from qobj circuits list
+            circuit (QobjExperiment): experiment from qobj experiments list
 
         Returns:
             dict: A dictionary of results which looks something like::
@@ -314,24 +313,24 @@ def run_circuit(self, circuit):
         Raises:
             SimulatorError: if an error occurred.
         """
-        ccircuit = circuit['compiled_circuit']
-        self._number_of_qubits = ccircuit['header']['number_of_qubits']
-        self._number_of_cbits = ccircuit['header']['number_of_clbits']
+        self._number_of_qubits = circuit.header.number_of_qubits
+        self._number_of_cbits = circuit.header.number_of_clbits
         self._statevector = 0
         self._classical_state = 0
         self._snapshots = {}
         cl_reg_index = []  # starting bit index of classical register
         cl_reg_nbits = []  # number of bits in classical register
         cbit_index = 0
-        for cl_reg in ccircuit['header']['clbit_labels']:
+        for cl_reg in circuit.header.clbit_labels:
             cl_reg_nbits.append(cl_reg[1])
             cl_reg_index.append(cbit_index)
             cbit_index += cl_reg[1]
-        if circuit['config']['seed'] is None:
-            self._seed = random.getrandbits(32)
-        else:
-            self._seed = circuit['config']['seed']
-        self._local_random.seed(self._seed)
+
+        # Get the seed looking in circuit, qobj, and then random.
+        seed = getattr(circuit.config, 'seed',
+                       getattr(self._qobj_config, 'seed',
+                               random.getrandbits(32)))
+        self._local_random.seed(seed)
         outcomes = []
 
         start = time.time()
@@ -340,69 +339,67 @@ def run_circuit(self, circuit):
                                          dtype=complex)
             self._statevector[0] = 1
             self._classical_state = 0
-            for operation in ccircuit['operations']:
-                if 'conditional' in operation:
-                    mask = int(operation['conditional']['mask'], 16)
+            for operation in circuit.instructions:
+                if getattr(operation, 'conditional', None):
+                    mask = int(operation.conditional.mask, 16)
                     if mask > 0:
                         value = self._classical_state & mask
                         while (mask & 0x1) == 0:
                             mask >>= 1
                             value >>= 1
-                        if value != int(operation['conditional']['val'], 16):
+                        if value != int(operation.conditional.val, 16):
                             continue
                 # Check if single  gate
-                if operation['name'] in ['U', 'u1', 'u2', 'u3']:
-                    if 'params' in operation:
-                        params = operation['params']
-                    else:
-                        params = None
-                    qubit = operation['qubits'][0]
-                    gate = single_gate_matrix(operation['name'], params)
+                if operation.name in ('U', 'u1', 'u2', 'u3'):
+                    params = getattr(operation, 'params', None)
+                    qubit = operation.qubits[0]
+                    gate = single_gate_matrix(operation.name, params)
                     self._add_qasm_single(gate, qubit)
                 # Check if CX gate
-                elif operation['name'] in ['id', 'u0']:
+                elif operation.name in ('id', 'u0'):
                     pass
-                elif operation['name'] in ['CX', 'cx']:
-                    qubit0 = operation['qubits'][0]
-                    qubit1 = operation['qubits'][1]
+                elif operation.name in ('CX', 'cx'):
+                    qubit0 = operation.qubits[0]
+                    qubit1 = operation.qubits[1]
                     self._add_qasm_cx(qubit0, qubit1)
                 # Check if measure
-                elif operation['name'] == 'measure':
-                    qubit = operation['qubits'][0]
-                    cbit = operation['clbits'][0]
+                elif operation.name == 'measure':
+                    qubit = operation.qubits[0]
+                    cbit = operation.clbits[0]
                     self._add_qasm_measure(qubit, cbit)
                 # Check if reset
-                elif operation['name'] == 'reset':
-                    qubit = operation['qubits'][0]
+                elif operation.name == 'reset':
+                    qubit = operation.qubits[0]
                     self._add_qasm_reset(qubit)
                 # Check if barrier
-                elif operation['name'] == 'barrier':
+                elif operation.name == 'barrier':
                     pass
                 # Check if snapshot command
-                elif operation['name'] == 'snapshot':
-                    params = operation['params']
+                elif operation.name == 'snapshot':
+                    params = operation.params
                     self._add_qasm_snapshot(params[0])
                 else:
                     backend = self._configuration['name']
                     err_msg = '{0} encountered unrecognized operation "{1}"'
                     raise SimulatorError(err_msg.format(backend,
-                                                        operation['name']))
+                                                        operation.name))
             # Turn classical_state (int) into bit string
             outcomes.append(bin(self._classical_state)[2:].zfill(
                 self._number_of_cbits))
         # Return the results
         counts = dict(Counter(outcomes))
-        data = {'counts': self._format_result(
-            counts, cl_reg_index, cl_reg_nbits)}
-        data['snapshots'] = self._snapshots
+        data = {
+            'counts': self._format_result(counts, cl_reg_index, cl_reg_nbits),
+            'snapshots': self._snapshots
+        }
         if self._shots == 1:
             # TODO: deprecated -- remove in v0.6
             data['statevector'] = self._statevector
             data['quantum_state'] = self._statevector
             data['classical_state'] = self._classical_state
         end = time.time()
-        return {'name': circuit['name'],
-                'seed': self._seed,
+        return {'name': circuit.header.name,
+                'seed': seed,
                 'shots': self._shots,
                 'data': data,
                 'status': 'DONE',
diff --git a/qiskit/backends/local/unitary_simulator_py.py b/qiskit/backends/local/unitary_simulator_py.py
--- a/qiskit/backends/local/unitary_simulator_py.py
+++ b/qiskit/backends/local/unitary_simulator_py.py
@@ -88,7 +88,6 @@
 from qiskit._result import Result
 from qiskit.backends import BaseBackend
 from qiskit.backends.local.localjob import LocalJob
-from qiskit.qobj import qobj_to_dict
 from ._simulatortools import enlarge_single_opt, enlarge_two_opt, single_gate_matrix
 
 logger = logging.getLogger(__name__)
@@ -128,8 +127,8 @@ def _add_unitary_single(self, gate, qubit):
             is q_{n-1} ... otimes q_1 otimes q_0.
         number_of_qubits is the number of qubits in the system.
         """
-        unitaty_add = enlarge_single_opt(gate, qubit, self._number_of_qubits)
-        self._unitary_state = np.dot(unitaty_add, self._unitary_state)
+        unitary_add = enlarge_single_opt(gate, qubit, self._number_of_qubits)
+        self._unitary_state = np.dot(unitary_add, self._unitary_state)
 
     def _add_unitary_two(self, gate, q_0, q_1):
         """Apply the two-qubit gate.
@@ -162,46 +161,49 @@ def _run_job(self, qobj):
             Result: Result object
         """
         result_list = []
-        qobj_converted = qobj_to_dict(qobj, version='0.0.1')
-        for circuit in qobj_converted['circuits']:
+        for circuit in qobj.experiments:
             result_list.append(self.run_circuit(circuit))
         job_id = str(uuid.uuid4())
         return Result(
             {'job_id': job_id, 'result': result_list, 'status': 'COMPLETED'})
 
     def run_circuit(self, circuit):
-        """Apply the single-qubit gate."""
-        ccircuit = circuit['compiled_circuit']
-        self._number_of_qubits = ccircuit['header']['number_of_qubits']
-        result = {}
-        result['data'] = {}
-        result['name'] = circuit.get('name')
-        self._unitary_state = np.identity(2**(self._number_of_qubits),
+        """Apply the single-qubit gate.
+
+        Args:
+            circuit (QobjExperiment): experiment from qobj experiments list
+
+        Returns:
+            dict: A dictionary of results.
+        """
+        self._number_of_qubits = circuit.header.number_of_qubits
+        result = {
+            'data': {},
+            'name': circuit.header.name
+        }
+        self._unitary_state = np.identity(2 ** self._number_of_qubits,
                                           dtype=complex)
-        for operation in ccircuit['operations']:
-            if operation['name'] in ['U', 'u1', 'u2', 'u3']:
-                if 'params' in operation:
-                    params = operation['params']
-                else:
-                    params = None
-                qubit = operation['qubits'][0]
-                gate = single_gate_matrix(operation['name'], params)
+        for operation in circuit.instructions:
+            if operation.name in ('U', 'u1', 'u2', 'u3'):
+                params = getattr(operation, 'params', None)
+                qubit = operation.qubits[0]
+                gate = single_gate_matrix(operation.name, params)
                 self._add_unitary_single(gate, qubit)
-            elif operation['name'] in ['id', 'u0']:
+            elif operation.name in ('id', 'u0'):
                 pass
-            elif operation['name'] in ['CX', 'cx']:
-                qubit0 = operation['qubits'][0]
-                qubit1 = operation['qubits'][1]
+            elif operation.name in ('CX', 'cx'):
+                qubit0 = operation.qubits[0]
+                qubit1 = operation.qubits[1]
                 gate = np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0],
                                  [0, 1, 0, 0]])
                 self._add_unitary_two(gate, qubit0, qubit1)
-            elif operation['name'] == 'measure':
+            elif operation.name == 'measure':
                 logger.info('Warning have dropped measure from unitary '
                             'simulator')
-            elif operation['name'] == 'reset':
+            elif operation.name == 'reset':
                 logger.info('Warning have dropped reset from unitary '
                             'simulator')
-            elif operation['name'] == 'barrier':
+            elif operation.name == 'barrier':
                 pass
             else:
                 result['status'] = 'ERROR'
diff --git a/qiskit/qobj/__init__.py b/qiskit/qobj/__init__.py
--- a/qiskit/qobj/__init__.py
+++ b/qiskit/qobj/__init__.py
@@ -7,5 +7,6 @@
 
 """Module for the Qobj structure."""
 
-from ._qobj import (Qobj, QobjConfig, QobjExperiment, QobjInstruction, QobjItem)
+from ._qobj import (Qobj, QobjConfig, QobjExperiment, QobjInstruction,
+                    QobjItem, QobjHeader)
 from ._converter import qobj_to_dict


Test patch:
diff --git a/test/python/test_qasm_simulator_py.py b/test/python/test_qasm_simulator_py.py
--- a/test/python/test_qasm_simulator_py.py
+++ b/test/python/test_qasm_simulator_py.py
@@ -16,9 +16,10 @@
 
 from matplotlib.backends.backend_pdf import PdfPages
 import numpy as np
-from qiskit import qasm, unroll, QuantumProgram
+from qiskit import (qasm, unroll, transpiler,
+                    ClassicalRegister, QuantumRegister, QuantumCircuit)
 from qiskit.backends.local.qasm_simulator_py import QasmSimulatorPy
-from qiskit.qobj import Qobj, QobjItem
+from qiskit.qobj import Qobj, QobjHeader, QobjItem, QobjConfig, QobjExperiment
 
 from ._random_qasm_generator import RandomQasmGenerator
 from .common import QiskitTestCase
@@ -42,30 +43,25 @@ def tearDownClass(cls):
             cls.pdf.close()
 
     def setUp(self):
+        self.qp = None
         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'
+        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,
+                                           register_slots=6,
+                                           max_credits=3),
+                         experiments=[circuit],
+                         header=QobjHeader(
+                             backend_name='local_qasm_simulator_py'))
 
     def test_qasm_simulator_single_shot(self):
         """Test single shot run."""
@@ -90,10 +86,9 @@ def test_if_statement(self):
         self.log.info('test_if_statement_x')
         shots = 100
         max_qubits = 3
-        qp = QuantumProgram()
-        qr = qp.create_quantum_register('qr', max_qubits)
-        cr = qp.create_classical_register('cr', max_qubits)
-        circuit_if_true = qp.create_circuit('test_if_true', [qr], [cr])
+        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])
@@ -102,7 +97,7 @@ def test_if_statement(self):
         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 = qp.create_circuit('test_if_false', [qr], [cr])
+        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])
@@ -112,38 +107,32 @@ def test_if_statement(self):
         circuit_if_false.measure(qr[2], cr[2])
         basis_gates = []  # unroll to base gates
         unroller = unroll.Unroller(
-            qasm.Qasm(data=qp.get_qasm('test_if_true')).parse(),
+            qasm.Qasm(data=circuit_if_true.qasm()).parse(),
             unroll.JsonBackend(basis_gates))
-        ucircuit_true = unroller.execute()
+        ucircuit_true = QobjExperiment.from_dict(unroller.execute())
         unroller = unroll.Unroller(
-            qasm.Qasm(data=qp.get_qasm('test_if_false')).parse(),
+            qasm.Qasm(data=circuit_if_false.qasm()).parse(),
             unroll.JsonBackend(basis_gates))
-        ucircuit_false = unroller.execute()
+        ucircuit_false = QobjExperiment.from_dict(unroller.execute())
 
-        qobj = {
-            'id': 'test_if_qobj',
-            'config': {
-                'max_credits': 3,
-                'shots': shots,
-            },
-            'experiments': [ucircuit_true, ucircuit_false],
-            'header': {'backend_name': 'local_qasm_simulator_py'}
-        }
-        qobj['experiments'][0]['header']['name'] = 'test_if_true'
-        qobj['experiments'][0]['config'] = {
-            'coupling_map': None,
-            'basis_gates': 'u1,u2,u3,cx,id',
-            'layout': None,
-            'seed': None
-        }
-        qobj['experiments'][1]['header']['name'] = 'test_if_false'
-        qobj['experiments'][1]['config'] = {
-            'coupling_map': None,
-            'basis_gates': 'u1,u2,u3,cx,id',
-            'layout': None,
-            'seed': None
-        }
-        qobj = Qobj.from_dict(qobj)
+        # 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,
+                                      register_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')
@@ -163,17 +152,14 @@ def test_if_statement(self):
                      "we have to disable this test until fixed")
     def test_teleport(self):
         """test teleportation as in tutorials"""
-
         self.log.info('test_teleport')
         pi = np.pi
         shots = 1000
-        qp = QuantumProgram()
-        qr = qp.create_quantum_register('qr', 3)
-        cr0 = qp.create_classical_register('cr0', 1)
-        cr1 = qp.create_classical_register('cr1', 1)
-        cr2 = qp.create_classical_register('cr2', 1)
-        circuit = qp.create_circuit('teleport', [qr],
-                                    [cr0, cr1, cr2])
+        qr = QuantumRegister(3, 'qr')
+        cr0 = ClassicalRegister(1, 'cr0')
+        cr1 = ClassicalRegister(1, 'cr1')
+        cr2 = ClassicalRegister(1, 'cr2')
+        circuit = QuantumCircuit(qr, cr0, cr1, cr2, name='teleport')
         circuit.h(qr[1])
         circuit.cx(qr[1], qr[2])
         circuit.ry(pi/4, qr[0])
@@ -185,20 +171,23 @@ def test_teleport(self):
         circuit.z(qr[2]).c_if(cr0, 1)
         circuit.x(qr[2]).c_if(cr1, 1)
         circuit.measure(qr[2], cr2[0])
-        backend = 'local_qasm_simulator_py'
-        qobj = qp.compile('teleport', backend=backend, shots=shots,
-                          seed=self.seed)
-        results = qp.run(qobj)
+        backend = QasmSimulatorPy()
+        qobj = transpiler.compile(circuit, backend=backend, shots=shots,
+                                  seed=self.seed)
+        results = backend.run(qobj).result()
         data = results.get_counts('teleport')
-        alice = {}
-        bob = {}
-        alice['00'] = data['0 0 0'] + data['1 0 0']
-        alice['01'] = data['0 1 0'] + data['1 1 0']
-        alice['10'] = data['0 0 1'] + data['1 0 1']
-        alice['11'] = data['0 1 1'] + data['1 1 1']
-        bob['0'] = data['0 0 0'] + data['0 1 0'] + data['0 0 1'] + data['0 1 1']
-        bob['1'] = data['1 0 0'] + data['1 1 0'] + data['1 0 1'] + data['1 1 1']
-        self.log.info('test_telport: circuit:')
+        alice = {
+            '00': data['0 0 0'] + data['1 0 0'],
+            '01': data['0 1 0'] + data['1 1 0'],
+            '10': data['0 0 1'] + data['1 0 1'],
+            '11': data['0 1 1'] + data['1 1 1']
+        }
+        bob = {
+            '0': data['0 0 0'] + data['0 1 0'] + data['0 0 1'] + data['0 1 1'],
+            '1': data['1 0 0'] + data['1 1 0'] + data['1 0 1'] + data['1 1 1']
+        }
+        self.log.info('test_teleport: circuit:')
+        self.log.info('test_teleport: circuit:')
         self.log.info(circuit.qasm())
         self.log.info('test_teleport: data %s', data)
         self.log.info('test_teleport: alice %s', alice)
diff --git a/test/python/test_unitary_simulator_py.py b/test/python/test_unitary_simulator_py.py
--- a/test/python/test_unitary_simulator_py.py
+++ b/test/python/test_unitary_simulator_py.py
@@ -14,10 +14,10 @@
 import unittest
 import numpy as np
 
-from qiskit import (qasm, unroll, QuantumProgram, QuantumCircuit,
+from qiskit import (qasm, unroll, QuantumCircuit,
                     QuantumRegister, ClassicalRegister, compile)
 from qiskit.backends.local.unitary_simulator_py import UnitarySimulatorPy
-from qiskit.qobj import Qobj, QobjItem
+from qiskit.qobj import Qobj, QobjItem, QobjExperiment, QobjConfig, QobjHeader
 from ._random_qasm_generator import RandomQasmGenerator
 from .common import QiskitTestCase
 
@@ -28,41 +28,30 @@ class LocalUnitarySimulatorTest(QiskitTestCase):
     def setUp(self):
         self.seed = 88
         self.qasm_filename = self._get_resource_path('qasm/example.qasm')
-        self.qp = QuantumProgram()
-
-    def tearDown(self):
-        pass
 
     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))
+            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']
-        # 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)
-
+        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)]
@@ -121,10 +110,10 @@ def profile_unitary_simulator(self):
                                               max_depth=max_depth,
                                               max_qubits=max_qubits)
         random_circuits.add_circuits(n_circuits, do_measure=False)
-        self.qp = random_circuits.get_program()
+        qp = random_circuits.get_program()
         pr.enable()
-        self.qp.execute(self.qp.get_circuit_names(),
-                        backend=UnitarySimulatorPy())
+        qp.execute(qp.get_circuit_names(),
+                   backend=UnitarySimulatorPy())
         pr.disable()
         sout = io.StringIO()
         ps = pstats.Stats(pr, stream=sout).sort_stats('cumulative')