Skip to content

Commit

Permalink
Save repetitions in CrossEntropyResult and make it into a JSON serial…
Browse files Browse the repository at this point in the history
…izable dataclass (#2765)

* save repetitions in CrossEntropyResult and make it into a JSON serializable dataclass

* lint

* ignore mypy error

* clarify definition of cycle

* test repr

* format
  • Loading branch information
kevinsung committed Feb 14, 2020
1 parent c0a1b55 commit 645af19
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 25 deletions.
52 changes: 28 additions & 24 deletions cirq/experiments/cross_entropy_benchmarking.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,26 @@
Set, Tuple, Union)
import numpy as np
from matplotlib import pyplot as plt
from cirq import devices, ops, circuits, sim, work
from cirq import circuits, devices, ops, protocols, sim, work

CrossEntropyPair = NamedTuple('CrossEntropyPair', [('num_cycle', int),
('xeb_fidelity', float)])


@protocols.json_serializable_dataclass(frozen=True)
class CrossEntropyResult:
"""Results from a cross-entropy benchmarking (XEB) experiment."""

def __init__(self, cross_entropy_pairs: Sequence[CrossEntropyPair]):
"""
Args:
cross_entropy_pairs: A sequence of NamedTuples, each of which
contains two fields: num_cycle which returns the circuit
depth as the number of cycles and xeb_fidelity which returns
the XEB fidelity after the given cycle number.
"""
self._data = cross_entropy_pairs

@property
def data(self) -> Sequence[CrossEntropyPair]:
"""Returns a sequence of CrossEntropyPairs.
Each CrossEntropyPair is a NamedTuple that contains a cycle number and
the corresponding XEB fidelity.
"""
return self._data
"""Results from a cross-entropy benchmarking (XEB) experiment.
Attributes:
data: A sequence of NamedTuples, each of which contains two fields:
num_cycle: the circuit depth as the number of cycles, where
a cycle consists of a layer of single-qubit gates followed
by a layer of two-qubit gates.
xeb_fidelity: the XEB fidelity after the given cycle number.
repetitions: The number of circuit repetitions used.
"""
data: List[CrossEntropyPair]
repetitions: int

def plot(self, ax: Optional[plt.Axes] = None,
**plot_kwargs: Any) -> plt.Axes:
Expand All @@ -58,8 +51,8 @@ def plot(self, ax: Optional[plt.Axes] = None,
show_plot = not ax
if not ax:
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
num_cycles = [d.num_cycle for d in self._data]
fidelities = [d.xeb_fidelity for d in self._data]
num_cycles = [d.num_cycle for d in self.data]
fidelities = [d.xeb_fidelity for d in self.data]
ax.set_ylim([0, 1.1])
ax.plot(num_cycles, fidelities, 'ro-', **plot_kwargs)
ax.set_xlabel('Number of Cycles')
Expand All @@ -68,6 +61,16 @@ def plot(self, ax: Optional[plt.Axes] = None,
fig.show()
return ax

@classmethod
def _from_json_dict_(cls, data, repetitions, **kwargs):
return cls(data=[CrossEntropyPair(d, f) for d, f in data],
repetitions=repetitions)

def __repr__(self):
return ('cirq.experiments.CrossEntropyResult('
f'data={[tuple(p) for p in self.data]!r}, '
f'repetitions={self.repetitions!r})')


def cross_entropy_benchmarking(
sampler: work.Sampler,
Expand Down Expand Up @@ -216,7 +219,8 @@ def cross_entropy_benchmarking(
xeb_data = [
CrossEntropyPair(c, k) for (c, k) in zip(cycle_range, fidelity_vals)
]
return CrossEntropyResult(xeb_data)
return CrossEntropyResult( # type: ignore
data=xeb_data, repetitions=repetitions)


def build_entangling_layers(qubits: Sequence[devices.GridQubit],
Expand Down
12 changes: 11 additions & 1 deletion cirq/experiments/cross_entropy_benchmarking_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import matplotlib.pyplot as plt
import cirq

from cirq.experiments import cross_entropy_benchmarking, build_entangling_layers
from cirq.experiments import (CrossEntropyResult, cross_entropy_benchmarking,
build_entangling_layers)
from cirq.experiments.cross_entropy_benchmarking import CrossEntropyPair


def test_cross_entropy_benchmarking():
Expand Down Expand Up @@ -81,3 +83,11 @@ def test_cross_entropy_benchmarking():
# Sanity test that plot runs.
ax = plt.subplot()
results_1.plot(ax)


def test_cross_entropy_result_repr():
result = CrossEntropyResult(
data=[CrossEntropyPair(2, 0.9),
CrossEntropyPair(5, 0.5)],
repetitions=1000)
cirq.testing.assert_equivalent_repr(result)
2 changes: 2 additions & 0 deletions cirq/protocols/json_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def cirq_class_resolver_dictionary(self) -> Dict[str, Type]:
if self._crd is None:
import cirq
from cirq.devices.noise_model import _NoNoiseModel
from cirq.experiments import CrossEntropyResult
from cirq.google.devices.known_devices import (
_NamedConstantXmonDevice)

Expand Down Expand Up @@ -82,6 +83,7 @@ def two_qubit_matrix_gate(matrix):
'ControlledOperation': cirq.ControlledOperation,
'CSwapGate': cirq.CSwapGate,
'CZPowGate': cirq.CZPowGate,
'CrossEntropyResult': CrossEntropyResult,
'Circuit': cirq.Circuit,
'DepolarizingChannel': cirq.DepolarizingChannel,
'ConstantQubitNoiseModel': cirq.ConstantQubitNoiseModel,
Expand Down
14 changes: 14 additions & 0 deletions cirq/protocols/json_test_data/CrossEntropyResult.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"cirq_type": "CrossEntropyResult",
"data": [
[
2,
0.9
],
[
4,
0.5
]
],
"repetitions": 1000
}
1 change: 1 addition & 0 deletions cirq/protocols/json_test_data/CrossEntropyResult.repr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cirq.experiments.CrossEntropyResult(data=[(2, 0.9), (4, 0.5)], repetitions=1000)

0 comments on commit 645af19

Please sign in to comment.