Java Collections - Shuffle重复项目

时间:2013-05-01 07:52:03

标签: java collections artificial-intelligence shuffle genetic

是的,我正在为一个大学项目做一个GA算法,但是当我做Crossover时,我注意到我的个人长度已经改变,应该是100。

我正在创建一个包含100个城市对象的ArrayList(它是旅行推销员的一个版本),并从中创建100个Id编号的路径并将其传递给String []。 ids从0到99.但是,当我使用Collections类进行洗牌时,它会改变它们,但它也是重复的条目。这是代码。

Random r = new Random(seed);
for (int i = 0; i < popSize; i++){ // popSize is population size which is 100 normally
    Collections.shuffle(baseInd, r); //baseInd is the ArrayList of 100 City objects
    for (int ii = 0; ii < baseInd.size(); ii++){
        indPath[ii] += String.valueOf(baseInd.get(ii).getID() + "."); // This is getting the current baseInd and outputting the ID to a String.
    }
    indDist[i] = Double.toString(calculateDistance(baseInd)); //method to calculate the distance from start to end on a individual.

}

这是当前的样本输出(我只会发布前3个,因为它长时间啰嗦)并且我加粗了一两次重复。可能会有更多,但有一个太多了!

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 + 距离: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 + 距离: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 + 距离:13178 + 332276530997

}

我确保baseInd只包含一个0到99的出现。

for (int a = 0; a < baseInd.size(); a++){
    System.out.print(baseInd.get(a).getID() + "+");
}

显然(可能!)是造成它的洗牌。有什么想法吗?

---更多代码----

这是创建City对象的方法。它从.csv文件中读取。我不关心这个,因为上面的代码在任何shuffle之前打印出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]))); //Struct is Name, X Co Ord, Y Co Ord, ID
        }
        reader.close();
    } catch (IOException e) {
        System.out.println("file not found");
                e.printStackTrace();
            }

        return baseInd;
}

由于在创建baseInd之后问题发生并且输出的此时尚未编辑输出(通过突变或交叉),因此我无法真正添加与问题相关的其他内容。

2 个答案:

答案 0 :(得分:2)

您应该从

更改内循环中的索引
indPath[ii] += String.valueOf(baseInd.get(ii).getID() + ".");

indPath[i] += String.valueOf(baseInd.get(ii).getID() + ".");

让我们看一个简单的示例,其中popSize2shuffle结果为[1, 2]两次:

在外循环的第一次迭代之后,你有

indPath[0] => 1.
indPath[1] => 2.

在外循环的第二次迭代之后,你有

indPath[0] => 1.1.
indPath[1] => 2.2.

两个路径都包含重复项。

答案 1 :(得分:0)

对于不熟悉的GA ==遗传算法。

对任何标准GA操作使用shuffle是不正确的。使用交叉,您有两个父项,您可以找到索引,并切换索引的这些部分。如果包含的是你的交叉方法,那就完全错了。它需要看起来像这样:

public TwoParents crossOver(ArrayList<> parentA, ArrayList<> parentB) {

  TwoParents toReturn = new TwoParents();  //This holds the new parent A and B.

  int index = r.nextInt(parentA.size());  //The crossover point

  //This is the copying part
  for(int i = 0;i<index;i++) {
    toReturn.parentA.add(parentA[i]);
    toReturn.parentB.add(parentB[i]);
  }

  //Now we crossover
  for(int i = index;i<parentA.size();i++) {
    toReturn.parentA.add(parentB[i]);
    toReturn.parentB.add(parentA[i]);
  }

  //return both parents
  return toReturn;
}

这是一个有趣的应用程序,但如果你必须访问所有城市,那么变异不适用于运营商。