Repository: Qiskit/qiskit

Issue:
Error when using size() method on a quantum circuit in terra 0.8.0
<!-- ⚠️ 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**: 0.8.0 (master)
- **Python version**: 3.7.3
- **Operating system**: Windows 10

### What is the current behavior?

size() method on a quantum circuit throws error :
```python
q = QuantumRegister(6)
circuit = QuantumCircuit(q)
circuit.h(q[0])
circuit.ccx(q[0], q[1], q[2])
circuit.size()
```
Error: 
```python
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-20-18ab26fa2a60> in <module>
      7 #circuit.h(q[2])
      8 #circuit.h(q[3])
----> 9 circuit.size()
     10 circuit.draw(output='mpl',style=style)

c:\users\francoisvarchon\anaconda3\envs\qis09z\lib\site-packages\qiskit_terra-0.8.0-py3.7-win-amd64.egg\qiskit\circuit\quantumcircuit.py in size(self)
    436         gate_ops = 0
    437         for item in self.data:
--> 438             if item.name not in ['barrier', 'snapshot']:
    439                 gate_ops += 1
    440         return gate_ops

AttributeError: 'tuple' object has no attribute 'name'
```


### Steps to reproduce the problem
circuit.size()


### What is the expected behavior?



### Suggested solutions





Discussion:

Resolving patch:
diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py
--- a/qiskit/circuit/quantumcircuit.py
+++ b/qiskit/circuit/quantumcircuit.py
@@ -468,8 +468,8 @@ def size(self):
             int: Total number of gate operations.
         """
         gate_ops = 0
-        for item in self.data:
-            if item.name not in ['barrier', 'snapshot']:
+        for instr, _, _ in self.data:
+            if instr.name not in ['barrier', 'snapshot']:
                 gate_ops += 1
         return gate_ops
 
@@ -507,20 +507,20 @@ def depth(self):
         # We do not consider barriers or snapshots as
         # They are transpiler and simulator directives.
         # The max stack height is the circuit depth.
-        for op in self.data:
-            if op[0].name not in ['barrier', 'snapshot']:
+        for instr, qargs, cargs in self.data:
+            if instr.name not in ['barrier', 'snapshot']:
                 levels = []
                 reg_ints = []
-                for ind, reg in enumerate(op[1]+op[2]):
+                for ind, reg in enumerate(qargs+cargs):
                     # Add to the stacks of the qubits and
                     # cbits used in the gate.
                     reg_ints.append(reg_map[reg[0].name]+reg[1])
                     levels.append(op_stack[reg_ints[ind]] + 1)
-                if op[0].control:
+                if instr.control:
                     # Controls operate over all bits in the
                     # classical register they use.
-                    cint = reg_map[op[0].control[0].name]
-                    for off in range(op[0].control[0].size):
+                    cint = reg_map[instr.control[0].name]
+                    for off in range(instr.control[0].size):
                         if cint+off not in reg_ints:
                             reg_ints.append(cint+off)
                             levels.append(op_stack[cint+off]+1)
@@ -546,11 +546,11 @@ def count_ops(self):
             dict: a breakdown of how many operations of each kind.
         """
         count_ops = {}
-        for op in self.data:
-            if op[0].name in count_ops.keys():
-                count_ops[op[0].name] += 1
+        for instr, _, _ in self.data:
+            if instr.name in count_ops.keys():
+                count_ops[instr.name] += 1
             else:
-                count_ops[op[0].name] = 1
+                count_ops[instr.name] = 1
         return count_ops
 
     def num_connected_components(self, unitary_only=False):
@@ -581,21 +581,21 @@ def num_connected_components(self, unitary_only=False):
 
         # Here we are traversing the gates and looking to see
         # which of the sub_graphs the gate joins together.
-        for op in self.data:
+        for instr, qargs, cargs in self.data:
             if unitary_only:
-                args = op[1]
+                args = qargs
                 num_qargs = len(args)
             else:
-                args = op[1]+op[2]
-                num_qargs = len(args) + (1 if op[0].control else 0)
+                args = qargs+cargs
+                num_qargs = len(args) + (1 if instr.control else 0)
 
-            if num_qargs >= 2 and op[0].name not in ['barrier', 'snapshot']:
+            if num_qargs >= 2 and instr.name not in ['barrier', 'snapshot']:
                 graphs_touched = []
                 num_touched = 0
                 # Controls necessarily join all the cbits in the
                 # register that they use.
-                if op[0].control and not unitary_only:
-                    creg = op[0].control[0]
+                if instr.control and not unitary_only:
+                    creg = instr.control[0]
                     creg_int = reg_map[creg.name]
                     for coff in range(creg.size):
                         temp_int = creg_int+coff


Test patch:
diff --git a/test/python/circuit/test_circuit_properties.py b/test/python/circuit/test_circuit_properties.py
--- a/test/python/circuit/test_circuit_properties.py
+++ b/test/python/circuit/test_circuit_properties.py
@@ -220,6 +220,57 @@ def test_circuit_depth_measurements3(self):
         qc.measure(q[3], c[0])
         self.assertEqual(qc.depth(), 5)
 
+    def test_circuit_size_empty(self):
+        """Circuit.size should return 0 for an empty circuit."""
+        size = 4
+        q = QuantumRegister(size, 'q')
+        c = ClassicalRegister(size, 'c')
+        qc = QuantumCircuit(q, c)
+
+        self.assertEqual(qc.size(), 0)
+
+    def test_circuit_size_single_qubit_gates(self):
+        """Circuit.size should increment for each added single qubit gate."""
+        size = 4
+        q = QuantumRegister(size, 'q')
+        c = ClassicalRegister(size, 'c')
+        qc = QuantumCircuit(q, c)
+
+        qc.h(q[0])
+        self.assertEqual(qc.size(), 1)
+        qc.h(q[1])
+        self.assertEqual(qc.size(), 2)
+
+    def test_circuit_size_two_qubit_gates(self):
+        """Circuit.size should increment for each added two qubit gate."""
+        size = 4
+        q = QuantumRegister(size, 'q')
+        c = ClassicalRegister(size, 'c')
+        qc = QuantumCircuit(q, c)
+
+        qc.cx(q[0], q[1])
+        self.assertEqual(qc.size(), 1)
+        qc.cx(q[2], q[3])
+        self.assertEqual(qc.size(), 2)
+
+    def test_circuit_size_ignores_barriers_snapshots(self):
+        """Circuit.size should not count barriers or snapshots."""
+
+        import qiskit.extensions.simulator  # pylint: disable=unused-import
+
+        size = 4
+        q = QuantumRegister(size, 'q')
+        c = ClassicalRegister(size, 'c')
+        qc = QuantumCircuit(q, c)
+
+        qc.h(q[0])
+        qc.cx(q[0], q[1])
+        self.assertEqual(qc.size(), 2)
+        qc.barrier(q)
+        self.assertEqual(qc.size(), 2)
+        qc.snapshot('snapshot_label')
+        self.assertEqual(qc.size(), 2)
+
     def test_circuit_count_ops(self):
         """Tet circuit count ops
         """