Repository: Qiskit/qiskit

Issue:
Transpilation fails with snapshot instruction
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **Qiskit Terra version**: master
- **Python version**: 3.8.5
- **Operating system**: Linux

### What is the current behavior?

Transpiling a simple circuit, which contains a snapshot, with basis gates `['u', 'cx']`, raises an error. The same happens with more sets of basis gates: `['r', 'cz'], ['rz', 'rx', 'cz'], ['p', 'sx', 'cx']`. However transpiling the same circuit with basis gates `['u3', 'cx']` is OK.

Note: this is working well with the stable version, the bug appears only in the master version.

### Steps to reproduce the problem

```
from qiskit import QuantumCircuit, transpile
from qiskit.providers.aer import QasmSimulator
from qiskit.providers.aer.extensions import snapshot_statevector

backend = QasmSimulator()

circ = QuantumCircuit(1)
circ.z(0)
circ.snapshot_statevector('final')

transpile(circ, backend, basis_gates=['u3', 'cx'])
print("Transpilation with ['u3', 'cx'] is fine")

transpile(circ, backend, basis_gates=['u', 'cx'])
print("Transpilation with ['u', 'cx'] is fine")
```

results with
```
(YaelEnv) yaelbh@iris-quantum2:~/work/not_qiskit$ python snapshot_invalid.py 
/home/yaelbh/work/terra/System/qiskit/__init__.py:69: RuntimeWarning: Could not import the IBMQ provider from the qiskit-ibmq-provider package. Install qiskit-ibmq-provider or check your installation.
  warnings.warn('Could not import the IBMQ provider from the '
/opt/anaconda3/envs/YaelEnv/lib/python3.8/site-packages/qiskit/aqua/operators/operator_globals.py:48: DeprecationWarning: `from_label` is deprecated and will be removed no earlier than 3 months after the release date. Use Pauli(label) instead.
  X = make_immutable(PrimitiveOp(Pauli.from_label('X')))
Transpilation with ['u3', 'cx'] is fine
Traceback (most recent call last):
  File "snapshot_invalid.py", line 14, in <module>
    transpile(circ, backend, basis_gates=['u', 'cx'])
  File "/home/yaelbh/work/terra/System/qiskit/compiler/transpile.py", line 241, in transpile
    circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_args)))
  File "/home/yaelbh/work/terra/System/qiskit/tools/parallel.py", line 112, in parallel_map
    return [task(values[0], *task_args, **task_kwargs)]
  File "/home/yaelbh/work/terra/System/qiskit/compiler/transpile.py", line 324, in _transpile_circuit
    result = pass_manager.run(circuit, callback=transpile_config['callback'],
  File "/home/yaelbh/work/terra/System/qiskit/transpiler/passmanager.py", line 225, in run
    return self._run_single_circuit(circuits, output_name, callback)
  File "/home/yaelbh/work/terra/System/qiskit/transpiler/passmanager.py", line 288, in _run_single_circuit
    result = running_passmanager.run(circuit, output_name=output_name, callback=callback)
  File "/home/yaelbh/work/terra/System/qiskit/transpiler/runningpassmanager.py", line 113, in run
    dag = self._do_pass(pass_, dag, passset.options)
  File "/home/yaelbh/work/terra/System/qiskit/transpiler/runningpassmanager.py", line 144, in _do_pass
    dag = self._run_this_pass(pass_, dag)
  File "/home/yaelbh/work/terra/System/qiskit/transpiler/runningpassmanager.py", line 156, in _run_this_pass
    new_dag = pass_.run(dag)
  File "/home/yaelbh/work/terra/System/qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py", line 87, in run
    operator = Operator(qc)
  File "/home/yaelbh/work/terra/System/qiskit/quantum_info/operators/operator.py", line 85, in __init__
    self._data = self._init_instruction(data).data
  File "/home/yaelbh/work/terra/System/qiskit/quantum_info/operators/operator.py", line 496, in _init_instruction
    op._append_instruction(instruction)
  File "/home/yaelbh/work/terra/System/qiskit/quantum_info/operators/operator.py", line 554, in _append_instruction
    self._append_instruction(instr, qargs=new_qargs)
  File "/home/yaelbh/work/terra/System/qiskit/quantum_info/operators/operator.py", line 532, in _append_instruction
    raise QiskitError('Cannot apply Instruction: {}'.format(obj.name))
qiskit.exceptions.QiskitError: 'Cannot apply Instruction: snapshot'
```


Discussion:
Oddly enough, I was just working on this as part of #5554. This is caused by `Optimize1qGatesDecomposition.run()` calling `Operator(qc)`. Operator will fail for 'snapshot', 'delay', and 'reset'. The reason it works with 'u3' in the basis is that if the basis has 'u1', 'u2', or 'u3', the optimizer calls `Optimize1qGates.run()` instead, which does not call `Operator()`.

It should run ok with `optimization_level=0` for transpile.

Resolving patch:
diff --git a/qiskit/dagcircuit/dagcircuit.py b/qiskit/dagcircuit/dagcircuit.py
--- a/qiskit/dagcircuit/dagcircuit.py
+++ b/qiskit/dagcircuit/dagcircuit.py
@@ -1384,6 +1384,8 @@ def filter_fn(node):
             return node.type == 'op' and len(node.qargs) == 1 \
                 and len(node.cargs) == 0 and node.condition is None \
                 and not node.op.is_parameterized() \
+                and isinstance(node.op, Gate) \
+                and hasattr(node.op, '__array__')
 
         group_list = rx.collect_runs(self._multi_graph, filter_fn)
         return set(tuple(x) for x in group_list)


Test patch:
diff --git a/test/python/dagcircuit/test_dagcircuit.py b/test/python/dagcircuit/test_dagcircuit.py
--- a/test/python/dagcircuit/test_dagcircuit.py
+++ b/test/python/dagcircuit/test_dagcircuit.py
@@ -24,6 +24,7 @@
 from qiskit.circuit import QuantumCircuit
 from qiskit.circuit import Measure
 from qiskit.circuit import Reset
+from qiskit.circuit import Delay
 from qiskit.circuit import Gate, Instruction
 from qiskit.circuit import Parameter
 from qiskit.circuit.library.standard_gates.i import IGate
@@ -712,6 +713,8 @@ def test_dag_collect_runs_conditional_in_middle(self):
 
     def test_dag_collect_1q_runs(self):
         """Test the collect_1q_runs method with 3 different gates."""
+        self.dag.apply_operation_back(Reset(), [self.qubit0])
+        self.dag.apply_operation_back(Delay(100), [self.qubit0])
         self.dag.apply_operation_back(U1Gate(3.14), [self.qubit0])
         self.dag.apply_operation_back(U1Gate(3.14), [self.qubit0])
         self.dag.apply_operation_back(U1Gate(3.14), [self.qubit0])
@@ -736,6 +739,8 @@ def test_dag_collect_1q_runs(self):
 
     def test_dag_collect_1q_runs_start_with_conditional(self):
         """Test collect 1q runs with a conditional at the start of the run."""
+        self.dag.apply_operation_back(Reset(), [self.qubit0])
+        self.dag.apply_operation_back(Delay(100), [self.qubit0])
         h_gate = HGate()
         h_gate.condition = self.condition
         self.dag.apply_operation_back(
@@ -752,6 +757,8 @@ def test_dag_collect_1q_runs_start_with_conditional(self):
 
     def test_dag_collect_1q_runs_conditional_in_middle(self):
         """Test collect_1q_runs with a conditional in the middle of a run."""
+        self.dag.apply_operation_back(Reset(), [self.qubit0])
+        self.dag.apply_operation_back(Delay(100), [self.qubit0])
         h_gate = HGate()
         h_gate.condition = self.condition
         self.dag.apply_operation_back(HGate(), [self.qubit0])
@@ -769,6 +776,8 @@ def test_dag_collect_1q_runs_conditional_in_middle(self):
     def test_dag_collect_1q_runs_with_parameterized_gate(self):
         """Test collect 1q splits on parameterized gates."""
         theta = Parameter('theta')
+        self.dag.apply_operation_back(Reset(), [self.qubit0])
+        self.dag.apply_operation_back(Delay(100), [self.qubit0])
         self.dag.apply_operation_back(HGate(), [self.qubit0])
         self.dag.apply_operation_back(HGate(), [self.qubit0])
         self.dag.apply_operation_back(U1Gate(theta), [self.qubit0])
@@ -783,6 +792,8 @@ def test_dag_collect_1q_runs_with_parameterized_gate(self):
 
     def test_dag_collect_1q_runs_with_cx_in_middle(self):
         """Test collect_1q_runs_with a cx in the middle of the run."""
+        self.dag.apply_operation_back(Reset(), [self.qubit0])
+        self.dag.apply_operation_back(Delay(100), [self.qubit0])
         self.dag.apply_operation_back(HGate(), [self.qubit0])
         self.dag.apply_operation_back(HGate(), [self.qubit0])
         self.dag.apply_operation_back(U1Gate(3.14), [self.qubit0])