code: def split_validation_random(
      validation_size: Union[int, float],
      shuffle: bool,
      seed: Optional[int] = None,
      dataset: Optional[AvalancheDataset] = None,
  ) -> Tuple[AvalancheDataset, AvalancheDataset]:
      """Splits an `AvalancheDataset` in two splits.
  
      The default splitting strategy used by
      :func:`benchmark_with_validation_stream`.
  
      This splitting strategy simply splits the datasets in two (e.g. a
      train and validation split) of size `validation_size`.
  
      When taking inspiration for your custom splitting strategy, please consider
      that all parameters preceding `experience` are filled by
      :func:`benchmark_with_validation_stream` by using `partial` from the
      `functools` standard library. A custom splitting strategy must have only
      a single parameter: the experience. Consider wrapping your custom
      splitting strategy with `partial` if more parameters are needed.
  
      You can use this split strategy with methdos that require a custom
      split strategy such as :func:`benchmark_with_validation_stream`to split
      a benchmark with::
  
          validation_size = 0.2
          foo = lambda exp: split_validation_class_balanced(validation_size, exp)
          bm = benchmark_with_validation_stream(bm, split_strategy=foo)
  
      :param validation_size: The number of instances to allocate to the
      validation experience. Can be an int value or a float between 0 and 1.
      :param shuffle: If True, instances will be shuffled before splitting.
          Otherwise, the first instances will be allocated to the training
          dataset by leaving the last ones to the validation dataset.
      :param dataset: The dataset to split.
      :return: A tuple containing 2 elements: the new training and validation
          datasets.
      """
      if dataset is None:
          raise ValueError("dataset must be provided")
      exp_indices = list(range(len(dataset)))
  
      if seed is None:
          seed = random.randint(0, 1000000)
      g = torch.Generator()
      g.manual_seed(seed)
  
      if shuffle:
          exp_indices = torch.as_tensor(exp_indices)[
              torch.randperm(len(exp_indices), generator=g)
          ].tolist()
  
      if 0.0 <= validation_size <= 1.0:
          valid_n_instances = int(validation_size * len(dataset))
      else:
          valid_n_instances = int(validation_size)
          if valid_n_instances > len(dataset):
              raise ValueError(
                  f"Can't split the dataset: not enough "
                  f"instances. Required {valid_n_instances}, got only"
                  f"{len(dataset)}"
              )
  
      train_n_instances = len(dataset) - valid_n_instances
      d1 = dataset.subset(exp_indices[:train_n_instances])
      d2 = dataset.subset(exp_indices[train_n_instances:])
      return d1, d2
  
imports: import random
  from avalanche.benchmarks.utils.data import AvalancheDataset
  import torch
  from itertools import tee
  from typing import Callable, Generator, Generic, List, Sequence, TypeVar, Union, Tuple, Optional, Iterable, Dict
  from .generic_scenario import EagerCLStream, CLScenario, CLExperience, make_stream
  from ..utils import TaskAwareSupervisedClassificationDataset
label_desc: Use image node_id 3 for calling a global function with example usage: split_validation_random(validation_size, shuffle, seed, dataset) and returns: d1,  d2