Generates Google Random Circuits v2 as in github.com/sboixo/GRCS cz_v2.
    See also https://arxiv.org/abs/1807.10749

    Args:
        qubits: qubit grid in which to generate the circuit.
        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)

def generate_supremacy_circuit_google_v2(qubits: Iterable[devices.GridQubit],
                                         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:
        qubits: qubit grid in which to generate the circuit.
        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)
    """

    non_diagonal_gates = [ops.pauli_gates.X**(1/2), ops.pauli_gates.Y**(1/2)]
    rand_gen = random.Random(seed).random

    circuit = circuits.Circuit()

    # Add an initial moment of Hadamards
    circuit.append(ops.common_gates.H(qubit) for qubit in qubits)

    layer_index = 0
    if cz_depth:
        layer_index = _add_cz_layer(layer_index, circuit)
        # In the first moment, add T gates when possible
        for qubit in qubits:
            if not circuit.operation_at(qubit, 1):
                circuit.append(ops.common_gates.T(qubit),
                               strategy=InsertStrategy.EARLIEST)

    for moment_index in range(2, cz_depth+1):
        layer_index = _add_cz_layer(layer_index, circuit)
        # Add single qubit gates in the same moment
        for qubit in qubits:
            if not circuit.operation_at(qubit, moment_index):
                last_op = circuit.operation_at(qubit, moment_index-1)
                if last_op:
                    gate = cast(ops.GateOperation, last_op).gate
                    # Add a random non diagonal gate after a CZ
                    if gate == ops.CZ:
                        circuit.append(_choice(rand_gen,
                                               non_diagonal_gates).on(qubit),
                                       strategy=InsertStrategy.EARLIEST)
                    # Add a T gate after a non diagonal gate
                    elif not gate == ops.T:
                        circuit.append(ops.common_gates.T(qubit),
                                       strategy=InsertStrategy.EARLIEST)

    # Add a final moment of Hadamards
    circuit.append([ops.common_gates.H(qubit) for qubit in qubits],
                   strategy=InsertStrategy.NEW_THEN_INLINE)

    return circuit