2010-02-18 25 views
4

很抱歉,如果我在写这样的移动设备上,我试图让它快,这是不明确的。在用户界面中使用GA

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

我有这个问题是因为我写一个使用GA找到通过迷宫的方法的迷宫解决程序的GUI中应用遗传算法。如何将我的随机二进制编码基因和适应度函数(将所有二进制值加在一起)转换为控制迷宫周围bot的方法?我用Java构建了一个基本的图形用户界面(GUI),其中包含一系列标签(如网格),可用路由为蓝色,墙壁为黑色。

重申我的遗传算法执行得很好,包含任何典型的遗传算法(健身方法,获取和设置种群,选择,交叉等),但现在我需要将其插入GUI以使我的迷宫运行。为了获得一个可以在不同方向移动的机器人,需要去哪里取决于GA所说的内容?如果可能的话

按照要求,一个人是使用一个单独的类(逐张)建,与所有的主要工作正在波普类完成粗糙的伪代码将是巨大的。当一个新个体被实例化时,一个int数组代表所述个体的基因,随机从0到1之间的数字中挑选基因。适应度函数仅将这些基因的值加在一起,并且在Pop类中处理选择,两个选定个体的突变和交叉。除此之外,命令行程序仅显示n代以上的进化,总体适应度在每次迭代中都有所提高。

编辑:它开始让更多的意义,现在,虽然有被窃听我的几件事情...

正如亚当斯基曾建议我想创建一个“代理”与如下所示的选项。我遇到的问题是随机比特串在这里发挥作用。代理知道墙壁在哪里,并且以4位字符串(即0111)排列,但这对随机32位字符串有什么影响? (即10001011011001001010011011010101)如果我有以下迷宫(x为出发地,2是目标,1是墙):

x 1 1 1 1 
0 0 1 0 0 
1 0 0 0 2 

如果我左转,我面对错误的方式,代理将如果向前移动,则完全离开迷宫。我认为第一代的字符串是完全随机的,随着健身的增长它会发展,但我不明白字符串如何在迷宫中工作。

因此,为了得到这个直...

健身是当代理能够移动,是一堵墙的结果。

基因是一串32比特,分成16组2比特以显示可用的动作,机器人移动两比特需要通过代理显示中的四位传递其靠近墙壁的位置。如果移动是通过墙壁移动,则该移动不被执行,并且被认为是无效的,如果移动已经完成,并且如果发现新的墙壁,则健身状态会上升。

是吗?

+0

也许你可以提供一些关于每个进化个体中编码信息的更多细节? – 2010-02-18 11:16:45

+0

我编辑了主要问题,但目前没有真正重要的编码,此刻每个个体有500个基因,随机数字方法在其中添加1或0。 – AlexT 2010-02-18 11:24:07

回答

4

,如果你想解决一个特定的迷宫BadHorse的回答是不错的;您只需解读为此你的位串作为精确指令一个序列通过迷宫引导代理。在这种情况下,你的健身不是比特串的总和(正如你在你的问题中陈述的那样),而是衡量代理人在解决问题方面取得成功的一些指标。例如,您的健身可能被定义为“在处理20条指令”之后从迷宫末端沿直线的距离“”。

因此,在评估每一个人,当你允许它从你的比特串处理第一个20条指令,然后计算其适应度,执行任何交叉/突变,然后创建下一代的个体。

如果你想开发你的代理来解决任何迷宫你需要在你的位串而不是一系列指令中编码规则。您可以根据墙壁是在机器人的后面,前面,左侧还是右侧来定义规则。例如

FBLR Action 
0000 Move Forward 
0001 Move Forward 
0010 Turn Right 
etc 

这给你由16个动作的比特串,编码为2位(00 =向前,01 =右转,10 =左转,11 =向后移动)的每个动作。在评估您的代理时,它只是简单地确定其当前状态,并使用位串作为查找表来确定它应该如何响应。然后,在评估其适应性之后,它会重复此操作若干次。

鉴于这种编码的代理可以评估规则人类通常使用,这是“连续跟踪左手墙”。很显然,如果迷宫没有完全连接,这种方法就会失败,在这种情况下,您需要将更多的状态编码为基于规则的方法(例如,如果经过“旧地”,代理可能会有不同的响应)。

希望有所帮助。

编辑

在回答您的最新编辑:

,我已经编码的代理“传感器”检测是否它旁边的墙壁或没有事实是不相关的(你的基因),也许我用我的例子稍微混淆了一些事情。该基因仅编码动作(向前移动等)而不是传感器状态。

因此,你应该写代码来查找给定的传感器读数的特定组合的比特串的相关部分;例如

/** 
* 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. 
} 

给出一个Gene的这个简单的定义,你可以在Agent实施中嵌入这个类,记录剂“已安装”当前基因如何执行;例如

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; 
    } 
} 
+0

后半部分是我想要做的,所以它会使用规则解决任何给定的迷宫。我遇到的问题是分配规则。据我了解,代理将有自己的“查找”与您在顶部给出的值,然后一串32位,分成16位2位(行动)从基因获得,与四可用的行动。我编辑了这个问题,以显示我遇到麻烦,以便我不会在这里耗尽空间。 – AlexT 2010-02-19 03:08:58

+0

@AlexT:很抱歉,我编辑了我的答案,并添加了一些示例代码以帮助您入门。 – Adamski 2010-02-22 22:44:24

+0

这看起来很棒!我会玩一些代码,然后尝试构建一个Maze类,然后如果一切按计划进行,我会回来接受这个答案。 – AlexT 2010-03-01 12:02:05

0

如果我理解正确的话,你需要确定如何你的机器人在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