一.模拟退火算法概述
模拟退火算法来源于固体退火原理,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。根据Metropolis准则,粒子在温度T时趋于平衡的概率为e-ΔE/(kT),其中E为温度T时的内能,ΔE为其改变量,k为Boltzmann常数。用固体退火模拟组合优化问题,将内能E模拟为目标函数值f,温度T演化成控制参数t,即得到解组合优化问题的模拟退火算法:由初始解i和控制参数初值t开始,对当前解重复“产生新解→计算目标函数差→接受或舍弃”的迭代,并逐步衰减t值,算法终止时的当前解即为所得近似最优解,这是基于蒙特卡罗迭代求解法的一种启发式随机搜索过程。退火过程由冷却进度表(Cooling Schedule)控制,包括控制参数的初值t及其衰减因子Δt、每个t值时的迭代次数L和停止条件S。
二.流程图
伪码描述: Simulated-Annealing() Create initial solution S repeat for i=1 to iteration-length do Generate a random transition from S to Si If ( C(S) <= C(Si) ) then S=Si else if( exp(C(S)-C(Si))/kt > random[0,1) ) then S=Si Reduce Temperature t until ( no change in C(S) ) C(S): Cost or Loss function of Solution S三.旅行商问题上的应用
旅行商问题就是指旅行商按一定的顺序访问N个城市的每个城市,使得每个城市都能被访问且仅能被访问一次,最后回到起点,而使花费的代价最小。本例中从第0个城市开始然后回到原点.
示例代码:
/** * */ package anneal.tsp; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.Arrays; import java.util.Random; /** * @author Dukie 下午02:22:13 2010 * */ public class Anneal { private static double[][] city; private static int[] currPath; private static int[] bestPath; private static double shortesDistance; private static int numOfCity = 20; //trace item private static int iterator = 0; public void printInfo() { System.out.println("bestPath: " + Arrays.toString(bestPath)); System.out.println("shortest distance: " + shortesDistance); System.out.println("iterator times: " + iterator); } private void init() throws IOException { city = new double[numOfCity][numOfCity]; currPath = new int[numOfCity]; bestPath = new int[numOfCity]; shortesDistance = 0; loadCity(); int lenth = currPath.length; for (int i = 0; i < lenth; i++) { currPath[i] = i; } } private void loadCity() throws IOException { //DistanceMatrix.csv" a file stores the distance info. File file = new File("E:\\TSP\\DistanceMatrix.csv"); inputGraph(file, city); } private void inputGraph(File file, double[][] city) throws IOException { BufferedReader in = new BufferedReader(new FileReader(file)); String str = ""; int length = 0; while ((str = in.readLine()) != null) { str = str.replaceAll(", ", ","); String[] line = str.split(","); for (int j = 0; j < numOfCity; j++) // ten cities city[length][j] = Double.parseDouble(line[j]); length++; } } /** * key function * @throws IOException */ public void anneal() throws IOException { double temperature = 10000.0D; double deltaDistance = 0.0D; double coolingRate = 0.9999; double absoluteTemperature = 0.00001; init(); double distance = getToatalDistance(currPath); int[] nextPath; Random random = new Random(); while (temperature > absoluteTemperature) { nextPath = generateNextPath(); deltaDistance = getToatalDistance(nextPath) - distance; if ((deltaDistance < 0) || (distance > 0 && Math.exp(-deltaDistance / temperature) > random.nextDouble())) { currPath = Arrays.copyOf(nextPath, nextPath.length); distance = deltaDistance + distance; } temperature *= coolingRate; iterator++; System.out.println("iterator: " + iterator + " path: " + Arrays.toString(currPath)); } shortesDistance = distance; System.arraycopy(currPath, 0, bestPath, 0, currPath.length); } /** * calculate total distance * @param currPath * @return */ private double getToatalDistance(int[] currPath) { int length = currPath.length; double totalDistance = 0.0D; for (int i = 0; i < length - 1; i++) { totalDistance += city[currPath[i]][currPath[i + 1]]; } totalDistance += city[currPath[length - 1]][0]; return totalDistance; } /** * swap two elements in the old array to genreate new array * @return */ private int[] generateNextPath() { int[] nextPath = Arrays.copyOf(currPath, currPath.length); Random random = new Random(); int length = nextPath.length; int fistIndex = random.nextInt(length - 1) + 1; int secIndex = random.nextInt(length - 1) + 1; while (fistIndex == secIndex) { secIndex = random.nextInt(length - 1) + 1; } int tmp = nextPath[fistIndex]; nextPath[fistIndex] = currPath[secIndex]; nextPath[secIndex] = tmp; return nextPath; } }
20个城市测试数据:
0, 11893, 14633, 10172, 8078, 12843, 10079, 14395, 8056, 14232, 11714, 9309, 12517, 11574, 9720, 13727, 13852, 14330, 10660, 8138 11893, 0, 10568, 9031, 11050, 9039, 10622, 14138, 8738, 9122, 8817, 13099, 9984, 13063, 11546, 11379, 8850, 14111, 13775, 8073 14633, 10568, 0, 14174, 13338, 12629, 14418, 10391, 14444, 12956, 14040, 12835, 13486, 14249, 14039, 8186, 14730, 8886, 12862, 12365 10172, 9031, 14174, 0, 9422, 11814, 14133, 11645, 10495, 13099, 14712, 14988, 11662, 14561, 13350, 10781, 14886, 11549, 13044, 11194 8078, 11050, 13338, 9422, 0, 9868, 11492, 12416, 14672, 12894, 11181, 14310, 9231, 12697, 12617, 8856, 11850, 13302, 12558, 11165 12843, 9039, 12629, 11814, 9868, 0, 10069, 10605, 8799, 9295, 14078, 12349, 14367, 9501, 11379, 13431, 10723, 8845, 10427, 14821 10079, 10622, 14418, 14133, 11492, 10069, 0, 12734, 8656, 13830, 12681, 13165, 11583, 8610, 9202, 9838, 10755, 10674, 13881, 13024 14395, 14138, 10391, 11645, 12416, 10605, 12734, 0, 11980, 13753, 11174, 14603, 13478, 12543, 12974, 11059, 8799, 11781, 13797, 9287 8056, 8738, 14444, 10495, 14672, 8799, 8656, 11980, 0, 11108, 8725, 11253, 12277, 13086, 9476, 12513, 9597, 11850, 13866, 8605 14232, 9122, 12956, 13099, 12894, 9295, 13830, 13753, 11108, 0, 14301, 8065, 13706, 9212, 8301, 8258, 14817, 9277, 12742, 14550 11714, 8817, 14040, 14712, 11181, 14078, 12681, 11174, 8725, 14301, 0, 8133, 13841, 9062, 10704, 13366, 13779, 13710, 12832, 12812 9309, 13099, 12835, 14988, 14310, 12349, 13165, 14603, 11253, 8065, 8133, 0, 8079, 9554, 9760, 11617, 10566, 9382, 12105, 11755 12517, 9984, 13486, 11662, 9231, 14367, 11583, 13478, 12277, 13706, 13841, 8079, 0, 9991, 14717, 13082, 11787, 14614, 11698, 10970 11574, 13063, 14249, 14561, 12697, 9501, 8610, 12543, 13086, 9212, 9062, 9554, 9991, 0, 14363, 8175, 12309, 9042, 11251, 9250 9720, 11546, 14039, 13350, 12617, 11379, 9202, 12974, 9476, 8301, 10704, 9760, 14717, 14363, 0, 12291, 12173, 10971, 9000, 9868 13727, 11379, 8186, 10781, 8856, 13431, 9838, 11059, 12513, 8258, 13366, 11617, 13082, 8175, 12291, 0, 14291, 12915, 9583, 9671 13852, 8850, 14730, 14886, 11850, 10723, 10755, 8799, 9597, 14817, 13779, 10566, 11787, 12309, 12173, 14291, 0, 13657, 8621, 9089 14330, 14111, 8886, 11549, 13302, 8845, 10674, 11781, 11850, 9277, 13710, 9382, 14614, 9042, 10971, 12915, 13657, 0, 9709, 10960 10660, 13775, 12862, 13044, 12558, 10427, 13881, 13797, 13866, 12742, 12832, 12105, 11698, 11251, 9000, 9583, 8621, 9709, 0, 13131 8138, 8073, 12365, 11194, 11165, 14821, 13024, 9287, 8605, 14550, 12812, 11755, 10970, 9250, 9868, 9671, 9089, 10960, 13131, 0在我机上对20个顸城市进行测试后,效果比较好. 对10城市时,在几秒钟来就达到全局最优解.
注意:模拟退火算法与初始值无关,算法求得的解与初始解状态S(是算法迭代的起点)无关;模拟退火算法具有渐近收敛性,已在理论上被证明是一种以概率l 收敛于全局最优解的全局优化算法;模拟退火算法具有并行性。