def count_neighbors(qubits, qubit): """Counts the qubits that the given qubit can interact with.""" possibles = [ devices.GridQubit(qubit.row + 1, qubit.col), devices.GridQubit(qubit.row - 1, qubit.col), devices.GridQubit(qubit.row, qubit.col + 1), devices.GridQubit(qubit.row, qubit.col - 1), ] return len(list(e for e in possibles if e in qubits))
def _coupled_qubit_pairs( qubits: List['cirq.GridQubit']) -> List[GridQubitPairT]: pairs = [] qubit_set = set(qubits) for qubit in qubits: def add_pair(neighbor: 'cirq.GridQubit'): if neighbor in qubit_set: pairs.append((qubit, neighbor)) add_pair(devices.GridQubit(qubit.row, qubit.col + 1)) add_pair(devices.GridQubit(qubit.row + 1, qubit.col)) return pairs
def grid_qubit_from_proto_id(proto_id: str) -> 'cirq.GridQubit': """Parse a proto id to a `cirq.GridQubit`. Proto ids for grid qubits are of the form `{row}_{col}` where `{row}` is the integer row of the grid qubit, and `{col}` is the integer column of the qubit. Args: proto_id: The id to convert. Returns: A `cirq.GridQubit` corresponding to the proto id. Raises: ValueError: If the string not of the correct format. """ match = re.match(GRID_QUBIT_ID_PATTERN, proto_id) if match is None: raise ValueError( 'GridQubit proto id must be of the form <int>_<int> but was {}'. format(proto_id)) try: row, col = match.groups() return devices.GridQubit(row=int(row), col=int(col)) except ValueError: raise ValueError( 'GridQubit proto id must be of the form <int>_<int> but was {}'. format(proto_id))
def __contains__(self, pair) -> bool: """Checks whether a pair is in this layer.""" if self.vertical: # Transpose row, col coords for vertical orientation. a, b = pair pair = devices.GridQubit(a.col, a.row), devices.GridQubit(b.col, b.row) a, b = sorted(pair) # qubits should be 1 column apart. if (a.row != b.row) or (b.col != a.col + 1): return False # mod to get the position in the 2 x 2 unit cell with column offset. pos = a.row % 2, (a.col - self.col_offset) % 2 return pos == (0, 0) or pos == (1, self.stagger)
def grid_qubit_from_proto_id(proto_id: str) -> 'cirq.GridQubit': """Parse a proto id to a `cirq.GridQubit`. Proto ids for grid qubits are of the form `{row}_{col}` where `{row}` is the integer row of the grid qubit, and `{col}` is the integer column of the qubit. Args: proto_id: The id to convert. Returns: A `cirq.GridQubit` corresponding to the proto id. Raises: ValueError: If the string not of the correct format. """ parts = proto_id.split('_') if len(parts) != 2: raise ValueError( 'GridQubit proto id must be of the form <int>_<int> but was {}'. format(proto_id)) try: row, col = parts return devices.GridQubit(row=int(row), col=int(col)) except ValueError: raise ValueError( 'GridQubit proto id must be of the form <int>_<int> but was {}'. format(proto_id))
def _make_cz_layer(qubits: Iterable[devices.GridQubit], layer_index: int) -> Iterable[ops.Operation]: """ Each layer index corresponds to a shift/transpose of this CZ pattern: ●───● ● ● ●───● ● ● . . . ● ● ●───● ● ● ●───● . . . ●───● ● ● ●───● ● ● . . . ● ● ●───● ● ● ●───● . . . ●───● ● ● ●───● ● ● . . . ● ● ●───● ● ● ●───● . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Labelled edges, showing the exact index-to-CZs mapping (mod 8): ●─0─●─2─●─4─●─6─●─0─. . . 3│ 7│ 3│ 7│ 3│ ●─4─●─6─●─0─●─2─●─4─. . . 1│ 5│ 1│ 5│ 1│ ●─0─●─2─●─4─●─6─●─0─. . . 7│ 3│ 7│ 3│ 7│ ●─4─●─6─●─0─●─2─●─4─. . . 5│ 1│ 5│ 1│ 5│ ●─0─●─2─●─4─●─6─●─0─. . . 3│ 7│ 3│ 7│ 3│ . . . . . . . . . . . . . . . . . . Note that, for small devices, some layers will be empty because the layer only contains edges not present on the device. NOTE: This is the almost the function in supremacy.py, but with a different order of CZ layers """ # map to an internal layer index to match the cycle order of public circuits LAYER_INDEX_MAP = [0, 3, 2, 1, 4, 7, 6, 5] internal_layer_index = LAYER_INDEX_MAP[layer_index % 8] dir_row = internal_layer_index % 2 dir_col = 1 - dir_row shift = (internal_layer_index >> 1) % 4 for q in qubits: q2 = devices.GridQubit(q.row + dir_row, q.col + dir_col) if q2 not in qubits: continue # This edge isn't on the device. if (q.row * (2 - dir_row) + q.col * (2 - dir_col)) % 4 != shift: continue # No CZ along this edge for this layer. yield ops.common_gates.CZ(q, q2)
def _make_cz_layer(device: google.XmonDevice, layer_index: int ) -> Iterable[cirq.Operation]: """ Each layer index corresponds to a shift/transpose of this CZ pattern: ●───● ● ● ●───● ● ● . . . ● ● ●───● ● ● ●───● . . . ●───● ● ● ●───● ● ● . . . ● ● ●───● ● ● ●───● . . . ●───● ● ● ●───● ● ● . . . ● ● ●───● ● ● ●───● . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Labelled edges, showing the exact index-to-CZs mapping (mod 8): ●─0─●─2─●─4─●─6─●─0─. . . 1│ 5│ 1│ 5│ 1│ ●─4─●─6─●─0─●─2─●─4─. . . 3│ 7│ 3│ 7│ 3│ ●─0─●─2─●─4─●─6─●─0─. . . 5│ 1│ 5│ 1│ 5│ ●─4─●─6─●─0─●─2─●─4─. . . 7│ 3│ 7│ 3│ 7│ ●─0─●─2─●─4─●─6─●─0─. . . 1│ 5│ 1│ 5│ 1│ . . . . . . . . . . . . . . . . . . Note that, for small devices, some layers will be empty because the layer only contains edges not present on the device. """ dir_row = layer_index % 2 dir_col = 1 - dir_row shift = (layer_index >> 1) % 4 for q in device.qubits: q2 = devices.GridQubit(q.row + dir_row, q.col + dir_col) if q2 not in device.qubits: continue # This edge isn't on the device. if (q.row * (2 - dir_row) + q.col * (2 - dir_col)) % 4 != shift: continue # No CZ along this edge for this layer. yield google.Exp11Gate().on(q, q2)
def generate_boixo_2018_supremacy_circuits_v2_grid( n_rows: int, n_cols: int, cz_depth: int, seed: int ) -> circuits.Circuit: """Generates Google Random Circuits v2 as in github.com/sboixo/GRCS cz_v2. See also https://arxiv.org/abs/1807.10749 Args: n_rows: number of rows of a 2D lattice. n_cols: number of columns. cz_depth: number of layers with CZ gates. seed: seed for the random instance. Returns: A circuit corresponding to instance inst_{n_rows}x{n_cols}_{cz_depth+1}_{seed} The mapping of qubits is cirq.GridQubit(j,k) -> q[j*n_cols+k] (as in the QASM mapping) """ qubits = [devices.GridQubit(i, j) for i in range(n_rows) for j in range(n_cols)] return generate_boixo_2018_supremacy_circuits_v2(qubits, cz_depth, seed)
def _qubit_from_proto_dict(proto_dict): """Proto dict must have 'row' and 'col' keys.""" if 'row' not in proto_dict or 'col' not in proto_dict: raise ValueError( 'Proto dict does not contain row or col: {}'.format(proto_dict)) return devices.GridQubit(row=proto_dict['row'], col=proto_dict['col'])
def test_cross_entropy_benchmarking(): # Check that the fidelities returned from a four-qubit XEB simulation are # close to 1 (deviations from 1 is expected due to finite number of # measurements). simulator = sim.Simulator() qubits = [ devices.GridQubit(0, 0), devices.GridQubit(0, 1), devices.GridQubit(1, 0), devices.GridQubit(1, 1) ] # Build a sequence of CZ gates. interleaved_ops = build_entangling_layers(qubits, ops.CZ**0.91) # Specify a set of single-qubit rotations. Pick prime numbers for the # exponent to avoid evolving the system into a basis state. single_qubit_rots = [[ops.X**0.37], [ops.Y**0.73, ops.X**0.53], [ops.Z**0.61, ops.X**0.43], [ops.Y**0.19]] # Simulate XEB using the default single-qubit gate set without two-qubit # gates, XEB using the specified single-qubit gate set without two-qubit # gates, and XEB using the specified single-qubit gate set with two-qubit # gate. Check that the fidelities are close to 1.0 in all cases. Also, # check that a single XEB fidelity is returned if a single cycle number # is specified. results_0 = cross_entropy_benchmarking(simulator, qubits, num_circuits=5, repetitions=5000, cycles=range(4, 30, 5)) results_1 = cross_entropy_benchmarking( simulator, qubits, num_circuits=5, repetitions=5000, cycles=range(4, 30, 5), scrambling_gates_per_cycle=single_qubit_rots) results_2 = cross_entropy_benchmarking( simulator, qubits, benchmark_ops=interleaved_ops, num_circuits=5, repetitions=5000, cycles=range(4, 30, 5), scrambling_gates_per_cycle=single_qubit_rots) results_3 = cross_entropy_benchmarking( simulator, qubits, benchmark_ops=interleaved_ops, num_circuits=5, repetitions=5000, cycles=20, scrambling_gates_per_cycle=single_qubit_rots) fidelities_0 = [datum.xeb_fidelity for datum in results_0.data] fidelities_1 = [datum.xeb_fidelity for datum in results_1.data] fidelities_2 = [datum.xeb_fidelity for datum in results_2.data] fidelities_3 = [datum.xeb_fidelity for datum in results_3.data] assert np.isclose(np.mean(fidelities_0), 1.0, atol=0.1) assert np.isclose(np.mean(fidelities_1), 1.0, atol=0.1) assert np.isclose(np.mean(fidelities_2), 1.0, atol=0.1) assert len(fidelities_3) == 1 # Sanity test that plot runs. results_1.plot()
seed: seed for the random instance. Returns: A circuit corresponding to instance inst_{n_rows}x{n_cols}_{cz_depth+1}_{seed} The mapping of qubits is cirq.GridQubit(j,k) -> q[j*n_cols+k] (as in the QASM mapping) """ qubits = [devices.GridQubit(i, j) for i in range(n_rows) for j in range(n_cols)] return generate_boixo_2018_supremacy_circuits_v2(qubits, cz_depth, seed) _bristlecone_qubits = frozenset( { devices.GridQubit(4, 8), devices.GridQubit(2, 5), devices.GridQubit(3, 2), devices.GridQubit(5, 10), devices.GridQubit(0, 6), devices.GridQubit(4, 3), devices.GridQubit(6, 7), devices.GridQubit(8, 4), devices.GridQubit(5, 5), devices.GridQubit(4, 9), devices.GridQubit(7, 8), devices.GridQubit(8, 5), devices.GridQubit(6, 2), devices.GridQubit(7, 3), devices.GridQubit(5, 0), devices.GridQubit(4, 4),
def _qubit_from_proto(proto: operations_pb2.Qubit): return devices.GridQubit(row=proto.row, col=proto.col)