docstr: Returns the classes timeline given the ID of a experience.
  
  Given a experience ID, this method returns the classes in that
  experience, previously seen classes, the cumulative class list and a
  list of classes that will be encountered in next experiences of the
  same stream.
  
  Beware that by default this will obtain the timeline of an experience
  of the **training** stream. Use the stream parameter to select another
  stream.
  
  :param current_experience: The reference experience ID.
  :param stream: The stream name.
  :return: A tuple composed of four lists: the first list contains the
      IDs of classes in this experience, the second contains IDs of
      classes seen in previous experiences, the third returns a cumulative
      list of classes (that is, the union of the first two list) while the
      last one returns a list of classes that will be encountered in next
      experiences. Beware that each of these elements can be None when
      the benchmark is initialized by using a lazy generator.
code: def get_classes_timeline(
      self, current_experience: int, stream: str = "train"
  ) -> Tuple[
      Optional[List[int]],
      Optional[List[int]],
      Optional[List[int]],
      Optional[List[int]],
  ]:
      """
      Returns the classes timeline given the ID of a experience.
  
      Given a experience ID, this method returns the classes in that
      experience, previously seen classes, the cumulative class list and a
      list of classes that will be encountered in next experiences of the
      same stream.
  
      Beware that by default this will obtain the timeline of an experience
      of the **training** stream. Use the stream parameter to select another
      stream.
  
      :param current_experience: The reference experience ID.
      :param stream: The stream name.
      :return: A tuple composed of four lists: the first list contains the
          IDs of classes in this experience, the second contains IDs of
          classes seen in previous experiences, the third returns a cumulative
          list of classes (that is, the union of the first two list) while the
          last one returns a list of classes that will be encountered in next
          experiences. Beware that each of these elements can be None when
          the benchmark is initialized by using a lazy generator.
      """
      class_set_current_exp = self.classes_in_experience[stream][
          current_experience
      ]
  
      if class_set_current_exp is not None:
          # May be None in lazy benchmarks
          classes_in_this_exp = list(class_set_current_exp)
      else:
          classes_in_this_exp = None
  
      prev_exps_not_none = True
      class_set_prev_exps: Set[int] = set()
      for exp_id in range(0, current_experience):
          prev_exp_classes = self.classes_in_experience[stream][exp_id]
          if prev_exp_classes is None:
              # May be None in lazy benchmarks
              prev_exps_not_none = False
              break
          class_set_prev_exps.update(prev_exp_classes)
  
      if prev_exps_not_none:
          previous_classes = list(class_set_prev_exps)
      else:
          previous_classes = None
  
      if class_set_current_exp is not None and prev_exps_not_none:
          classes_seen_so_far = list(
              class_set_current_exp.union(class_set_prev_exps)
          )
      else:
          classes_seen_so_far = None
  
      future_exps_not_none = True
      class_set_future_exps: Set[int] = set()
      stream_n_exps = len(self.classes_in_experience[stream])
      for exp_id in range(current_experience + 1, stream_n_exps):
          future_exp_classes = self.classes_in_experience[stream][
              exp_id
          ]
          if future_exp_classes is None:
              future_exps_not_none = False
              break
          class_set_future_exps.update(future_exp_classes)
  
      if future_exps_not_none:
          future_classes = list(class_set_future_exps)
      else:
          future_classes = None
  
      return (
          classes_in_this_exp,
          previous_classes,
          classes_seen_so_far,
          future_classes,
      )
  
imports: from abc import ABC, abstractmethod
  from dataclasses import dataclass
  import re
  from typing import Generic, TypeVar, Union, Sequence, Callable, Optional, Dict, Any, Iterable, List, Set, Tuple, Mapping, TYPE_CHECKING
  from .None import DatasetExperience
  from ..generic_scenario import CLScenario, CLExperience, CLStream, SequenceCLStream
  from .lazy_dataset_sequence import LazyDatasetSequence
  from avalanche.benchmarks.utils import AvalancheDataset
  from torch.utils.data.dataset import Dataset
label_desc: Use image node_id 2 for calling the ClassesTimelineCLScenario obj's underlying member method code with example usage: obj.get_classes_timeline(current_experience, stream) and returns: classes_in_this_exp,  previous_classes,  classes_seen_so_far,  future_classes