我正在开发一些非常有趣的东西,遗传算法中的TSP,更具体地说是部分映射的交叉。对于代码的背景,它接收两个int类型的数组,它们对应于相关的城市,例如,第一个和第二个可以是1,2,3,4,5,6,7和2,3,4,5, 2,4,3。接下来发生的事情是我尝试跨越城市而没有任何重复,但是当我执行while循环时,它似乎无法解决我的问题,因为它陷入无限循环。
基本上,我很困惑,为什么它会陷入循环,最终它应该越过城市并摆脱所有重复,但由于某种原因,我永远陷入困境! / p>
代码背景: SIZE =数组中的城市大小,父级和父级2包含大小为SIZE的随机城市。
任何帮助都会大大降低!
private int[][] partiallyMappedCrossover(int first, int second){
//Used to return an array of type int
int[][] tempArray = new int[2][SIZE];
//Used to represent the selected individuals
ArrayList<Integer> parentOne = new ArrayList<Integer>();
ArrayList<Integer> parentTwo = new ArrayList<Integer>();
ArrayList<Integer> parentOneExchange = new ArrayList<Integer>();
ArrayList<Integer> parentTwoExchange = new ArrayList<Integer>();
//Used to generate crossOverPoints
ArrayList<Integer> crossOverPoints = new ArrayList<Integer>();
crossOverPoints.add(random.nextInt(SIZE));
crossOverPoints.add(random.nextInt(SIZE));
Collections.sort(crossOverPoints);
//Used for checking the parents contents
int currentCity = 0;
int arrayIndex = 0;
int newCity = 0;
//Assign the contents of the selected parents to my parentArrays
for(int i = 0; i < SIZE; i++){
parentOne.add(population[first][i]);
parentTwo.add(population[second][i]);
}
//used to gather cities from tours and swap between randomly selected crossoverpoints
for(int k = crossOverPoints.get(0) ; k < crossOverPoints.get(1) ; k++){
//declare ints to store the city value
int a = parentOne.get(k);
int b = parentTwo.get(k);
//excahnge cities between the two crossOverPoints
parentOneExchange.add(b);
parentTwoExchange.add(a);
}
for(int i = 0; i < crossOverPoints.get(0); i++){
//get the first city from the parentOne
currentCity = parentOne.get(i);
//Check the cities
if(parentOneExchange.contains(currentCity)){
//If it does contain the city, give one the index from the exchange
arrayIndex = parentOneExchange.indexOf(currentCity);
// get the city where we have a repitition
newCity = parentTwo.get(arrayIndex);
//if the new city is also a duplicated one, do another check
while(parentOneExchange.contains(newCity)){
// get the index of the city to replace the repeated city
arrayIndex = parentOneExchange.indexOf(newCity);
// get the city that is intended to replace the repeated city
newCity = parentTwo.get(arrayIndex);
}
//replace the duplicated city with the new city
parentOne.set(i,newCity);
}
currentCity = parentTwo.get(i);
if(parentTwoExchange.contains(currentCity)){
//If it does contain the city, give one the index from the exchange
arrayIndex = parentTwoExchange.indexOf(currentCity);
// get the city where we have a repitition
newCity = parentOne.get(arrayIndex);
//if the new city is also a duplicated one, do another check
while(parentTwoExchange.contains(newCity)){
// get the index of the city to replace the repeated city
arrayIndex = parentTwoExchange.indexOf(newCity);
// get the city that is intended to replace the repeated city
newCity = parentOne.get(arrayIndex);
}
//replace the duplicated city with the new city
parentTwo.set(i,newCity);
}
}
//loop the second crosschange
for(int i = crossOverPoints.get(1); i < SIZE; i++){
//get the first city from the parentOne
currentCity = parentOne.get(i);
//Check the cities
if(parentOneExchange.contains(currentCity)){
//If it does contain the city, give one the index from the exchange
arrayIndex = parentOneExchange.indexOf(currentCity);
// get the city where we have a repitition
newCity = parentTwo.get(arrayIndex);
//if the new city is also a duplicated one, do another check
while(parentOneExchange.contains(newCity)){
// get the index of the city to replace the repeated city
arrayIndex = parentOneExchange.indexOf(newCity);
// get the city that is intended to replace the repeated city
newCity = parentTwo.get(arrayIndex);
}
//replace the duplicated city with the new city
parentOne.set(i,newCity);
}
currentCity = parentTwo.get(i);
if(parentTwoExchange.contains(currentCity)){
//If it does contain the city, give one the index from the exchange
arrayIndex = parentTwoExchange.indexOf(currentCity);
// get the city where we have a repitition
newCity = parentOne.get(arrayIndex);
//if the new city is also a duplicated one, do another check
while(parentTwoExchange.contains(newCity)){
// get the index of the city to replace the repeated city
arrayIndex = parentTwoExchange.indexOf(newCity);
// get the city that is intended to replace the repeated city
newCity = parentOne.get(arrayIndex);
}
//replace the duplicated city with the new city
parentTwo.set(i,newCity);
}
}
//Assign the new offspring to the temp array for return
for(int i = 0; i<SIZE; i++){
tempArray[0][i] = parentOne.get(i);
tempArray[1][i] = parentTwo.get(i);
}
//return the contents of my tempArray
return tempArray;
}
答案 0 :(得分:1)
阅读代码以找到这样的错误是非常困难和费力的。有很多简单的方法可以找到这些类型的错误。我会给你四个考虑(按照我粗略的偏好顺序):
将方法中的各种操作拆分为单独的方法,然后为每个方法编写单元测试,确保它们在移动到下一个方法之前完全符合您的预期。一旦它们全部工作,那么你编写一个使用它们的方法。调试一个小方法要比调试一个大方法容易得多。
添加assert
语句,检查您期望为真的条件实际上是否为真。我将在下面给出一个例子。
交互式调试器可以找到循环未完成的原因。这样,您就可以确切地看到变量在循环中的每个点处具有的值。
随着方法的进展,添加日志语句以记录临时值。这样可以确保在算法进行时满足预期条件。
查看你的一个while循环:
while(parentOneExchange.contains(newCity)){
// get the index of the city to replace the repeated city
arrayIndex = parentOneExchange.indexOf(newCity);
// get the city that is intended to replace the repeated city
newCity = parentTwo.get(arrayIndex);
}
这将在任何时候parentTwo.get
返回之前遇到过的城市时无限循环。我希望这是由于代码中早期的逻辑错误而发生的事情。您可以添加断言以确保不是这种情况:
List<Integer> previous = new ArrayList<>();
while(parentOneExchange.contains(newCity)){
assert !previous.contains(newCity): previous;
previous.add(newCity);
arrayIndex = parentOneExchange.indexOf(newCity);
newCity = parentTwo.get(arrayIndex);
}
当这个断言失败时,您可以看到以前访问过的城市的列表,并尝试理解它为什么循环。