class_docstr: Turns while loops in TensorFlow dataflow graph into the functional form:
  while(cond_function, body_function)
  
  Usage:
  Given a graph in tfssa (the NetworkEnsemble defined in network.py) form:
  
  This will functionalize *ONE* loop in the main function.
  
      f = FunctionalizeLoops()
      ret = f.functionalize_loops(self, tfssa, "main")
  
  if ret is True, one loop has been functionalized, and the new functions
  added to tfssa. If False, there is no loop to functionalize.
  
  Generally, repeated calls to this will be necessary to catch all loops.
  
  Instead, use functionalize_loops.
class_docstr_tok: ["Turns","while","loops","in","TensorFlow","dataflow","graph","into","the","functional","form",":","while","(","cond_function",",","body_function",")","Usage",":","Given","a","graph","in","tfssa","(","the","NetworkEnsemble","defined","in","network.py",")","form",":","This","will","functionalize","*","ONE","*","loop","in","the","main","function",".","f","=","FunctionalizeLoops","(",")","ret","=","f.functionalize_loops","(","self",",","tfssa",",","``","main","''",")","if","ret","is","True",",","one","loop","has","been","functionalized",",","and","the","new","functions","added","to","tfssa",".","If","False",",","there","is","no","loop","to","functionalize",".","Generally",",","repeated","calls","to","this","will","be","necessary","to","catch","all","loops",".","Instead",",","use","functionalize_loops","."]
code: def _fix_graph_invariants(self, g):
      import copy
  
      check = lambda x: x is not None and len(x) > 0
      check(self.exits)
      check(self.merges)
      check(self.enters)
      check(self.switches)
      check(self.subgraph)
      check(self.cond)
      check(self.loopcond)
      assert len(self.loopcond) == 1
      # maintain the invariant of a unique Enter node per argument
      # functionalize_control_flow.cc:FunctionalizeLoop (295)
      for i in copy.copy(self.enters):
          node = g[i]
          assert len(node.outputs) > 0
          assert len(node.inputs) == 1
          assert len(node.control_inputs) == 0
          assert len(node.control_outputs) == 0
          if len(node.outputs) == 1:
              continue
          node_output_copy = copy.copy(node.outputs)
          for j in range(1, len(node_output_copy)):
              # make a new enter node for each
              new_enter_node = copy.deepcopy(node)
              new_enter_node.inputs = []
              new_enter_node.outputs = []
              new_enter_node.name = node.name + "/trsplit%d" % (j)
              g[new_enter_node.name] = new_enter_node
              logger.debug("splitting %s", node.name)
              # connect the new node
              enter_output = node_output_copy[j]
              disconnect_edge(g, node.name, enter_output)
              connect_edge(g, new_enter_node.name, enter_output)
              connect_sources(g, node.inputs, new_enter_node.name)
              # insert into graph
              self.enters.append(new_enter_node.name)
  
file_path: coremltools/coremltools/converters/mil/frontend/tensorflow/tf_graph_pass/functionalize_loops.py
imports: from coremltools import _logger
  from ..basic_graph_ops import connect_dests, connect_edge, connect_sources, delete_node, disconnect_edge, replace_dest, replace_source
  from ..parsed_tf_node import ParsedTFNode
  from ..tfssa import SSAFunction
  from .visitors import FindAllReachableNodes, FindImmediateDownstreamNodes, FindImmediateUpstreamNodes, FindSubgraph
label_desc: Use image node_id 3 for calling the FunctionalizeLoops obj's underlying member method code with example usage: obj._fix_graph_invariants(g) without return types