docstr: Creates a generator/sequence object for training or evaluation
  with the supplied node ids and numeric targets.
  
  The node IDs are the nodes to train or inference on: the embeddings
  calculated for these nodes are passed to the downstream task. These
  are a subset of the nodes in the graph.
  
  The targets are an array of numeric targets corresponding to the
  supplied node_ids to be used by the downstream task. They should
  be given in the same order as the list of node IDs.
  If they are not specified (for example, for use in prediction),
  the targets will not be available to the downstream task.
  
  Note that the shuffle argument should be True for training and
  False for prediction.
  
  Args:
      link_ids: an iterable of tuples of node IDs as (source, target)
      targets: a 2D array of numeric targets with shape
          ``(len(link_ids), target_size)``
      shuffle (bool): If True the links will be shuffled at each
          epoch, if False the links will be processed in order.
      seed (int, optional): Random seed
  
  Returns:
      A NodeSequence object to use with with StellarGraph models
      in Keras methods ``fit``, ``evaluate``,
      and ``predict``
code: def flow(self, link_ids, targets=None, shuffle=False, seed=None):
      """
      Creates a generator/sequence object for training or evaluation
      with the supplied node ids and numeric targets.
  
      The node IDs are the nodes to train or inference on: the embeddings
      calculated for these nodes are passed to the downstream task. These
      are a subset of the nodes in the graph.
  
      The targets are an array of numeric targets corresponding to the
      supplied node_ids to be used by the downstream task. They should
      be given in the same order as the list of node IDs.
      If they are not specified (for example, for use in prediction),
      the targets will not be available to the downstream task.
  
      Note that the shuffle argument should be True for training and
      False for prediction.
  
      Args:
          link_ids: an iterable of tuples of node IDs as (source, target)
          targets: a 2D array of numeric targets with shape
              ``(len(link_ids), target_size)``
          shuffle (bool): If True the links will be shuffled at each
              epoch, if False the links will be processed in order.
          seed (int, optional): Random seed
  
      Returns:
          A NodeSequence object to use with with StellarGraph models
          in Keras methods ``fit``, ``evaluate``,
          and ``predict``
  
      """
      if self.head_node_types is not None:
          expected_src_type = self.head_node_types[0]
          expected_dst_type = self.head_node_types[1]
  
      # Pass sampler to on-demand link sequence generation
      if isinstance(link_ids, UnsupervisedSampler):
          return OnDemandLinkSequence(
              self.sample_features, self.batch_size, link_ids
          )
  
      # Otherwise pass iterable (check?) to standard LinkSequence
      elif isinstance(link_ids, collections.abc.Iterable):
          # Check all IDs are actually in the graph and are of expected type
          for link in link_ids:
              if len(link) != 2:
                  raise KeyError(
                      "Expected link IDs to be a tuple of length 2"
                  )
  
              src, dst = link
              try:
                  node_type_src = self.graph.node_type(src)
              except KeyError:
                  raise KeyError(
                      f"Node ID {src} supplied to generator not found in graph"
                  )
              try:
                  node_type_dst = self.graph.node_type(dst)
              except KeyError:
                  raise KeyError(
                      f"Node ID {dst} supplied to generator not found in graph"
                  )
  
              if self.head_node_types is not None and (
                  node_type_src != expected_src_type
                  or node_type_dst != expected_dst_type
              ):
                  raise ValueError(
                      f"Node pair ({src}, {dst}) not of expected type ({expected_src_type}, {expected_dst_type})"
                  )
  
          link_ids = [
              self.graph.node_ids_to_ilocs(ids) for ids in link_ids
          ]
  
          return LinkSequence(
              self.sample_features,
              self.batch_size,
              link_ids,
              targets=targets,
              shuffle=shuffle,
              seed=seed,
          )
  
      else:
          raise TypeError(
              "Argument to .flow not recognised. "
              "Please pass a list of samples or a UnsupervisedSampler object."
          )
  
imports: import random
  import operator
  import numpy
  import itertools
  import operator
  import collections
  import abc
  import warnings
  from functools import reduce
  from tensorflow import keras
  from ..core.graph import StellarGraph, GraphSchema
  from ..data import SampledBreadthFirstWalk, SampledHeterogeneousBreadthFirstWalk, UniformRandomWalk, UnsupervisedSampler, DirectedBreadthFirstNeighbours
  from ..core.utils import is_real_iterable
  from .None import LinkSequence, OnDemandLinkSequence
  from ..random import SeededPerBatch
  from .base import Generator
label_desc: Use image node_id 4 for calling the BatchedLinkGenerator obj's underlying member method code with example usage: obj.flow(link_ids, targets, shuffle, seed) and returns: OnDemandLinkSequence, LinkSequence