anchor.diff:  
       @Override
       public void setup(final Memory memory) {
  -
  +        memory.set(TELEPORTATION_ENERGY, null == this.initialRankTraversal ? 1.0d : 0.0d);
  +        memory.set(VERTEX_COUNT, 0.0d);
  +        memory.set(CONVERGENCE_ERROR, 1.0d);
       }
   
       @Override
       public void execute(final Vertex vertex, Messenger<Double> messenger, final Memory memory) { <7>
           if (memory.isInitialIteration()) {
  -            messenger.sendMessage(this.countMessageScope, 1.0d); <8>
  -        } else if (1 == memory.getIteration()) {
  -            double initialPageRank = (null == this.initialRankTraversal ?
  -                    1.0d :
  -                    TraversalUtil.apply(vertex, this.initialRankTraversal.get()).doubleValue()) / this.vertexCountAsDouble;  <9>
  -            double edgeCount = IteratorUtils.reduce(messenger.receiveMessages(), 0.0d, (a, b) -> a + b);
  -            vertex.property(VertexProperty.Cardinality.single, this.property, initialPageRank);
  -            vertex.property(VertexProperty.Cardinality.single, EDGE_COUNT, edgeCount);
  -            if (!this.terminate(memory)) // don't send messages if this is the last iteration
  -                messenger.sendMessage(this.incidentMessageScope, initialPageRank / edgeCount);
  +            messenger.sendMessage(this.countMessageScope, 1.0d);  <8>
  +            memory.add(VERTEX_COUNT, 1.0d);
           } else {
  -            double newPageRank = IteratorUtils.reduce(messenger.receiveMessages(), 0.0d, (a, b) -> a + b); <10>
  -            newPageRank = (this.alpha * newPageRank) + ((1.0d - this.alpha) / this.vertexCountAsDouble);
  -            vertex.property(VertexProperty.Cardinality.single, this.property, newPageRank);
  -            if (!this.terminate(memory)) // don't send messages if this is the last iteration
  -                messenger.sendMessage(this.incidentMessageScope, newPageRank / vertex.<Double>value(EDGE_COUNT));
  +            final double vertexCount = memory.<Double>get(VERTEX_COUNT);
  +            final double edgeCount;
  +            double pageRank;
  +            if (1 == memory.getIteration()) {
  +                edgeCount = IteratorUtils.reduce(messenger.receiveMessages(), 0.0d, (a, b) -> a + b);
  +                vertex.property(VertexProperty.Cardinality.single, EDGE_COUNT, edgeCount);
  +                pageRank = null == this.initialRankTraversal ?
  +                        0.0d :
  +                        TraversalUtil.apply(vertex, this.initialRankTraversal.get()).doubleValue(); <9>
  +            } else {
  +                edgeCount = vertex.value(EDGE_COUNT);
  +                pageRank = IteratorUtils.reduce(messenger.receiveMessages(), 0.0d, (a, b) -> a + b); <10>
  +            }
  +            //////////////////////////
  +            final double teleporationEnergy = memory.get(TELEPORTATION_ENERGY);
  +            if (teleporationEnergy > 0.0d) {
  +                final double localTerminalEnergy = teleporationEnergy / vertexCount;
  +                pageRank = pageRank + localTerminalEnergy;
  +                memory.add(TELEPORTATION_ENERGY, -localTerminalEnergy);
  +            }
  +            final double previousPageRank = vertex.<Double>property(this.property).orElse(0.0d);
  +            memory.add(CONVERGENCE_ERROR, Math.abs(pageRank - previousPageRank));
  +            vertex.property(VertexProperty.Cardinality.single, this.property, pageRank);
  +            memory.add(TELEPORTATION_ENERGY, (1.0d - this.alpha) * pageRank);
  +            pageRank = this.alpha * pageRank;
  +            if (edgeCount > 0.0d)
  +                messenger.sendMessage(this.incidentMessageScope, pageRank / edgeCount);
  +            else
  +                memory.add(TELEPORTATION_ENERGY, pageRank);
           }
       }
   
       @Override
  -    public boolean terminate(final Memory memory) {
  -        return memory.getIteration() >= this.totalIterations;  <11>
  +    public boolean terminate(final Memory memory) { <11>
  +        boolean terminate = memory.<Double>get(CONVERGENCE_ERROR) < this.epsilon || memory.getIteration() >= this.maxIterations;
  +        memory.set(CONVERGENCE_ERROR, 0.0d);
  +        return terminate;
       }
   
       @Override
       public String toString() {
  -        return StringFactory.vertexProgramString(this, "alpha=" + this.alpha + ", iterations=" + this.totalIterations);
  +        return StringFactory.vertexProgramString(this, "alpha=" + this.alpha + ", epsilon=" + this.epsilon + ", iterations=" + this.maxIterations);
       }
   }
   ----
  
positive.code:     }
  
      @Override
      public Set<VertexComputeKey> getVertexComputeKeys() {   <6>
          return this.vertexComputeKeys;
      }
  
      @Override
      public Optional<MessageCombiner<Double>> getMessageCombiner() {
          return (Optional) PageRankMessageCombiner.instance();
      }
  
      @Override
  
negative.code: <8> In order to determine how to distribute the energy to neighbors, a "1"-count is used to determine how many incident vertices exist for the `MessageScope`.
  <9> Initially, each vertex is provided an equal amount of energy represented as a double.
  <10> Energy is aggregated, computed on according to the PageRank algorithm, and then disseminated according to the defined `MessageScope.Local`.
  <11> The computation is terminated after epsilon-convergence is met or a pre-defined number of iterations have taken place.
  
  The above `PageRankVertexProgram` is used as follows.
  
  