class_docstr: Repeat a block by a variable number of times.
  
  Parameters
  ----------
  blocks : function, list of function, module or list of module
      The block to be repeated. If not a list, it will be replicated (**deep-copied**) into a list.
      If a list, it should be of length ``max_depth``, the modules will be instantiated in order and a prefix will be taken.
      If a function, it will be called (the argument is the index) to instantiate a module.
      Otherwise the module will be deep-copied.
  depth : int or tuple of int
      If one number, the block will be repeated by a fixed number of times. If a tuple, it should be (min, max),
      meaning that the block will be repeated at least ``min`` times and at most ``max`` times.
      If a ValueChoice, it should choose from a series of positive integers.
  
      .. versionadded:: 2.8
  
         Minimum depth can be 0. But this feature is NOT supported on graph engine.
  
  Examples
  --------
  Block() will be deep copied and repeated 3 times. ::
  
      self.blocks = nn.Repeat(Block(), 3)
  
  Block() will be repeated 1, 2, or 3 times. ::
  
      self.blocks = nn.Repeat(Block(), (1, 3))
  
  Can be used together with layer choice.
  With deep copy, the 3 layers will have the same label, thus share the choice. ::
  
      self.blocks = nn.Repeat(nn.LayerChoice([...]), (1, 3))
  
  To make the three layer choices independent,
  we need a factory function that accepts index (0, 1, 2, ...) and returns the module of the ``index``-th layer. ::
  
      self.blocks = nn.Repeat(lambda index: nn.LayerChoice([...], label=f'layer{index}'), (1, 3))
  
  Depth can be a ValueChoice to support arbitrary depth candidate list. ::
  
      self.blocks = nn.Repeat(Block(), nn.ValueChoice([1, 3, 5]))
class_docstr_tok: ["Repeat","a","block","by","a","variable","number","of","times",".","Parameters","--","--","--","--","--","blocks",":","function",",","list","of","function",",","module","or","list","of","module","The","block","to","be","repeated",".","If","not","a","list",",","it","will","be","replicated","(","*","*","deep-copied","*","*",")","into","a","list",".","If","a","list",",","it","should","be","of","length","``","max_depth","``",",","the","modules","will","be","instantiated","in","order","and","a","prefix","will","be","taken",".","If","a","function",",","it","will","be","called","(","the","argument","is","the","index",")","to","instantiate","a","module",".","Otherwise","the","module","will","be","deep-copied",".","depth",":","int","or","tuple","of","int","If","one","number",",","the","block","will","be","repeated","by","a","fixed","number","of","times",".","If","a","tuple",",","it","should","be","(","min",",","max",")",",","meaning","that","the","block","will","be","repeated","at","least","``","min","``","times","and","at","most","``","max","``","times",".","If","a","ValueChoice",",","it","should","choose","from","a","series","of","positive","integers",".","..","versionadded",":",":","2.8","Minimum","depth","can","be","0",".","But","this","feature","is","NOT","supported","on","graph","engine",".","Examples","--","--","--","--","Block","(",")","will","be","deep","copied","and","repeated","3","times",".",":",":","self.blocks","=","nn.Repeat","(","Block","(",")",",","3",")","Block","(",")","will","be","repeated","1",",","2",",","or","3","times",".",":",":","self.blocks","=","nn.Repeat","(","Block","(",")",",","(","1",",","3",")",")","Can","be","used","together","with","layer","choice",".","With","deep","copy",",","the","3","layers","will","have","the","same","label",",","thus","share","the","choice",".",":",":","self.blocks","=","nn.Repeat","(","nn.LayerChoice","(","[","...","]",")",",","(","1",",","3",")",")","To","make","the","three","layer","choices","independent",",","we","need","a","factory","function","that","accepts","index","(","0",",","1",",","2",",","...",")","and","returns","the","module","of","the","``","index","``","-th","layer",".",":",":","self.blocks","=","nn.Repeat","(","lambda","index",":","nn.LayerChoice","(","[","...","]",",","label=f'layer","{","index","}","'",")",",","(","1",",","3",")",")","Depth","can","be","a","ValueChoice","to","support","arbitrary","depth","candidate","list",".",":",":","self.blocks","=","nn.Repeat","(","Block","(",")",",","nn.ValueChoice","(","[","1",",","3",",","5","]",")",")"]
code: def __init__(
      self,
      blocks: Union[
          Callable[[int], nn.Module],
          List[Callable[[int], nn.Module]],
          nn.Module,
          List[nn.Module],
      ],
      depth: Union[int, Tuple[int, int], SymbolicExpression],
      *,
      label: Optional[str] = None,
  ):
      super().__init__()
  
      self._label = None  # by default, no label
  
      if isinstance(depth, SymbolicExpression):
          assert isinstance(
              depth, Mutable
          ), "depth must be Mutable and SymbolicExpression at the same time."
          if label is not None:
              warnings.warn(
                  "In repeat, `depth` is already a mutable, but `label` is still set. It will be ignored.",
                  RuntimeWarning,
              )
  
          self.depth_choice: Union[int, MutableExpression] = cast(
              Union[int, MutableExpression], depth
          )
          all_values = _all_finite_integers(depth)
          self.min_depth = min(all_values)
          self.max_depth = max(all_values)
  
      elif isinstance(depth, tuple):
          self.min_depth = depth if isinstance(depth, int) else depth[0]
          self.max_depth = depth if isinstance(depth, int) else depth[1]
          self.depth_choice: Union[
              int, MutableExpression
          ] = Categorical(
              list(range(self.min_depth, self.max_depth + 1)),
              label=label,
          )
          self._label = self.depth_choice.label
  
      elif isinstance(depth, int):
          self.min_depth = self.max_depth = depth
          self.depth_choice: Union[int, MutableExpression] = depth
      else:
          raise TypeError(f'Unsupported "depth" type: {type(depth)}')
      assert (
          self.max_depth >= self.min_depth >= 0 and self.max_depth >= 1
      ), f"Depth of {self.min_depth} to {self.max_depth} is invalid."
  
      if isinstance(self.depth_choice, Mutable):
          self.add_mutable(self.depth_choice)
          self._dry_run_depth = ensure_frozen(self.depth_choice)
      else:
          self._dry_run_depth = self.depth_choice
  
      if isinstance(blocks, nn.ModuleList):
          _logger.warning(
              "Using ModuleList as blocks will make the whole module list be treated as one block, "
              "and it will be deep-copied. This might be not intended in most cases. "
              "Consider using a pure python list of modules if you want to specify a sequence of blocks."
          )
  
      self.blocks = nn.ModuleList(
          self._replicate_and_instantiate(blocks, self.max_depth)
      )
  
imports: import copy
  import logging
  import warnings
  from contextlib import contextmanager
  from typing import Callable, List, Union, Tuple, Optional, cast
  import torch
  import torch.nn
  from nni.mutable import Categorical, LabeledMutable, Mutable, Sample, SampleValidationError, ensure_frozen
  from nni.mutable.mutable import MutableExpression
  from nni.mutable.symbol import SymbolicExpression
  from .base import MutableModule, recursive_freeze
label_desc: Use image node_id 3 to create a new Repeat object from inherited base classes: MutableModule with example: obj = Repeat(blocks, depth)