def run_rb_and_xeb(
    sampler: cirq.Sampler,
    qubits: Sequence[cirq.GridQubit] | None = None,
    repetitions: int = 10**3,
    num_circuits: int = 20,
    num_clifford_range: Sequence[int] = tuple(
        np.logspace(np.log10(5), np.log10(1000), 5, dtype=int)
    ),
    entangling_gate: cirq.Gate = ops.CZ,
    depths_xeb: Sequence[int] = (5, 25, 50, 100, 200, 300),
    xeb_combinations: int = 10,
    random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
    pairs: Sequence[tuple[cirq.GridQubit, cirq.GridQubit]] | None = None,
    batch_size: int = 9,
    tags: Sequence[Any] = (),
) -> InferredXEBResult:
    """A convenience method that runs both RB and XEB workflows.

    Args:
        sampler: The quantum engine or simulator to run the circuits.
        qubits: Qubits under test. If none, uses all qubits on the sampler's device.
        repetitions: The number of repetitions to use for RB and XEB.
        num_circuits: The number of circuits to generate for RB and XEB.
        num_clifford_range: The different numbers of Cliffords in the RB study.
        entangling_gate: The entangling gate to use.
        depths_xeb: The cycle depths to use for XEB.
        xeb_combinations: The number of combinations to generate for XEB.
        random_state: The random state to use.
        pairs: Pairs to use. If not specified, use all pairs between adjacent qubits.
        batch_size: We call `run_batch` on the sampler, which can speed up execution in certain
            environments. The number of (circuit, cycle_depth) tasks to be run in each batch
            is given by this number.
        tags: Tags to add to two qubit operations.

    Returns:
        An InferredXEBResult object representing the results of the experiment.

    Raises:
        ValueError: If qubits are not specified and the sampler has no device.
    """

    qubits, pairs = qubits_and_pairs(sampler, qubits, pairs)

    rb = parallel_single_qubit_randomized_benchmarking(
        sampler=sampler,
        qubits=qubits,
        repetitions=repetitions,
        num_circuits=num_circuits,
        num_clifford_range=num_clifford_range,
    )

    xeb = parallel_two_qubit_xeb(
        sampler=sampler,
        qubits=qubits,
        pairs=pairs,
        entangling_gate=entangling_gate,
        n_repetitions=repetitions,
        n_circuits=num_circuits,
        cycle_depths=depths_xeb,
        n_combinations=xeb_combinations,
        random_state=random_state,
        batch_size=batch_size,
        tags=tags,
    )

    return InferredXEBResult(rb, xeb)
A convenience method that runs both RB and XEB workflows.

    Args:
        sampler: The quantum engine or simulator to run the circuits.
        qubits: Qubits under test. If none, uses all qubits on the sampler's device.
        repetitions: The number of repetitions to use for RB and XEB.
        num_circuits: The number of circuits to generate for RB and XEB.
        num_clifford_range: The different numbers of Cliffords in the RB study.
        entangling_gate: The entangling gate to use.
        depths_xeb: The cycle depths to use for XEB.
        xeb_combinations: The number of combinations to generate for XEB.
        random_state: The random state to use.
        pairs: Pairs to use. If not specified, use all pairs between adjacent qubits.
        batch_size: We call `run_batch` on the sampler, which can speed up execution in certain
            environments. The number of (circuit, cycle_depth) tasks to be run in each batch
            is given by this number.
        tags: Tags to add to two qubit operations.

    Returns:
        An InferredXEBResult object representing the results of the experiment.

    Raises:
        ValueError: If qubits are not specified and the sampler has no device.
    
cirq-core/cirq/experiments/two_qubit_xeb.py