def qubits_and_pairs(
    sampler: cirq.Sampler,
    qubits: Sequence[cirq.GridQubit] | None = None,
    pairs: Sequence[tuple[cirq.GridQubit, cirq.GridQubit]] | None = None,
) -> tuple[Sequence[cirq.GridQubit], Sequence[tuple[cirq.GridQubit, cirq.GridQubit]]]:
    """Extract qubits and pairs from sampler.


    If qubits are not provided, then they are extracted from the pairs (if given) or the sampler.
    If pairs are not provided then all pairs of adjacent qubits are used.

    Args:
        sampler: The quantum engine or simulator to run the circuits.
        qubits: Optional list of qubits.
        pairs: Optional list of pair to use.

    Returns:
        - Qubits to use.
        - Pairs of qubits to use.

    Raises:
        ValueError: If qubits are not specified and can't be deduced from other arguments.
    """
    if qubits is None:
        if pairs is None:
            qubits = _grid_qubits_for_sampler(sampler)
            if qubits is None:
                raise ValueError("Couldn't determine qubits from sampler. Please specify them.")
        else:
            qubits_set = set(itertools.chain(*pairs))
            qubits = list(qubits_set)

    if pairs is None:
        pairs = [
            pair for pair in itertools.combinations(qubits, 2) if _manhattan_distance(*pair) == 1
        ]

    return qubits, pairs
Extract qubits and pairs from sampler.


    If qubits are not provided, then they are extracted from the pairs (if given) or the sampler.
    If pairs are not provided then all pairs of adjacent qubits are used.

    Args:
        sampler: The quantum engine or simulator to run the circuits.
        qubits: Optional list of qubits.
        pairs: Optional list of pair to use.

    Returns:
        - Qubits to use.
        - Pairs of qubits to use.

    Raises:
        ValueError: If qubits are not specified and can't be deduced from other arguments.
    
cirq-core/cirq/experiments/two_qubit_xeb.py