public DefaultGraph copy() {
   DefaultGraph ret = new DefaultGraph();
   for (int i = 0; i < getNodeCount(); i++)
     for (int j : getNeighbors(i)) ret.addEdge(i, j, getEdgeWeight(i, j));
   return ret;
 }
  @Override
  public ResultGraph compressGraph(DefaultGraph ig, double goalRatio) {
    mergeModel.init(ig);

    int totalCost = mergeModel.getStartCost();

    int goalCost = (int) (totalCost * goalRatio);

    int size = ig.getNodeCount();

    int thldN = 0;
    System.out.println("goalCost = " + goalCost);

    while (totalCost > goalCost) {

      double minFound = 100;
      int a, b;
      a = b = 0;
      int theReduction = 0;
      for (int i = 0; i < size; i++) {
        if (!mergeModel.isAlive(i)) continue;
        Collection<Integer> mergeCheck;
        if (hop2) mergeCheck = mergeModel.getHopNeighbors(i, 2);
        else {
          mergeCheck = new ArrayList<Integer>();
          for (int j = i + 1; j < size; j++) mergeCheck.add(j);
        }

        // System.out.println("N1("+i+")="+mergeModel.getNeighbors(i).size());
        // System.out.println("N2("+i+")="+foo.size());
        // Collection<Integer>

        for (int j : mergeCheck) {
          if (i == j) continue;
          if (!mergeModel.isAlive(j)) continue;

          double d = mergeModel.mergeError(i, j);
          int reduction = mergeModel.mergeCostReduction(i, j);
          // if(reduction<=0)continue;

          // System.out.println(threshold(thldN));
          // minFound=Math.min(d,minFound);
          // System.out.println("md "+i+" "+j+" = "+d);

          double s = d; // d/reduction;
          if (s < minFound) {
            minFound = s;
            a = i;
            b = j;
            theReduction = reduction;
          }
        }
      }
      if (a != b) mergeModel.merge(a, b);
      totalCost -= theReduction;
      if (minFound >= 1.0) break;

      System.out.println("totalCost = " + totalCost);
    }

    System.out.println("totalCost = " + totalCost);

    return mergeModel.getResult();
  }