code: def _expand_repeat(self, network):
      def _search_repeat_id(mes, rid):
          return (
              list(mes.repeat_id).index(rid)
              if rid in mes.repeat_id
              else None
          )
  
      def _add_suffix(name, suffix, num):
          return "{}_{}[{}]".format(name, suffix, num)
  
      ########################################################################
      # Prepare output network message
      net = nnabla_pb2.NNablaProtoBuf().network.add()
      net.CopyFrom(network)
  
      ########################################################################
      # Finish when repeat_info is not present
      if len(net.repeat_info) == 0:
          return net
  
      ########################################################################
      # Use first repeat_info
      ri = net.repeat_info[0]
      del net.repeat_info[0]
  
      ########################################################################
      # Expand variables
      net.ClearField("variable")
      for vpos, var in enumerate(network.variable):
          if var.type == "Parameter":
              if var.name not in self._parameter_original_names:
                  self._parameter_original_names[var.name] = []
  
          pos = _search_repeat_id(var, ri.id)
          if pos is not None:
              for i in range(ri.times):
                  if var.type == "Parameter":
                      pv_repeat_id = "{" + ri.id + "}"
                      if not pv_repeat_id in var.name:
                          name = _add_suffix(var.name, ri.id, i)
                      else:
                          name = var.name.replace(
                              "{{{}}}".format(ri.id), "[{}]".format(i)
                          )
                      self._parameter_original_names[var.name].append(
                          name
                      )
                  else:
                      name = _add_suffix(var.name, ri.id, i)
  
                  v = net.variable.add()
                  v.CopyFrom(var)
                  v.name = name
                  del v.repeat_id[pos]
          else:
              if (
                  var.type == "Parameter"
                  and len(var.repeat_id) == 0
                  and len(self._parameter_original_names[var.name]) == 0
              ):
                  self._parameter_original_names[var.name].append(
                      var.name
                  )
              v = net.variable.add()
              v.CopyFrom(var)
  
      ########################################################################
      # Expand functions
      ########################################################################
  
      ########################################################################
      # Prepare delayed inputs
      delay_var = {}
      for fpos, func in enumerate(network.function):
          if func.type == "Delay":
              if func.recurrent_param.repeat_id == ri.id:
                  delay_var[func.output[0]] = []
                  for i in range(ri.times):
                      if i == 0:
                          delay_var[func.output[0]].append(
                              func.input[1]
                          )
                      else:
                          v = func.input[0]
                          v = _add_suffix(v, ri.id, i - 1)
                          delay_var[func.output[0]].append(v)
  
      ########################################################################
      # Prepare repeat end inputs
      repeat_end_var = {}
      for fpos, func in enumerate(network.function):
          if func.type == "RepeatEnd":
              if func.repeat_param.repeat_id == ri.id:
                  repeat_end_var[func.output[0]] = []
                  for i in range(func.repeat_param.times):
                      repeat_end_var[func.output[0]].append(
                          _add_suffix(
                              func.input[0],
                              func.repeat_param.repeat_id,
                              i,
                          )
                      )
  
      ########################################################################
      # Prepare repeat start inputs
      repeat_start_var = {}
      for fpos, func in enumerate(network.function):
          if func.type == "RepeatStart":
              if func.repeat_param.repeat_id == ri.id:
                  repeat_start_var[func.output[0]] = []
                  for i in range(ri.times):
                      if i == 0:
                          v = func.input[0]
                          if v in repeat_end_var:
                              v = repeat_end_var[v][ri.times - 1]
                          repeat_start_var[func.output[0]].append(v)
                      else:
                          v = func.input[1]
                          if v in repeat_end_var:
                              v = repeat_end_var[v][i - 1]
                          else:
                              v = _add_suffix(v, ri.id, i - 1)
                          repeat_start_var[func.output[0]].append(v)
  
      ########################################################################
      # Expand network
      net.ClearField("function")
      for fpos, func in enumerate(network.function):
          if func.type == "RepeatStart" or func.type == "RepeatEnd":
              if func.repeat_param.repeat_id == ri.id:
                  continue
          if func.type == "Delay":
              if func.recurrent_param.repeat_id == ri.id:
                  continue
          if func.type == "RecurrentInput":
              if func.recurrent_param.repeat_id == ri.id:
                  f = net.function.add()
                  f.CopyFrom(func)
                  f.type = "Split"
                  f.split_param.axis = func.recurrent_param.axis
  
                  f.ClearField("output")
                  for i in range(ri.times):
                      f.output.append(
                          _add_suffix(func.output[0], ri.id, i)
                      )
  
                  pos = _search_repeat_id(func, ri.id)
                  del f.repeat_id[pos]
                  f.ClearField("recurrent_param")
                  continue
  
          if func.type == "RecurrentOutput":
              if func.recurrent_param.repeat_id == ri.id:
                  f = net.function.add()
                  f.CopyFrom(func)
                  f.type = "Stack"
                  f.stack_param.axis = func.recurrent_param.axis
  
                  f.ClearField("input")
                  for i in range(ri.times):
                      f.input.append(
                          _add_suffix(func.input[0], ri.id, i)
                      )
  
                  f.ClearField("recurrent_param")
                  continue
  
          pos = _search_repeat_id(func, ri.id)
          if pos is not None:
              for i in range(ri.times):
                  f = net.function.add()
                  f.CopyFrom(func)
  
                  del f.repeat_id[pos]
  
                  f.name = _add_suffix(func.name, ri.id, i)
                  for n, v in enumerate(func.input):
                      vname = None
                      if v in self._parameter_original_names:
                          if (
                              len(self._parameter_original_names[v])
                              == ri.times
                          ):
                              vname = self._parameter_original_names[v][
                                  i
                              ]
                          else:
                              vname = v
                      elif v in repeat_start_var:
                          vname = repeat_start_var[v][i]
                      elif v in repeat_end_var:
                          vname = repeat_end_var[v][i]
                      elif v in delay_var:
                          vname = delay_var[v][i]
                      else:
                          vname = _add_suffix(v, ri.id, i)
                      f.input[n] = vname
                  for n, v in enumerate(func.output):
                      vname = _add_suffix(v, ri.id, i)
                      f.output[n] = vname
  
          else:
              f = net.function.add()
              f.CopyFrom(func)
              for n, v in enumerate(func.input):
                  if v in repeat_end_var:
                      vname = repeat_end_var[v][ri.times - 1]
                      f.input[n] = vname
  
      return self._expand_repeat(net)
  
file_path: nnabla/python/test/core/legacy_expander.py
imports: import collections
  import re
  from nnabla.utils import nnabla_pb2
label_desc: Use image node_id 2 for calling the NnpExpander obj's underlying member method code with example usage: obj._expand_repeat(network) and returns: self, unknown, str, net