Repository: quantumlib/Cirq

Issue:
Empty Moments are rendered incorrectly in transposed circuit diagrams
Empty Moments arise when optimizations leave existing Moments empty. For example:

Input:
```
import cirq

a, b = cirq.LineQubit.range(2)
circuit = cirq.Circuit.from_ops(
    cirq.Z.on_each([a, b]),
    cirq.Z.on_each([a, b]),
    cirq.CZ(a, b)
)
print('Original circuit:')
print(circuit.to_text_diagram(transpose=True))
print()

cirq.merge_single_qubit_gates_into_phased_x_z(circuit)
print('Optimized circuit:')
print(circuit.to_text_diagram(transpose=True))
print()

print('repr(circuit):')
print(repr(circuit))
```
Output:
```
Original circuit:
0 1
│ │
Z Z
│ │
Z Z
│ │
@─@
│ │

Optimized circuit:
0 1
│ │
  │
│ │
  │
│ │
@─@
│ │

repr(circuit):
cirq.Circuit(moments=[
    cirq.Moment(),
    cirq.Moment(),
    cirq.Moment(operations=[
        cirq.CZ.on(cirq.LineQubit(0), cirq.LineQubit(1)),
    ]),
])
```

As you can see, there are gaps in the wires in the diagram of the optimized circuit.

I think there's a case to be made that in this situation, the empty Moments shouldn't be rendered at all.


Discussion:
How is this issue related to https://github.com/quantumlib/Cirq/issues/1131? 
#1131 was resolved by PR #1193 , but that PR did not include any tests for transposed text diagrams (specifically, in `test_empty_moments` in `circuit_test.py`).

Resolving patch:
diff --git a/cirq/circuits/text_diagram_drawer.py b/cirq/circuits/text_diagram_drawer.py
--- a/cirq/circuits/text_diagram_drawer.py
+++ b/cirq/circuits/text_diagram_drawer.py
@@ -226,7 +226,8 @@ def render(self,
 
         # Place entries.
         for (x, y), v in self.entries.items():
-            grid[y][x] = v.text
+            if v.text:
+                grid[y][x] = v.text
 
         # Pad rows and columns to fit contents with desired spacing.
         multiline_grid = _pad_into_multiline(w,


Test patch:
diff --git a/cirq/circuits/circuit_test.py b/cirq/circuits/circuit_test.py
--- a/cirq/circuits/circuit_test.py
+++ b/cirq/circuits/circuit_test.py
@@ -219,10 +219,40 @@ def test_empty_moments():
     cirq.testing.assert_has_diagram(circuit,
                                     "a: ───X───X───────X───",
                                     use_unicode_characters=True)
+    cirq.testing.assert_has_diagram(circuit, """
+a
+│
+X
+│
+X
+│
+│
+│
+X
+│
+""",
+            use_unicode_characters=True,
+            transpose=True)
+
     # 1-qubit ascii-only test
     cirq.testing.assert_has_diagram(circuit,
                                     "a: ---X---X-------X---",
                                     use_unicode_characters=False)
+    cirq.testing.assert_has_diagram(circuit, """
+a
+|
+X
+|
+X
+|
+|
+|
+X
+|
+""",
+            use_unicode_characters=False,
+            transpose=True)
+
     # 2-qubit test
     op = cirq.CNOT(cirq.NamedQubit('a'), cirq.NamedQubit('b'))
     op_moment = cirq.Moment([op])
@@ -232,12 +262,40 @@ def test_empty_moments():
 a: ───@───@───────@───
       │   │       │
 b: ───X───X───────X───""", use_unicode_characters=True)
+    cirq.testing.assert_has_diagram(circuit, """
+a b
+│ │
+@─X
+│ │
+@─X
+│ │
+│ │
+│ │
+@─X
+│ │
+""",
+        use_unicode_characters=True,
+        transpose=True)
 
      # 2-qubit ascii-only test
     cirq.testing.assert_has_diagram(circuit, """
 a: ---@---@-------@---
       |   |       |
 b: ---X---X-------X---""", use_unicode_characters=False)
+    cirq.testing.assert_has_diagram(circuit, """
+a b
+| |
+@-X
+| |
+@-X
+| |
+| |
+| |
+@-X
+| |
+""",
+        use_unicode_characters=False,
+        transpose=True)
 
 def test_slice():
     a = cirq.NamedQubit('a')