Repository: Qiskit/qiskit

Issue:
Deprecate Qobj in unitary_simulator.py
> I also just realized that `qiskit.providers.basicaer.UnitarySimulatorPy.run()` (https://github.com/Qiskit/qiskit/blob/main/qiskit/providers/basicaer/unitary_simulator.py#L206) never deprecated a Qobj input and will still support it while the qasm simulator and statevector simulator will not. I still think we should move forward with your PR, but it's something we'll want to clean up in a subsequent PR.

_Originally posted by @mtreinish in https://github.com/Qiskit/qiskit/pull/10872#pullrequestreview-1685997898_
            


Discussion:
Hi, I'd like to work on this. the description isn't very clear, though, could you help me with what needs to be done? Should I just deprecate Qobj input or remove this functionality?
When a `QasmQobj` is supplied to `QasmSimulatorPy.run` or `StatevectorSimulatorPy.run`, the error raised is:
```python
QiskitError: 'bad input to assemble() function; must be either circuits or schedules'
```

And when a  `QasmQobj` is supplied to `QasmSimulatorPy.run`, it complains that there's no `n_qubits` property for `QasmQobj` rather than clearly stating that only circuits are supported. (as the `assemble` call is tucked under a conditional)

Since a `Qobj` input cannot be used anyway, I think it's better to **remove** `Qobj` support directly rather than deprecate it and remove it in a later release. What do you think @1ucian0 @mtreinish?

Based on the conversation [here](https://qiskit.slack.com/archives/C024ELK40TW/p1701877287222499) with @1ucian0 I'll start with a deprecation PR to `stable\0.46` and once that's done, I'll do a removal PR to `main`. 

Resolving patch:
diff --git a/qiskit/providers/basicaer/unitary_simulator.py b/qiskit/providers/basicaer/unitary_simulator.py
--- a/qiskit/providers/basicaer/unitary_simulator.py
+++ b/qiskit/providers/basicaer/unitary_simulator.py
@@ -17,11 +17,11 @@
 
 .. code-block:: python
 
-    UnitarySimulator().run(qobj)
+    UnitarySimulator().run(run_input)
 
-Where the input is a Qobj object and the output is a BasicAerJob object, which can
-later be queried for the Result object. The result will contain a 'unitary'
-data field, which is a 2**n x 2**n complex numpy array representing the
+Where the input is a either Qobj object (deprecated) or QuantumCircuit or a list of circuits and 
+the output is a BasicAerJob object, which can later be queried for the Result object. The result 
+will contain a 'unitary' data field, which is a 2**n x 2**n complex numpy array representing the
 circuit's unitary matrix.
 """
 import logging
@@ -32,7 +32,6 @@
 
 import numpy as np
 
-from qiskit.circuit.quantumcircuit import QuantumCircuit
 from qiskit.utils.multiprocessing import local_hardware_info
 from qiskit.providers.models import QasmBackendConfiguration
 from qiskit.providers.backend import BackendV1
@@ -203,11 +202,11 @@ def _get_unitary(self):
         unitary[abs(unitary) < self._chop_threshold] = 0.0
         return unitary
 
-    def run(self, qobj, **backend_options):
-        """Run qobj asynchronously.
+    def run(self, run_input, **backend_options):
+        """Run experiments in run_input asynchronously.
 
         Args:
-            qobj (Qobj): payload of the experiment
+            run_input (Qobj, QuantumCircuit, list): payload of the experiment
             backend_options (dict): backend options
 
         Returns:
@@ -222,7 +221,7 @@ def run(self, qobj, **backend_options):
             The "initial_unitary" option specifies a custom initial unitary
             matrix for the simulator to be used instead of the identity
             matrix. This size of this matrix must be correct for the number
-            of qubits inall experiments in the qobj.
+            of qubits in all experiments in the run_input.
 
             The "chop_threshold" option specifies a truncation value for
             setting small values to zero in the output unitary. The default
@@ -238,21 +237,19 @@ def run(self, qobj, **backend_options):
                     "chop_threshold": 1e-15
                 }
         """
-        if isinstance(qobj, (QuantumCircuit, list)):
-            from qiskit.compiler import assemble
-
-            out_options = {}
-            for key in backend_options:
-                if not hasattr(self.options, key):
-                    warnings.warn(
-                        "Option %s is not used by this backend" % key, UserWarning, stacklevel=2
-                    )
-                else:
-                    out_options[key] = backend_options[key]
-            qobj = assemble(qobj, self, **out_options)
-            qobj_options = qobj.config
-        else:
-            qobj_options = None
+        from qiskit.compiler import assemble
+
+        out_options = {}
+        for key in backend_options:
+            if not hasattr(self.options, key):
+                warnings.warn(
+                    "Option %s is not used by this backend" % key, UserWarning, stacklevel=2
+                )
+            else:
+                out_options[key] = backend_options[key]
+        qobj = assemble(run_input, self, **out_options)
+        qobj_options = qobj.config
+
         self._set_options(qobj_config=qobj_options, backend_options=backend_options)
         job_id = str(uuid.uuid4())
         job = BasicAerJob(self, job_id, self._run_job(job_id, qobj))


Test patch: