code: def GetInnerOuterExpo2DynamicSendRecvRanks(
      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-Exp2-Outer-Exp2 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.GetInnerOuterExpo2DynamicSendRecvRanks(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."
      )
  
      exp_2_out_size = int(np.log2(num_machines - 1))
      if nodes_per_machine == 2:
          exp_2_in_size = 0
      else:
          # -2 because we need to remove outgoing node
          exp_2_in_size = int(np.log2(nodes_per_machine - 2))
  
      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:
              # Note: currently design is still not very good. Because some local rank i may NEVER
              # directly talk to other machine's local rank i. Example:
              #
              # Assume num_machines=16, nodes_per_machine=4, and self_rank=1, then we know that
              # exp_2_out_size=3, and local_rank_id=1. If this branch is reached,
              # local_rank_to_go_outside_id=1, and index % (exp_2_out_size+1)=1, resulting in
              # next_machine_dist always equal to 2.
              next_machine_dist = 2 ** (index % (exp_2_out_size + 1))
              # find send_rank
              target_machine_id = (
                  machine_id + next_machine_dist
              ) % 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 - next_machine_dist
              ) % num_machines
              source_rank_id = (
                  source_machine_id * nodes_per_machine + local_rank_id
              )
              recv_rank = source_rank_id
  
          else:
              # Distance from self to out-rank:
              dist_to_out = (
                  local_rank_to_go_outside_id - local_rank_id
              ) % nodes_per_machine
              next_inner_dist = 2 ** (index % (exp_2_in_size + 1))
              if next_inner_dist >= dist_to_out:
                  next_inner_dist += 1
  
              # find send_rank
              target_local_rank_id = (
                  local_rank_id + next_inner_dist
              ) % nodes_per_machine
              target_rank_id = (
                  target_local_rank_id + machine_id * nodes_per_machine
              )
              send_rank = target_rank_id
  
              reverse_inner_dist = 2 ** (index % (exp_2_in_size + 1))
              reverse_dist_to_out = (
                  local_rank_id - local_rank_to_go_outside_id
              ) % nodes_per_machine
              if reverse_inner_dist >= reverse_dist_to_out:
                  reverse_inner_dist += 1
  
              # find recv_rank
              source_local_rank_id = (
                  local_rank_id - reverse_inner_dist
              ) % 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 16 for calling a global function with example usage: GetInnerOuterExpo2DynamicSendRecvRanks(world_size, local_size, _rank) without return types