docs: def get_best_gain(mapping, candidate_mappings, weight_dict, instance_len, cur_match_num):
      """
      Hill-climbing method to return the best gain swap/move can get
      Arguments:
      mapping: current node mapping
      candidate_mappings: the candidates mapping list
      weight_dict: the weight dictionary
      instance_len: the number of the nodes in AMR 2
      cur_match_num: current triple match number
      Returns:
      the best gain we can get via swap/move operation
  
      """
      largest_gain = 0
      # True: using swap; False: using move
      use_swap = True
      # the node to be moved/swapped
      node1 = None
      # store the other node affected. In swap, this other node is the node swapping with node1. In move, this other
      # node is the node node1 will move to.
      node2 = None
      # unmatched nodes in AMR 2
      unmatched = set(range(instance_len))
      # exclude nodes in current mapping
      # get unmatched nodes
      for nid in mapping:
          if nid in unmatched:
              unmatched.remove(nid)
      for i, nid in enumerate(mapping):
          # current node i in AMR 1 maps to node nid in AMR 2
          for nm in unmatched:
              if nm in candidate_mappings[i]:
                  # remap i to another unmatched node (move)
                  # (i, m) -> (i, nm)
                  if veryVerbose:
                      print("Remap node", i, "from ", nid, "to", nm, file=DEBUG_LOG)
                  mv_gain = move_gain(mapping, i, nid, nm, weight_dict, cur_match_num)
                  if veryVerbose:
                      print("Move gain:", mv_gain, file=DEBUG_LOG)
                      new_mapping = mapping[:]
                      new_mapping[i] = nm
                      new_match_num = compute_match(new_mapping, weight_dict)
                      if new_match_num != cur_match_num + mv_gain:
                          print(mapping, new_mapping, file=ERROR_LOG)
                          print("Inconsistency in computing: move gain", cur_match_num, mv_gain, new_match_num,
                                file=ERROR_LOG)
                  if mv_gain > largest_gain:
                      largest_gain = mv_gain
                      node1 = i
                      node2 = nm
                      use_swap = False
      # compute swap gain
      for i, m in enumerate(mapping):
          for j in range(i + 1, len(mapping)):
              m2 = mapping[j]
              # swap operation (i, m) (j, m2) -> (i, m2) (j, m)
              # j starts from i+1, to avoid duplicate swap
              if veryVerbose:
                  print("Swap node", i, "and", j, file=DEBUG_LOG)
                  print("Before swapping:", i, "-", m, ",", j, "-", m2, file=DEBUG_LOG)
                  print(mapping, file=DEBUG_LOG)
                  print("After swapping:", i, "-", m2, ",", j, "-", m, file=DEBUG_LOG)
              sw_gain = swap_gain(mapping, i, m, j, m2, weight_dict, cur_match_num)
              if veryVerbose:
                  print("Swap gain:", sw_gain, file=DEBUG_LOG)
                  new_mapping = mapping[:]
                  new_mapping[i] = m2
                  new_mapping[j] = m
                  print(new_mapping, file=DEBUG_LOG)
                  new_match_num = compute_match(new_mapping, weight_dict)
                  if new_match_num != cur_match_num + sw_gain:
                      print(mapping, new_mapping, file=ERROR_LOG)
                      print("Inconsistency in computing: swap gain", cur_match_num, sw_gain, new_match_num,
                            file=ERROR_LOG)
              if sw_gain > largest_gain:
                  largest_gain = sw_gain
                  node1 = i
                  node2 = j
                  use_swap = True
      # generate a new mapping based on swap/move
      cur_mapping = mapping[:]
      if node1 is not None:
          if use_swap:
              if veryVerbose:
                  print("Use swap gain", file=DEBUG_LOG)
              temp = cur_mapping[node1]
              cur_mapping[node1] = cur_mapping[node2]
              cur_mapping[node2] = temp
          else:
              if veryVerbose:
                  print("Use move gain", file=DEBUG_LOG)
              cur_mapping[node1] = node2
      else:
          if veryVerbose:
              print("no move/swap gain found", file=DEBUG_LOG)
      if veryVerbose:
          print("Original mapping", mapping, file=DEBUG_LOG)
          print("Current mapping", cur_mapping, file=DEBUG_LOG)
      return largest_gain, cur_mapping