// returns the energy of i (looping over all other nodes)
 private double getDeltaM(
     int i,
     DenseDoubleMatrix2D lMatrix,
     DenseDoubleMatrix2D kMatrix,
     double[] xPos,
     double[] yPos) {
   int nNodes = lMatrix.rows();
   double deltaM = 0;
   double xPartial = 0;
   double yPartial = 0;
   double dx, dy, dd;
   for (int j = 0; j < nNodes; j++) {
     if (i != j) {
       dx = xPos[i] - xPos[j];
       dy = yPos[i] - yPos[j];
       dd = Math.sqrt(dx * dx + dy * dy);
       double kMatrixVal = kMatrix.getQuick(i, j);
       double lMatrixVal = lMatrix.getQuick(i, j);
       xPartial += kMatrixVal * (dx - lMatrixVal * dx / dd);
       yPartial += kMatrixVal * (dy - lMatrixVal * dy / dd);
     }
   }
   // deltaM = sqrt(xPartial^2+yPartial^2)
   deltaM = Math.sqrt(xPartial * xPartial + yPartial * yPartial);
   return deltaM;
 }
  // the bulk of the KK inner loop, estimates location of local minima
  private double[] getDeltas(
      int i,
      DenseDoubleMatrix2D lMatrix,
      DenseDoubleMatrix2D kMatrix,
      double[] xPos,
      double[] yPos) {
    // solve deltaM partial eqns to figure out new position for node of index i
    // where deltaM is close to 0 (or less then epsilon)
    int nNodes = lMatrix.rows();
    double[] deltas = new double[2]; // holds x and y coords to return
    double dx, dy, dd;
    // double deltaX, deltaY;
    double xPartial = 0;
    double yPartial = 0;
    double xxPartial = 0;
    double xyPartial = 0;
    double yxPartial = 0;
    double yyPartial = 0;
    for (int j = 0; j < nNodes; j++) {
      if (i != j) {
        dx = xPos[i] - xPos[j];
        dy = yPos[i] - yPos[j];
        dd = Math.sqrt(dx * dx + dy * dy);

        double kMatrixVal = kMatrix.getQuick(i, j);
        double lMatrixVal = lMatrix.getQuick(i, j);
        double ddCubed = dd * dd * dd;

        xPartial += kMatrixVal * (dx - lMatrixVal * dx / dd);
        yPartial += kMatrixVal * (dy - lMatrixVal * dy / dd);
        xxPartial += kMatrixVal * (1 - lMatrixVal * dy * dy / ddCubed);
        xyPartial += kMatrixVal * (lMatrixVal * dx * dy / ddCubed);
        yxPartial += kMatrixVal * (lMatrixVal * dy * dx / ddCubed);
        yyPartial += kMatrixVal * (1 - lMatrixVal * dx * dx / ddCubed);
      }
    }

    // calculate x and y position difference using partials
    deltas[0] =
        ((-xPartial) * yyPartial - xyPartial * (-yPartial))
            / (xxPartial * yyPartial - xyPartial * yxPartial);
    deltas[1] =
        (xxPartial * (-yPartial) - (-xPartial) * yxPartial)
            / (xxPartial * yyPartial - xyPartial * yxPartial);

    return deltas;
  }
 // calculate the diameter of the graph (longest shortest path)
 // requires that path lengths are calc'd first
 private int getDiam(DenseDoubleMatrix2D distMatrix) {
   int nNodes = distMatrix.rows();
   double graphDiam = 0;
   for (int i = 0; i < nNodes; i++) {
     for (int j = 0; j < nNodes; j++) {
       graphDiam = Math.max(graphDiam, distMatrix.getQuick(i, j));
     }
   }
   return (int) graphDiam;
 }
 // set up matrix of desired edge lengths using L*d[i][j]
 private DenseDoubleMatrix2D calcLMatrix(DenseDoubleMatrix2D distMatrix, double optDist) {
   int nNodes = distMatrix.rows();
   DenseDoubleMatrix2D lMatrix = new DenseDoubleMatrix2D(nNodes, nNodes);
   for (int i = 0; i < nNodes; i++) {
     for (int j = 0; j < nNodes; j++) {
       lMatrix.setQuick(i, j, (optDist * distMatrix.getQuick(i, j)));
     }
   }
   return lMatrix;
 }
 private double getEnergy(
     DenseDoubleMatrix2D lMatrix, DenseDoubleMatrix2D kMatrix, double[] xPos, double[] yPos) {
   int nNodes = lMatrix.rows();
   double energy = 0;
   double dx, dy, lij;
   int limit = nNodes - 1;
   // for all pairs..
   for (int i = 0; i < limit; i++) {
     for (int j = i + 1; j < nNodes; j++) {
       dx = xPos[i] - xPos[j];
       dy = yPos[i] - yPos[j];
       lij = lMatrix.getQuick(i, j);
       energy +=
           0.5
               * kMatrix.getQuick(i, j)
               * (dx * dx + dy * dy + lij * lij - 2 * lij * Math.sqrt(dx * dx + dy * dy));
     }
   }
   return energy;
 }
 // set up matrix of spring forces between pairs using K/(d[i][j]^2)
 private DenseDoubleMatrix2D calcKMatrix(DenseDoubleMatrix2D distMatrix, double spring) {
   int nNodes = distMatrix.rows();
   DenseDoubleMatrix2D kMatrix = new DenseDoubleMatrix2D(nNodes, nNodes);
   for (int i = 0; i < nNodes; i++) {
     for (int j = 0; j < nNodes; j++) {
       double distMVal = distMatrix.getQuick(i, j);
       kMatrix.setQuick(i, j, (spring / (distMVal * distMVal)));
     }
   }
   return kMatrix;
 }
  /**
   * Copies the matrix elements from the specified DenseDoubleMatrix2D. The matrix element at ij is
   * set to 0 if the element at DoubleMatrix[i][j] = 0, otherwise the matrix element at ij is set to
   * 1.
   *
   * @param m the actual matrix data for this AdjacencyMatrix
   */
  public void setMatrix(DenseDoubleMatrix2D m) {
    int rows = m.rows();
    int cols = m.columns();

    matrix = new BitMatrix2D(rows, cols);

    for (int i = 0; i < rows; i++) {
      for (int j = 0; j < cols; j++) {
        matrix.set(i, j, (byte) m.getQuick(i, j));
      }
    }
  }