class_docstr: Implementation of VF2 algorithm for matching undirected graphs.
  
  Suitable for Graph and MultiGraph instances.
class_docstr_tok: ["Implementation","of","VF2","algorithm","for","matching","undirected","graphs",".","Suitable","for","Graph","and","MultiGraph","instances","."]
docstr: Returns True if adding (G1_node, G2_node) is syntactically feasible.
  
  This function returns True if it is adding the candidate pair
  to the current partial isomorphism/monomorphism mapping is allowable.
  The addition is allowable if the inclusion of the candidate pair does
  not make it impossible for an isomorphism/monomorphism to be found.
docstr_tok: ["Returns","True","if","adding","(","G1_node",",","G2_node",")","is","syntactically","feasible",".","This","function","returns","True","if","it","is","adding","the","candidate","pair","to","the","current","partial","isomorphism\/monomorphism","mapping","is","allowable",".","The","addition","is","allowable","if","the","inclusion","of","the","candidate","pair","does","not","make","it","impossible","for","an","isomorphism\/monomorphism","to","be","found","."]
code: def syntactic_feasibility(self, G1_node, G2_node):
      """Returns True if adding (G1_node, G2_node) is syntactically feasible.
  
      This function returns True if it is adding the candidate pair
      to the current partial isomorphism/monomorphism mapping is allowable.
      The addition is allowable if the inclusion of the candidate pair does
      not make it impossible for an isomorphism/monomorphism to be found.
      """
  
      # The VF2 algorithm was designed to work with graphs having, at most,
      # one edge connecting any two nodes.  This is not the case when
      # dealing with an MultiGraphs.
      #
      # Basically, when we test the look-ahead rules R_neighbor, we will
      # make sure that the number of edges are checked. We also add
      # a R_self check to verify that the number of selfloops is acceptable.
      #
      # Users might be comparing Graph instances with MultiGraph instances.
      # So the generic GraphMatcher class must work with MultiGraphs.
      # Care must be taken since the value in the innermost dictionary is a
      # singlet for Graph instances.  For MultiGraphs, the value in the
      # innermost dictionary is a list.
  
      ###
      # Test at each step to get a return value as soon as possible.
      ###
  
      # Look ahead 0
  
      # R_self
  
      # The number of selfloops for G1_node must equal the number of
      # self-loops for G2_node. Without this check, we would fail on
      # R_neighbor at the next recursion level. But it is good to prune the
      # search tree now.
  
      if self.test == "mono":
          if self.G1.number_of_edges(
              G1_node, G1_node
          ) < self.G2.number_of_edges(G2_node, G2_node):
              return False
      else:
          if self.G1.number_of_edges(
              G1_node, G1_node
          ) != self.G2.number_of_edges(G2_node, G2_node):
              return False
  
      # R_neighbor
  
      # For each neighbor n' of n in the partial mapping, the corresponding
      # node m' is a neighbor of m, and vice versa. Also, the number of
      # edges must be equal.
      if self.test != "mono":
          for neighbor in self.G1[G1_node]:
              if neighbor in self.core_1:
                  if self.core_1[neighbor] not in self.G2[G2_node]:
                      return False
                  elif self.G1.number_of_edges(
                      neighbor, G1_node
                  ) != self.G2.number_of_edges(
                      self.core_1[neighbor], G2_node
                  ):
                      return False
  
      for neighbor in self.G2[G2_node]:
          if neighbor in self.core_2:
              if self.core_2[neighbor] not in self.G1[G1_node]:
                  return False
              elif self.test == "mono":
                  if self.G1.number_of_edges(
                      self.core_2[neighbor], G1_node
                  ) < self.G2.number_of_edges(neighbor, G2_node):
                      return False
              else:
                  if self.G1.number_of_edges(
                      self.core_2[neighbor], G1_node
                  ) != self.G2.number_of_edges(neighbor, G2_node):
                      return False
  
      if self.test != "mono":
          # Look ahead 1
  
          # R_terminout
          # The number of neighbors of n in T_1^{inout} is equal to the
          # number of neighbors of m that are in T_2^{inout}, and vice versa.
          num1 = 0
          for neighbor in self.G1[G1_node]:
              if (neighbor in self.inout_1) and (
                  neighbor not in self.core_1
              ):
                  num1 += 1
          num2 = 0
          for neighbor in self.G2[G2_node]:
              if (neighbor in self.inout_2) and (
                  neighbor not in self.core_2
              ):
                  num2 += 1
          if self.test == "graph":
              if num1 != num2:
                  return False
          else:  # self.test == 'subgraph'
              if not (num1 >= num2):
                  return False
  
          # Look ahead 2
  
          # R_new
  
          # The number of neighbors of n that are neither in the core_1 nor
          # T_1^{inout} is equal to the number of neighbors of m
          # that are neither in core_2 nor T_2^{inout}.
          num1 = 0
          for neighbor in self.G1[G1_node]:
              if neighbor not in self.inout_1:
                  num1 += 1
          num2 = 0
          for neighbor in self.G2[G2_node]:
              if neighbor not in self.inout_2:
                  num2 += 1
          if self.test == "graph":
              if num1 != num2:
                  return False
          else:  # self.test == 'subgraph'
              if not (num1 >= num2):
                  return False
  
      # Otherwise, this node pair is syntactically feasible!
      return True
  
imports: import sys
label_desc: Use image node_id 13 for calling the GraphMatcher obj's underlying member method code with example usage: obj.syntactic_feasibility(G1_node, G2_node) and returns: True, False, False, False, False, False, False, False, False, False, False, False