遗传算法求最短路径

无所事事,就想找个题目练一下遗传算法。然后想到可以用遗传算法找遍历给定城市的最短路径。从网上搜了一些中国的城市,各城市之间的距离取它们之间的直线距离,每个城市一个编号,然后每个所有编号构成的排列就是一个解,每个解会得到一个相应的总距离。问题就变成寻找最优排列的问题。

用遗传算法处理这个问题,先随机生成一群初始解作为初始种群。每个解作为一个个体可以进行增殖和变异,然后种群的数量增加,再通过筛选函数以更高的概率挑选一部分更加满足要求的个体进行增殖,通过数代的进化,以期得到总距离尽可能短的解。写好程序测试后发现效果还不错。

下面是对程序中一些问题的说明。遗传算法中的一步是要求两个个体通过交叉和变异产生一个新个体,模仿生物的有性生殖。但是对于两个12345或者31452的排列,实在不知道该怎么进行交叉。所以程序只对原始排列进行变异,但是不进行两个排列之间的交叉。

变异的方法可以有很多,这里为了提高程序的运行速度,把变异分为两点之间交换和两个序列之间的交换,其中序列交换时可以进行翻转。

在程序运行过程中发现种群的进化速度较慢,一些优秀的个体会因为随机性被淘汰,所以程序里加上了保留最优个体的规则。尽管这样做可能会降低种群的多样性,降低算法对所有解的“遍历性”,但是实践发现确实能够得到更好的解,而且解优化的速度快很多。不保留最优个体的时候优化速度在越接近极值的时候速度越慢,甚至不会进一步优化。也许是因为这时候选择压力太小了,可能一个更好的办法是提供一个可变的选择压力而不是保留最优个体。

至于筛选函数,不知道该怎么做到尽可能好,就简单的选择了距离平均值乘一个系数作为筛选标准。为了防止出现大小年的现象,进行了二次筛选。

为了提高序列的质量,对序列的子序列进行了优化,重新排列相邻的四个值,使新的子序列对应的长度最小。

为了图简单,程序需要的各城市之间距离的矩阵和城市名直接写在程序里了,改成从文件里读取也是很容易的。

代码如下:

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <list>
  4 #include <random>
  5 #define NUM 37
  6 
  7 double dis_mat[NUM][NUM] = {{0.00,101.26,543.55,624.38,270.58,408.52,421.60,618.75,457.61,855.97,1052.50,1066.24,897.04,1050.24,1341.21,1884.46,2287.62,2051.23,1522.09,1462.87,1024.61,1124.39,1206.52,1377.53,898.06,1564.50,1726.42,1248.46,362.94,1718.93,2417.35,1328.53,1185.95,917.73,2090.88,2575.17,1735.43}
  8 ,{101.26,0.00,442.45,581.22,268.00,427.52,505.13,601.62,386.93,857.93,1065.92,966.74,804.46,985.11,1280.91,1816.36,2229.02,2003.83,1521.70,1444.72,926.52,1028.59,1107.84,1282.31,813.68,1474.14,1640.55,1171.72,278.25,1623.61,2502.20,1374.80,1223.32,915.77,2073.10,2608.50,1704.83}
  9 ,{543.55,442.45,0.00,617.67,566.63,717.80,920.76,690.41,335.80,970.23,1199.59,550.96,468.91,821.97,1117.58,1585.54,2037.59,1874.12,1622.44,1474.56,527.26,646.97,697.39,897.52,546.73,1119.76,1311.45,920.28,301.46,1232.26,2897.35,1655.67,1480.03,1055.27,2079.11,2815.16,1665.86}
 10 ,{624.38,581.22,617.67,0.00,374.61,361.57,698.60,1152.84,844.16,1425.05,1640.78,821.18,556.95,461.60,730.30,1286.82,1669.30,1426.87,1008.78,885.79,749.88,784.81,914.64,996.41,461.14,1106.84,1220.35,703.70,369.87,1314.75,2448.23,1092.94,905.93,441.65,1509.29,2201.37,1126.66}
 11 ,{270.58,268.00,566.63,374.61,0.00,166.63,389.01,869.08,633.73,1119.95,1321.31,994.58,774.86,826.65,1104.36,1658.56,2043.48,1793.95,1256.65,1192.29,938.06,1014.70,1120.55,1257.41,736.12,1412.72,1552.72,1050.21,276.53,1594.22,2331.46,1125.98,966.09,650.88,1820.34,2345.77,1467.15}
 12 ,{408.52,427.52,717.80,361.57,166.63,0.00,337.38,1023.15,800.08,1264.37,1457.52,1098.63,858.07,820.85,1073.64,1634.38,1992.72,1722.71,1116.61,1076.41,1035.97,1097.63,1214.46,1328.76,793.72,1459.84,1580.80,1065.20,418.00,1657.76,2190.94,959.58,799.73,516.59,1700.25,2181.53,1368.71}
 13 ,{421.60,505.13,920.76,698.60,389.01,337.38,0.00,987.11,878.93,1173.66,1330.62,1382.60,1162.70,1158.18,1406.02,1967.04,2311.62,2026.95,1318.04,1332.96,1326.93,1402.90,1509.54,1643.36,1115.27,1788.37,1915.69,1401.75,656.00,1977.98,1997.27,969.74,860.07,766.65,1937.12,2235.80,1646.09}
 14 ,{618.75,601.62,690.41,1152.84,869.08,1023.15,987.11,0.00,354.93,282.49,510.81,1191.46,1158.81,1483.23,1784.60,2273.73,2719.84,2534.78,2122.56,2034.63,1189.05,1316.28,1335.14,1554.70,1232.31,1792.40,1992.59,1608.16,790.12,1872.38,2905.84,1939.59,1803.11,1516.90,2661.05,3192.79,2276.35}
 15 ,{457.61,386.93,335.80,844.16,633.73,800.08,878.93,354.93,0.00,636.02,865.14,856.45,804.63,1136.29,1436.51,1919.09,2367.11,2190.09,1843.57,1729.35,846.15,971.18,1002.69,1215.62,877.98,1447.06,1643.36,1253.51,474.37,1542.04,2871.80,1757.05,1599.79,1246.32,2349.41,2977.03,1951.37}
 16 ,{855.97,857.93,970.23,1425.05,1119.95,1264.37,1173.66,282.49,636.02,0.00,229.38,1454.15,1437.28,1765.40,2066.86,2555.06,3002.22,2816.23,2376.46,2301.38,1457.33,1585.66,1594.98,1818.31,1513.98,2060.56,2264.18,1889.49,1067.34,2127.68,2997.08,2142.22,2019.46,1770.83,2929.28,3405.84,2551.05}
 17 ,{1052.50,1065.92,1199.59,1640.78,1321.31,1457.52,1330.62,510.81,865.14,229.38,0.00,1679.15,1666.61,1991.71,2293.36,2784.24,3230.47,3040.85,2573.83,2510.29,1684.25,1812.82,1818.68,2043.19,1742.99,2286.99,2491.73,2118.66,1288.47,2348.69,3059.36,2299.04,2187.82,1970.20,3138.77,3565.77,2767.42}
 18 ,{1066.24,966.74,550.96,821.18,994.58,1098.63,1382.60,1191.46,856.45,1454.15,1679.15,0.00,269.60,680.39,887.38,1201.33,1675.07,1596.81,1656.10,1438.49,75.92,160.69,146.97,364.15,401.49,610.52,821.95,603.48,730.77,685.79,3266.39,1903.85,1713.65,1218.13,1957.10,2910.99,1521.19}
 19 ,{897.04,804.46,468.91,556.95,774.86,858.07,1162.70,1158.81,804.63,1437.28,1666.61,269.60,0.00,450.20,706.81,1124.68,1585.55,1454.09,1403.56,1198.82,195.21,240.44,359.60,484.87,143.27,671.19,849.75,465.45,537.44,825.11,3005.10,1634.55,1444.21,948.68,1749.11,2653.79,1316.76}
 20 ,{1050.24,985.11,821.97,461.60,826.65,820.85,1158.18,1483.23,1136.29,1765.40,1991.71,680.39,450.20,0.00,301.74,834.75,1247.09,1054.07,982.01,758.10,607.41,560.72,699.48,676.50,310.79,705.30,779.80,262.02,717.61,940.04,2764.34,1335.73,1146.42,649.19,1299.62,2239.44,869.08}
 21 ,{1341.21,1280.91,1117.58,730.30,1104.36,1073.64,1406.02,1784.60,1436.51,2066.86,2293.36,887.38,706.81,301.74,0.00,561.03,948.18,756.74,899.12,637.78,823.51,739.42,861.29,757.16,583.10,677.61,662.39,295.01,1017.40,924.34,2841.44,1398.80,1221.00,772.66,1073.88,2132.83,638.48}
 22 ,{1884.46,1816.36,1585.54,1286.82,1658.56,1634.38,1967.04,2273.73,1919.09,2555.06,2784.24,1201.33,1124.68,834.75,561.03,0.00,474.36,508.55,1236.25,977.40,1162.31,1041.42,1110.31,910.61,1041.59,686.67,504.99,665.58,1543.36,859.33,3280.12,1857.52,1697.86,1304.10,1095.79,2327.33,764.08}
 23 ,{2287.62,2229.02,2037.59,1669.30,2043.48,1992.72,2311.62,2719.84,2367.11,3002.22,3230.47,1675.07,1585.55,1247.09,948.18,474.36,0.00,357.42,1327.91,1117.50,1634.41,1514.88,1584.40,1381.40,1490.85,1147.99,947.70,1120.69,1964.64,1289.97,3366.79,2013.16,1883.41,1583.86,946.83,2201.49,805.65}
 24 ,{2051.23,2003.83,1874.12,1426.87,1793.95,1722.71,2026.95,2534.78,2190.09,2816.23,3040.85,1596.81,1454.09,1054.07,756.74,508.55,357.42,0.00,972.50,773.57,1543.23,1437.89,1533.95,1362.49,1337.68,1167.34,1006.69,999.46,1754.84,1361.10,3009.60,1661.52,1538.23,1276.31,627.13,1885.96,451.91}
 25 ,{1522.09,1521.70,1622.44,1008.78,1256.65,1116.61,1318.04,2122.56,1843.57,2376.46,2573.83,1656.10,1403.56,982.01,899.12,1236.25,1327.91,972.50,0.00,268.40,1581.17,1542.73,1681.23,1631.38,1261.18,1576.72,1542.06,1161.95,1372.27,1823.43,2055.13,695.37,600.88,605.98,637.04,1257.47,522.55}
 26 ,{1462.87,1444.72,1474.56,885.79,1192.29,1076.41,1332.96,2034.63,1729.35,2301.38,2510.29,1438.49,1198.82,758.10,637.78,977.40,1117.50,773.57,268.40,0.00,1365.29,1314.17,1449.71,1382.61,1055.62,1314.50,1274.19,911.58,1255.48,1560.51,2304.01,900.79,766.02,568.35,628.49,1499.21,332.15}
 27 ,{1024.61,926.52,527.26,749.88,938.06,1035.97,1326.93,1189.05,846.15,1457.33,1684.25,75.92,195.21,607.41,823.51,1162.31,1634.41,1543.23,1581.17,1365.29,0.00,129.01,183.56,370.68,325.57,603.53,808.13,545.36,680.23,705.69,3196.88,1829.74,1639.36,1143.00,1889.92,2835.64,1454.30}
 28 ,{1124.39,1028.59,646.97,784.81,1014.70,1097.63,1402.90,1316.28,971.18,1585.66,1812.82,160.69,240.44,560.72,739.42,1041.42,1514.88,1437.89,1542.73,1314.17,129.01,0.00,140.77,254.28,328.59,476.24,679.22,449.76,770.35,595.13,3230.17,1840.28,1649.01,1146.84,1812.69,2800.15,1376.78}
 29 ,{1206.52,1107.84,697.39,914.64,1120.55,1214.46,1509.54,1335.14,1002.69,1594.98,1818.68,146.97,359.60,699.48,861.29,1110.31,1584.40,1533.95,1681.23,1449.71,183.56,140.77,0.00,228.27,465.01,481.77,697.89,567.09,863.78,539.35,3362.50,1978.64,1787.46,1285.97,1934.86,2938.69,1499.76}
 30 ,{1377.53,1282.31,897.52,996.41,1257.41,1328.76,1643.36,1554.70,1215.62,1818.31,2043.19,364.15,484.87,676.50,757.16,910.61,1381.40,1362.49,1631.38,1382.61,370.68,254.28,228.27,0.00,537.11,254.64,472.05,471.03,1021.15,341.40,3420.71,2006.15,1815.48,1312.74,1812.43,2881.79,1383.82}
 31 ,{898.06,813.68,546.73,461.14,736.12,793.72,1115.27,1232.31,877.98,1513.98,1742.99,401.49,143.27,310.79,583.10,1041.59,1490.85,1337.68,1261.18,1055.62,325.57,328.59,465.01,537.11,0.00,676.84,828.46,376.36,536.05,864.23,2902.18,1513.90,1322.80,822.46,1610.35,2512.86,1179.67}
 32 ,{1564.50,1474.14,1119.76,1106.84,1412.72,1459.84,1788.37,1792.40,1447.06,2060.56,2286.99,610.52,671.19,705.30,677.61,686.67,1147.99,1167.34,1576.72,1314.50,603.53,476.24,481.77,254.64,676.84,0.00,217.86,449.20,1202.04,247.17,3466.87,2031.26,1844.40,1353.13,1669.68,2802.95,1257.00}
 33 ,{1726.42,1640.55,1311.45,1220.35,1552.72,1580.80,1915.69,1992.59,1643.36,2264.18,2491.73,821.95,849.75,779.80,662.39,504.99,947.70,1006.69,1542.06,1274.19,808.13,679.22,697.89,472.05,828.46,217.86,0.00,520.08,1363.94,354.77,3500.60,2058.04,1876.97,1405.06,1552.62,2732.91,1163.18}
 34 ,{1248.46,1171.72,920.28,703.70,1050.21,1065.20,1401.75,1608.16,1253.51,1889.49,2118.66,603.48,465.45,262.02,295.01,665.58,1120.69,999.46,1161.95,911.58,545.36,449.76,567.09,471.03,376.36,449.20,520.08,0.00,894.24,690.53,3017.76,1582.46,1395.27,904.96,1367.82,2410.77,933.02}
 35 ,{362.94,278.25,301.46,369.87,276.53,418.00,656.00,790.12,474.37,1067.34,1288.47,730.77,537.44,717.61,1017.40,1543.36,1964.64,1754.84,1372.27,1255.48,680.23,770.35,863.78,1021.15,536.05,1202.04,1363.94,894.24,0.00,1362.13,2605.16,1356.31,1183.16,782.44,1877.49,2533.80,1486.56}
 36 ,{1718.93,1623.61,1232.26,1314.75,1594.22,1657.76,1977.98,1872.38,1542.04,2127.68,2348.69,685.79,825.11,940.04,924.34,859.33,1289.97,1361.10,1823.43,1560.51,705.69,595.13,539.35,341.40,864.23,247.17,354.77,690.53,1362.13,0.00,3704.38,2272.42,2084.47,1589.23,1894.22,3045.55,1490.66}
 37 ,{2417.35,2502.20,2897.35,2448.23,2331.46,2190.94,1997.27,2905.84,2871.80,2997.08,3059.36,3266.39,3005.10,2764.34,2841.44,3280.12,3366.79,3009.60,2055.13,2304.01,3196.88,3230.17,3362.50,3420.71,2902.18,3466.87,3500.60,3017.76,2605.16,3704.38,0.00,1442.74,1624.64,2115.18,2491.22,1598.96,2571.40}
 38 ,{1328.53,1374.80,1655.67,1092.94,1125.98,959.58,969.74,1939.59,1757.05,2142.22,2299.04,1903.85,1634.55,1335.73,1398.80,1857.52,2013.16,1661.52,695.37,900.79,1829.74,1840.28,1978.64,2006.15,1513.90,2031.26,2058.04,1582.46,1356.31,2272.42,1442.74,0.00,191.33,694.82,1288.98,1266.79,1209.62}
 39 ,{1185.95,1223.32,1480.03,905.93,966.09,799.73,860.07,1803.11,1599.79,2019.46,2187.82,1713.65,1444.21,1146.42,1221.00,1697.86,1883.41,1538.23,600.88,766.02,1639.36,1649.01,1787.46,1815.48,1322.80,1844.40,1876.97,1395.27,1183.16,2084.47,1624.64,191.33,0.00,503.59,1228.00,1389.70,1089.40}
 40 ,{917.73,915.77,1055.27,441.65,650.88,516.59,766.65,1516.90,1246.32,1770.83,1970.20,1218.13,948.68,649.19,772.66,1304.10,1583.86,1276.31,605.98,568.35,1143.00,1146.84,1285.97,1312.74,822.46,1353.13,1405.06,904.96,782.44,1589.23,2115.18,694.82,503.59,0.00,1185.74,1760.44,879.99}
 41 ,{2090.88,2073.10,2079.11,1509.29,1820.34,1700.25,1937.12,2661.05,2349.41,2929.28,3138.77,1957.10,1749.11,1299.62,1073.88,1095.79,946.83,627.13,637.04,628.49,1889.92,1812.69,1934.86,1812.43,1610.35,1669.68,1552.62,1367.82,1877.49,1894.22,2491.22,1288.98,1228.00,1185.74,0.00,1259.87,436.01}
 42 ,{2575.17,2608.50,2815.16,2201.37,2345.77,2181.53,2235.80,3192.79,2977.03,3405.84,3565.77,2910.99,2653.79,2239.44,2132.83,2327.33,2201.49,1885.96,1257.47,1499.21,2835.64,2800.15,2938.69,2881.79,2512.86,2802.95,2732.91,2410.77,2533.80,3045.55,1598.96,1266.79,1389.70,1760.44,1259.87,0.00,1574.69}
 43 ,{1735.43,1704.83,1665.86,1126.66,1467.15,1368.71,1646.09,2276.35,1951.37,2551.05,2767.42,1521.19,1316.76,869.08,638.48,764.08,805.65,451.91,522.55,332.15,1454.30,1376.78,1499.76,1383.82,1179.67,1257.00,1163.18,933.02,1486.56,1490.66,2571.40,1209.62,1089.40,879.99,436.01,1574.69,0.00}
 44 };
 45 
 46 unsigned int order[24][4] = {
 47     {0,1,2,3},{0,1,3,2},{0,2,1,3}
 48     ,{0,2,3,1},{0,3,1,2},{0,3,2,1}
 49     ,{1,0,2,3},{1,0,3,2},{1,2,0,3}
 50     ,{1,2,3,0},{1,3,0,2},{1,3,2,0}
 51     ,{2,0,1,3},{2,0,3,1},{2,1,0,3}
 52     ,{2,1,3,0},{2,3,0,1},{2,3,1,0}
 53     ,{3,0,1,2},{3,0,2,1},{3,1,0,2}
 54     ,{3,1,2,0},{3,2,0,1},{3,2,1,0}};
 55 //个体,随机生成一个初始序列
 56 struct unit{
 57     unsigned int path[NUM];
 58     inline unit(){
 59         for( unsigned int i = 0; i < NUM; ++i)
 60             path[i] = i;
 61         std::random_shuffle(path, path+NUM);
 62     }
 63     inline unit(const unit & val){
 64         for( unsigned int i = 0; i < NUM; ++i)
 65             path[i] = val.path[i];
 67     }
 68     inline unit operator = (const unit & val){
 69         for(unsigned int i = 0; i < NUM; ++i)
 70             path[i] = val.path[i];
 71         return *this;
 72     }
 76     inline double distance(){
 77         double dis = 0.0;
 78         for(unsigned int i = 1; i < NUM; ++i)
 79             dis += dis_mat[path[i-1]][path[i]];
 80         return dis;
 81     }
 82 };
 83 //序列左端点处的优化,返回重新的排列顺序对应的编号(order)
 84 unsigned int shortest_path4l(unit & theone){
 85     unsigned int reti = 0;
 86     double shortdis = 0.0;
 87     for(unsigned int j = 0; j < 3; ++j)
 88         shortdis += dis_mat[theone.path[order[0][j]]][theone.path[order[0][j+1]]];
 89     shortdis += dis_mat[theone.path[order[0][3]]][theone.path[4]];
 90     for( unsigned int i = 1; i < 24; ++i){
 91         double dis = 0.0;
 92         for(unsigned int j = 0; j < 3; ++j){
 93             dis += dis_mat[theone.path[order[i][j]]][theone.path[order[i][j+1]]];
 94         }
 95         dis += dis_mat[theone.path[order[i][3]]][theone.path[4]];
 96         if(dis < shortdis){
 97             shortdis = dis;
 98             reti = i;
 99         }
100     }
101     return reti;
102 }
103 //右端点对应的优化函数
104 unsigned int shortest_path4r(unit & theone, unsigned int o){
105     unsigned int reti = 0;
106     double shortdis = 0.0;
107     shortdis += dis_mat[theone.path[o-1]][theone.path[o+order[0][0]]];
108     for( unsigned int j = 0; j < 3; ++j)
109         shortdis += dis_mat[theone.path[o+order[0][j]]][theone.path[o+order[0][j+1]]];
110     for(unsigned int i = 1; i < 24; ++i){
111         double dis = dis_mat[theone.path[o-1]][theone.path[o+order[i][0]]];
112         for(unsigned int j = 0; j < 3; ++j)
113             dis += dis_mat[theone.path[o+order[i][j]]][theone.path[o+order[i][j+1]]];
114         if(dis < shortdis){
115             shortdis = dis;
116             reti = i;
117         }
118     }
119     return reti;
120 }
121 //一般情况下的优化函数
122 unsigned int shortest_path4(unit & theone, unsigned int o){
123     unsigned int reti = 0;
124     double shortdis = dis_mat[theone.path[o-1]][theone.path[o+order[0][0]]];
125     for(unsigned int j = 0; j < 3; ++j)
126         shortdis += dis_mat[theone.path[o+order[0][j]]][theone.path[o+order[0][j+1]]];
127     shortdis += dis_mat[theone.path[o+order[0][3]]][theone.path[o+4]];
128     for(unsigned int i = 1; i < 24; ++i){
129         double dis = dis_mat[theone.path[o-1]][theone.path[o+order[i][0]]];
130         for( unsigned int j = 0; j < 3; ++j)
131             dis += dis_mat[theone.path[o+order[i][j]]][theone.path[o+order[i][j+1]]];
132         dis += dis_mat[theone.path[o+order[i][3]]][theone.path[o+4]];
133         if(dis < shortdis){
134             shortdis = dis;
135             reti = i;
136         }
137     }
138     return reti;
139 }
140 //对子序列重新排序
141 void ch_order( unit & theone, unsigned int o, unsigned int i){
142     unsigned int ach[4];
143     for(unsigned int j = 0; j < 4; ++j)
144         ach[j] = theone.path[o+order[i][j]];
145     for(unsigned int j = 0; j < 4; ++j)
146         theone.path[o+j] = ach[j];
147 }
148 //优化函数,调用上面的四个函数,实现对整个序列的优化
149 void optimize(unit & theone){
150     ch_order(theone, 0, shortest_path4l(theone));
151     for( unsigned int i = 1; i < NUM - 5; ++i)
152         ch_order(theone, i, shortest_path4(theone, i));
153     ch_order(theone, NUM-4, shortest_path4r(theone,NUM-4));
154 }
155 
156 std::random_device rd;
157 std::mt19937 mt(rd());
158 std::bernoulli_distribution witera(0.5); //是否迭代
159 std::bernoulli_distribution wch(0.5); //是否变异
160 std::bernoulli_distribution porl(0.5);//选择点或序列变异
161 std::bernoulli_distribution wrev(0.5);//是否翻转
162 std::uniform_int_distribution<> startpoint(0, NUM-1);//点或序列变异起始点或结束点
163 //变异函数,以一定的概率选择各个变异方向
164 unit ch_unit( const unit & theone){
165     unit ret(theone);
166     if(wch(mt)){
167         if(porl(mt)){
168             auto start1 = startpoint(mt);
169             auto start2 = startpoint(mt);
170             if( start1 != start2){
171                 auto temp = ret.path[start1];
172                 ret.path[start1] = ret.path[start2];
173                 ret.path[start2] = temp;
174             }
175         }
176         else {//选择序列变异
177             decltype(startpoint(mt)) cutpoint[4];
178             do{//选择两个变异序列开始和结束的位置
179                 for(unsigned int i1 = 0; i1 < 4; ++i1)
180                     cutpoint[i1] = startpoint(mt);
181                 for(unsigned int i1 = 0; i1 < 3; ++i1)
182                     for( unsigned int i2 = i1+1; i2 < 4; ++i2)
183                         if(cutpoint[i1] > cutpoint[i2])
184                             std::swap(cutpoint[i1], cutpoint[i2]);
185             }
186             while(cutpoint[1] == cutpoint[2]);
188             unsigned int tmp[NUM];
189             unsigned int pos = 0;
190             for(unsigned int i3 = 0; i3 < cutpoint[0]; ++i3)
191                 tmp[pos++] = ret.path[i3];
192             if(wrev(mt)){
193                 for(unsigned int i3 = cutpoint[3]; i3 >= cutpoint[2]; --i3)
194                     tmp[pos++] = ret.path[i3];
195             }
196             else{
197                 for(unsigned int i3 = cutpoint[2]; i3 <= cutpoint[3]; ++i3)
198                     tmp[pos++] = ret.path[i3];
199             }
200             for(unsigned int i3 = cutpoint[1]+1; i3 < cutpoint[2]; ++i3)
201                 tmp[pos++] = ret.path[i3];
202             if(wrev(mt)){
203                 for(int i3 = cutpoint[1]; i3 >= cutpoint[0]; --i3)
204                     tmp[pos++] = ret.path[i3];
205             }
206             else{
207                 for(unsigned int i3 = cutpoint[0]; i3 <= cutpoint[1]; ++i3)
208                     tmp[pos++] = ret.path[i3];
209             }
210             for(unsigned int i3 = cutpoint[3]+1; i3 < NUM; ++i3)
211                 tmp[pos++] = ret.path[i3];
212             for(unsigned int i3 = 0; i3 < NUM; ++i3)
213                 ret.path[i3] = tmp[i3];
214         }
215     }
216     if(witera(mt))
217         return ch_unit(ret);
218     else
219         return ret;
220 }
221 //增殖函数
222 void add_unit( std::list<unit> & conti){
223     const unsigned int SIZE = conti.size();
224     unsigned int i = 0;
225     auto itr = conti.begin();
227     while(i < SIZE){
228         conti.push_back(ch_unit(*itr));
229         ++itr;
230         ++i;
232     }
233 }
234 //筛选函数使用的满足正态分布的相乘系数,使优秀或不好的个体都有一定概率被选择和淘汰,目的是增加随机性、遍历性,减少取得局部极小值的可能
235 std::normal_distribution<double> normald(1., 0.25);
236 
237 void select(std::list<unit> & conti )
238     auto thekeep = *(conti.begin());//保留最优个体
239     for(auto itk = conti.begin(); itk != conti.end(); ++itk)
240         if(thekeep.distance() > itk->distance())
241             thekeep = *itk;
242     double av_dis = 0.0;
243     auto SIZE = conti.size();
244     for(auto itr = conti.begin(); itr != conti.end(); ++itr)
245         av_dis += itr->distance();
246     av_dis /= conti.size();
247     std::list<unit> tmp_conti;
248     auto itr = conti.begin();
249     while(itr != conti.end()){
250         if(normald(mt) * itr->distance() > av_dis*2000./SIZE){
251             tmp_conti.push_back(*itr);
252             itr = conti.erase(itr);
253         }
254         else{
255             ++itr;
256         }
257     }
258     conti.push_back(thekeep);
259     unsigned int looplimit = 0;
260     while(conti.size() < 2000*0.5){//二次筛选,避免出现大小年现象
261         auto back_num = 2000 - conti.size();
262         auto itb = tmp_conti.begin();
263         auto TMPSIZE = tmp_conti.size();
264         while(itb != tmp_conti.end()){
265             if(normald(mt) * itb->distance() < av_dis*back_num/TMPSIZE){
266                 conti.push_back(*itb);
267                 itb = tmp_conti.erase(itb);
268             }
269             else{
270                 ++itb;
271             }
272         }
273         if(++looplimit < 10)
274             break;
275     }
276 }
277 
278 void print_city(unsigned int order[NUM]){
279     std::vector<std::string> cityname = {
280     "北京","天津",    "青岛",    "郑州",    "石家庄","太原","呼和浩特","沈阳",    "大连",    "长春",    "哈尔滨","上海","南京","武汉",    "长沙",    "广州",    "海口",    "南宁",    "成都",    "重庆",    "苏州",    "杭州",    "宁波","温州",    "合肥",    "福州",    "厦门",    "南昌",    "济南",    "台北",    "乌鲁木齐","西宁",    "兰州",    "西安",    "昆明",    "拉萨",    "贵阳"};
281     for(unsigned int i = 0; i < NUM; ++i)
282         std::cout << cityname[order[i]] << std::endl;
283 }
284     
285 int main(){
286     std::list<unit> conti;
287     for( unsigned int i = 0; i < 10000; ++i){
288         conti.push_back(unit());
289     }
290 //    std::cout << "biaozhi 1" << std::endl;
291     //繁殖的代数
292     for(unsigned int i = 0; i < 100000; ++i){
293         add_unit(conti);
294         std::cout << "种群数量:" << conti.size() << std::endl;
295         for(auto itr = conti.begin(); itr != conti.end(); ++itr)
296             optimize(*itr);
297         select(conti);
298         auto itr = conti.begin();
299         auto dis = itr->distance();
300         while(itr != conti.end()){
301             if(dis > itr->distance())
302                 dis = itr->distance();
303             ++itr;
304         }
305         std::cout << "distance = " << dis << std::endl;
306     }
307     auto itr = conti.begin();
308     auto dis = itr->distance();
309     auto theone = *itr;
310     while(itr != conti.end()){
311         if(dis > itr->distance()){
312             dis = itr->distance();
313             theone = *itr;
314         }
315         ++itr;
316     }
317     std::cout << "short distance " << dis << std::endl;
318     print_city(theone.path);
319     return 0;
320 }

最终得到的路径如图所示,似乎不错的样子。

《遗传算法求最短路径》

后来使用了88个城市,得到的路径如下所示,分别是保留最优个体得到的更好路径和不保留最优个体得到的路径:

《遗传算法求最短路径》

《遗传算法求最短路径》

    原文作者:pap
    原文地址: https://www.cnblogs.com/orrg/p/4574466.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞