def run_shuffled_with_readout_benchmarking(
    input_circuits: list[circuits.Circuit],
    sampler: work.Sampler,
    circuit_repetitions: int | list[int],
    rng_or_seed: np.random.Generator | int,
    num_random_bitstrings: int = 100,
    readout_repetitions: int = 1000,
    qubits: list[ops.Qid] | list[list[ops.Qid]] | None = None,
) -> tuple[list[ResultDict], dict[tuple[ops.Qid, ...], SingleQubitReadoutCalibrationResult]]:
    """Run the circuits in a shuffled order with readout error benchmarking.

    Args:
        input_circuits: The circuits to run.
        sampler: The sampler to use.
        circuit_repetitions: The repetitions for `circuits`.
        rng_or_seed: A random number generator used to generate readout circuits.
                     Or an integer seed.
        num_random_bitstrings: The number of random bitstrings for measuring readout.
            If set to 0, no readout calibration circuits are generated.
        readout_repetitions: The number of repetitions for each readout bitstring.
        qubits: The qubits to benchmark readout errors. If None, all qubits in the
                input_circuits are used. Can be a list of qubits or a list of tuples
                of qubits.

    Returns:
        A tuple containing:
        - A list of dictionaries with the unshuffled measurement results.
        - A dictionary mapping each tuple of qubits to a SingleQubitReadoutCalibrationResult.

    """

    _validate_input(
        input_circuits, circuit_repetitions, rng_or_seed, num_random_bitstrings, readout_repetitions
    )

    # If input qubits is None, extract qubits from input circuits
    qubits_to_measure: list[list[ops.Qid]] = []
    if qubits is None:
        qubits_set: set[ops.Qid] = set()
        for circuit in input_circuits:
            qubits_set.update(circuit.all_qubits())
        qubits_to_measure = [sorted(qubits_set)]
    elif isinstance(qubits[0], ops.Qid):
        qubits_to_measure = [qubits]  # type: ignore
    else:
        qubits_to_measure = qubits  # type: ignore

    # Generate the readout calibration circuits if num_random_bitstrings>0
    # Else all_readout_calibration_circuits and all_random_bitstrings are empty
    all_readout_calibration_circuits = []
    all_random_bitstrings = []

    rng = (
        rng_or_seed
        if isinstance(rng_or_seed, np.random.Generator)
        else np.random.default_rng(rng_or_seed)
    )
    if num_random_bitstrings > 0:
        for qubit_group in qubits_to_measure:
            readout_calibration_circuits, random_bitstrings = (
                _generate_readout_calibration_circuits(qubit_group, rng, num_random_bitstrings)
            )
            all_readout_calibration_circuits.extend(readout_calibration_circuits)
            all_random_bitstrings.append(random_bitstrings)

    # Shuffle the circuits
    if isinstance(circuit_repetitions, int):
        circuit_repetitions = [circuit_repetitions] * len(input_circuits)
    all_repetitions = circuit_repetitions + [readout_repetitions] * len(
        all_readout_calibration_circuits
    )

    shuffled_circuits, all_repetitions, unshuf_order = _shuffle_circuits(
        input_circuits + all_readout_calibration_circuits, all_repetitions, rng
    )

    # Run the shuffled circuits and measure
    results = sampler.run_batch(shuffled_circuits, repetitions=all_repetitions)
    timestamp = time.time()
    shuffled_measurements = [res[0] for res in results]
    unshuffled_measurements = [shuffled_measurements[i] for i in unshuf_order]

    unshuffled_input_circuits_measiurements = unshuffled_measurements[: len(input_circuits)]
    unshuffled_readout_measurements = unshuffled_measurements[len(input_circuits) :]

    # Analyze results
    readout_calibration_results = {}
    start_idx = 0
    for qubit_group, random_bitstrings in zip(qubits_to_measure, all_random_bitstrings):
        end_idx = start_idx + len(random_bitstrings)
        group_measurements = unshuffled_readout_measurements[start_idx:end_idx]
        calibration_result = _analyze_readout_results(
            group_measurements, random_bitstrings, readout_repetitions, qubit_group, timestamp
        )
        readout_calibration_results[tuple(qubit_group)] = calibration_result
        start_idx = end_idx

    return unshuffled_input_circuits_measiurements, readout_calibration_results
Run the circuits in a shuffled order with readout error benchmarking.

    Args:
        input_circuits: The circuits to run.
        sampler: The sampler to use.
        circuit_repetitions: The repetitions for `circuits`.
        rng_or_seed: A random number generator used to generate readout circuits.
                     Or an integer seed.
        num_random_bitstrings: The number of random bitstrings for measuring readout.
            If set to 0, no readout calibration circuits are generated.
        readout_repetitions: The number of repetitions for each readout bitstring.
        qubits: The qubits to benchmark readout errors. If None, all qubits in the
                input_circuits are used. Can be a list of qubits or a list of tuples
                of qubits.

    Returns:
        A tuple containing:
        - A list of dictionaries with the unshuffled measurement results.
        - A dictionary mapping each tuple of qubits to a SingleQubitReadoutCalibrationResult.

    
cirq-core/cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py