Repository: Qiskit/qiskit

Issue:
Circuit_to_instruction converter missing classical register for conditional gates
<!-- ⚠️ 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@c59caac
- **Python version**: 3.7
- **Operating system**: Linux

### What is the current behavior?

From https://travis-ci.com/github/Qiskit/qiskit-terra/jobs/358424742#L3190 , in some cases, the transpiler is generating conditional gates without the clbits on which they are conditioned. This was noticed in (but not necessarily caused by) code added in #4622 ( https://github.com/Qiskit/qiskit-terra/pull/4622/files#diff-dd64919667465e6a3c40b2a4ed00f8e5R117 ) when building instructions from circuits with conditional gates. 

### Steps to reproduce the problem

Transpile the QASM from the below stack trace at `optimization_level=3` targeting `FakeJohannesburg`.

```
======================================================================
ERROR: runTest (hypothesis.stateful.QCircuitMachine.TestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/travis/build/Qiskit/qiskit-terra/test/randomized/test_transpiler_equivalence.py", line 230, in equivalent_transpile
    xpiled_qc = transpile(self.qc, backend=backend, optimization_level=opt_level)
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/compiler/transpile.py", line 214, in transpile
    circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_args)))
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/tools/parallel.py", line 106, in parallel_map
    return [task(values[0], *task_args, **task_kwargs)]
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/compiler/transpile.py", line 312, in _transpile_circuit
    output_name=transpile_config['output_name'])
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/transpiler/passmanager.py", line 214, in run
    return self._run_single_circuit(circuits, output_name, callback)
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/transpiler/passmanager.py", line 277, in _run_single_circuit
    result = running_passmanager.run(circuit, output_name=output_name, callback=callback)
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/transpiler/runningpassmanager.py", line 115, in run
    dag = self._do_pass(pass_, dag, passset.options)
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/transpiler/runningpassmanager.py", line 145, in _do_pass
    dag = self._run_this_pass(pass_, dag)
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/transpiler/runningpassmanager.py", line 157, in _run_this_pass
    new_dag = pass_.run(dag)
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/transpiler/passes/optimization/consolidate_blocks.py", line 128, in run
    unitary = UnitaryGate(Operator(subcirc))  # simulates the circuit
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/quantum_info/operators/operator.py", line 86, in __init__
    self._data = self._init_instruction(data).data
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/quantum_info/operators/operator.py", line 490, in _init_instruction
    instruction = instruction.to_instruction()
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/circuit/quantumcircuit.py", line 819, in to_instruction
    return circuit_to_instruction(self, parameter_map)
  File "/home/travis/build/Qiskit/qiskit-terra/qiskit/converters/circuit_to_instruction.py", line 119, in circuit_to_instruction
    if reg.size == c.size:
UnboundLocalError: local variable 'c' referenced before assignment

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/hypothesis/stateful.py", line 393, in runTest
    run_state_machine_as_test(state_machine_class)
  File "/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/hypothesis/stateful.py", line 75, in run_state_machine_as_test
    def run_state_machine_as_test(state_machine_factory, *, settings=None):
  File "/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/hypothesis/internal/reflection.py", line 652, in accept
    return func(*bound.args, **bound.kwargs)
  File "/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/hypothesis/stateful.py", line 200, in run_state_machine_as_test
    run_state_machine(state_machine_factory)
  File "/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/hypothesis/stateful.py", line 92, in run_state_machine
    @given(st.data())
  File "/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/hypothesis/core.py", line 1141, in wrapped_test
    raise the_error_hypothesis_found
  File "/home/travis/build/Qiskit/qiskit-terra/test/randomized/test_transpiler_equivalence.py", line 234, in equivalent_transpile
    raise RuntimeError(failed_qasm) from e
RuntimeError: Exception caught during transpilation of circuit: 
OPENQASM 2.0;
include "qelib1.inc";
qreg q3110[12];
qreg q3157[2];
creg c95[5];
creg c96[2];
creg c97[5];
creg c98[5];
u2(-24.508971,1.5216458) q3110[6];
cz q3110[8],q3110[7];
u2(-17.363907,-22.934491) q3110[9];
rz(-8.7083803) q3110[4];
reset q3110[7];
cy q3110[10],q3110[3];
measure q3110[4] -> c95[0];
cz q3110[3],q3110[11];
h q3110[0];
u2(-9.6786822,2.9792195) q3110[1];
cu3(-12.105011,-7.0180632,-18.792019) q3110[5],q3110[0];
u3(28.464436,-11.005153,-3.6969371) q3110[9];
cu3(23.569199,4.5776732,-2.6956357) q3110[9],q3110[0];
rz(-11.654972) q3110[8];
u3(16.36128,25.832861,28.922542) q3110[1];
cswap q3110[9],q3110[4],q3110[3];
measure q3110[4] -> c96[0];
ch q3110[6],q3110[7];
x q3110[4];
barrier q3110[7];
ccx q3110[1],q3110[9],q3110[10];
cu3(21.612624,-18.30063,1.3315713) q3110[1],q3110[7];
cy q3110[7],q3110[10];
cy q3110[11],q3110[10];
measure q3110[6] -> c97[4];
swap q3157[0],q3110[6];
rzz(22.30788) q3110[11],q3110[6];
if(c97==13) cu3(-13.732855,-10.110604,29.464678) q3110[8],q3157[0];
ccx q3110[10],q3110[9],q3110[7];
if(c97==25) u3(9.6297074,22.387267,26.921443) q3110[2];
if(c97==8) sdg q3110[3];
rx(-7.769637) q3110[3];
ccx q3110[0],q3157[1],q3110[7];
```


### What is the expected behavior?



### Suggested solutions





Discussion:
The minimal code which seems to reproduce the bug is,
```
OPENQASM 2.0;
include "qelib1.inc";
qreg q1[2];
creg c1[1];

if(c1==1) cx q1[0], q1[1];
```
During transpilation the dag seems to become invalid, when running `_check_condition` over nodes, in `consolidate_blocks`. It seems `consolidate_blocks` relies on being able to create and simulate a circuit with a classical condition but no classical register. 

A workaround would be for `circuit_to_instruction` to change,

`if condition:` -> `if condition and instruction.num_clbits > 0:`

although it seems strange for circuit_to_instruction to have to check both conditions.
@kdk @ewinston The following diff seems to take care of the problem and passes all the auto-tests. If this seems like a reasonable approach, let me know and I'll do a PR.
```
--- a/qiskit/transpiler/passes/optimization/consolidate_blocks.py
+++ b/qiskit/transpiler/passes/optimization/consolidate_blocks.py
@@ -16,7 +16,7 @@
 
 """Replace each block of consecutive gates by a single Unitary node."""
 
-from qiskit.circuit import QuantumRegister, QuantumCircuit
+from qiskit.circuit import QuantumRegister, ClassicalRegister, QuantumCircuit
 from qiskit.dagcircuit import DAGCircuit
 from qiskit.quantum_info.operators import Operator
 from qiskit.quantum_info.synthesis import TwoQubitBasisDecomposer
@@ -112,12 +112,19 @@ class ConsolidateBlocks(TransformationPass):
             else:
                 # find the qubits involved in this block
                 block_qargs = set()
+                block_cargs = set()
                 for nd in block:
                     block_qargs |= set(nd.qargs)
+                    if nd.condition:
+                        block_cargs |= set(nd.condition[0])
                 # convert block to a sub-circuit, then simulate unitary and add
-                block_width = len(block_qargs)
-                q = QuantumRegister(block_width)
-                subcirc = QuantumCircuit(q)
+                q = QuantumRegister(len(block_qargs))
+                # if condition in node, add clbits to circuit
+                if len(block_cargs) > 0:
+                    c = ClassicalRegister(len(block_cargs))
+                    subcirc = QuantumCircuit(q, c)
+                else:
+                    subcirc = QuantumCircuit(q)
                 block_index_map = self._block_qargs_to_indices(block_qargs,
                                                                global_index_map)
                 basis_count = 0
```

Resolving patch:
diff --git a/qiskit/transpiler/passes/optimization/consolidate_blocks.py b/qiskit/transpiler/passes/optimization/consolidate_blocks.py
--- a/qiskit/transpiler/passes/optimization/consolidate_blocks.py
+++ b/qiskit/transpiler/passes/optimization/consolidate_blocks.py
@@ -17,7 +17,7 @@
 """Replace each block of consecutive gates by a single Unitary node."""
 
 
-from qiskit.circuit import QuantumRegister, QuantumCircuit
+from qiskit.circuit import QuantumRegister, ClassicalRegister, QuantumCircuit
 from qiskit.dagcircuit import DAGCircuit
 from qiskit.quantum_info.operators import Operator
 from qiskit.quantum_info.synthesis import TwoQubitBasisDecomposer
@@ -122,12 +122,19 @@ def run(self, dag):
             else:
                 # find the qubits involved in this block
                 block_qargs = set()
+                block_cargs = set()
                 for nd in block:
                     block_qargs |= set(nd.qargs)
+                    if nd.condition:
+                        block_cargs |= set(nd.condition[0])
                 # convert block to a sub-circuit, then simulate unitary and add
-                block_width = len(block_qargs)
-                q = QuantumRegister(block_width)
-                subcirc = QuantumCircuit(q)
+                q = QuantumRegister(len(block_qargs))
+                # if condition in node, add clbits to circuit
+                if len(block_cargs) > 0:
+                    c = ClassicalRegister(len(block_cargs))
+                    subcirc = QuantumCircuit(q, c)
+                else:
+                    subcirc = QuantumCircuit(q)
                 block_index_map = self._block_qargs_to_indices(block_qargs,
                                                                global_index_map)
                 basis_count = 0


Test patch:
diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py
--- a/test/python/transpiler/test_preset_passmanagers.py
+++ b/test/python/transpiler/test_preset_passmanagers.py
@@ -21,7 +21,7 @@
 from qiskit.transpiler import CouplingMap
 from qiskit.circuit.library import U2Gate, U3Gate
 from qiskit.test import QiskitTestCase
-from qiskit.test.mock import (FakeTenerife, FakeMelbourne,
+from qiskit.test.mock import (FakeTenerife, FakeMelbourne, FakeJohannesburg,
                               FakeRueschlikon, FakeTokyo, FakePoughkeepsie)
 from qiskit.converters import circuit_to_dag
 
@@ -454,3 +454,19 @@ def test_2(self, level):
         self.assertIsInstance(result, QuantumCircuit)
         resulting_basis = {node.name for node in circuit_to_dag(result).op_nodes()}
         self.assertIn('swap', resulting_basis)
+
+
+@ddt
+class TestOptimizationWithCondition(QiskitTestCase):
+    """Test optimization levels with condition in the circuit"""
+
+    @data(0, 1, 2, 3)
+    def test_optimization_condition(self, level):
+        """Test optimization levels with condition in the circuit"""
+        qr = QuantumRegister(2)
+        cr = ClassicalRegister(1)
+        qc = QuantumCircuit(qr, cr)
+        qc.cx(0, 1).c_if(cr, 1)
+        backend = FakeJohannesburg()
+        circ = transpile(qc, backend, optimization_level=level)
+        self.assertIsInstance(circ, QuantumCircuit)