code: def GetInnerOuterRingDynamicSendRecvRanks(
      world_size: int, local_size: int, self_rank: int
  ) -> Iterator[Tuple[List[int], List[int]]]:
      """
      A utility function to generate 1-outgoing send rank and corresponding recieving rank(s)
      for Inner-Ring-Outer-Ring topology.
  
      Args:
          world_size (int): the size of all nodes; world_size = num_machines * nodes_per_machine
          local_size (int): number of nodes in each machine
          self_rank (int): The self rank.
  
      Yields:
          Iterator[Tuple[List[int], List[int]]]: send_ranks, recv_ranks.
  
      Example:
  
          >>> from bluefog.common import topology_util
          >>> world_size, local_size = bf.size(), bf.local_size()
          >>> gen = topology_util.GetInnerOuterRingDynamicSendRecvRanks(world_size, local_size, 0)
          >>> for _ in range(10):
          >>>     print(next(gen))
      """
      num_machines = world_size // local_size
      nodes_per_machine = local_size
      assert (
          world_size % local_size == 0
      ), "It should be used under homogeneous environment only."
      assert local_size > 2, (
          "Do no support the case where nodes_per_machine is equal or "
          "less than 2. Consider use hierarchical_neighbor_allreduce or GetDynamicOnePeerSendRecvRanks."
      )
  
      index = 0
      while True:
          machine_id = self_rank // nodes_per_machine
          local_rank_id = self_rank % nodes_per_machine
          local_rank_to_go_outside_id = index % nodes_per_machine
  
          if local_rank_to_go_outside_id == local_rank_id:
              # find send_rank
              target_machine_id = (machine_id + 1) % num_machines
              target_rank_id = (
                  target_machine_id * nodes_per_machine + local_rank_id
              )
              send_rank = target_rank_id
  
              # find recv_rank
              source_machine_id = (machine_id - 1) % num_machines
              source_rank_id = (
                  source_machine_id * nodes_per_machine + local_rank_id
              )
              recv_rank = source_rank_id
  
          else:
              # find send_rank
              target_local_rank_id = (
                  local_rank_id + 1
              ) % nodes_per_machine
              if target_local_rank_id == local_rank_to_go_outside_id:
                  target_local_rank_id = (
                      target_local_rank_id + 1
                  ) % nodes_per_machine
              target_rank_id = (
                  target_local_rank_id + machine_id * nodes_per_machine
              )
              send_rank = target_rank_id
  
              # find recv_rank
              source_local_rank_id = (
                  local_rank_id - 1
              ) % nodes_per_machine
              if source_local_rank_id == local_rank_to_go_outside_id:
                  source_local_rank_id = (
                      source_local_rank_id - 1
                  ) % nodes_per_machine
              source_rank_id = (
                  source_local_rank_id + machine_id * nodes_per_machine
              )
              recv_rank = source_rank_id
  
          yield [send_rank], [recv_rank]
          index += 1
  
imports: from typing import List, Tuple, Dict, Iterator, Optional
  import math
  import numpy
  import networkx
label_desc: Use image node_id 15 for calling a global function with example usage: GetInnerOuterRingDynamicSendRecvRanks(world_size, local_size, _rank) without return types