code: def _class_balanced_indices(
      data: ClassificationDataset,
      num_experiences: int,
      shuffle: bool = True,
      seed: Optional[int] = None,
  ) -> List[List[int]]:
      """class-balanced indices.
  
      Internal helper for `new_instances_benchmark`.
  
      :param data: the `AvalancheDataset` to split
      :param num_experiences: length of the stream
      :param shuffle: -
      :param seed: -
      """
      if seed is not None:
          torch.random.manual_seed(seed)
  
      # Validate function arguments
      if num_experiences < 1:
          raise ValueError(
              "Invalid number of experiences (n_experiences "
              "parameter): must be greater than 0"
          )
  
      # experience -> idxs assignment
      exps_idxs: List[List[int]] = [[] for _ in range(num_experiences)]
      # TODO: fix pycharm type hints
      for class_id, class_idxs in data.targets.val_to_idx.items():
          # INVARIANT: class_idxs keeps only indices that are not assigned yet.
          # Whenever we add idxs to an experience, we remove them from class_idxs
  
          if shuffle:  # shuffle each class
              perm = torch.randperm(len(class_idxs))
              class_idxs = torch.as_tensor(class_idxs)[perm].tolist()
  
          # distribute equally each class to experiences
          npats = len(class_idxs) // num_experiences
          for eid in range(num_experiences):
              exps_idxs[eid].extend(class_idxs[:npats])
              class_idxs = class_idxs[npats:]
  
          # distribute remainder if not divisible by num_experiences
          if len(class_idxs) > 0:
              if shuffle:
                  exps_remaining: Iterable[int] = torch.randperm(
                      num_experiences
                  ).tolist()[: len(class_idxs)]
              else:
                  exps_remaining = range(len(class_idxs))
              for eid in exps_remaining:
                  exps_idxs[eid].append(class_idxs[0])
                  class_idxs = class_idxs[1:]
  
      # sort to keep original order instead of class-order
      for eid in range(len(exps_idxs)):
          exps_idxs[eid].sort()
      return exps_idxs
  
imports: import warnings
  from copy import copy
  from typing import Iterable, Sequence, Optional, Dict, List, Protocol
  import torch
  from avalanche.benchmarks.utils.classification_dataset import ClassificationDataset, _as_taskaware_supervised_classification_dataset, TaskAwareSupervisedClassificationDataset
  from avalanche.benchmarks.utils.data import AvalancheDataset
  from avalanche.benchmarks.utils.data_attribute import DataAttribute
  from .dataset_scenario import _split_dataset_by_attribute, DatasetExperience
  from ..None import CLScenario, CLStream, EagerCLStream
label_desc: Use image node_id 2 for calling a global function with example usage: _class_balanced_indices(data, num_experiences, shuffle, seed) and returns: exps_idxs