我正在使用 GA 方法研究 Maze Solver。每个基因组都有编码为字符('N'、'S'、'E'、'W')的方向,并且使用加权轮盘赌评估一代中的每个基因组的适应性和杂交。
到目前为止,这项任务进展顺利,但我注意到我的适应度函数有一个怪癖,即(我认为)给了我更长/不太理想的解决方案。
由于我的目标是在没有事先解决方案的情况下解决通用迷宫,我将我的适应度函数设置如下:(请忽略硬编码的开始和结束位置,这些将在以后变得通用......)
private static double calculateMazeScore(Genome genome) {
int start_row = 1;
int start_col = 0;
int end_row = 12;
int end_col = 8;
MazePosition pos = new MazePosition(start_row, start_col);
int penalty = 0;
for (char gene : genome.geneString().toCharArray()) {
int n, e, s, w;
n = pos.getNeighborValueNeg1IfEdge(Direction.N);
e = pos.getNeighborValueNeg1IfEdge(Direction.E);
s = pos.getNeighborValueNeg1IfEdge(Direction.S);
w = pos.getNeighborValueNeg1IfEdge(Direction.W);
// System.out.printf("pos:[%d,%d] val:%d next:%s n:%d s:%d e:%d w:%d \n",
// pos.getRowIdx(), pos.getColumnIdx(), pos.getValue(), gene, n, s, e, w);
if (gene == 'N') {
if (n == 0 || n == 2 || n == 3) {
pos = pos.getNeighbor(Direction.N);
penalty -= 1.5;
} else {
penalty++;
}
} else if (gene == 'E') {
if (e == 0 || e == 2 || e == 3) {
pos = pos.getNeighbor(Direction.E);
penalty -= 1.5;
} else {
penalty++;
}
} else if (gene == 'S') {
if (s == 0 || s == 2 || s == 3) {
pos = pos.getNeighbor(Direction.S);
penalty -= 1.5;
} else {
penalty++;
}
} else if (gene == 'W') {
if (w == 0 || w == 2 || w == 3) {
pos = pos.getNeighbor(Direction.W);
penalty -= 1.5;
}
}
}
double x1 = pos.getRowIdx();
double y1 = pos.getColumnIdx();
double distFromStart = Math.sqrt(Math.pow(start_row - x1, 2) + Math.pow(start_col - y1, 2));
double distFromGoal = Math.sqrt(Math.pow(end_row - x1, 2) + Math.pow(end_col - y1, 2));
double mazeScore = distFromStart - distFromGoal - penalty;
if (mazeScore <= 0)
mazeScore = 0;
return mazeScore;
}
当我通过迷宫评估基因组字符串时,当基因组“撞”到墙上时,我增加一个惩罚计数器,当它没有时,我减少计数器。完成基因组后,我进行距离计算以找到从起点到终点的距离。最终适应度是 dist_from_start - dist_from_end - 惩罚。
这实际上工作得很好,基因组非常接近终点而不会撞到太多的墙壁......但我认为我过多地鼓励在迷宫中徘徊。我得到了很多人为增加分数的“WEWEWEWENSNSNSNSNS”......最近10代左右中最适合的人在迷宫中徘徊了很长时间才走到出口,有时他们没有得到所有的分数方式他们,因为他们花了太多时间来回。
我现在所拥有的还可以……但不是很好。我想要一些关于改善我的健身功能的建议。稍后我还将尝试不同的交叉和选择过程。提前致谢!