【问题标题】:How to prevent genetic algorithm from converging on local minima?如何防止遗传算法收敛于局部最小值?
【发布时间】:2015-01-15 03:50:34
【问题描述】:

我正在尝试使用遗传算法构建一个 4 x 4 数独求解器。我对收敛到局部最小值的值有一些问题。我正在使用排名方法并删除排名最低的两个答案可能性,并用两个排名最高的答案可能性之间的交叉替换它们。为了额外帮助避免局部最小值,我也在使用突变。如果在特定的生成数量内没有确定答案,我的人口将充满全新的随机状态值。但是,我的算法似乎陷入了局部最小值。作为健身功能,我正在使用:

(开放方格的总数 * 7(每个方格可能的违规;行、列和框))- 总违规次数

population 是一个整数数组的 ArrayList,其中每个数组都是基于输入的数独的可能结束状态。为总体中的每个数组确定适合度。

是否有人能够帮助我确定我的算法为何会收敛于局部最小值,或者可能会推荐一种用于避免局部最小值的技术。非常感谢任何帮助。

健身功能:

public int[] fitnessFunction(ArrayList<int[]> population)
{
    int emptySpaces = this.blankData.size();
    int maxError = emptySpaces*7;
    int[] fitness = new int[populationSize];

    for(int i=0; i<population.size();i++)
    {
        int[] temp = population.get(i);
        int value = evaluationFunc(temp);

        fitness[i] = maxError - value;
        System.out.println("Fitness(i)" + fitness[i]);
    }

    return fitness;
}

分频功能:

public void crossover(ArrayList<int[]> population, int indexWeakest, int indexStrong, int indexSecStrong, int indexSecWeak)
{
    int[] tempWeak = new int[16];
    int[] tempStrong = new int[16];
    int[] tempSecStrong = new int[16];
    int[] tempSecWeak = new int[16];

    tempStrong = population.get(indexStrong);
    tempSecStrong = population.get(indexSecStrong);
    tempWeak = population.get(indexWeakest);
    tempSecWeak = population.get(indexSecWeak);
    population.remove(indexWeakest);
    population.remove(indexSecWeak);


    int crossoverSite = random.nextInt(14)+1;

    for(int i=0;i<tempWeak.length;i++)
    {
        if(i<crossoverSite)
        {
            tempWeak[i] = tempStrong[i];
            tempSecWeak[i] = tempSecStrong[i];
        }
        else
        {
            tempWeak[i] = tempSecStrong[i];
            tempSecWeak[i] = tempStrong[i];
        }
    }
    mutation(tempWeak);
    mutation(tempSecWeak);
    population.add(tempWeak);
    population.add(tempSecWeak);

    for(int j=0; j<tempWeak.length;j++)
    {
        System.out.print(tempWeak[j] + ", ");
    }
    for(int j=0; j<tempWeak.length;j++)
    {
        System.out.print(tempSecWeak[j] + ", ");
    }
}

变异函数:

public void mutation(int[] mutate)
{
    if(this.blankData.size() > 2)
    {
        Blank blank = this.blankData.get(0);
        int x = blank.getPosition();

        Blank blank2 = this.blankData.get(1);
        int y = blank2.getPosition();

        Blank blank3 = this.blankData.get(2);
        int z = blank3.getPosition();

        int rando = random.nextInt(4) + 1;

        if(rando == 2)
        {
            int rando2 = random.nextInt(4) + 1;
            mutate[x] = rando2;
        }
        if(rando == 3)
        {
            int rando2 = random.nextInt(4) + 1;
            mutate[y] = rando2;
        }
        if(rando==4)
        {
            int rando3 = random.nextInt(4) + 1;
            mutate[z] = rando3;
        }
    }

【问题讨论】:

  • 另外,对于 4x4 数独游戏,合适的种群规模和最大世代数是多少?
  • 坦率地说,我认为这是对技术的误用。遗传算法最适合于最优答案难以捉摸的模糊问题(例如旅行商问题),但很容易找到相当好的答案。在精心设计的数独游戏中,只有一个正确答案,而且通过详尽的搜索可以快速轻松地找到。

标签: java algorithm genetic-algorithm sudoku convergence


【解决方案1】:

您看到快速收敛的原因是您的“交配”方法不是很好。你总是从得分最高的两个个体的“交配”中产生两个后代。想象一下,当其中一个新后代与您的顶级个体相同时会发生什么(偶然地,没有交叉和突变,或者至少没有对适应度产生影响)。一旦发生这种情况,前两个个体是相同的,这就消除了交叉的有效性。

更典型的方法是替换每一代的每一个人。这里有很多可能的变化,但您可以随机选择两个父母加权适应度。

关于人口规模:我不知道数独问题对你的基因表示和适应度功能有多难,但我建议你考虑数百万个人,而不是几十个人。

如果您正在处理非常困难的问题,当您将人口放在二维网格上并从附近的个体中为网格中的每个点选择“父母”时,遗传算法会更有效。您将获得局部收敛,但每个局部都会收敛到不同的解决方案;您会从网格的局部收敛区域之间的边界处获得大量变化。

您可能会考虑的另一种技术是多次运行以从随机种群中收敛,并存储每次运行的最高个体。在你构建了一堆不同的局部最小值基因组之后,从这些顶级个体中构建一个新的随机种群。

【讨论】:

  • 我完全同意你所说的,“百万个人”。通过对每行有 4 个唯一数字的简单限制,可以将穷举搜索空间减少到 331,776 种可能性。当暴力解决方案只需要考虑 30 万种可能性时,用数百万个人运行多代似乎毫无意义。
  • 所以遗传算法的问题在于它使用启发式方法来尝试预测正确答案。这意味着一个糟糕的实现可能比蛮力方法需要更多的时间/空间。
  • 关于人口规模,一般有2种思想流派——大人口少代或小人口多代。由你来选择你想要追求的路径(我个人更喜欢小流行的方法)。有很多资源可以告诉你使用的一般价值(我在某个地方看到了大约 12 个人,1000 代人),但这真的取决于你
  • @user3386109 正如我所说,我不知道 sudoko 有多“难”。如果搜索空间像你说的那样微不足道,那么遗传算法就是一个愚蠢的工具。
  • @HedonicHedgehog 在困难的问题上,小种群会在你到达很远之前(当然在你达到 1000 代之前)收敛。如果您想使用小群体,那么您将希望使用一种方法进行多次运行,该方法利用获胜者进行进一步的工作(正如我在回答中概述的那样)。
【解决方案2】:

我认为数独是一个排列问题。因此我建议您使用随机排列数来初始化种群,并使用与排列问题兼容的交叉方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多