4

私はこれをモバイルデバイスで書いているので、これが明確でない場合は申し訳ありませんが、私はそれを速くしようとしています。

私は、適応度の値を構築し、トーナメントの選択、突然変異、およびクロスオーバーを使用していくつかの反復を通じて進化するバイナリエンコーディング(遺伝子)を使用して、基本的な遺伝的アルゴリズムを作成しました。基本的なコマンドラインの例としては、機能しているようです。

私が抱えている問題は、GAを使用して迷路からメソッドを見つける迷路解決プログラムを作成しているときに、GUI内に遺伝的アルゴリズムを適用することです。ランダムなバイナリエンコードされた遺伝子と適応度関数(すべてのバイナリ値を合計する)を、迷路の周りのボットを制御する方法に変換するにはどうすればよいですか?利用可能なルートが青で、壁が黒である、迷路のようなラベル(グリッドなど)で構成される基本的なGUIをJavaで構築しました。

GAのパフォーマンスが高く、一般的なGAの機能(フィットネス方法、母集団の取得と設定、選択、クロスオーバーなど)が含まれていることを繰り返すと、迷路を実行するためにGUIにプラグインする必要があります。GAの内容に応じてさまざまな方向に移動できるボットを取得するには、どこに行く必要がありますか?可能であれば、大まかな擬似コードは素晴らしいでしょう

要求に応じて、Individualは別のクラス(Indiv)を使用して構築され、すべての主要な作業はPopクラスで実行されます。新しい個体がインスタンス化されると、intの配列はその個体の遺伝子を表し、遺伝子は0〜1の数値からランダムに選択されます。適応度関数は、これらの遺伝子の値を加算するだけで、Popクラスで選択を処理します。 、2人の選択された個人の突然変異と交叉。それ以外に多くはありません。コマンドラインプログラムは、n世代にわたる進化を示し、反復ごとに全体的な適合性が向上します。

編集:私を悩ませていることがいくつかありますが、今はもう少し意味がわかり始めています...

Adamskiが提案したように、以下に示すオプションを使用して「エージェント」を作成したいと思います。私が抱えている問題は、ここでランダムビット文字列が機能する場所です。エージェントは壁がどこにあるかを知っており、4ビット文字列(つまり0111)に配置されていますが、これはランダムな32ビット文字列にどのように影響しますか?(つまり、10001011011001001010011011010101)次の迷路がある場合(xが開始場所、2が目標、1が壁):

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

左に曲がると、私は間違った方向を向いており、エージェントが前方に移動すると、エージェントは迷路から完全に外れます。ストリングの第1世代は完全にランダムであり、適応度が上がるにつれて進化すると思いますが、迷路の中でストリングがどのように機能するかはわかりません。

だから、これをまっすぐにするために...

フィットネスは、エージェントが移動でき、壁のそばにいるときの結果です。

遺伝子は32ビットの文字列であり、利用可能なアクションを示すために2ビットの16セットに分割され、ロボットが2ビットを移動するには、壁の近くの位置を示すエージェントからの4ビットを渡す必要があります。移動が壁を通過する場合、移動は行われず、無効と見なされます。移動が行われ、新しい壁が見つかった場合、フィットネスは上がります。

そうですか?

4

2 に答える 2

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;
  }
}
于 2010-02-18T12:25:02.810 に答える
0

私の理解が正しければ、GUI でのボットのアクションが遺伝的アルゴリズムの結果によってどのように表現されるかを判断する必要がありますか? 使用したい表現を決定することが出発点になると思います。したがって、ボットの動作アルゴリズムの特定のアクションまたは特定の変更に対する、個人の各 (グループの) 「遺伝子」のマッピングを作成する必要があります。

実行可能な表現を選択するとすぐに、実装はいくらか論理的になります。

動きの非常に単純な表現は、遺伝子に特定のルートをハードコーディングさせることです。4 つの遺伝子のブロックを使用してさまざまな方向を表すことができます。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
于 2010-02-18T11:56:09.647 に答える