private Matrix walk() throws IOException {

    // Step 0. Initialise transition probabilities
    this.logger.showTimedMessage("Initialise transition probabilities");
    Matrix P = this.initialiseTransitionProbabilities();

    logger.showMemoryUsage();

    // 2. initialise random walkers.
    // keep in mind that this makes sense because of the way the indexes were
    // loaded into this.goTermIndex. Otherwise, we would have to retrieve
    // from this.goTermIndex
    Matrix W = new Matrix(this.getNumGoTerms(), this.getNumGoTerms());
    for (int i = 0; i < this.getNumGoTerms(); i++) {
      W.set(i, i, 1.0f);
    }

    // walk!
    Matrix W_star = W.copy();
    double convergence;
    // int i=0;
    do {
      W = W_star;
      W_star = P.times(W);
      convergence = W_star.minus(W).normF();
      this.logger.showTimedMessage(
          "\t Convergence difference: " + (new Double(convergence)).toString());
      // this.logger.showTimedMessage("\t Doing iteration i=" + i);
      //  i++;
      // }while (i<15);
    } while (convergence > this.epsilon);

    return W_star;
  }
  public Matrix computeISM() throws IOException {
    logger.showMemoryUsage();

    // Step 1. Walk!
    this.logger.showTimedMessage("Walking...");
    Matrix W = walk();

    logger.showMemoryUsage();

    // Step 2. Compute the random wal contribution
    if (this.termwise) {
      this.setRandomWalkContributionTermwise(W);
    } else {
      this.setRandomWalkContributionGeneWise(W);
    }
    W = null;
    System.gc();

    logger.showMemoryUsage();

    // Step 3. get the ISM which we return.
    logger.showMemoryUsage();
    return this.getISM();
  }