@SuppressWarnings({"unchecked", "rawtypes"}) @Override protected boolean executeMoveImplem(S solution, IMove move) { if (!(move instanceof TwoOptMove)) { throw new IllegalArgumentException("The move must be of type TwoOptMove"); } boolean r; TwoOptMove twoOptMove = (TwoOptMove) move; IRoute rI = solution.getRoute(twoOptMove.getRouteI()); IRoute rJ = null; int i = twoOptMove.getI(); int j = twoOptMove.getJ(); // Intra route move if (twoOptMove.getRouteI() == twoOptMove.getRouteJ()) { // Remove (nodeI,nodeI+1) and (nodeJ,nodeJ+1) // Reconnect nodeI with nodeJ and nodeI+1 with nodeJ+1 rI.reverseSubRoute(i + 1, j); // rI.updateCost(-twoOptMove.getImprovement()); r = true; // Inter route move } else { rJ = solution.getRoute(twoOptMove.getRouteJ()); // Auxiliary method to solve type safety problems r = executeMove(rI, rJ, i, j, twoOptMove.isStar()); } return r; }
/** * 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; }