Java GA在GUI中的应用

Java GA在GUI中的应用,java,genetic-algorithm,Java,Genetic Algorithm,抱歉,如果这不清楚,因为我正在移动设备上写这篇文章,并且我正在努力使它快速 我已经写了一个基本的遗传算法,它使用二进制编码(基因)来构建适应值,并通过使用锦标赛选择、变异和交叉进行多次迭代来进化。作为一个基本的命令行示例,它似乎是有效的 我遇到的问题是在GUI中应用遗传算法,因为我正在编写一个迷宫求解程序,该程序使用遗传算法在迷宫中找到一种方法。我如何将随机二进制编码的基因和适应度函数(将所有二进制值相加)转化为一种方法来控制迷宫中的机器人?我已经用Java构建了一个基本的GUI,它由迷宫式的标

抱歉,如果这不清楚,因为我正在移动设备上写这篇文章,并且我正在努力使它快速

我已经写了一个基本的遗传算法,它使用二进制编码(基因)来构建适应值,并通过使用锦标赛选择、变异和交叉进行多次迭代来进化。作为一个基本的命令行示例,它似乎是有效的

我遇到的问题是在GUI中应用遗传算法,因为我正在编写一个迷宫求解程序,该程序使用遗传算法在迷宫中找到一种方法。我如何将随机二进制编码的基因和适应度函数(将所有二进制值相加)转化为一种方法来控制迷宫中的机器人?我已经用Java构建了一个基本的GUI,它由迷宫式的标签(如网格)组成,可用的路径是蓝色的,墙壁是黑色的

重申一下,我的遗传算法性能良好,包含了任何典型遗传算法都会有的功能(适应度方法、获取和设置种群、选择、交叉等),但现在我需要将其插入GUI以运行迷宫。需要去哪里才能得到一个机器人,它可以根据GA的说法向不同的方向移动?如果可能的话,粗略的伪代码会很好

根据要求,个人使用单独的类(Indiv)构建,所有主要工作都在Pop类中完成。当一个新个体被实例化时,一个int数组代表该个体的基因,基因从0到1之间的数字中随机选取。适应度函数仅仅是将这些基因的价值相加,而在Pop类中处理两个选定个体的选择、变异和交叉。除此之外,命令行程序只显示了n代的进化,每次迭代的总适应度都有所提高

编辑:现在开始变得更有意义了,尽管有一些事情困扰着我

正如亚当斯基所建议的,我想创建一个具有如下选项的“代理”。我的问题是随机位字符串在哪里起作用。代理知道墙在哪里,并以4位字符串(即0111)进行布局,但这如何影响随机32位字符串?(即10001011001001010011010101)如果我有以下迷宫(x是起点,2是目标,1是墙):

如果我向左转,我将面对错误的方向,如果它向前移动,代理将完全离开迷宫。我假设第一代字符串是完全随机的,它会随着适应度的增长而发展,但我不知道字符串在迷宫中是如何工作的

所以,为了澄清这一点

当代理能够移动并靠近墙时,适应度是结果

基因是一个由32位组成的字符串,分为16组,每组2位,以显示可用的动作,机器人移动这两个位时,需要从代理传递四个位,以显示其在墙壁附近的位置。如果这个动作要越过一堵墙,那么这个动作就没有做出,并且被认为是无效的。如果这个动作是做出的,并且如果发现了一堵新墙,那么这个动作的适合度就会提高


是吗?

如果我理解正确,您需要确定您的机器人在GUI中的操作如何由遗传算法的结果表示?我认为,确定您想要使用的表示应该是您的出发点。因此,您需要为您个人中的每一组“基因”创建一个映射,映射到您机器人的某个动作或移动算法中的某个变化

一旦您选择了一个可行的表示形式,实现就会更符合逻辑

运动的一个非常简单的表示就是让基因硬编码某条路线。你可以使用四个基因块来表示不同的方向,然后0表示“不要朝这个方向移动”,1表示移动

然后表示法
01001101
可以翻译为以下运动模式:

stand still
go one step east
stand still
stand still
go one step north
go one step east
stand still
go one step west

如果你想解决一个特定的迷宫,BadHorse的答案是好的;您只需将位字符串解释为精确的指令的序列,以引导代理通过迷宫。在这种情况下,您的适应度不是位字符串的总和(如您在问题中所述),而是衡量代理解决问题的成功程度的指标。例如,您的适应度可以定义为“在处理20条指令后,从迷宫末端沿直线的距离”

因此,在评估每个个体时,您允许它处理位字符串中的前20条指令,然后计算其适合度,执行任何交叉/突变,然后创建下一代个体

如果您希望开发代理来解决任何迷宫,您需要在位字符串中编码规则,而不是一系列指令。您可以根据墙是紧靠机器人的后面、前面、左边还是右边来定义规则;e、 g

FBLR Action
0000 Move Forward
0001 Move Forward
0010 Turn Right
etc
这将为您提供一个由16个操作组成的位字符串,每个操作编码为2位(00=向前移动,01=向右旋转,10=向左旋转,11=向后移动)。在评估代理时,它只确定其当前状态,并使用位字符串作为查找表来确定其响应方式。然后它会重复一定次数,然后再评估它的适合性

考虑到这种编码,代理可以评估人类通常使用的规则,即“不断地沿着左手边的墙走”。显然,如果迷宫没有完全连接,这种方法将失败,在这种情况下,您需要将更多的状态编码到基于规则的方法中(例如,如果越过“旧场地”,代理可能会做出不同的响应)

希望有帮助

编辑

回应您最近的编辑:

事实上,我已经将检测它是否靠近墙的代理“传感器”编码了
FBLR Action
0000 Move Forward
0001 Move Forward
0010 Turn Right
etc
/**
 * Enumeration describing the four available actions to the agent
 * and methods for decoding a given action from the "bit" string
 * (actually represented using booleans).
 */
public enum Action {
  MOVE_FORWARD, REVERSE, TURN_LEFT, TURN_RIGHT

  Action decodeAction(boolean b1, boolean b2) {
    Action ret;

    if (b1) {
      ret = b2 ? Action.MOVE_FORWARD : Action.TURN_LEFT;
    } else {
      ret = b2 ? Action.TURN_RIGHT : Action.REVERSE;
    }

    return ret;
  }
}

/**
 * Class encapsulating the 32-bit "bit string" represented using booleans.
 * Given the state of the four agent inputs the gene will provide a specific
 * action for the agent to perform.
 */
public class Gene {
  private final boolean[] values = new boolean[32];

  public Action getActionForSensorInputs(boolean wallInFront,
    boolean wallBehind, boolean wallToLeft, boolean wallToRight) {

    int i=0;

    // Encode the four sensor inputs as a single integer value by
    // bitwise-ORing each sensor value with a power of 2.
    // The encoded value will be in the range [0, 15].
    if (wallToRight) {
      i |= 0x01;
    }

    if (wallToLeft) {
      i |= 0x02;
    }

    if (wallBehind) {
      i |= 0x04;
    }

    if (wallInFront) {
      i |= 0x08;
    }

    // The look-up index is i * 2 because each action is encoded as 2
    // booleans.
    int index = i * 2;

    // Retrieve the two action bits from the bit string.
    boolean b1 = this.values[index];
    boolean b2 = this.values[index + 1];

    // Finally decode the action to perform.
    return Action.decodeAction(b1, b2);
  }

  // TODO: Add method to support crossover and mutation with other Genes.
}
private enum Direction { NORTH, SOUTH, EAST, WEST };

public class Agent {
  private final Geneva gene;
  private final int x; // x position in maze;
  private final int y; // y position in maze;
  private Direction currentDirection;

  public double evaluate() {
    double fitness;

    // Perform up to 20 actions and then evaluate fitness.
    for (int i=0; i<20; ++i) {
      // TODO Determine sensor inputs.

      Action action = gene.getActionForSensorInputs(...);

      // TODO: Now apply action to update agent's state.
      // If agent has reached goal exit loop and return fitness 1.0 (max fitness).
      // If agent has exited the maze then exit loop and return 0.0 (min fitness).
    }

    // Calculate fitness after 100 steps taken.  For example could be
    // calculated as sqrt((goal.x - x) ^ 2 + (goal.y - y) ^ 2).

    return fitness;
  }
}