Repository: Qiskit/qiskit

Issue:
barriers are ignored in QuantumCircuit.depth()
The depth method on QuantumCircuit ignores barriers:
```python
from qiskit import QuantumCircuit
circ_serial = QuantumCircuit(4)
circ_serial.h(0)
circ_serial.cx(0, 1)
circ_serial.barrier()
circ_serial.h(2)
circ_serial.cx(2, 3)
print(circ_serial)
print('depth: ', circ_serial.depth())

circ_parallel = QuantumCircuit(4)
circ_parallel.h(0)
circ_parallel.cx(0, 1)
circ_parallel.h(2)
circ_parallel.cx(2, 3)
print(circ_parallel)
print('depth: ', circ_parallel.depth())
```
```
        ┌───┐      ░           
q_0: |0>┤ H ├──■───░───────────
        └───┘┌─┴─┐ ░           
q_1: |0>─────┤ X ├─░───────────
             └───┘ ░ ┌───┐     
q_2: |0>───────────░─┤ H ├──■──
                   ░ └───┘┌─┴─┐
q_3: |0>───────────░──────┤ X ├
                   ░      └───┘
depth:  2
        ┌───┐     
q_0: |0>┤ H ├──■──
        └───┘┌─┴─┐
q_1: |0>─────┤ X ├
        ┌───┐└───┘
q_2: |0>┤ H ├──■──
        └───┘┌─┴─┐
q_3: |0>─────┤ X ├
             └───┘
depth:  2
```

The depth method on DAGCircuit is correct however:
```python
from qiskit.converters import circuit_to_dag
circuit_to_dag(circ_serial).depth()
```
```
5
```

Note: `snapshot` should also behave similarly to `barrier` and extend the depth.


Discussion:
This was by design. Should a snapshot actually change the depth?  I think not as it is not a physical operation. As for barrier. Otherwise depth losses it property of being a measure of circuit length and gauge of whether a circuit can actually run. 
Depending on your model. If eg considering only T1 relaxation, real clock time is the relevant, and hence barriers increase the depth. Repeating Ali's example to many qubits will fail the circuit once the clock time becomes larger than T1. Depth with barriers is then 2n which captures this fail, depth without barriers is just 2 which does not capture the fail
Except maybe the barrier itself should not be counted in depth. Not sure what's the hardware time for barrier enforcement compared to gate time.
So the question is does the barrier actually take time on a device?  If so then yes, it should be included. But then that brings up other questions like why is barrier not converted to basis gates for example. Or why is it not possible to prevent cross barrier optimizations without adding time?  Let me check what happens when I use 100 barriers in a circuit. 
No, that wasn't the (main) point. Suppose even if the barrier takes no time on hardware. For Ali's example circuit with n qubits, the actual runtime will be nT_g with T_g the gate-time. For a T1 model, you want your depth to scale as the actual runtime, because the probability of failure scales with the actual runtime. If you include barriers in the depth calculation - you get depth=n which is ok. If you don't include them, you get depth=2 for whatever n, which wrongly suggests that you may run your circuit without failure
This is related to https://github.com/Qiskit/qiskit-aer/pull/237. You can add I gates to model the T1 noise in such cases of barriers, but probably better that depth() returns you the relevant depth (at least for relaxation noise) on your original circuit, without you needing to manipulate the circuit first.
Ok I  see what is going on. The hardware is using the barrier as an alignment for timing. In that case, the barrier is still not added to the depth, but instead makes the stacks of all the barrier qubits equal to the max of the set. In the above example the depth should be 4.
Yes the depth of the above example should be 4. Barrier is a compiler directive and will serialize operations that happen before/after it. The barrier itself should not be counted towards depth.

The reason that dag.depth() is reporting 5 is because the dag operations are pure graph operations, and are not intelligent about what the graph nodes are (here `barrier` is a node in the graph). I'm not sure how useful it is, maybe it is. But circuit.depth should definitely be 4.

Also `snapshot` acts like a barrier, so should be the same.

Resolving patch:
diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py
--- a/qiskit/circuit/quantumcircuit.py
+++ b/qiskit/circuit/quantumcircuit.py
@@ -624,30 +624,39 @@ def depth(self):
         # line so that they all stacked at the same depth.
         # Conditional gates act on all cbits in the register
         # they are conditioned on.
-        # We do not consider barriers or snapshots as
+        # We treat barriers or snapshots different as
         # They are transpiler and simulator directives.
         # The max stack height is the circuit depth.
         for instr, qargs, cargs in self.data:
-            if instr.name not in ['barrier', 'snapshot']:
-                levels = []
-                reg_ints = []
-                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.register.name] + reg.index)
+            levels = []
+            reg_ints = []
+            # If count then add one to stack heights
+            count = True
+            if instr.name in ['barrier', 'snapshot']:
+                count = False
+            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.register.name] + reg.index)
+                if count:
                     levels.append(op_stack[reg_ints[ind]] + 1)
-                if instr.control:
-                    # Controls operate over all bits in the
-                    # classical register they use.
-                    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)
-
-                max_level = max(levels)
-                for ind in reg_ints:
-                    op_stack[ind] = max_level
+                else:
+                    levels.append(op_stack[reg_ints[ind]])
+            # Assuming here that there is no controlled
+            # snapshots or barriers ever.
+            if instr.control:
+                # Controls operate over all bits in the
+                # classical register they use.
+                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)
+
+            max_level = max(levels)
+            for ind in reg_ints:
+                op_stack[ind] = max_level
+
         return max(op_stack)
 
     def width(self):


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
@@ -20,6 +20,8 @@
 import numpy as np
 from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
 from qiskit.test import QiskitTestCase
+# pylint: disable=unused-import
+from qiskit.extensions.simulator import snapshot
 
 
 class TestCircuitProperties(QiskitTestCase):
@@ -227,6 +229,93 @@ def test_circuit_depth_measurements3(self):
         qc.measure(q[3], c[0])
         self.assertEqual(qc.depth(), 5)
 
+    def test_circuit_depth_barriers1(self):
+        """Test circuit depth for barriers #1.
+        """
+        q = QuantumRegister(4, 'q')
+        c = ClassicalRegister(4, 'c')
+        circ = QuantumCircuit(q, c)
+        circ.h(0)
+        circ.cx(0, 1)
+        circ.barrier(q)
+        circ.h(2)
+        circ.cx(2, 3)
+        self.assertEqual(circ.depth(), 4)
+
+    def test_circuit_depth_barriers2(self):
+        """Test circuit depth for barriers #2.
+        """
+        q = QuantumRegister(4, 'q')
+        c = ClassicalRegister(4, 'c')
+        circ = QuantumCircuit(q, c)
+        circ.h(0)
+        circ.barrier(q)
+        circ.cx(0, 1)
+        circ.barrier(q)
+        circ.h(2)
+        circ.barrier(q)
+        circ.cx(2, 3)
+        self.assertEqual(circ.depth(), 4)
+
+    def test_circuit_depth_barriers3(self):
+        """Test circuit depth for barriers #3.
+        """
+        q = QuantumRegister(4, 'q')
+        c = ClassicalRegister(4, 'c')
+        circ = QuantumCircuit(q, c)
+        circ.h(0)
+        circ.barrier(q)
+        circ.cx(0, 1)
+        circ.barrier(q)
+        circ.barrier(q)
+        circ.barrier(q)
+        circ.h(2)
+        circ.barrier(q)
+        circ.cx(2, 3)
+        self.assertEqual(circ.depth(), 4)
+
+    def test_circuit_depth_snap1(self):
+        """Test circuit depth for snapshots #1.
+        """
+        q = QuantumRegister(4, 'q')
+        c = ClassicalRegister(4, 'c')
+        circ = QuantumCircuit(q, c)
+        circ.h(0)
+        circ.cx(0, 1)
+        circ.snapshot('snap')
+        circ.h(2)
+        circ.cx(2, 3)
+        self.assertEqual(circ.depth(), 4)
+
+    def test_circuit_depth_snap2(self):
+        """Test circuit depth for snapshots #2.
+        """
+        q = QuantumRegister(4, 'q')
+        c = ClassicalRegister(4, 'c')
+        circ = QuantumCircuit(q, c)
+        circ.h(0)
+        circ.snapshot('snap0')
+        circ.cx(0, 1)
+        circ.snapshot('snap1')
+        circ.h(2)
+        circ.snapshot('snap2')
+        circ.cx(2, 3)
+        self.assertEqual(circ.depth(), 4)
+
+    def test_circuit_depth_snap3(self):
+        """Test circuit depth for snapshots #3.
+        """
+        q = QuantumRegister(4, 'q')
+        c = ClassicalRegister(4, 'c')
+        circ = QuantumCircuit(q, c)
+        circ.h(0)
+        circ.cx(0, 1)
+        circ.snapshot('snap0')
+        circ.snapshot('snap1')
+        circ.h(2)
+        circ.cx(2, 3)
+        self.assertEqual(circ.depth(), 4)
+
     def test_circuit_size_empty(self):
         """Circuit.size should return 0 for an empty circuit."""
         size = 4