public void update() {
    stressBeforeUpdate = stressAfterUpdate;

    computeBofCoordinates();
    BZ.multiply(newPositionMatrix, positionMatrix);
    positionMatrix.set(newPositionMatrix);
    vPlus.substituteBack(positionMatrix);
    distances.set(new DistanceMatrix(positions));
    stressAfterUpdate = stress();

    iterations++;
  }
  public void initialize(
      Space space, Matrix dissimilarities, List<Vector> positions, Matrix weights)
      throws Exception {
    this.space = space;
    dimensions = positions.size();
    positionSpace = new ListSpace(positions);

    distances = new RowArrayMatrix(positionSpace, positionSpace);
    distances.set(new DistanceMatrix(positions));

    this.dissimilarities = new RowArrayMatrix(dissimilarities);
    this.positions = positions;

    if (weights != null) this.weights = new RowArrayMatrix(weights);
    else {
      this.weights = new RowArrayMatrix(positionSpace, positionSpace);
      this.weights.ones();
    }

    newPositions = new ArrayList<Vector>();

    for (int i = 0; i < positions.size(); i++) newPositions.add(new ArrayVector(space));

    positionMatrix = new RowVectorMatrix(positions, space);
    newPositionMatrix = new RowVectorMatrix(newPositions, space);

    normalizeWeights();

    vPlus = computeVPlus(this.weights);
    stressBeforeUpdate = Double.MAX_VALUE;
    stressAfterUpdate = stress();
    iterations = 0;
    BZ = new RowArrayMatrix(positionSpace, positionSpace);
  }
  public void dump() {
    System.out.println("Distances:");
    distances.dump();

    System.out.println("Coordinates:");
    for (Vector coordinate : positions) coordinate.dump();

    System.out.println("Stress: " + stressAfterUpdate);
  }
  private PermutedLUDecomposition computeVPlus(RowArrayMatrix weights) throws Exception {
    RowArrayMatrix V = new RowArrayMatrix(positionSpace, positionSpace);

    for (int i = 0; i < dimensions; i++) {
      for (int j = 0; j < dimensions; j++) {
        if (i == j) {
          double sum = 0;

          for (int k = 0; k < dimensions; k++) if (k != i) sum += weights.values[i][k];

          V.values[i][j] = sum;
        } else V.values[i][j] = -weights.values[i][j];
      }
    }

    V.add(1);

    return new PermutedLUDecomposition(V);
  }
 private void normalizeWeights() {
   weights.setMainDiagonal(0);
   weights.divide(weights.maximum());
   weights.setMainDiagonal(1);
 }