Repository: Qiskit/qiskit

Issue:
internal error from optimize_1q_gates from conditional cy gate
```
>>> qc = qk.QuantumCircuit(2,2)
>>> qc.cy(0,1).c_if(qc.cregs[0], 0)
<qiskit.circuit.instructionset.InstructionSet object at 0x12c540160>
>>> qk.transpile(qc, backend=FakeTenerife())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/kevin.krsulichibm.com/q/qiskit-terra/qiskit/compiler/transpile.py", line 147, in transpile
    circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_configs)))
  File "/Users/kevin.krsulichibm.com/q/qiskit-terra/qiskit/tools/parallel.py", line 100, in parallel_map
    return [task(values[0], *task_args, **task_kwargs)]
  File "/Users/kevin.krsulichibm.com/q/qiskit-terra/qiskit/compiler/transpile.py", line 168, in _transpile_circuit
    return transpile_circuit(circuit, transpile_config)
  File "/Users/kevin.krsulichibm.com/q/qiskit-terra/qiskit/transpiler/transpile_circuit.py", line 62, in transpile_circuit
    return pass_manager.run(circuit)
  File "/Users/kevin.krsulichibm.com/q/qiskit-terra/qiskit/transpiler/passmanager.py", line 147, in run
    dag = self._do_pass(pass_, dag, passset.options)
  File "/Users/kevin.krsulichibm.com/q/qiskit-terra/qiskit/transpiler/passmanager.py", line 180, in _do_pass
    new_dag = pass_.run(dag)
  File "/Users/kevin.krsulichibm.com/q/qiskit-terra/qiskit/transpiler/passes/optimize_1q_gates.py", line 53, in run
    raise TranspilerError("internal error")
qiskit.transpiler.exceptions.TranspilerError: 'internal error'
```


Discussion:
It looks like this is potentially caused by an issue in `dagcircuit.collect_runs()` It's supposed to return a list of non-conditional runs of op nodes with the given names. But in the cy().c_if() example above a conditional is being returned which is triggering the if for a condition here: https://github.com/Qiskit/qiskit-terra/blob/master/qiskit/transpiler/passes/optimize_1q_gates.py#L50

Resolving patch:
diff --git a/qiskit/dagcircuit/dagcircuit.py b/qiskit/dagcircuit/dagcircuit.py
--- a/qiskit/dagcircuit/dagcircuit.py
+++ b/qiskit/dagcircuit/dagcircuit.py
@@ -1142,7 +1142,8 @@ def collect_runs(self, namelist):
                 s = list(self._multi_graph.successors(node))
                 while len(s) == 1 and \
                         s[0].type == "op" and \
-                        s[0].name in namelist:
+                        s[0].name in namelist and \
+                        s[0].condition is None:
                     group.append(s[0])
                     nodes_seen[s[0]] = True
                     s = list(self._multi_graph.successors(s[0]))


Test patch:
diff --git a/test/python/test_dagcircuit.py b/test/python/test_dagcircuit.py
--- a/test/python/test_dagcircuit.py
+++ b/test/python/test_dagcircuit.py
@@ -27,6 +27,7 @@
 from qiskit.extensions.standard.h import HGate
 from qiskit.extensions.standard.cx import CnotGate
 from qiskit.extensions.standard.x import XGate
+from qiskit.extensions.standard.u1 import U1Gate
 from qiskit.extensions.standard.barrier import Barrier
 from qiskit.dagcircuit.exceptions import DAGCircuitError
 from qiskit.converters import circuit_to_dag
@@ -351,6 +352,64 @@ def test_remove_non_op_node(self):
         in_node = next(self.dag.topological_nodes())
         self.assertRaises(DAGCircuitError, self.dag.remove_op_node, in_node)
 
+    def test_dag_collect_runs(self):
+        """Test the collect_runs method with 3 different gates."""
+        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])
+        self.dag.apply_operation_back(CnotGate(), [self.qubit2, self.qubit1])
+        self.dag.apply_operation_back(CnotGate(), [self.qubit1, self.qubit2])
+        self.dag.apply_operation_back(HGate(), [self.qubit2])
+        collected_runs = self.dag.collect_runs(['u1', 'cx', 'h'])
+        self.assertEqual(len(collected_runs), 3)
+        for run in collected_runs:
+            if run[0].name == 'cx':
+                self.assertEqual(len(run), 2)
+                self.assertEqual(['cx'] * 2, [x.name for x in run])
+                self.assertEqual(
+                    [[self.qubit2, self.qubit1], [self.qubit1, self.qubit2]],
+                    [x.qargs for x in run])
+            elif run[0].name == 'h':
+                self.assertEqual(len(run), 1)
+                self.assertEqual(['h'], [x.name for x in run])
+                self.assertEqual([[self.qubit2]], [x.qargs for x in run])
+            elif run[0].name == 'u1':
+                self.assertEqual(len(run), 3)
+                self.assertEqual(['u1'] * 3, [x.name for x in run])
+                self.assertEqual(
+                    [[self.qubit0], [self.qubit0], [self.qubit0]],
+                    [x.qargs for x in run])
+            else:
+                self.fail('Unknown run encountered')
+
+    def test_dag_collect_runs_start_with_conditional(self):
+        """Test collect runs with a conditional at the start of the run."""
+        self.dag.apply_operation_back(
+            HGate(), [self.qubit0], condition=self.condition)
+        self.dag.apply_operation_back(HGate(), [self.qubit0])
+        self.dag.apply_operation_back(HGate(), [self.qubit0])
+        collected_runs = self.dag.collect_runs(['h'])
+        self.assertEqual(len(collected_runs), 1)
+        run = collected_runs.pop()
+        self.assertEqual(len(run), 2)
+        self.assertEqual(['h', 'h'], [x.name for x in run])
+        self.assertEqual([[self.qubit0], [self.qubit0]],
+                         [x.qargs for x in run])
+
+    def test_dag_collect_runs_conditional_in_middle(self):
+        """Test collect_runs with a conditional in the middle of a run."""
+        self.dag.apply_operation_back(HGate(), [self.qubit0])
+        self.dag.apply_operation_back(
+            HGate(), [self.qubit0], condition=self.condition)
+        self.dag.apply_operation_back(HGate(), [self.qubit0])
+        collected_runs = self.dag.collect_runs(['h'])
+        # Should return 2 single h gate runs (1 before condtion, 1 after)
+        self.assertEqual(len(collected_runs), 2)
+        for run in collected_runs:
+            self.assertEqual(len(run), 1)
+            self.assertEqual(['h'], [x.name for x in run])
+            self.assertEqual([[self.qubit0]], [x.qargs for x in run])
+
 
 class TestDagLayers(QiskitTestCase):
     """Test finding layers on the dag"""