class TabuSearch {
public static int[] getBestNeighbour(TabuList tabuList,
TSPEnvironment tspEnviromnet,
int[] initSolution) {
int[] bestSol = new int[initSolution.length]; //this is the best Solution So Far
System.
arraycopy(initSolution,
0, bestSol,
0, bestSol.
length); int bestCost = tspEnviromnet.getObjectiveFunctionValue(initSolution);
int city1 = 0;
int city2 = 0;
boolean firstNeighbor = true;
for (int i = 1; i < bestSol.length - 1; i++) {
for (int j = 2; j < bestSol.length - 1; j++) {
if (i == j) {
continue;
}
int[] newBestSol = new int[bestSol.length]; //this is the best Solution So Far
System.
arraycopy(bestSol,
0, newBestSol,
0, newBestSol.
length); printSolution(newBestSol);
newBestSol = swapOperator(i, j, initSolution); //Try swapping cities i and j
printSolution(neeBestSol);
// , maybe we get a bettersolution
int newBestCost = tspEnviromnet.getObjectiveFunctionValue(newBestSol);
if ((newBestCost > bestCost || firstNeighbor) && tabuList.tabuList[i][j] == 0) { //if better move found, store it
firstNeighbor = false;
city1 = i;
city2 = j;
System.
arraycopy(newBestSol,
0, bestSol,
0, newBestSol.
length); bestCost = newBestCost;
}
}
}
if (city1 != 0) {
tabuList.decrementTabu();
tabuList.tabuMove(city1, city2);
}
return bestSol;
}
//swaps two cities
public static int[] swapOperator(int city1, int city2, int[] solution) {
int temp = solution[city1];
solution[city1] = solution[city2];
solution[city2] = temp;
return solution;
}
public static void main
(String[] args
) {
TSPEnvironment tspEnvironment = new TSPEnvironment();
tspEnvironment.distances = //Distance matrix, 5x5, used to represent distances
new int[][]{{0, 1, 3, 4, 5},
{1, 0, 1, 4, 8},
{3, 1, 0, 5, 1},
{4, 4, 5, 0, 2},
{5, 8, 1, 2, 0}};
//Between cities. 0,1 represents distance between cities 0 and 1, and so on.
int[] currSolution = new int[]{0, 1, 2, 4, 3, 0}; //initial solution
//city numbers start from 0
// the first and last cities' positions do not change
int numberOfIterations = 100;
int tabuLength = 10;
TabuList tabuList = new TabuList(tabuLength);
int[] bestSol = new int[currSolution.length]; //this is the best Solution So Far
System.
arraycopy(currSolution,
0, bestSol,
0, bestSol.
length); int bestCost = tspEnvironment.getObjectiveFunctionValue(bestSol);
for (int i = 0; i < numberOfIterations; i++) { // perform iterations here
currSolution = TabuSearch.getBestNeighbour(tabuList, tspEnvironment, currSolution);
//printSolution(currSolution);
int currCost = tspEnvironment.getObjectiveFunctionValue(currSolution);
//System.out.println("Current best cost = " + tspEnvironment.getObjectiveFunctionValue(currSolution));
if (currCost < bestCost) {
System.
arraycopy(currSolution,
0, bestSol,
0, bestSol.
length); bestCost = currCost;
}
}
System.
out.
println("Search done! \nBest Solution cost found = " + bestCost
+ "\nBest Solution :");
printSolution(bestSol);
}
public static void printSolution(int[] solution) {
for (int i = 0; i < solution.length; i++) {
System.
out.
print(solution
[i
] + " "); }
}
}
/**
*
* @author http://v...content-available-to-author-only...y.com
* Use this code at your own risk ;)
*/
class TabuList {
int [][] tabuList ;
public TabuList(int numCities){
tabuList = new int[numCities][numCities]; //city 0 is not used here, but left for simplicity
}
public void tabuMove(int city1, int city2){ //tabus the swap operation
tabuList[city1][city2]+= 5;
tabuList[city2][city1]+= 5;
}
public void decrementTabu(){
for(int i = 0; i<tabuList.length; i++){
for(int j = 0; j<tabuList.length; j++){
tabuList[i][j]-=tabuList[i][j]<=0?0:1;
}
}
}
}
/**
*
* @author http://v...content-available-to-author-only...y.com
* Use this code at your own risk ;)
*/
class TSPEnvironment { //Tabu Search Environment
public int [][] distances;
public TSPEnvironment(){
}
public int getObjectiveFunctionValue(int solution[]){ //returns the path cost
//the first and the last cities'
// positions do not change.
// example solution : {0, 1, 3, 4, 2, 0}
int cost = 0;
for(int i = 0 ; i < solution.length-1; i++){
cost+= distances[solution[i]][solution[i+1]];
}
return cost;
}
}
Y2xhc3MgVGFidVNlYXJjaCB7CiAKcHVibGljIHN0YXRpYyBpbnRbXSBnZXRCZXN0TmVpZ2hib3VyKFRhYnVMaXN0IHRhYnVMaXN0LApUU1BFbnZpcm9ubWVudCB0c3BFbnZpcm9tbmV0LAppbnRbXSBpbml0U29sdXRpb24pIHsKIAogCmludFtdIGJlc3RTb2wgPSBuZXcgaW50W2luaXRTb2x1dGlvbi5sZW5ndGhdOyAvL3RoaXMgaXMgdGhlIGJlc3QgU29sdXRpb24gU28gRmFyClN5c3RlbS5hcnJheWNvcHkoaW5pdFNvbHV0aW9uLCAwLCBiZXN0U29sLCAwLCBiZXN0U29sLmxlbmd0aCk7CmludCBiZXN0Q29zdCA9IHRzcEVudmlyb21uZXQuZ2V0T2JqZWN0aXZlRnVuY3Rpb25WYWx1ZShpbml0U29sdXRpb24pOwppbnQgY2l0eTEgPSAwOwppbnQgY2l0eTIgPSAwOwpib29sZWFuIGZpcnN0TmVpZ2hib3IgPSB0cnVlOwogCmZvciAoaW50IGkgPSAxOyBpIDwgYmVzdFNvbC5sZW5ndGggLSAxOyBpKyspIHsKZm9yIChpbnQgaiA9IDI7IGogPCBiZXN0U29sLmxlbmd0aCAtIDE7IGorKykgewppZiAoaSA9PSBqKSB7CmNvbnRpbnVlOwp9CiAKaW50W10gbmV3QmVzdFNvbCA9IG5ldyBpbnRbYmVzdFNvbC5sZW5ndGhdOyAvL3RoaXMgaXMgdGhlIGJlc3QgU29sdXRpb24gU28gRmFyClN5c3RlbS5hcnJheWNvcHkoYmVzdFNvbCwgMCwgbmV3QmVzdFNvbCwgMCwgbmV3QmVzdFNvbC5sZW5ndGgpOwpwcmludFNvbHV0aW9uKG5ld0Jlc3RTb2wpOyAKbmV3QmVzdFNvbCA9IHN3YXBPcGVyYXRvcihpLCBqLCBpbml0U29sdXRpb24pOyAvL1RyeSBzd2FwcGluZyBjaXRpZXMgaSBhbmQgagpwcmludFNvbHV0aW9uKG5lZUJlc3RTb2wpOwovLyAsIG1heWJlIHdlIGdldCBhIGJldHRlcnNvbHV0aW9uCmludCBuZXdCZXN0Q29zdCA9IHRzcEVudmlyb21uZXQuZ2V0T2JqZWN0aXZlRnVuY3Rpb25WYWx1ZShuZXdCZXN0U29sKTsKIAogCiAKaWYgKChuZXdCZXN0Q29zdCA+IGJlc3RDb3N0IHx8IGZpcnN0TmVpZ2hib3IpICYmIHRhYnVMaXN0LnRhYnVMaXN0W2ldW2pdID09IDApIHsgLy9pZiBiZXR0ZXIgbW92ZSBmb3VuZCwgc3RvcmUgaXQKZmlyc3ROZWlnaGJvciA9IGZhbHNlOwpjaXR5MSA9IGk7CmNpdHkyID0gajsKU3lzdGVtLmFycmF5Y29weShuZXdCZXN0U29sLCAwLCBiZXN0U29sLCAwLCBuZXdCZXN0U29sLmxlbmd0aCk7CmJlc3RDb3N0ID0gbmV3QmVzdENvc3Q7Cn0KIAogCn0KfQogCmlmIChjaXR5MSAhPSAwKSB7CnRhYnVMaXN0LmRlY3JlbWVudFRhYnUoKTsKdGFidUxpc3QudGFidU1vdmUoY2l0eTEsIGNpdHkyKTsKfQpyZXR1cm4gYmVzdFNvbDsKIAogCn0KIAovL3N3YXBzIHR3byBjaXRpZXMKcHVibGljIHN0YXRpYyBpbnRbXSBzd2FwT3BlcmF0b3IoaW50IGNpdHkxLCBpbnQgY2l0eTIsIGludFtdIHNvbHV0aW9uKSB7CmludCB0ZW1wID0gc29sdXRpb25bY2l0eTFdOwpzb2x1dGlvbltjaXR5MV0gPSBzb2x1dGlvbltjaXR5Ml07CnNvbHV0aW9uW2NpdHkyXSA9IHRlbXA7CnJldHVybiBzb2x1dGlvbjsKfQogCnB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsKIApUU1BFbnZpcm9ubWVudCB0c3BFbnZpcm9ubWVudCA9IG5ldyBUU1BFbnZpcm9ubWVudCgpOwogCnRzcEVudmlyb25tZW50LmRpc3RhbmNlcyA9IC8vRGlzdGFuY2UgbWF0cml4LCA1eDUsIHVzZWQgdG8gcmVwcmVzZW50IGRpc3RhbmNlcwpuZXcgaW50W11bXXt7MCwgMSwgMywgNCwgNX0sCnsxLCAwLCAxLCA0LCA4fSwKezMsIDEsIDAsIDUsIDF9LAp7NCwgNCwgNSwgMCwgMn0sCns1LCA4LCAxLCAyLCAwfX07Ci8vQmV0d2VlbiBjaXRpZXMuIDAsMSByZXByZXNlbnRzIGRpc3RhbmNlIGJldHdlZW4gY2l0aWVzIDAgYW5kIDEsIGFuZCBzbyBvbi4KIAppbnRbXSBjdXJyU29sdXRpb24gPSBuZXcgaW50W117MCwgMSwgMiwgNCwgMywgMH07IC8vaW5pdGlhbCBzb2x1dGlvbgovL2NpdHkgbnVtYmVycyBzdGFydCBmcm9tIDAKLy8gdGhlIGZpcnN0IGFuZCBsYXN0IGNpdGllcycgcG9zaXRpb25zIGRvIG5vdCBjaGFuZ2UKIAppbnQgbnVtYmVyT2ZJdGVyYXRpb25zID0gMTAwOwppbnQgdGFidUxlbmd0aCA9IDEwOwpUYWJ1TGlzdCB0YWJ1TGlzdCA9IG5ldyBUYWJ1TGlzdCh0YWJ1TGVuZ3RoKTsKIAppbnRbXSBiZXN0U29sID0gbmV3IGludFtjdXJyU29sdXRpb24ubGVuZ3RoXTsgLy90aGlzIGlzIHRoZSBiZXN0IFNvbHV0aW9uIFNvIEZhcgpTeXN0ZW0uYXJyYXljb3B5KGN1cnJTb2x1dGlvbiwgMCwgYmVzdFNvbCwgMCwgYmVzdFNvbC5sZW5ndGgpOwppbnQgYmVzdENvc3QgPSB0c3BFbnZpcm9ubWVudC5nZXRPYmplY3RpdmVGdW5jdGlvblZhbHVlKGJlc3RTb2wpOwogCmZvciAoaW50IGkgPSAwOyBpIDwgbnVtYmVyT2ZJdGVyYXRpb25zOyBpKyspIHsgLy8gcGVyZm9ybSBpdGVyYXRpb25zIGhlcmUKIApjdXJyU29sdXRpb24gPSBUYWJ1U2VhcmNoLmdldEJlc3ROZWlnaGJvdXIodGFidUxpc3QsIHRzcEVudmlyb25tZW50LCBjdXJyU29sdXRpb24pOwovL3ByaW50U29sdXRpb24oY3VyclNvbHV0aW9uKTsKaW50IGN1cnJDb3N0ID0gdHNwRW52aXJvbm1lbnQuZ2V0T2JqZWN0aXZlRnVuY3Rpb25WYWx1ZShjdXJyU29sdXRpb24pOwogCi8vU3lzdGVtLm91dC5wcmludGxuKCJDdXJyZW50IGJlc3QgY29zdCA9ICIgKyB0c3BFbnZpcm9ubWVudC5nZXRPYmplY3RpdmVGdW5jdGlvblZhbHVlKGN1cnJTb2x1dGlvbikpOwogCmlmIChjdXJyQ29zdCA8IGJlc3RDb3N0KSB7ClN5c3RlbS5hcnJheWNvcHkoY3VyclNvbHV0aW9uLCAwLCBiZXN0U29sLCAwLCBiZXN0U29sLmxlbmd0aCk7CmJlc3RDb3N0ID0gY3VyckNvc3Q7Cn0KfQogClN5c3RlbS5vdXQucHJpbnRsbigiU2VhcmNoIGRvbmUhIFxuQmVzdCBTb2x1dGlvbiBjb3N0IGZvdW5kID0gIiArIGJlc3RDb3N0ICsgIlxuQmVzdCBTb2x1dGlvbiA6Iik7CiAKcHJpbnRTb2x1dGlvbihiZXN0U29sKTsKIAogCiAKfQogCnB1YmxpYyBzdGF0aWMgdm9pZCBwcmludFNvbHV0aW9uKGludFtdIHNvbHV0aW9uKSB7CmZvciAoaW50IGkgPSAwOyBpIDwgc29sdXRpb24ubGVuZ3RoOyBpKyspIHsKU3lzdGVtLm91dC5wcmludChzb2x1dGlvbltpXSArICIgIik7Cn0KU3lzdGVtLm91dC5wcmludGxuKCk7Cn0KfQogCi8qKgogKgogKiBAYXV0aG9yIGh0dHA6Ly92Li4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi55LmNvbQogKiBVc2UgdGhpcyBjb2RlIGF0IHlvdXIgb3duIHJpc2sgOykKICovCmNsYXNzIFRhYnVMaXN0IHsKIAppbnQgW11bXSB0YWJ1TGlzdCA7CnB1YmxpYyBUYWJ1TGlzdChpbnQgbnVtQ2l0aWVzKXsKdGFidUxpc3QgPSBuZXcgaW50W251bUNpdGllc11bbnVtQ2l0aWVzXTsgLy9jaXR5IDAgaXMgbm90IHVzZWQgaGVyZSwgYnV0IGxlZnQgZm9yIHNpbXBsaWNpdHkKfQogCnB1YmxpYyB2b2lkIHRhYnVNb3ZlKGludCBjaXR5MSwgaW50IGNpdHkyKXsgLy90YWJ1cyB0aGUgc3dhcCBvcGVyYXRpb24KdGFidUxpc3RbY2l0eTFdW2NpdHkyXSs9IDU7CnRhYnVMaXN0W2NpdHkyXVtjaXR5MV0rPSA1OwogCn0KIApwdWJsaWMgdm9pZCBkZWNyZW1lbnRUYWJ1KCl7CmZvcihpbnQgaSA9IDA7IGk8dGFidUxpc3QubGVuZ3RoOyBpKyspewpmb3IoaW50IGogPSAwOyBqPHRhYnVMaXN0Lmxlbmd0aDsgaisrKXsKdGFidUxpc3RbaV1bal0tPXRhYnVMaXN0W2ldW2pdPD0wPzA6MTsKfQp9Cn0KIAp9CiAKLyoqCiAqCiAqIEBhdXRob3IgaHR0cDovL3YuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLnkuY29tCiAqIFVzZSB0aGlzIGNvZGUgYXQgeW91ciBvd24gcmlzayA7KQogKi8KY2xhc3MgVFNQRW52aXJvbm1lbnQgeyAvL1RhYnUgU2VhcmNoIEVudmlyb25tZW50CiAKcHVibGljIGludCBbXVtdIGRpc3RhbmNlczsKIApwdWJsaWMgVFNQRW52aXJvbm1lbnQoKXsKIAp9CiAKcHVibGljIGludCBnZXRPYmplY3RpdmVGdW5jdGlvblZhbHVlKGludCBzb2x1dGlvbltdKXsgLy9yZXR1cm5zIHRoZSBwYXRoIGNvc3QKLy90aGUgZmlyc3QgYW5kIHRoZSBsYXN0IGNpdGllcycKLy8gcG9zaXRpb25zIGRvIG5vdCBjaGFuZ2UuCi8vIGV4YW1wbGUgc29sdXRpb24gOiB7MCwgMSwgMywgNCwgMiwgMH0KIAppbnQgY29zdCA9IDA7CiAKZm9yKGludCBpID0gMCA7IGkgPCBzb2x1dGlvbi5sZW5ndGgtMTsgaSsrKXsKY29zdCs9IGRpc3RhbmNlc1tzb2x1dGlvbltpXV1bc29sdXRpb25baSsxXV07Cn0KIApyZXR1cm4gY29zdDsKIAp9CiAKIAogCn0=