Repository: quantumlib/Cirq

Issue:
ParallelGateOperation does not support JSON serialization
**Description of the issue**

`ParallelGateOperation` does not appear to support json serialization using `cirq.to_json`.

**How to reproduce the issue**

```python
import cirq
circuit = cirq.Circuit()
qubit_a = cirq.NamedQubit('a')
qubit_b = cirq.NamedQubit('b')
pgo = cirq.ParallelGateOperation(gate=cirq.Y, qubits=[qubit_a, qubit_b,])
circuit.append(pgo)
text = cirq.to_json(circuit)

# `TypeError: Object of type ParallelGateOperation is not JSON serializable`
```
**Cirq version**

0.9.1




Discussion:

Resolving patch:
diff --git a/cirq/ops/parallel_gate_operation.py b/cirq/ops/parallel_gate_operation.py
--- a/cirq/ops/parallel_gate_operation.py
+++ b/cirq/ops/parallel_gate_operation.py
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 
-from typing import AbstractSet, Sequence, Tuple, Union, Any, Optional, TYPE_CHECKING
+from typing import AbstractSet, Sequence, Tuple, Union, Any, Optional, TYPE_CHECKING, Dict
 
 import numpy as np
 
@@ -157,3 +157,6 @@ def __pow__(self, exponent: Any) -> 'ParallelGateOperation':
         if new_gate is NotImplemented:
             return NotImplemented
         return self.with_gate(new_gate)
+
+    def _json_dict_(self) -> Dict[str, Any]:
+        return protocols.obj_to_dict_helper(self, attribute_names=["gate", "qubits"])
diff --git a/cirq/protocols/json_serialization.py b/cirq/protocols/json_serialization.py
--- a/cirq/protocols/json_serialization.py
+++ b/cirq/protocols/json_serialization.py
@@ -134,6 +134,7 @@ def two_qubit_matrix_gate(matrix):
         '_PauliY': cirq.ops.pauli_gates._PauliY,
         '_PauliZ': cirq.ops.pauli_gates._PauliZ,
         'ParamResolver': cirq.ParamResolver,
+        'ParallelGateOperation': cirq.ParallelGateOperation,
         'PasqalDevice': cirq.pasqal.PasqalDevice,
         'PasqalVirtualDevice': cirq.pasqal.PasqalVirtualDevice,
         'PauliString': cirq.PauliString,


Test patch:
diff --git a/cirq/protocols/json_serialization_test.py b/cirq/protocols/json_serialization_test.py
--- a/cirq/protocols/json_serialization_test.py
+++ b/cirq/protocols/json_serialization_test.py
@@ -298,7 +298,6 @@ def test_mutually_exclusive_blacklist():
     'Linspace',
     'ListSweep',
     'NeutralAtomDevice',
-    'ParallelGateOperation',
     'PauliInteractionGate',
     'PauliStringPhasor',
     'PauliSum',
diff --git a/cirq/protocols/json_test_data/ParallelGateOperation.json b/cirq/protocols/json_test_data/ParallelGateOperation.json
new file mode 100644
--- /dev/null
+++ b/cirq/protocols/json_test_data/ParallelGateOperation.json
@@ -0,0 +1,18 @@
+{
+  "cirq_type": "ParallelGateOperation",
+  "gate": {
+    "cirq_type": "_PauliY",
+    "exponent": 1.0,
+    "global_shift": 0.0
+  },
+  "qubits": [
+    {
+      "cirq_type": "NamedQubit",
+      "name": "a"
+    },
+    {
+      "cirq_type": "NamedQubit",
+      "name": "b"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/cirq/protocols/json_test_data/ParallelGateOperation.repr b/cirq/protocols/json_test_data/ParallelGateOperation.repr
new file mode 100644
--- /dev/null
+++ b/cirq/protocols/json_test_data/ParallelGateOperation.repr
@@ -0,0 +1 @@
+cirq.ParallelGateOperation(gate=cirq.Y, qubits=[cirq.NamedQubit('a'), cirq.NamedQubit('b')])
\ No newline at end of file