code: def split_continuous_linear_decay_stream(
      original_stream: Iterable[DatasetExperience[TCLDataset]],
      experience_size: int,
      iters_per_virtual_epoch: int,
      beta: float,
      shuffle: bool,
  ) -> CLStream[DatasetExperience[TCLDataset]]:
      """Creates a stream of sub-experiences from a list of overlapped
          experiences with a linear decay in the overlapping areas.
  
      :param original_stream: The original stream.
      :param experience_size: The size of each sub-experience.
      :param iters_per_virtual_epoch: The number of iterations per virtual epoch.
          This parameter determines the number of (sub-)experiences that we want
          to create from each experience in the original stream, after "merging"
          all experiences with a certain level of "overlap".
      :param beta: The beta parameter for the linear decay function which
          indicates the amount of overlap.
      :param shuffle: Whether to shuffle the sub-experiences.
  
      Terminology is taken from the official implementation of the paper:
      "Task Agnostic Continual Learning Using Online Variational Bayes" by
      Zero et al. (https://arxiv.org/abs/2006.05990)
      Code repo: https://github.com/chenzeno/FOO-VB/tree/main
  
      :return: A stream of sub-experiences.
  
      """
  
      def _get_linear_line(start, end, direction="up"):
          if direction == "up":
              return torch.FloatTensor(
                  [
                      (i - start) / (end - start)
                      for i in range(start, end)
                  ]
              )
          return torch.FloatTensor(
              [
                  1 - ((i - start) / (end - start))
                  for i in range(start, end)
              ]
          )
  
      def _create_task_probs(iters, tasks, task_id, beta=3):
          if beta <= 1:
              peak_start = int((task_id / tasks) * iters)
              peak_end = int(((task_id + 1) / tasks) * iters)
              start = peak_start
              end = peak_end
          else:
              start = max(
                  int(((beta * task_id - 1) * iters) / (beta * tasks)),
                  0,
              )
              peak_start = int(
                  ((beta * task_id + 1) * iters) / (beta * tasks)
              )
              peak_end = int(
                  ((beta * task_id + (beta - 1)) * iters)
                  / (beta * tasks)
              )
              end = min(
                  int(
                      ((beta * task_id + (beta + 1)) * iters)
                      / (beta * tasks)
                  ),
                  iters,
              )
  
          probs = torch.zeros(iters, dtype=torch.float)
          if task_id == 0:
              probs[start:peak_start].add_(1)
          else:
              probs[start:peak_start] = _get_linear_line(
                  start, peak_start, direction="up"
              )
          probs[peak_start:peak_end].add_(1)
          if task_id == tasks - 1:
              probs[peak_end:end].add_(1)
          else:
              probs[peak_end:end] = _get_linear_line(
                  peak_end, end, direction="down"
              )
          return probs
  
      # Total number of iterations
      total_iters = len(original_stream) * iters_per_virtual_epoch
  
      # Probabilities over all iterations (sub-experiences)
      n_experiences = len(original_stream)
      tasks_probs_over_iterations = [
          _create_task_probs(
              total_iters, n_experiences, exp_id, beta=beta
          )
          for exp_id in range(n_experiences)
      ]
  
      # Normalize probabilities
      normalize_probs = torch.zeros_like(tasks_probs_over_iterations[0])
      for probs in tasks_probs_over_iterations:
          normalize_probs.add_(probs)
      for probs in tasks_probs_over_iterations:
          probs.div_(normalize_probs)
      tasks_probs_over_iterations = torch.cat(
          tasks_probs_over_iterations
      ).view(-1, tasks_probs_over_iterations[0].shape[0])
      tasks_probs_over_iterations_lst = []
      for col in range(tasks_probs_over_iterations.shape[1]):
          tasks_probs_over_iterations_lst.append(
              tasks_probs_over_iterations[:, col]
          )
      tasks_probs_over_iterations = tasks_probs_over_iterations_lst
  
      # Random cylic samplers over the datasets of all experiences in the stream
      samplers = [
          iter(CyclicSampler(len(exp.dataset), shuffle=shuffle))
          for exp in original_stream
      ]
  
      # The main iterator for the stream
      def exps_iter():
          for sub_exp_id in range(total_iters):
              is_first_sub_exp = is_last_sub_exp = False
              if sub_exp_id == 0:
                  is_first_sub_exp = True
              if sub_exp_id == total_iters - 1:
                  is_last_sub_exp = True
  
              n_samples = torch.Size([experience_size])
              exp_per_sample_list = Categorical(
                  probs=tasks_probs_over_iterations[sub_exp_id]
              ).sample(n_samples)
  
              yield create_sub_exp_from_multi_exps(
                  original_stream,
                  samplers,
                  exp_per_sample_list,
                  total_iters,
                  is_first_sub_exp,
                  is_last_sub_exp,
              )
  
      stream_name: str = getattr(original_stream, "name", "train")
      return CLStream(
          name=stream_name,
          exps_iter=exps_iter(),
          set_stream_info=True,
      )
  
imports: from functools import partial
  import random
  from typing import Callable, Generator, Generic, Iterable, List, Optional, TypeVar, Union, Protocol
  from typing_extensions import Literal
  import warnings
  from avalanche.benchmarks.utils.data import AvalancheDataset
  from avalanche.benchmarks.utils.utils import concat_datasets
  import torch
  from torch.distributions.categorical import Categorical
  from torch.utils.data import Sampler
  from .deprecated.benchmark_wrapper_utils import wrap_stream
  from .generic_scenario import CLStream, CLScenario
  from .dataset_scenario import DatasetExperience
label_desc: Use image node_id 5 for calling a global function with example usage: split_continuous_linear_decay_stream(original_stream, experience_size, iters_per_virtual_epoch, beta, shuffle) and returns: CLStream, torch, probs, torch