/**
   * Auxiliary method used for type safety
   *
   * @param <V>
   * @param rI
   * @param rJ
   * @param nodeI
   * @param nodeJ
   * @param star
   * @return
   */
  protected <V extends INodeVisit> boolean executeMove(
      IRoute<V> rI, IRoute<V> rJ, int i, int j, boolean star) {

    if (!star) {
      // standard 2-opt
      // nodeI linked with nodeJ
      // nodeI+1 linked with nodeJ+1

      IRoute<V> startJ = rJ.extractSubroute(0, j);
      IRoute<V> endI = rI.extractSubroute(i + 1, rI.length() - 1);

      startJ.reverseRoute();
      endI.reverseRoute();

      rI.appendRoute(startJ);
      rJ.insertSubroute(0, endI);

    } else {
      // special 2-opt*
      // nodeI linked with nodeJ+1
      // nodeI+1 linked with nodeJ

      IRoute<V> endJ = rJ.extractSubroute(j + 1, rJ.length() - 1);
      IRoute<V> endI = rI.extractSubroute(i + 1, rI.length() - 1);

      rI.appendRoute(endJ);
      rJ.appendRoute(endI);
    }

    return true;
  }