/* * Copyright © 2011 by Oleg Kovarik. All Rights Reserved */ package cz.cvut.felk.cig.jcop.problem.tspfast; import cz.cvut.felk.cig.jcop.problem.Configuration; import cz.cvut.felk.cig.jcop.problem.Operation; import cz.cvut.felk.cig.jcop.problem.OperationHistory; import java.util.ArrayList; import java.util.List; /** * Inverts subtour and optimize with 3-OPT local optimization. * * @author Oleg Kovarik */ public class FastInvertSubtourOperation implements Operation { /** * Source index to find switched city on. */ protected int sourceIndex; /** * Destination index to find switched city on. */ protected int destinationIndex; /** * Matrix of distances between cities */ protected int[][] distances; /** * Matrix of nearest neighbors (city, i-th nearest neighbor) */ protected int[][] nearestNeighbors; /** * Number of available nearest neighbors */ protected int nn; public FastInvertSubtourOperation(int sourceIndex, int destinationIndex, int[][] distances, int[][] nearestNeighbors) { this.destinationIndex = destinationIndex; this.sourceIndex = sourceIndex; this.distances = distances; this.nearestNeighbors = nearestNeighbors; this.nn = nearestNeighbors[0].length; } public Configuration execute(Configuration configuration) { int[] result = configuration.asSimpleArray(); int si = sourceIndex; int di = destinationIndex; int dimension = configuration.getDimension(); if (si > di) { di += dimension; } while (di > si) { int tmp = result[si % dimension]; result[si % dimension] = result[di % dimension]; result[di % dimension] = tmp; //newConfiguration.set(si % dimension, configuration.valueAt(di % dimension)); //newConfiguration.set(di % dimension, configuration.valueAt(si % dimension)); di--; si++; } optimize(result, nn); List<Integer> newConfiguration = new ArrayList<Integer>(); for (int i=0; i<dimension; i++) newConfiguration.add(i, new Integer(result[i])); return new Configuration(newConfiguration, new OperationHistory(this, configuration.getOperationHistory())); } @Override public String toString() { return "FastInvertSubtourOperation{" + "sourceIndex=" + sourceIndex + ", destinationIndex=" + destinationIndex + '}'; } /** * Fast 3-OPT local search. Rewritten from C code by Thomas Stuetzle: * * Original code published under GPL v2 (see gpl-ACOTSP.txt). * * Original readme follows: * * --------------------------------------------------- * * * AAAA CCCC OOOO TTTTTT SSSSS PPPPP * AA AA CC OO OO TT SS PP PP * AAAAAA CC OO OO TT SSSS PPPPP * AA AA CC OO OO TT SS PP * AA AA CCCC OOOO TT SSSSS PP * * ###################################################### * ########## ACO algorithms for the TSP ########## * ###################################################### * * Version: 1.0 * Author: Thomas Stuetzle * Copyright (c) Thomas Stuetzle, 2002 * * * This is the README file to the software package ACOTSP. * * This software package was developed by Thomas Stuetzle in connection * with the Book * * [DorStu04] Marco Dorigo and Thomas Stuetzle, "Ant Colony * Optimization", MIT Press, Cambridge, MA, USA, 2004. * * The software package is freely available subject to the * GNU General Public Licence, which is included in file gpl.txt. * * If you use ACOTSP in your research, I would appreciate a citation in * your publication(s). Please cite it as * * Thomas Stuetzle. ACOTSP, Version 1.0. Available from * http://www.aco-metaheuristic.org/aco-code, 2004. * * This software package provides an implementation of various Ant Colony * Optimization (ACO) algorithms for the symmetric Traveling * Salesman Problem (TSP). The ACO algorithms implemented are Ant System, * Elitist Ant System, MAX-MIN Ant System, Rank-based version of Ant * System, Best-Worst Ant System, and Ant Colony System. This is Version * 1.0 of ACOTSP; it is in large part identical to the software used to * produce the results in [DorStu04], but it has been slightly adapted to * make the code more readable, more comments were added, and a new * command line parser was generated with opag. * * AIMS OF THE SOFTWARE: This software was developed to have one common * code for the various known ACO algorithms that were at some point * applied to the TSP in the literature. The software tries to provide a * reasonably efficient implementation of these ACO algorithms while at * the same time aiming for readability and understandability of the * code. * * * @param tour TSP tour to optimize * @param nn_ls number of nearest neighbors */ public void optimize(int[] tour, int nn_ls) { //TODO: rewrite /* In case a 2-opt move should be performed, we only need to store opt2_move = TRUE, as h1, .. h4 are used in such a way that they store the indices of the correct move */ int c1, c2, c3; /* cities considered for an exchange */ int s_c1, s_c2, s_c3; /* successors of these cities */ int p_c1, p_c2, p_c3; /* predecessors of these cities */ int pos_c1, pos_c2, pos_c3; /* positions of cities c1, c2, c3 */ int i, j, h, g, l; boolean improvement_flag; int help; int h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0; /* memorize cities involved in a move */ int diffs, diffp; boolean between = false; boolean opt2_flag; /* = TRUE: perform 2-opt move, otherwise none or 3-opt move */ int move_flag; /* move_flag = 0 --> no 3-opt move move_flag = 1 --> between_move (c3 between c1 and c2) move_flag = 2 --> not_between with successors of c2 and c3 move_flag = 3 --> not_between with predecessors of c2 and c3 move_flag = 4 --> cyclic move */ int gain, move_value, radius, add1, add2; int decrease_breaks; /* Stores decrease by breaking two edges (a,b) (c,d) */ int[] val; int n1, n2, n3; int[] pos; /* positions of cities in tour */ boolean[] dlb; /* vector containing don't look bits */ boolean dlb_flag = true; int[] h_tour; /* help vector for performing exchange move */ int[] hh_tour; /* help vector for performing exchange move */ int[] random_vector; int n = tour.length; random_vector = new int[n]; pos = new int[n]; dlb = new boolean[n]; h_tour = new int[n]; hh_tour = new int[n]; val = new int[3]; for (i = 0; i < n; i++) { pos[tour[i]] = i; dlb[i] = false; } improvement_flag = true; TSPPaths.randomPathFast(random_vector, random_vector.length); //System.out.println("Warning: fast 3 opt used"); while (improvement_flag) { move_value = 0; improvement_flag = false; for (l = 0; l < n; l++) { c1 = random_vector[l]; if (dlb_flag && dlb[c1]) continue; opt2_flag = false; move_flag = 0; pos_c1 = pos[c1]; s_c1 = tour[(pos_c1 + 1)%n]; if (pos_c1 > 0) p_c1 = tour[pos_c1 - 1]; else p_c1 = tour[n - 1]; h = 0; /* Search for one of the h-nearest neighbours */ labelNNsearch: while (h < nn_ls) { c2 = nearestNeighbors[c1][h]; /* second city, determine its position */ pos_c2 = pos[c2]; s_c2 = tour[(pos_c2 + 1)%n]; if (pos_c2 > 0) p_c2 = tour[pos_c2 - 1]; else p_c2 = tour[n - 1]; diffs = 0; diffp = 0; radius = distances[c1][s_c1]; add1 = distances[c1][c2]; /* Here a fixed radius neighbour search is performed */ if (radius > add1) { decrease_breaks = -radius - distances[c2][s_c2]; diffs = decrease_breaks + add1 + distances[s_c1][s_c2]; diffp = -radius - distances[c2][p_c2] + distances[c1][p_c2] + distances[s_c1][c2]; } else break; if (p_c2 == c1) /* in case p_c2 == c1 no exchange is possible */ diffp = 0; if ((diffs < move_value) || (diffp < move_value)) { improvement_flag = true; if (diffs <= diffp) { h1 = c1; h2 = s_c1; h3 = c2; h4 = s_c2; move_value = diffs; opt2_flag = true; move_flag = 0; /* goto exchange; */ } else { h1 = c1; h2 = s_c1; h3 = p_c2; h4 = c2; move_value = diffp; opt2_flag = true; move_flag = 0; /* goto exchange; */ } } /* Now perform the innermost search */ g = 0; while (g < nn_ls) { c3 = nearestNeighbors[s_c1][g]; pos_c3 = pos[c3]; s_c3 = tour[(pos_c3 + 1)%n]; if (pos_c3 > 0) p_c3 = tour[pos_c3 - 1]; else p_c3 = tour[n - 1]; if (c3 == c1) { g++; continue; } else { add2 = distances[s_c1][c3]; /* Perform fixed radius neighbour search for innermost search */ if (decrease_breaks + add1 < add2) { if (pos_c2 > pos_c1) { if (pos_c3 <= pos_c2 && pos_c3 > pos_c1) between = true; else between = false; } else if (pos_c2 < pos_c1) if (pos_c3 > pos_c1 || pos_c3 < pos_c2) between = true; else between = false; else { System.out.println(" Strange !!, pos_1 " + pos_c1 + " == pos_2 " + pos_c2); } if (between) { /* We have to add edges (c1,c2), (c3,s_c1), (p_c3,s_c2) to get valid tour; it's the only possibility */ gain = decrease_breaks - distances[c3][p_c3] + add1 + add2 + distances[p_c3][s_c2]; /* check for improvement by move */ if (gain < move_value) { improvement_flag = true; /* g = neigh_ls + 1; */ move_value = gain; opt2_flag = false; move_flag = 1; /* store nodes involved in move */ h1 = c1; h2 = s_c1; h3 = c2; h4 = s_c2; h5 = p_c3; h6 = c3; break labelNNsearch; //goto exchange; } } else { /* not between(pos_c1,pos_c2,pos_c3) */ /* We have to add edges (c1,c2), (s_c1,c3), (s_c2,s_c3) */ gain = decrease_breaks - distances[c3][s_c3] + add1 + add2 + distances[s_c2][s_c3]; if (pos_c2 == pos_c3) { gain = 20000; } /* check for improvement by move */ if (gain < move_value) { improvement_flag = true; /* g = neigh_ls + 1; */ move_value = gain; opt2_flag = false; move_flag = 2; /* store nodes involved in move */ h1 = c1; h2 = s_c1; h3 = c2; h4 = s_c2; h5 = c3; h6 = s_c3; break labelNNsearch; //goto exchange; } /* or add edges (c1,c2), (s_c1,c3), (p_c2,p_c3) */ gain = -radius - distances[p_c2][c2] - distances[p_c3][c3] + add1 + add2 + distances[p_c2][p_c3]; if (c3 == c2 || c2 == c1 || c1 == c3 || p_c2 == c1) { gain = 2000000; } if (gain < move_value) { improvement_flag = true; move_value = gain; opt2_flag = false; move_flag = 3; h1 = c1; h2 = s_c1; h3 = p_c2; h4 = c2; h5 = p_c3; h6 = c3; break labelNNsearch; // goto exchange; } /* Or perform the 3-opt move where no subtour inversion is necessary i.e. delete edges (c1,s_c1), (c2,p_c2), (c3,s_c3) and add edges (c1,c2), (c3,s_c1), (p_c2,s_c3) */ gain = -radius - distances[p_c2][c2] - distances[c3][s_c3] + add1 + add2 + distances[p_c2][s_c3]; /* check for improvement */ if (gain < move_value) { improvement_flag = true; move_value = gain; opt2_flag = false; move_flag = 4; improvement_flag = true; /* store nodes involved in move */ h1 = c1; h2 = s_c1; h3 = p_c2; h4 = c2; h5 = c3; h6 = s_c3; break labelNNsearch; //goto exchange; } } } else g = nn_ls + 1; } g++; } h++; } if (move_flag > 0 || opt2_flag) { exchange: move_value = 0; /* Now make the exchange */ if (move_flag > 0) { dlb[h1] = false; dlb[h2] = false; dlb[h3] = false; dlb[h4] = false; dlb[h5] = false; dlb[h6] = false; pos_c1 = pos[h1]; pos_c2 = pos[h3]; pos_c3 = pos[h5]; if (move_flag == 4) { if (pos_c2 > pos_c1) n1 = pos_c2 - pos_c1; else n1 = n - (pos_c1 - pos_c2); if (pos_c3 > pos_c2) n2 = pos_c3 - pos_c2; else n2 = n - (pos_c2 - pos_c3); if (pos_c1 > pos_c3) n3 = pos_c1 - pos_c3; else n3 = n - (pos_c3 - pos_c1); /* n1: length h2 - h3, n2: length h4 - h5, n3: length h6 - h1 */ val[0] = n1; val[1] = n2; val[2] = n3; /* Now order the partial tours */ h = 0; help = Integer.MIN_VALUE; for (g = 0; g <= 2; g++) { if (help < val[g]) { help = val[g]; h = g; } } /* order partial tours according length */ if (h == 0) { /* copy part from pos[h4] to pos[h5] direkt kopiert: Teil von pos[h6] to pos[h1], it remains the part from pos[h2] to pos[h3] */ j = pos[h4]; h = pos[h5]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j++; if (j >= n) j = 0; h_tour[i] = tour[j]; n1++; } /* First copy partial tour 3 in new position */ j = pos[h4]; i = pos[h6]; tour[j] = tour[i]; pos[tour[i]] = j; while (i != pos_c1) { i++; if (i >= n) i = 0; j++; if (j >= n) j = 0; tour[j] = tour[i]; pos[tour[i]] = j; } /* Now copy stored part from h_tour */ j++; if (j >= n) j = 0; for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } //tour[n] = tour[0]; } else if (h == 1) { /* copy part from pos[h6] to pos[h1] direkt kopiert: Teil von pos[h2] to pos[h3], it remains the part from pos[h4] to pos[h5] */ j = pos[h6]; h = pos[h1]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j++; if (j >= n) j = 0; h_tour[i] = tour[j]; n1++; } /* First copy partial tour 3 in new position */ j = pos[h6]; i = pos[h2]; tour[j] = tour[i]; pos[tour[i]] = j; while (i != pos_c2) { i++; if (i >= n) i = 0; j++; if (j >= n) j = 0; tour[j] = tour[i]; pos[tour[i]] = j; } /* Now copy stored part from h_tour */ j++; if (j >= n) j = 0; for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } //tour[n] = tour[0]; } else if (h == 2) { /* copy part from pos[h2] to pos[h3] direkt kopiert: Teil von pos[h4] to pos[h5], it remains the part from pos[h6] to pos[h1] */ j = pos[h2]; h = pos[h3]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j++; if (j >= n) j = 0; h_tour[i] = tour[j]; n1++; } /* First copy partial tour 3 in new position */ j = pos[h2]; i = pos[h4]; tour[j] = tour[i]; pos[tour[i]] = j; while (i != pos_c3) { i++; if (i >= n) i = 0; j++; if (j >= n) j = 0; tour[j] = tour[i]; pos[tour[i]] = j; } /* Now copy stored part from h_tour */ j++; if (j >= n) j = 0; for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } //tour[n] = tour[0]; } } else if (move_flag == 1) { if (pos_c3 < pos_c2) n1 = pos_c2 - pos_c3; else n1 = n - (pos_c3 - pos_c2); if (pos_c3 > pos_c1) n2 = pos_c3 - pos_c1 + 1; else n2 = n - (pos_c1 - pos_c3 + 1); if (pos_c2 > pos_c1) n3 = n - (pos_c2 - pos_c1 + 1); else n3 = pos_c1 - pos_c2 + 1; /* n1: length h6 - h3, n2: length h5 - h2, n2: length h1 - h3 */ val[0] = n1; val[1] = n2; val[2] = n3; /* Now order the partial tours */ h = 0; help = Integer.MIN_VALUE; for (g = 0; g <= 2; g++) { if (help < val[g]) { help = val[g]; h = g; } } /* order partial tours according length */ if (h == 0) { /* copy part from pos[h5] to pos[h2] (inverted) and from pos[h4] to pos[h1] (inverted) it remains the part from pos[h6] to pos[h3] */ j = pos[h5]; h = pos[h2]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; h_tour[i] = tour[j]; n1++; } j = pos[h1]; h = pos[h4]; i = 0; hh_tour[i] = tour[j]; n2 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; hh_tour[i] = tour[j]; n2++; } j = pos[h4]; for (i = 0; i < n2; i++) { tour[j] = hh_tour[i]; pos[hh_tour[i]] = j; j++; if (j >= n) j = 0; } /* Now copy stored part from h_tour */ for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } //tour[n] = tour[0]; } else if (h == 1) { /* copy part from h3 to h6 (wird inverted) erstellen : */ j = pos[h3]; h = pos[h6]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; h_tour[i] = tour[j]; n1++; } j = pos[h6]; i = pos[h4]; tour[j] = tour[i]; pos[tour[i]] = j; while (i != pos_c1) { i++; j++; if (j >= n) j = 0; if (i >= n) i = 0; tour[j] = tour[i]; pos[tour[i]] = j; } /* Now copy stored part from h_tour */ j++; if (j >= n) j = 0; i = 0; tour[j] = h_tour[i]; pos[h_tour[i]] = j; while (j != pos_c1) { j++; if (j >= n) j = 0; i++; tour[j] = h_tour[i]; pos[h_tour[i]] = j; } //tour[n] = tour[0]; } else if (h == 2) { /* copy part from pos[h2] to pos[h5] and from pos[h3] to pos[h6] (inverted), it remains the part from pos[h4] to pos[h1] */ j = pos[h2]; h = pos[h5]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j++; if (j >= n) j = 0; h_tour[i] = tour[j]; n1++; } j = pos_c2; h = pos[h6]; i = 0; hh_tour[i] = tour[j]; n2 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; hh_tour[i] = tour[j]; n2++; } j = pos[h2]; for (i = 0; i < n2; i++) { tour[j] = hh_tour[i]; pos[hh_tour[i]] = j; j++; if (j >= n) j = 0; } /* Now copy stored part from h_tour */ for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } //tour[n] = tour[0]; } } else if (move_flag == 2) { if (pos_c3 < pos_c1) n1 = pos_c1 - pos_c3; else n1 = n - (pos_c3 - pos_c1); if (pos_c3 > pos_c2) n2 = pos_c3 - pos_c2; else n2 = n - (pos_c2 - pos_c3); if (pos_c2 > pos_c1) n3 = pos_c2 - pos_c1; else n3 = n - (pos_c1 - pos_c2); val[0] = n1; val[1] = n2; val[2] = n3; /* Determine which is the longest part */ h = 0; help = Integer.MIN_VALUE; for (g = 0; g <= 2; g++) { if (help < val[g]) { help = val[g]; h = g; } } /* order partial tours according length */ if (h == 0) { /* copy part from pos[h3] to pos[h2] (inverted) and from pos[h5] to pos[h4], it remains the part from pos[h6] to pos[h1] */ j = pos[h3]; h = pos[h2]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; h_tour[i] = tour[j]; n1++; } j = pos[h5]; h = pos[h4]; i = 0; hh_tour[i] = tour[j]; n2 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; hh_tour[i] = tour[j]; n2++; } j = pos[h2]; for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } for (i = 0; i < n2; i++) { tour[j] = hh_tour[i]; pos[hh_tour[i]] = j; j++; if (j >= n) j = 0; } //tour[n] = tour[0]; /* getchar(); */ } else if (h == 1) { /* copy part from pos[h2] to pos[h3] and from pos[h1] to pos[h6] (inverted), it remains the part from pos[h4] to pos[h5] */ j = pos[h2]; h = pos[h3]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j++; if (j >= n) j = 0; h_tour[i] = tour[j]; n1++; } j = pos[h1]; h = pos[h6]; i = 0; hh_tour[i] = tour[j]; n2 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; hh_tour[i] = tour[j]; n2++; } j = pos[h6]; for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } for (i = 0; i < n2; i++) { tour[j] = hh_tour[i]; pos[hh_tour[i]] = j; j++; if (j >= n) j = 0; } //tour[n] = tour[0]; } else if (h == 2) { /* copy part from pos[h1] to pos[h6] (inverted) and from pos[h4] to pos[h5], it remains the part from pos[h2] to pos[h3] */ j = pos[h1]; h = pos[h6]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; h_tour[i] = tour[j]; n1++; } j = pos[h4]; h = pos[h5]; i = 0; hh_tour[i] = tour[j]; n2 = 1; while (j != h) { i++; j++; if (j >= n) j = 0; hh_tour[i] = tour[j]; n2++; } j = pos[h4]; /* Now copy stored part from h_tour */ for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } /* Now copy stored part from h_tour */ for (i = 0; i < n2; i++) { tour[j] = hh_tour[i]; pos[hh_tour[i]] = j; j++; if (j >= n) j = 0; } //tour[n] = tour[0]; } } else if (move_flag == 3) { if (pos_c3 < pos_c1) n1 = pos_c1 - pos_c3; else n1 = n - (pos_c3 - pos_c1); if (pos_c3 > pos_c2) n2 = pos_c3 - pos_c2; else n2 = n - (pos_c2 - pos_c3); if (pos_c2 > pos_c1) n3 = pos_c2 - pos_c1; else n3 = n - (pos_c1 - pos_c2); /* n1: length h6 - h1, n2: length h4 - h5, n2: length h2 - h3 */ val[0] = n1; val[1] = n2; val[2] = n3; /* Determine which is the longest part */ h = 0; help = Integer.MIN_VALUE; for (g = 0; g <= 2; g++) { if (help < val[g]) { help = val[g]; h = g; } } /* order partial tours according length */ if (h == 0) { /* copy part from pos[h2] to pos[h3] (inverted) and from pos[h4] to pos[h5] it remains the part from pos[h6] to pos[h1] */ j = pos[h3]; h = pos[h2]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; h_tour[i] = tour[j]; n1++; } j = pos[h2]; h = pos[h5]; i = pos[h4]; tour[j] = h4; pos[h4] = j; while (i != h) { i++; if (i >= n) i = 0; j++; if (j >= n) j = 0; tour[j] = tour[i]; pos[tour[i]] = j; } j++; if (j >= n) j = 0; for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } //tour[n] = tour[0]; } else if (h == 1) { /* copy part from pos[h3] to pos[h2] (inverted) and from pos[h6] to pos[h1], it remains the part from pos[h4] to pos[h5] */ j = pos[h3]; h = pos[h2]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; h_tour[i] = tour[j]; n1++; } j = pos[h6]; h = pos[h1]; i = 0; hh_tour[i] = tour[j]; n2 = 1; while (j != h) { i++; j++; if (j >= n) j = 0; hh_tour[i] = tour[j]; n2++; } j = pos[h6]; for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } for (i = 0; i < n2; i++) { tour[j] = hh_tour[i]; pos[hh_tour[i]] = j; j++; if (j >= n) j = 0; } //tour[n] = tour[0]; } else if (h == 2) { /* copy part from pos[h4] to pos[h5] (inverted) and from pos[h6] to pos[h1] (inverted) it remains the part from pos[h2] to pos[h3] */ j = pos[h5]; h = pos[h4]; i = 0; h_tour[i] = tour[j]; n1 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; h_tour[i] = tour[j]; n1++; } j = pos[h1]; h = pos[h6]; i = 0; hh_tour[i] = tour[j]; n2 = 1; while (j != h) { i++; j--; if (j < 0) j = n - 1; hh_tour[i] = tour[j]; n2++; } j = pos[h4]; /* Now copy stored part from h_tour */ for (i = 0; i < n1; i++) { tour[j] = h_tour[i]; pos[h_tour[i]] = j; j++; if (j >= n) j = 0; } /* Now copy stored part from h_tour */ for (i = 0; i < n2; i++) { tour[j] = hh_tour[i]; pos[hh_tour[i]] = j; j++; if (j >= n) j = 0; } // tour[n] = tour[0]; } } else { System.out.println(" Some very strange error must have occurred !!!"); System.exit(0); } } if (opt2_flag) { /* Now perform move */ dlb[h1] = false; dlb[h2] = false; dlb[h3] = false; dlb[h4] = false; if (pos[h3] < pos[h1]) { help = h1; h1 = h3; h3 = help; help = h2; h2 = h4; h4 = help; } if (pos[h3] - pos[h2] < n / 2 + 1) { /* reverse inner part from pos[h2] to pos[h3] */ i = pos[h2]; j = pos[h3]; while (i < j) { c1 = tour[i]; c2 = tour[j]; tour[i] = c2; tour[j] = c1; pos[c1] = j; pos[c2] = i; i++; j--; } } else { /* reverse outer part from pos[h4] to pos[h1] */ i = pos[h1]; j = pos[h4]; if (j > i) help = n - (j - i) + 1; else help = (i - j) + 1; help = help / 2; for (h = 0; h < help; h++) { c1 = tour[i]; c2 = tour[j]; tour[i] = c2; tour[j] = c1; pos[c1] = j; pos[c2] = i; i--; j++; if (i < 0) i = n - 1; if (j >= n) j = 0; } // tour[n] = tour[0]; } } } else { dlb[c1] = true; } } } } }