/**
   * Finds the matching vertices between graphs g1 and g2
   *
   * @param g1
   * @param g2
   * @param threshold - if node similarity is >= than threshold then these nodes are considered to
   *     be matched.
   * @param stemmer - stemmer for wrord stemming, if == null, then english stemmer is used
   * @return matching vertex pairs
   */
  public static ArrayList<VertexPair> getMappingsGraph(
      Graph g1, Graph g2, double threshold, SnowballStemmer stemmer) {

    ArrayList<Vertex> g1Vertices = g1.getFunctions();
    ArrayList<Vertex> g2Vertices = g2.getFunctions();

    if (Settings.considerEvents) {
      g1Vertices.addAll(g1.getEvents());
      g2Vertices.addAll(g2.getEvents());
    }

    return getMappingsVetrex(g1Vertices, g2Vertices, threshold, stemmer, 0);
  }
  public static ArrayList<VertexPair> getMappingsVetrexUsingNodeMapping(
      Graph g1, Graph g2, double threshold, double semanticThreshold) {

    ArrayList<Vertex> g1Vertices = (ArrayList<Vertex>) g1.getVertices();
    ArrayList<Vertex> g2Vertices = (ArrayList<Vertex>) g2.getVertices();

    ArrayList<VertexPair> solutionMappings = new ArrayList<VertexPair>();

    if (g1Vertices.size() == 0 || g2Vertices.size() == 0) {
      return solutionMappings;
    }

    if (g1Vertices.size() > 0 && g2Vertices.size() > 0) {
      int dimFunc = g1Vertices.size() > g2Vertices.size() ? g1Vertices.size() : g2Vertices.size();
      double costs[][] = new double[dimFunc][dimFunc];
      double costsCopy[][] = new double[dimFunc][dimFunc];
      int nrZeros = 0;

      // function mapping score
      for (int i = 0; i < g1Vertices.size(); i++) {
        for (int j = 0; j < g2Vertices.size(); j++) {
          double edScore =
              NodeSimilarity.findNodeSimilarity(g1Vertices.get(i), g2Vertices.get(j), threshold);
          if (g1Vertices.get(i).getType().equals(Type.gateway)
              && g2Vertices.get(j).getType().equals(Type.gateway)
              && edScore < semanticThreshold) {
            edScore = 0;
          } else if (!(g1Vertices.get(i).getType().equals(Type.gateway)
                  && g2Vertices.get(j).getType().equals(Type.gateway))
              && edScore < threshold) edScore = 0;

          if (edScore == 0) {
            nrZeros++;
          }
          costs[i][j] = (-1) * edScore;
        }
      }

      if (nrZeros != g1Vertices.size() * g2Vertices.size()) {
        for (int i = 0; i < costs.length; i++) {
          for (int j = 0; j < costs[0].length; j++) {
            costsCopy[i][j] = costs[i][j];
          }
        }

        int[][] result = HungarianAlgorithm.computeAssignments(costsCopy);

        for (int i = 0; i < result.length; i++) {
          double pairCost = (-1) * costs[result[i][0]][result[i][1]];
          if (result[i][0] < g1Vertices.size()
              && result[i][1] < g2Vertices.size()
              && pairCost > 0
              && AssingmentProblem.canMap(
                  g1Vertices.get(result[i][0]), g2Vertices.get(result[i][1]))) {
            solutionMappings.add(
                new VertexPair(
                    g1Vertices.get(result[i][0]), g2Vertices.get(result[i][1]), pairCost));
          }
        }
      }
    }
    return solutionMappings;
  }