code: def _generate_channels(self, operator):
          
          channels = {}  # destination operator id -> channels
          strategies = operator.partitioning_strategies
          for dst_operator, p_scheme in strategies.items():
              num_dest_instances = self.operators[dst_operator].num_instances
              entry = channels.setdefault(dst_operator, [])
              if p_scheme.strategy == PStrategy.Forward:
                  for i in range(operator.num_instances):
                      # ID of destination instance to connect
                      id = i % num_dest_instances
                      channel = DataChannel(self, operator.id, dst_operator, i,
                                            id)
                      entry.append(channel)
              elif p_scheme.strategy in all_to_all_strategies:
                  for i in range(operator.num_instances):
                      for j in range(num_dest_instances):
                          channel = DataChannel(self, operator.id, dst_operator,
                                                i, j)
                          entry.append(channel)
              else:
                  # TODO (john): Add support for other partitioning strategies
                  sys.exit("Unrecognized or unsupported partitioning strategy.")
          return channels
docs: Generates all output data channels
          (see: DataChannel in communication.py) for all instances of
          the given logical operator.
  
          The function constructs one data channel for each pair of
          communicating operator instances (instance_1,instance_2),
          where instance_1 is an instance of the given operator and instance_2
          is an instance of a direct downstream operator.
  
          The number of total channels generated depends on the partitioning
          strategy specified by the user.