【问题标题】:Genetic Algorithm using Roulette Wheel Selection使用轮盘选择的遗传算法
【发布时间】:2018-04-13 19:19:07
【问题描述】:

我正在尝试为我正在研究的遗传算法创建不同的选择方法,但我在所有选择方法中遇到的一个问题是我对每个节点的适应度必须不同。这对我来说是个问题,因为我的健身计算器非常基础,会产生几个相同的健身

public static Map<String, Double> calculateRouletteSelection(Map<String, Double> population) {
        String[] keys = new String[population.size()];
        Double[] values = new Double[population.size()];
        Double[] unsortedValues = new Double[population.size()];
        int index = 0;
        for(Map.Entry<String, Double> mapEntry : population.entrySet()) {
            keys[index] = mapEntry.getKey();
            values[index] = mapEntry.getValue();
            unsortedValues[index] = mapEntry.getValue();
            index++;
        }
        Arrays.sort(values);
        ArrayList<Integer> numbers = new ArrayList<>();
        while(numbers.size() < values.length/2) {
            int random = rnd.nextInt(values.length);
            if (!numbers.contains(random)) {
                numbers.add(random);
            }
        }

        HashMap<String, Double> finalHashMap = new HashMap<>();
        for(int i = 0; i<numbers.size(); i++) {
            for(int j = 0; j<values.length; j++) {
                if(values[numbers.get(i)] == unsortedValues[j]) {
                    finalHashMap.put(keys[j], unsortedValues[j]);
                }
            }
        }

        return finalHashMap;

    } 

我所有不同的选择方法中有 90% 是相同的,所以我确定如果我能解决一个问题,我就能解决所有问题。 对我做错的任何帮助将不胜感激

编辑:我看到我打算发布正在发生的事情的一般行为,所以基本上该方法采用 HashMap,根据它们的适应度对值进行排序,随机选择一半排序的值并将这些值添加到新的 HashMap 及其对应的染色体。

【问题讨论】:

  • 如果以后要随机选择,为什么要先排序呢?到底有多少标本应该存活下来?我希望像“最适者的随机一半”这样的东西,但是您的代码会随机选择整个人口的一半。
  • 这里是这个问题的伪代码。 stackoverflow.com/questions/177271/…
  • @daniu 建议您在使用轮盘赌选择算法时首先对项目进行排序。它认为其目的是随机选择将均匀分布好的和坏的解决方案,以保持人口多样化
  • 在轮盘赌中,选择值是根据它们的适应度来选择的。更高的适应度意味着更高的被选中的机会,并且机会与适应度成正比。我在您的情况下看到您只是从排序的适应度列表中随机选择适应度并将它们匹配回它们的节点以构造输出。所以你需要以某种方式确保被选中的机会与适应度成正比,而不仅仅是随机的。

标签: java algorithm genetic-algorithm


【解决方案1】:

我认为你最好使用集合类。

List<Map.Entry<String, Double>> sorted = new ArrayList<>(population.entrySet());
// sort by fitness
Collections.sort(sorted, Comparator.comparing(Map.Entry::getValue));

Set<Integer> usedIndices = new HashSet<>(); // keep track of used indices
Map<String, Double> result = new HashMap<>();
while (result.size() < sorted.size()/2) {
    int index = rnd.nextInt(sorted.size());
    if (!usedIndices.add(index)) {
        continue; // was already used
    }
    Map.Entry<String,Double> survivor = sorted.get(index);
    result.put(survivor.getKey(), survivor.getValue());
}
return result;

但是,正如 Sergey 所说,我认为这不是您的算法所需要的;您确实需要偏爱具有较高适应度的人。

【讨论】:

    【解决方案2】:

    如 cmets 中所述,在轮盘赌中,选择顺序并不重要,只有权重很重要。轮盘就像一个饼图,不同的部分占据了圆盘的不同部分,但最终它们总和为单位面积(圆盘的面积)。

    我不确定 Java 中是否有等价物,但在 C++ 中你有 std::discrete_distribution。它会生成一个分布[0,n),您可以使用代表每个整数被选取的概率的权重对其进行初始化。所以我通常做的是将我的代理的 ID 放在一个数组中,并将它们对应的适应度值放在另一个数组中。只要索引匹配,顺序并不重要。我将适应度值数组传递给离散分布,它返回一个可解释为数组索引的整数。然后我使用该整数从另一个数组中选择个人。

    【讨论】:

      猜你喜欢
      • 2020-08-06
      • 2014-05-25
      • 2010-09-15
      • 2012-09-28
      • 2011-05-02
      • 1970-01-01
      • 1970-01-01
      • 2016-07-18
      相关资源
      最近更新 更多