Repository: quantumlib/Cirq

Issue:
Glitched Circuit Diagram after flatten
**Description of the issue**
When a circuit has a parameterised gate as a product of symbols, flattening the circuit will produce a glitched circuit diagram where the parameterised expression is gone. This will further affect the circuit diagram if two qubit gates are also present in the circuit. 
**How to reproduce the issue**

```
import sympy as sp
from cirq import CNOT, rz, Circuit
cq = cirq.Circuit()
qubits = cirq.GridQubit.rect(2,1)
x = sp.symarray('x', 2)
cq.append([rz(x[0]*x[1])(qubits[-1]), CNOT(*tuple(qubits))])
new_cq, _= cirq.flatten(cq)
new_cq
```
This will product circuit diagram like this

This will product circuit diagram like this

(0, 0): ─────────────────────────@───
　　　　　　　　　　　│
(1, 0): ───Rz(pi*)───X───

**Cirq version**
0.8.2



Discussion:
Hi @AlkaidCheng  - the result on the CLI is 

```
(0, 0): ─────────────────────────@───
                                 │
(1, 0): ───Rz(pi*<x_0*x_1/pi>)───X───

```

I'm guessing that the angle brackets `<` `>` create the problem in a browser for you - maybe Jupyter notebooks? 
Yeah I just confirmed that that's the issue. In Jupyter notebooks this shows up incorrectly, but only if the object is returned as the result of the cell - if you use print, it works
```
print(new_cq)
```
Gives a workaround, but it might be a bit annoying. Not sure yet what the right solution is here. 
Right, I was using Colab notebooks and doing print will solve the problem.
I have been using the circuit returned as the result of the cell for printing circuits because for jupyter notebooks, doing print(circuit) will mess up the diagram by introducing extra newlines if the circuit is too long. Interestingly doing print(circuit) in Colab notebooks does not have this problem. 
For someone who wants to look at this should review the possibility of replacing `<>` angle brackets with another pair of symbols (e.g. `{}` or `[]`) here: https://github.com/quantumlib/Cirq/blob/master/cirq/study/flatten_expressions.py
Hey! Can I contribute to this issue?
Hi @abhik-99 - yes please, feel free to grab it! 
After a quick internal chat - consensus is on using `[ ]`. 
I haven't been following this issue but it sounds like the angle brackets are a problem in the Jupyter scrollable view because they are interpreted as HTML tags.  An easy fix for this would be to escape any special characters in the code for `Circuit._repr_html_` (probably with the builtin `html` module).
Oooo awesome suggestion @cduck, I didn't know about `_repr_html_` - @abhik-99 - please try that out - if we could implement the escaping there that would be even better and actually more robust against future similar issues. 
Sure @balopat! On it. Thanks.
xref #2905 `<virtual>` labels for noise tags also get eaten in jupyter sometimes
So hey @balopat and @cduck I tried out two possible solutions.

1. Replacing the ```< >``` with ```[ ]``` in https://github.com/quantumlib/Cirq/blob/master/cirq/study/flatten_expressions.py in [here](https://drive.google.com/file/d/1NwHgvITmaMHpIEjZuN6Vwq9jJszeABDZ/view?usp=sharing).
2. Trying to escape using the builtin ```html``` module in https://github.com/quantumlib/Cirq/blob/master/cirq/circuits/circuit.py in [here](https://drive.google.com/file/d/1PXxrrZR8Jhs7w0M3E28-Fqed2K1ihpq3/view?usp=sharing).

Solution 1 is the easiest one but solution 2 is better in preventing similar future issues. The thing is that in solution 2, as the ```&lt;``` and ```&gt;``` are being shown as ```<``` and ```>```, there is a space that needs to be filled. Adding in spaces only enlarges the image width-wise. I have tried using ```cirq.circuits._text_diagram_drawer.TextDiagramDrawer.shift()``` but that only shifts the whole diagram not a single qubit line.

Any suggestions?
It would be helpful to give the code you used for those examples.  I would do the second solution by changing line https://github.com/quantumlib/Cirq/blob/master/cirq/circuits/circuit.py#L378 to `+ html.escape(...)`.  This way circuit diagram will make space for `<` *before* it is replaced with the escape code.
Thanks a lot @cduck ! Just did that and turns out it works great. Opening a PR on a side branch on the lint and tests pass.

Resolving patch:
diff --git a/cirq/circuits/circuit.py b/cirq/circuits/circuit.py
--- a/cirq/circuits/circuit.py
+++ b/cirq/circuits/circuit.py
@@ -27,6 +27,7 @@
                     List, Optional, overload, Sequence, Set, Tuple, Type,
                     TYPE_CHECKING, TypeVar, Union)
 
+import html
 import re
 import numpy as np
 
@@ -374,9 +375,8 @@ def _repr_pretty_(self, p: Any, cycle: bool) -> None:
 
     def _repr_html_(self) -> str:
         """Print ASCII diagram in Jupyter notebook without wrapping lines."""
-        return ('<pre style="overflow: auto; white-space: pre;">'
-                + self.to_text_diagram()
-                + '</pre>')
+        return ('<pre style="overflow: auto; white-space: pre;">' +
+                html.escape(self.to_text_diagram()) + '</pre>')
 
     def _first_moment_operating_on(self, qubits: Iterable['cirq.Qid'],
                                    indices: Iterable[int]) -> Optional[int]:


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
@@ -3817,3 +3817,27 @@ def test_zip():
             cirq.Circuit(cirq.X(a), cirq.CNOT(a, b)),
             cirq.Circuit(cirq.X(b), cirq.Z(b)),
         )
+
+
+def test_repr_html_escaping():
+
+    class TestGate(cirq.Gate):
+
+        def num_qubits(self):
+            return 2
+
+        def _circuit_diagram_info_(self, args):
+            return cirq.CircuitDiagramInfo(
+                wire_symbols=["< ' F ' >", "< ' F ' >"])
+
+    F2 = TestGate()
+    a = cirq.LineQubit(1)
+    c = cirq.NamedQubit("|c>")
+
+    circuit = cirq.Circuit([F2(a, c)])
+
+    # Escaping Special Characters in Gate names.
+    assert '&lt; &#x27; F &#x27; &gt;' in circuit._repr_html_()
+
+    # Escaping Special Characters in Qubit names.
+    assert '|c&gt;' in circuit._repr_html_()