Repository: quantumlib/Cirq

Issue:
For QASM of decomposed circuits add comment
I noticed that if I export CCZ into qasm, I get the h, ccx, h operations with no leading comment saying that they correspond to a CCZ. I'm pretty sure this used to happen.


Discussion:
Confirmed this is still true. 
```
a, b, c = cirq.LineQubit.range(3)
circuit = cirq.Circuit(cirq.CCZ(a, b, c))
print(cirq.qasm(circuit))
```
returns
```
// Generated from Cirq v0.7.0

OPENQASM 2.0;
include "qelib1.inc";


// Qubits: [0, 1, 2]
qreg q[3];


h q[2];
ccx q[0],q[1],q[2];
h q[2];
```
I can take this as a first issue.

The hacky way to do this would be to hard-code this comment string into [`CCZ._qasm_`](https://github.com/quantumlib/Cirq/blob/0ff2894e053e4ce3bb1b54e9b9de1cc4345d10b3/cirq/ops/three_qubit_gates.py#L138). 

The better way would be to have ccz with exponent=1 decompose into [h, ccx, h]. The problem is that ccx decomposes into ccz, so it gives an infinite loop. Would we want to muck around with the decomposition orders just for this?

Another option would be to augment [`should_annotate`](https://github.com/quantumlib/Cirq/blob/0ff2894e053e4ce3bb1b54e9b9de1cc4345d10b3/cirq/circuits/qasm_output.py#L311) with an extra condition that checks if the generated qasm is multi-line. This change would cause some additional gates that are not currently commented to be so. [`h_with_parameter`](https://github.com/quantumlib/Cirq/blob/0ff2894e053e4ce3bb1b54e9b9de1cc4345d10b3/cirq/circuits/qasm_output_test.py#L185) would be `// Gate: H**0.25`, and [multi-qubit identities](https://github.com/quantumlib/Cirq/blob/0ff2894e053e4ce3bb1b54e9b9de1cc4345d10b3/cirq/circuits/qasm_output_test.py#L460) would be annotated e.g. `// Gate: I(3)`. (Note I think `H**0.25` could also be fixed by removing the [custom qasm for non-one exponents](https://github.com/quantumlib/Cirq/blob/0ff2894e053e4ce3bb1b54e9b9de1cc4345d10b3/cirq/ops/common_gates.py#L861) and replacing with `None`)

Resolving patch:
diff --git a/cirq/circuits/qasm_output.py b/cirq/circuits/qasm_output.py
--- a/cirq/circuits/qasm_output.py
+++ b/cirq/circuits/qasm_output.py
@@ -308,7 +308,9 @@ def on_stuck(bad_op):
                 main_op, keep=keep, fallback_decomposer=fallback, on_stuck_raise=on_stuck
             )
 
-            should_annotate = decomposed != [main_op]
+            qasms = [protocols.qasm(op, args=self.args) for op in decomposed]
+
+            should_annotate = decomposed != [main_op] or qasms[0].count('\n') > 1
             if should_annotate:
                 output_line_gap(1)
                 if isinstance(main_op, ops.GateOperation):
@@ -318,8 +320,8 @@ def on_stuck(bad_op):
                     x = str(main_op).replace('\n', '\n //')
                     output('// Operation: {!s}\n'.format(x))
 
-            for decomposed_op in decomposed:
-                output(protocols.qasm(decomposed_op, args=self.args))
+            for qasm in qasms:
+                output(qasm)
 
             if should_annotate:
                 output_line_gap(1)


Test patch:
diff --git a/cirq/circuits/qasm_output_test.py b/cirq/circuits/qasm_output_test.py
--- a/cirq/circuits/qasm_output_test.py
+++ b/cirq/circuits/qasm_output_test.py
@@ -183,6 +183,7 @@ def test_h_gate_with_parameter():
 qreg q[1];
 
 
+// Gate: H**0.25
 ry(pi*0.25) q[0];
 rx(pi*0.25) q[0];
 ry(pi*-0.25) q[0];
@@ -414,9 +415,11 @@ def filter_unpredictable_numbers(text):
 ry(pi*0.5) q[0];
 cx q[0],q[1];
 
+// Gate: CCZ
 h q[2];
 ccx q[0],q[1],q[2];
 h q[2];
+
 ccx q[0],q[1],q[2];
 
 // Gate: CCZ**0.5
@@ -457,6 +460,8 @@ def filter_unpredictable_numbers(text):
 
 cswap q[0],q[1],q[2];
 id q[0];
+
+// Gate: I(3)
 id q[0];
 id q[1];
 id q[2];
@@ -480,10 +485,13 @@ def filter_unpredictable_numbers(text):
 measure q[3] -> m_X[0];
 measure q[4] -> m__x[0];
 measure q[2] -> m_x_a[0];
+
+// Gate: cirq.MeasurementGate(3, 'multi', (False, True))
 measure q[1] -> m_multi[0];
 x q[2];  // Invert the following measurement
 measure q[2] -> m_multi[1];
 measure q[3] -> m_multi[2];
+
 // Dummy operation
 
 // Operation: DummyCompositeOperation()