docstr: Replace all uses of `old_var` with `new_var` after `anchor_op`,
  and before `end_op` (inclusive).
  
  That is all the ops that use `old_var` will now use `new_var`.
  The op that produces the `old_var` will continue to produce it, its output
  won't be replaced by `new_var`.
  
  If `anchor_op` is None, replace all input occurrences of `old_var` in the block.
  If `end_op` is None, all occurrences of `old_var` are replaced in the block starting from the op just
  after `anchor_op`
  
  no_check_var_visibility: True to disable the check ensuring new_var is visible
  (visibility requirement depends on anchor_op).
  
  no_check_var_types: An error will be raised if the type of new_var is not same as the old_var, unless
  `no_check_var_types` is set to True. Normally type inference is re-invoked for all the child ops of `old_var`
   after updating it to `new_var`. However, this is skipped if `no_check_var_types` is set to True.
  
  old_var, new_var must meet the following conditions:
  
  - old_var, new_var both existing within the block. This implies that
    the op generating new_var must be inserted prior to this
    replacement.
  
  - Affected ops (i.e., Operation after anchor_op that take old_var as
    input) must generate the same type inference results as before.
  
  - new_var must be visible at or before anchor_op in the order of
    self.operations.
  
  Given:   %2 = op0(%1, %1)
           %3 = op1(%1, %2)
           %4 = op2(%1)
           %6 = op3(%4, %4)
  
  Execute: replace_uses_of_var_after_op(op2, %4, %3)
  
  Result:  %2 = op0(%1, %1)
           %3 = op1(%1, %2)
           %4 = op2(%1)
           %6 = op3(%3, %3)     # type inference check against %6
  
  
  Comment: Execute: replace_uses_of_var_after_op(op1, %4, %3) would lead to
  identical results, as op2 does not take %4 as input.
  
  Comment: replace_uses_of_var_after_op(op0, %4, %3) would cause error as %3 is
  after op0
  
  Comment: To avoid clutter, we drop the names of arguments and return
  Var in the illustration above.
  
  
  Another example, usage of "end_op":
  
  Given:   %2 = op0(%1, %1)
           %3 = op1()
           %4 = op2(%1, %2)
           %5 = op3(%2)
  
  if execute replace_uses_of_var_after_op(anchor_op=op0, old_var=%2, new_var=%3)
  
  Result:  %2 = op0(%1, %1)
           %3 = op1()
           %4 = op2(%1, %3)
           %5 = op3(%3)
  
  if execute replace_uses_of_var_after_op(anchor_op=op0, old_var=%2, new_var=%3, end_op=op2)
  
  Result:  %2 = op0(%1, %1)
           %3 = op1()
           %4 = op2(%1, %3)           # %2 is replaced with %3 till here
           %5 = op3(%2)               # will continue using %2
docstr_tok: ["Replace","all","uses","of","`","old_var","`","with","`","new_var","`","after","`","anchor_op","`",",","and","before","`","end_op","`","(","inclusive",")",".","That","is","all","the","ops","that","use","`","old_var","`","will","now","use","`","new_var","`",".","The","op","that","produces","the","`","old_var","`","will","continue","to","produce","it",",","its","output","wo","n't","be","replaced","by","`","new_var","`",".","If","`","anchor_op","`","is","None",",","replace","all","input","occurrences","of","`","old_var","`","in","the","block",".","If","`","end_op","`","is","None",",","all","occurrences","of","`","old_var","`","are","replaced","in","the","block","starting","from","the","op","just","after","`","anchor_op","`","no_check_var_visibility",":","True","to","disable","the","check","ensuring","new_var","is","visible","(","visibility","requirement","depends","on","anchor_op",")",".","no_check_var_types",":","An","error","will","be","raised","if","the","type","of","new_var","is","not","same","as","the","old_var",",","unless","`","no_check_var_types","`","is","set","to","True",".","Normally","type","inference","is","re-invoked","for","all","the","child","ops","of","`","old_var","`","after","updating","it","to","`","new_var","`",".","However",",","this","is","skipped","if","`","no_check_var_types","`","is","set","to","True",".","old_var",",","new_var","must","meet","the","following","conditions",":","-","old_var",",","new_var","both","existing","within","the","block",".","This","implies","that","the","op","generating","new_var","must","be","inserted","prior","to","this","replacement",".","-","Affected","ops","(","i.e.",",","Operation","after","anchor_op","that","take","old_var","as","input",")","must","generate","the","same","type","inference","results","as","before",".","-","new_var","must","be","visible","at","or","before","anchor_op","in","the","order","of","self.operations",".","Given",":","%","2","=","op0","(","%","1",",","%","1",")","%","3","=","op1","(","%","1",",","%","2",")","%","4","=","op2","(","%","1",")","%","6","=","op3","(","%","4",",","%","4",")","Execute",":","replace_uses_of_var_after_op","(","op2",",","%","4",",","%","3",")","Result",":","%","2","=","op0","(","%","1",",","%","1",")","%","3","=","op1","(","%","1",",","%","2",")","%","4","=","op2","(","%","1",")","%","6","=","op3","(","%","3",",","%","3",")","#","type","inference","check","against","%","6","Comment",":","Execute",":","replace_uses_of_var_after_op","(","op1",",","%","4",",","%","3",")","would","lead","to","identical","results",",","as","op2","does","not","take","%","4","as","input",".","Comment",":","replace_uses_of_var_after_op","(","op0",",","%","4",",","%","3",")","would","cause","error","as","%","3","is","after","op0","Comment",":","To","avoid","clutter",",","we","drop","the","names","of","arguments","and","return","Var","in","the","illustration","above",".","Another","example",",","usage","of","``","end_op","''",":","Given",":","%","2","=","op0","(","%","1",",","%","1",")","%","3","=","op1","(",")","%","4","=","op2","(","%","1",",","%","2",")","%","5","=","op3","(","%","2",")","if","execute","replace_uses_of_var_after_op","(","anchor_op=op0",",","old_var=","%","2",",","new_var=","%","3",")","Result",":","%","2","=","op0","(","%","1",",","%","1",")","%","3","=","op1","(",")","%","4","=","op2","(","%","1",",","%","3",")","%","5","=","op3","(","%","3",")","if","execute","replace_uses_of_var_after_op","(","anchor_op=op0",",","old_var=","%","2",",","new_var=","%","3",",","end_op=op2",")","Result",":","%","2","=","op0","(","%","1",",","%","1",")","%","3","=","op1","(",")","%","4","=","op2","(","%","1",",","%","3",")","#","%","2","is","replaced","with","%","3","till","here","%","5","=","op3","(","%","2",")","#","will","continue","using","%","2"]
code: def replace_uses_of_var_after_op(
      self,
      anchor_op,
      old_var,
      new_var,
      no_check_var_visibility=False,
      end_op=None,
      no_check_var_types=False,
  ):
      """
      Replace all uses of `old_var` with `new_var` after `anchor_op`,
      and before `end_op` (inclusive).
  
      That is all the ops that use `old_var` will now use `new_var`.
      The op that produces the `old_var` will continue to produce it, its output
      won't be replaced by `new_var`.
  
      If `anchor_op` is None, replace all input occurrences of `old_var` in the block.
      If `end_op` is None, all occurrences of `old_var` are replaced in the block starting from the op just
      after `anchor_op`
  
      no_check_var_visibility: True to disable the check ensuring new_var is visible
      (visibility requirement depends on anchor_op).
  
      no_check_var_types: An error will be raised if the type of new_var is not same as the old_var, unless
      `no_check_var_types` is set to True. Normally type inference is re-invoked for all the child ops of `old_var`
       after updating it to `new_var`. However, this is skipped if `no_check_var_types` is set to True.
  
      old_var, new_var must meet the following conditions:
  
      - old_var, new_var both existing within the block. This implies that
        the op generating new_var must be inserted prior to this
        replacement.
  
      - Affected ops (i.e., Operation after anchor_op that take old_var as
        input) must generate the same type inference results as before.
  
      - new_var must be visible at or before anchor_op in the order of
        self.operations.
  
      Given:   %2 = op0(%1, %1)
               %3 = op1(%1, %2)
               %4 = op2(%1)
               %6 = op3(%4, %4)
  
      Execute: replace_uses_of_var_after_op(op2, %4, %3)
  
      Result:  %2 = op0(%1, %1)
               %3 = op1(%1, %2)
               %4 = op2(%1)
               %6 = op3(%3, %3)     # type inference check against %6
  
  
      Comment: Execute: replace_uses_of_var_after_op(op1, %4, %3) would lead to
      identical results, as op2 does not take %4 as input.
  
      Comment: replace_uses_of_var_after_op(op0, %4, %3) would cause error as %3 is
      after op0
  
      Comment: To avoid clutter, we drop the names of arguments and return
      Var in the illustration above.
  
  
      Another example, usage of "end_op":
  
      Given:   %2 = op0(%1, %1)
               %3 = op1()
               %4 = op2(%1, %2)
               %5 = op3(%2)
  
      if execute replace_uses_of_var_after_op(anchor_op=op0, old_var=%2, new_var=%3)
  
      Result:  %2 = op0(%1, %1)
               %3 = op1()
               %4 = op2(%1, %3)
               %5 = op3(%3)
  
      if execute replace_uses_of_var_after_op(anchor_op=op0, old_var=%2, new_var=%3, end_op=op2)
  
      Result:  %2 = op0(%1, %1)
               %3 = op1()
               %4 = op2(%1, %3)           # %2 is replaced with %3 till here
               %5 = op3(%2)               # will continue using %2
  
      """
      if not no_check_var_visibility:
          self.validate()
      # Get visible vars from enclosing block
      visible_vars = self._visible_vars_from_enclosing_block()
  
      if anchor_op is not None:
          # Get visible vars from the current block
          idx, block_vars = self._visible_vars_in_block(
              anchor_op, inclusive=True
          )
          visible_vars.update(block_vars)
  
          # start from the next op, excluding `anchor_op`
          start = idx + 1
      else:
          visible_vars.update(self._block_inputs)
          visible_vars.update(self._internal_vars)
          # Perform replacement from beginning
          start = 0
  
      if not no_check_var_visibility and new_var not in visible_vars:
          msg = (
              "new_var '{}' is not visible in block '{}' at or before "
              + "anchor_op '{}'"
          )
          anchor_op_name = (
              "None" if anchor_op is None else anchor_op.name
          )
          raise ValueError(
              msg.format(new_var.name, self.name, anchor_op_name)
          )
  
      if end_op is not None:
          end_id, _ = self._visible_vars_in_block(
              end_op, inclusive=True
          )
      else:
          end_id = -1
  
      if end_id != -1 and end_id < start:
          msg = "end_op '{}' comes before the anchor_op '{}'"
          raise ValueError(msg.format(end_op.name, anchor_op.name))
  
      num_ops_affected = self._replace_var(
          old_var,
          new_var,
          start=start,
          end_id=end_id,
          no_check_var_visibility=no_check_var_visibility,
          no_check_var_types=no_check_var_types,
      )
  
      logging.debug(
          "Num ops affected in replacing var: {}".format(
              num_ops_affected
          )
      )
  
imports: from collections import Counter, OrderedDict
  import copy
  import logging
  import numpy
  from six import string_types
  from .None import SPACES, types
  from .var import Var, InternalVar, ListVar
  from .visitors.dot_visitor import DotVisitor
  from .types.symbolic import k_used_symbols, k_num_internal_syms, any_symbolic, is_symbolic
  from .input_type import TupleInputType
label_desc: Use image node_id 16 for calling the Block obj's underlying member method code with example usage: obj.replace_uses_of_var_after_op(anchor_op, old_var, new_var, no_check_var_visibility, end_op, no_check_var_types) without return types