遺伝的アルゴリズムを使用して 4 x 4 数独ソルバーを構築しようとしています。極小値に収束する値に問題があります。ランク付けされたアプローチを使用して、ランク付けされた下位 2 つの回答の可能性を削除し、ランク付けされた上位 2 つの回答の可能性の間のクロスオーバーに置き換えます。局所最小値を回避するための追加のヘルプとして、突然変異も使用しています。特定の世代内で答えが決定されない場合、私の母集団はまったく新しいランダムな状態値で満たされます。ただし、私のアルゴリズムは極小値で動けなくなっているようです。フィットネス関数として、私は以下を使用しています:
(開いている四角の合計数 * 7 (各四角、行、列、およびボックスでの違反の可能性)) - 違反の合計
集団は整数配列の 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;
}
}