def simulate_circuit_library(
    circuit_templates: Sequence[cirq.Circuit],
    target_or_dict: _CANONICAL_TARGET_T,
    cycle_depths: Sequence[int],
    pool: futures.Executor | None = None,
) -> Sequence[Sequence[np.ndarray]] | dict[_QUBIT_PAIR_T, Sequence[Sequence[np.ndarray]]]:
    """Simulate the given sequence of circuits.

    Args:
        circuit_templates: A sequence of circuits to simulate.
        target_or_dict: The target operation or dictionary mapping qubit-pairs to operations.
        cycle_depths: A list of integers giving the cycle depths to use in benchmarking.
        pool: An optional concurrent.futures.Executor pool (e.g. ThreadPoolExecutor).
            If given, the simulations are performed asynchronously.

    Returns:
        If target_or_dict is an operation:
            A sequence of the result of simulate_circuit for each circuit_templates.
        Else:
            A dictionary mapping the keys of the map to a sequence of the result of
            simulate_circuit for each circuit_templates.
    """
    two_qubit_ops = []
    keys = None
    if isinstance(target_or_dict, dict):
        keys = tuple(target_or_dict.keys())
        two_qubit_ops = list(target_or_dict[k] for k in keys)
    else:
        two_qubit_ops = [target_or_dict]

    all_circuits = []
    for target_op in two_qubit_ops:

        def _map_op(op: ops.Operation) -> ops.Operation:
            num_qubits = protocols.num_qubits(op)
            if num_qubits <= 1:
                return op
            assert num_qubits == 2
            return target_op.with_qubits(*op.qubits)

        for circuit in circuit_templates:
            all_circuits.append(circuit.map_operations(_map_op))

    if pool is None:
        simulation_results = [
            simulate_circuit(
                sim.Simulator(seed=np.random.RandomState(), dtype=np.complex128),
                circuit=circuit,
                cycle_depths=cycle_depths,
            )
            for circuit in all_circuits
        ]
    else:
        simulation_results = [[np.empty(0)] for _ in range(len(all_circuits))]
        tasks = [
            pool.submit(
                simulate_circuit,
                simulator=sim.Simulator(seed=np.random.RandomState(), dtype=np.complex128),
                circuit=circuit,
                cycle_depths=cycle_depths,
            )
            for circuit in all_circuits
        ]
        tasks_index = {t: i for i, t in enumerate(tasks)}
        for task in futures.as_completed(tasks):
            sim_result = task.result()
            i = tasks_index[task]
            simulation_results[i] = sim_result

    if keys is None:
        return simulation_results

    num_templates = len(circuit_templates)
    return {
        keys[i]: simulation_results[i * num_templates : (i + 1) * num_templates]
        for i in range(len(keys))
    }
Simulate the given sequence of circuits.

    Args:
        circuit_templates: A sequence of circuits to simulate.
        target_or_dict: The target operation or dictionary mapping qubit-pairs to operations.
        cycle_depths: A list of integers giving the cycle depths to use in benchmarking.
        pool: An optional concurrent.futures.Executor pool (e.g. ThreadPoolExecutor).
            If given, the simulations are performed asynchronously.

    Returns:
        If target_or_dict is an operation:
            A sequence of the result of simulate_circuit for each circuit_templates.
        Else:
            A dictionary mapping the keys of the map to a sequence of the result of
            simulate_circuit for each circuit_templates.
    
cirq-core/cirq/experiments/benchmarking/parallel_xeb.py