我正在为大学项目做一个遗传算法,但在进行交叉操作时,我注意到个体长度发生了变化,而它本应是100。
我创建了一个包含100个City对象的ArrayList(这是一个旅行商问题版本),并从中创建了一个包含100个ID号的路径,并将其传递到一个String[]中。ID从0到99。然而,当我使用Collections类进行洗牌时,虽然它确实进行了洗牌,但也出现了重复的条目。以下是代码。
Random r = new Random(seed);for (int i = 0; i < popSize; i++){ // popSize是种群大小,通常为100 Collections.shuffle(baseInd, r); //baseInd是包含100个City对象的ArrayList for (int ii = 0; ii < baseInd.size(); ii++){ indPath[ii] += String.valueOf(baseInd.get(ii).getID() + "."); // 这是在获取当前的baseInd并将其ID输出到一个字符串中。 } indDist[i] = Double.toString(calculateDistance(baseInd)); //计算个体从起点到终点的距离的方法。}
这是当前的样本输出(我只发布前三个,因为它太长了),我已经加粗了一两个重复项。可能还有更多,但一个已经太多了!
0: 60+74+94+39+13+76+42+60+59+27+3+19+13+44+90+33+3+84+94+66+26+15+30+65+75+37+82+86+97+60+54+10+72+22+87+59+68+82+58+33+94+13+70+58+54+31+93+25+91+10+94+14+89+73+39+67+12+41+99+46+28+62+32+96+37+46+9+81+33+36+42+77+1+21+39+61+41+81+23+73+42+13+66+35+51+64+2+11+96+87+75+24+50+8+86+52+32+35+73+77+Distance: 13781+834427040787
1: 2+89+43+7+58+32+71+44+96+63+2+57+12+34+53+43+94+14+97+18+91+40+18+86+46+70+46+46+46+98+50+0+45+44+94+34+17+89+72+1+9+99+40+97+88+3+12+38+5+41+2+26+74+96+33+33+29+16+74+18+10+13+96+12+16+76+77+2+0+89+18+36+88+56+35+33+28+88+35+86+61+98+99+66+31+90+23+86+45+74+2+88+80+84+19+33+81+23+90+37+Distance: 14157+066270019255
2: 69+13+20+68+8+80+58+26+57+1+45+73+83+13+32+58+10+17+76+25+99+29+28+31+68+95+88+91+19+22+86+97+75+64+1+49+19+88+55+96+3+62+23+45+31+63+39+52+70+70+35+2+86+49+34+49+7+2+72+37+37+81+46+23+82+7+35+65+74+64+80+43+48+3+5+46+35+30+94+55+47+45+79+83+58+40+95+94+98+84+28+94+61+87+1+40+83+55+18+74+Distance: 13178+332276530997
}
我确保baseInd只包含0到99的一个实例。
for (int a = 0; a < baseInd.size(); a++){ System.out.print(baseInd.get(a).getID() + "+");}
这似乎(可能!)是洗牌导致的问题。有什么想法吗?
— 更多代码 —-
这是创建City对象的方法。它从一个.csv文件中读取。我不担心这个,因为上面的代码在任何洗牌之前都打印出0到99。
public static ArrayList<City> createBaseInd(ArrayList<City> baseInd){ BufferedReader reader; try { reader = new BufferedReader(new FileReader("towns.csv")); String line; String[] lines; while ((line = reader.readLine()) != null) { lines = line.split(","); baseInd.add(new City(lines[0], Double.parseDouble(lines[1]), Double.parseDouble(lines[2]), Integer.parseInt(lines[3]))); //结构是名称,X坐标,Y坐标,ID } reader.close(); } catch (IOException e) { System.out.println("文件未找到"); e.printStackTrace(); } return baseInd;}
关于这个问题,我实在没有其他相关的内容可以补充,因为问题发生在baseInd创建之后,并且在输出这一阶段,输出尚未通过突变或交叉进行编辑。
回答:
你应该将内循环中的索引从
indPath[ii] += String.valueOf(baseInd.get(ii).getID() + ".");
更改为
indPath[i] += String.valueOf(baseInd.get(ii).getID() + ".");
让我们看一个简单的例子,其中popSize
是2
,并且shuffle
结果是两次[1, 2]
:
在外循环的第一次迭代之后,你有
indPath[0] => 1.indPath[1] => 2.
在外循环的第二次迭代之后,你有
indPath[0] => 1.1.indPath[1] => 2.2.
两个路径都包含重复项。