class_docstr: Implements the ISMAGS subgraph matching algorithm. [1]_ ISMAGS stands for
  "Index-based Subgraph Matching Algorithm with General Symmetries". As the
  name implies, it is symmetry aware and will only generate non-symmetric
  isomorphisms.
  
  Notes
  -----
  The implementation imposes additional conditions compared to the VF2
  algorithm on the graphs provided and the comparison functions
  (:attr:`node_equality` and :attr:`edge_equality`):
  
   - Node keys in both graphs must be orderable as well as hashable.
   - Equality must be transitive: if A is equal to B, and B is equal to C,
     then A must be equal to C.
  
  Attributes
  ----------
  graph: networkx.Graph
  subgraph: networkx.Graph
  node_equality: collections.abc.Callable
      The function called to see if two nodes should be considered equal.
      It's signature looks like this:
      ``f(graph1: networkx.Graph, node1, graph2: networkx.Graph, node2) -> bool``.
      `node1` is a node in `graph1`, and `node2` a node in `graph2`.
      Constructed from the argument `node_match`.
  edge_equality: collections.abc.Callable
      The function called to see if two edges should be considered equal.
      It's signature looks like this:
      ``f(graph1: networkx.Graph, edge1, graph2: networkx.Graph, edge2) -> bool``.
      `edge1` is an edge in `graph1`, and `edge2` an edge in `graph2`.
      Constructed from the argument `edge_match`.
  
  References
  ----------
  .. [1] M. Houbraken, S. Demeyer, T. Michoel, P. Audenaert, D. Colle,
     M. Pickavet, "The Index-Based Subgraph Matching Algorithm with General
     Symmetries (ISMAGS): Exploiting Symmetry for Faster Subgraph
     Enumeration", PLoS One 9(5): e97896, 2014.
     https://doi.org/10.1371/journal.pone.0097896
class_docstr_tok: ["Implements","the","ISMAGS","subgraph","matching","algorithm",".","[","1","]","_","ISMAGS","stands","for","''","Index-based","Subgraph","Matching","Algorithm","with","General","Symmetries","''",".","As","the","name","implies",",","it","is","symmetry","aware","and","will","only","generate","non-symmetric","isomorphisms",".","Notes","--","--","-","The","implementation","imposes","additional","conditions","compared","to","the","VF2","algorithm","on","the","graphs","provided","and","the","comparison","functions","(",":","attr",":","`","node_equality","`","and",":","attr",":","`","edge_equality","`",")",":","-","Node","keys","in","both","graphs","must","be","orderable","as","well","as","hashable",".","-","Equality","must","be","transitive",":","if","A","is","equal","to","B",",","and","B","is","equal","to","C",",","then","A","must","be","equal","to","C.","Attributes","--","--","--","--","--","graph",":","networkx.Graph","subgraph",":","networkx.Graph","node_equality",":","collections.abc.Callable","The","function","called","to","see","if","two","nodes","should","be","considered","equal",".","It","'s","signature","looks","like","this",":","``","f","(","graph1",":","networkx.Graph",",","node1",",","graph2",":","networkx.Graph",",","node2",")","-",">","bool","``",".","`","node1","`","is","a","node","in","`","graph1","`",",","and","`","node2","`","a","node","in","`","graph2","`",".","Constructed","from","the","argument","`","node_match","`",".","edge_equality",":","collections.abc.Callable","The","function","called","to","see","if","two","edges","should","be","considered","equal",".","It","'s","signature","looks","like","this",":","``","f","(","graph1",":","networkx.Graph",",","edge1",",","graph2",":","networkx.Graph",",","edge2",")","-",">","bool","``",".","`","edge1","`","is","an","edge","in","`","graph1","`",",","and","`","edge2","`","an","edge","in","`","graph2","`",".","Constructed","from","the","argument","`","edge_match","`",".","References","--","--","--","--","--","..","[","1","]","M.","Houbraken",",","S.","Demeyer",",","T.","Michoel",",","P.","Audenaert",",","D.","Colle",",","M.","Pickavet",",","``","The","Index-Based","Subgraph","Matching","Algorithm","with","General","Symmetries","(","ISMAGS",")",":","Exploiting","Symmetry","for","Faster","Subgraph","Enumeration","''",",","PLoS","One","9","(","5",")",":","e97896",",","2014.","https",":","\/\/doi.org\/10.1371\/journal.pone.0097896"]
docstr: Find all largest common subgraphs honoring constraints.
code: def _largest_common_subgraph(
      self, candidates, constraints, to_be_mapped=None
  ):
      """
      Find all largest common subgraphs honoring constraints.
      """
      if to_be_mapped is None:
          to_be_mapped = {frozenset(self.subgraph.nodes)}
  
      # The LCS problem is basically a repeated subgraph isomorphism problem
      # with smaller and smaller subgraphs. We store the nodes that are
      # "part of" the subgraph in to_be_mapped, and we make it a little
      # smaller every iteration.
  
      current_size = len(next(iter(to_be_mapped), []))
  
      found_iso = False
      if current_size <= len(self.graph):
          # There's no point in trying to find isomorphisms of
          # graph >= subgraph if subgraph has more nodes than graph.
  
          # Try the isomorphism first with the nodes with lowest ID. So sort
          # them. Those are more likely to be part of the final
          # correspondence. This makes finding the first answer(s) faster. In
          # theory.
          for nodes in sorted(to_be_mapped, key=sorted):
              # Find the isomorphism between subgraph[to_be_mapped] <= graph
              next_sgn = min(
                  nodes, key=lambda n: min(candidates[n], key=len)
              )
              isomorphs = self._map_nodes(
                  next_sgn, candidates, constraints, to_be_mapped=nodes
              )
  
              # This is effectively `yield from isomorphs`, except that we look
              # whether an item was yielded.
              try:
                  item = next(isomorphs)
              except StopIteration:
                  pass
              else:
                  yield item
                  yield from isomorphs
                  found_iso = True
  
      # BASECASE
      if found_iso or current_size == 1:
          # Shrinking has no point because either 1) we end up with a smaller
          # common subgraph (and we want the largest), or 2) there'll be no
          # more subgraph.
          return
  
      left_to_be_mapped = set()
      for nodes in to_be_mapped:
          for sgn in nodes:
              # We're going to remove sgn from to_be_mapped, but subject to
              # symmetry constraints. We know that for every constraint we
              # have those subgraph nodes are equal. So whenever we would
              # remove the lower part of a constraint, remove the higher
              # instead. This is all dealth with by _remove_node. And because
              # left_to_be_mapped is a set, we don't do double work.
  
              # And finally, make the subgraph one node smaller.
              # REDUCTION
              new_nodes = self._remove_node(sgn, nodes, constraints)
              left_to_be_mapped.add(new_nodes)
      # COMBINATION
      yield from self._largest_common_subgraph(
          candidates, constraints, to_be_mapped=left_to_be_mapped
      )
  
imports: import itertools
  from collections import Counter, defaultdict
  from functools import reduce, wraps
label_desc: Use image node_id 30 for calling the ISMAGS obj's underlying member method code with example usage: obj._largest_common_subgraph(candidates, constraints, to_be_mapped) without return types