code: def graph_edit_distance(
      G1,
      G2,
      node_substitution_cost=None,
      edge_substitution_cost=None,
      G1_node_deletion_cost=None,
      G2_node_insertion_cost=None,
      G1_edge_deletion_cost=None,
      G2_edge_insertion_cost=None,
      algorithm="bipartite",
      max_beam_size=100,
  ):
      """Returns GED (graph edit distance) between DGLGraphs G1 and G2.
  
  
      Parameters
      ----------
      G1, G2: DGLGraphs
  
      node_substitution_cost, edge_substitution_cost : 2D numpy arrays
          node_substitution_cost[i,j] is the cost of substitution node i of G1 with node j of G2,
          similar definition for edge_substitution_cost. If None, default cost of 0 is used.
  
      G1_node_deletion_cost, G1_edge_deletion_cost : 1D numpy arrays
          G1_node_deletion_cost[i] is the cost of deletion of node i of G1,
          similar definition for G1_edge_deletion_cost. If None, default cost of 1 is used.
  
      G2_node_insertion_cost, G2_edge_insertion_cost : 1D numpy arrays
          G2_node_insertion_cost[i] is the cost of insertion of node i of G2,
          similar definition for G2_edge_insertion_cost. If None, default cost of 1 is used.
  
      algorithm : string
          Algorithm to use to calculate the edit distance.
          For now, 4 algorithms are supported
          i) astar: Calculates exact GED using A* graph traversal algorithm,
          the heuristic used is the one proposed in (Riesen and Bunke, 2009) [1].
          ii) beam: Calculates approximate GED using A* graph traversal algorithm,
          with a maximum number of nodes in the open list. [2]
          iii) bipartite (default): Calculates approximate GED using linear assignment on the nodes,
          with jv (Jonker-Volgerand) algorithm. [3]
          iv) hausdorff: Approximation of graph edit distance based on Hausdorff matching [4].
  
      max_beam_size : int
          Maximum number of nodes in the open list, in case the algorithm is 'beam'.
  
  
      Returns
      -------
      A tuple of three objects: (edit_distance, node_mapping, edge_mapping)
      edit distance is the calculated edit distance (float)
      node_mapping is a tuple of size two, containing the node assignments of the two graphs respectively
      eg., node_mapping[0][i] is the node mapping of node i of graph G1 (None means that the node is deleted)
      Similar definition for the edge_mapping
  
      For 'hausdorff', node_mapping and edge_mapping are returned as None, as this approximation does not return a unique edit path
  
      Examples
      --------
      >>> src1 = [0, 1, 2, 3, 4, 5];
      >>> dst1 = [1, 2, 3, 4, 5, 6];
      >>> src2 = [0, 1, 3, 4, 5];
      >>> dst2 = [1, 2, 4, 5, 6];
  
      >>> G1 = dgl.DGLGraph((src1, dst1))
      >>> G2 = dgl.DGLGraph((src2, dst2))
      >>> distance, node_mapping, edge_mapping = graph_edit_distance(G1, G1, algorithm='astar')
      >>> print(distance)
      0.0
      >>> distance, node_mapping, edge_mapping = graph_edit_distance(G1, G2, algorithm='astar')
      >>> print(distance)
      1.0
  
      References
      ----------
      [1] Riesen, Kaspar, Stefan Fankhauser, and Horst Bunke.
      "Speeding Up Graph Edit Distance Computation with a Bipartite Heuristic."
      MLG. 2007.
      [2] Neuhaus, Michel, Kaspar Riesen, and Horst Bunke.
      "Fast suboptimal algorithms for the computation of graph edit distance."
      Joint IAPR International Workshops on Statistical Techniques in Pattern Recognition (SPR)
      and Structural and Syntactic Pattern Recognition (SSPR). 2006.
      [3] Fankhauser, Stefan, Kaspar Riesen, and Horst Bunke.
      "Speeding up graph edit distance computation through fast bipartite matching."
      International Workshop on Graph-Based Representations in Pattern Recognition. 2011.
      [4] Fischer, Andreas, et al. "A hausdorff heuristic for efficient computation of graph edit distance."
      Joint IAPR International Workshops on Statistical Techniques in Pattern Recognition (SPR)
      and Structural and Syntactic Pattern Recognition (SSPR). 2014.
  
      """
      # Handle corner cases
      if G1 is None and G2 is None:
          return (0.0, ([], []), ([], []))
      elif G1 is None:
          edit_cost = 0.0
  
      # Validate
      if algorithm != "beam":
          max_beam_size = -1
      (
          node_substitution_cost,
          edge_substitution_cost,
          G1_node_deletion_cost,
          G1_edge_deletion_cost,
          G2_node_insertion_cost,
          G2_edge_insertion_cost,
      ) = validate_cost_functions(
          G1,
          G2,
          node_substitution_cost,
          edge_substitution_cost,
          G1_node_deletion_cost,
          G1_edge_deletion_cost,
          G2_node_insertion_cost,
          G2_edge_insertion_cost,
      )
  
      # cost matrices for LAP solution
      cost_matrix_nodes, cost_matrix_edges = construct_cost_functions(
          G1,
          G2,
          node_substitution_cost,
          edge_substitution_cost,
          G1_node_deletion_cost,
          G1_edge_deletion_cost,
          G2_node_insertion_cost,
          G2_edge_insertion_cost,
      )
  
      if algorithm == "astar" or algorithm == "beam":
          (matched_cost, matched_nodes, matched_edges) = a_star_search(
              G1,
              G2,
              cost_matrix_nodes,
              cost_matrix_edges,
              max_beam_size,
          )
          return (
              matched_cost,
              get_sorted_mapping(
                  matched_nodes, G1.num_nodes(), G2.num_nodes()
              ),
              get_sorted_mapping(
                  matched_edges, G1.num_edges(), G2.num_edges()
              ),
          )
  
      elif algorithm == "hausdorff":
          hausdorff_cost = hausdorff_matching(
              G1,
              G2,
              node_substitution_cost,
              edge_substitution_cost,
              G1_node_deletion_cost,
              G1_edge_deletion_cost,
              G2_node_insertion_cost,
              G2_edge_insertion_cost,
          )
  
          return (hausdorff_cost, None, None)
  
      else:
          cost_matrix = contextual_cost_matrix_construction(
              G1,
              G2,
              node_substitution_cost,
              edge_substitution_cost,
              G1_node_deletion_cost,
              G1_edge_deletion_cost,
              G2_node_insertion_cost,
              G2_edge_insertion_cost,
          )
          # Match the nodes as per the LAP solution
          row_ind, col_ind, _ = lapjv(cost_matrix)
  
          (
              matched_cost,
              matched_nodes,
              matched_edges,
          ) = edit_cost_from_node_matching(
              G1, G2, cost_matrix_nodes, cost_matrix_edges, row_ind
          )
  
          return (
              matched_cost,
              get_sorted_mapping(
                  matched_nodes, G1.num_nodes(), G2.num_nodes()
              ),
              get_sorted_mapping(
                  matched_edges, G1.num_edges(), G2.num_edges()
              ),
          )
  
file_path: dgl/examples/pytorch/graph_matching/ged.py
imports: from copy import deepcopy
  from heapq import heapify, heappop, heappush, nsmallest
  import dgl
  import numpy
  from lapjv import lapjv
label_desc: Use image node_id 10 for calling a global function with example usage: graph_edit_distance(G1, G2, node_substitution_cost, edge_substitution_cost, G1_node_deletion_cost, G2_node_insertion_cost, G1_edge_deletion_cost, G2_edge_insertion_cost, algorithm, max_beam_size) and returns: int,  list,  list,  list,  list, matched_cost,  get_sorted_mapping,  get_sorted_mapping, hausdorff_cost,  None,  None, matched_cost,  get_sorted_mapping,  get_sorted_mapping