def parallel_xeb_workflow(
    sampler: cirq.Sampler,
    target: _TARGET_T | dict[_QUBIT_PAIR_T, _TARGET_T],
    ideal_target: _TARGET_T | dict[_QUBIT_PAIR_T, _TARGET_T] | None = None,
    qubits: Sequence[cirq.GridQubit] | None = None,
    pairs: Sequence[_QUBIT_PAIR_T] | None = None,
    parameters: XEBParameters = XEBParameters(),
    rng: np.random.Generator | None = None,
    pool: futures.Executor | None = None,
) -> Sequence[XEBFidelity]:
    """A utility method that runs the full XEB workflow.

    Args:
        sampler: The quantum engine or simulator to run the circuits.
        target: The entangling gate, op, circuit or dict mapping pairs to ops.
        ideal_target: The ideal target(s) to branch mark against. If None, use `target`.
        qubits: Qubits under test. If None, uses all qubits on the sampler's device.
        pairs: Pairs to use. If not specified, use all pairs between adjacent qubits.
        parameters: An `XEBParameters` containing the parameters of the XEB experiment.
        rng: The random number generator to use.
        pool: An optional `concurrent.futures.Executor` pool.

    Returns:
        A sequence of XEBFidelity listing the estimated fidelity for each qubit_pair per depth.

    Raises:
        ValueError: If qubits are not specified and the sampler has no device.
    """
    if rng is None:
        rng = np.random.default_rng()
    rs = np.random.RandomState(rng.integers(0, 10**9))

    pairs = _extract_pairs(sampler, target, qubits, pairs)
    graph = nx.Graph(pairs)

    circuit_templates = rqcg.generate_library_of_2q_circuits(
        n_library_circuits=parameters.n_circuits,
        random_state=rs,
        # Any two qubit gate works here since we creating templates rather than the actual circuits.
        two_qubit_gate=ops.CZ,
        max_cycle_depth=max(parameters.cycle_depths),
    )

    combs_by_layer = rqcg.get_random_combinations_for_device(
        n_library_circuits=len(circuit_templates),
        n_combinations=parameters.n_combinations,
        device_graph=graph,
        random_state=rs,
    )

    canonical_target = _canonize_target(target)
    if ideal_target is None:
        canonical_ideal_target = canonical_target
    else:
        canonical_ideal_target = _canonize_target(ideal_target)

    if isinstance(canonical_target, dict):
        assert all(
            all(pair in canonical_target for pair in layer_comb.pairs)
            for layer_comb in combs_by_layer
        )

    if isinstance(canonical_ideal_target, dict):
        assert all(
            all(pair in canonical_ideal_target for pair in layer_comb.pairs)
            for layer_comb in combs_by_layer
        )

    wide_circuits_info = create_combination_circuits(
        circuit_templates, combs_by_layer, canonical_target
    )
    wide_circuits_info = [
        info_with_depth
        for info in wide_circuits_info
        for info_with_depth in info.sliced_circuits(parameters.cycle_depths)
    ]

    # A map {measurement_key: sampled_probs}  for each wide circuit
    sampling_results = sample_all_circuits(
        sampler, [info.wide_circuit for info in wide_circuits_info], parameters.n_repetitions
    )

    # Either of a pure_probability[circuit_template_idx][cycle_depth_index] or
    #   A map pure_probability[pair][circuit_template_idx][cycle_depth_index]
    simulation_results = simulate_circuit_library(
        circuit_templates, canonical_ideal_target, parameters.cycle_depths, pool
    )

    estimated_fidelities = estimate_fidelities(
        sampling_results,
        simulation_results,
        parameters.cycle_depths,
        wide_circuits_info,
        pairs,
        parameters.n_circuits,
    )
    return estimated_fidelities
A utility method that runs the full XEB workflow.

    Args:
        sampler: The quantum engine or simulator to run the circuits.
        target: The entangling gate, op, circuit or dict mapping pairs to ops.
        ideal_target: The ideal target(s) to branch mark against. If None, use `target`.
        qubits: Qubits under test. If None, uses all qubits on the sampler's device.
        pairs: Pairs to use. If not specified, use all pairs between adjacent qubits.
        parameters: An `XEBParameters` containing the parameters of the XEB experiment.
        rng: The random number generator to use.
        pool: An optional `concurrent.futures.Executor` pool.

    Returns:
        A sequence of XEBFidelity listing the estimated fidelity for each qubit_pair per depth.

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