2

私は遺伝的アルゴリズムでいくつかの作業を行っており、独自のGAクラスを作成したいと考えています。GAには、選択、突然変異、クロスオーバー、初期母集団の生成、適合度の計算、およびアルゴリズムの終了を行うさまざまな方法があるため、これらのさまざまな組み合わせをプラグインする方法が必要です。私の最初のアプローチは、これらすべてのメソッドが純粋な仮想として定義された抽象クラスを持つことであり、具体的なクラスはそれらを実装する必要がありました。たとえば、同じでクロスオーバーメソッドが異なる2つのGAを試してみたい場合は、GeneticAlgorithmを継承し、クロスオーバーメソッドを除くすべてのメソッドを実装する抽象クラスを作成してから、2つの具象クラスを作成する必要があります。このクラスから継承し、クロスオーバーメソッドのみを実装します。

この問題によりよく適用できる別のアプローチはありますか?

4

6 に答える 6

2

GAフレームワークを実装するときに採用したアプローチは、次のとおりです。次のクラスを作成します。GenerationGeneticAlgorithm GeneticAlgorithmAdapter GeneticAlgorithmParameters Population Individual

さまざまな操作の戦略パターンを実装していませんが、GeneticAlgorithmインスタンスのパラメーターとしてさまざまなGA操作の実装を作成するのは簡単だと確信しています。

GeneticAlgorithmクラスは、基本的なアルゴリズムをキャプチャします。実際には、さまざまなステップ(母集団の作成、個々のランダム化、選択、クロスオーバー、突然変異など)を定義し、アルゴリズムの実行時に個人の母集団を管理します。ここでは、必要に応じてさまざまな操作をプラグインできると思います。

本当の魔法はアダプターにあります。これは、問題のドメイン(個人の特定のサブクラスとすべての関連データ)を遺伝的アルゴリズムに適応させるものです。ここではジェネリックスを頻繁に使用して、特定のタイプの母集団、パラメーター、および個人が実装に渡されるようにします。これにより、アダプターの実装に関するインテリセンスと強い型のチェックが可能になります。アダプターは基本的に、特定の個人(およびそのゲノム)に対して特定の操作を実行する方法を定義する必要があります。たとえば、アダプタのインターフェイスは次のとおりです。

/// <summary>
/// The interface for an adapter that adapts a domain problem so that it can be optimised with a genetic algorithm.
    /// It is a strongly typed version of the adapter.
    /// </summary>
    /// <typeparam name="TGA"></typeparam>
    /// <typeparam name="TIndividual"></typeparam>
    /// <typeparam name="TPopulation"></typeparam>
    public interface IGeneticAlgorithmAdapter<TGA, TIndividual, TGeneration, TPopulation> : IGeneticAlgorithmAdapter
        where TGA : IGeneticAlgorithm
        where TIndividual : class, IIndividual, new()
        where TGeneration : class, IGeneration<TIndividual>, new()
        where TPopulation : class, IPopulation<TIndividual, TGeneration>, new()
    {
        /// <summary>
        /// This gets called before the adapter is used for an optimisation.
        /// </summary>
        /// <param name="pso"></param>
        void InitialiseAdapter(TGA ga);

        /// <summary>
        /// This initialises the individual so that it is ready to be used for the genetic algorithm.
        /// It gets randomised in the RandomiseIndividual method.
        /// </summary>
        /// <param name="ga">The genetic algorithm that is running.</param>
        /// <param name="individual">The individual to initialise.</param>
        void InitialiseIndividual(TGA ga, TIndividual individual);

        /// <summary>
        /// This initialises the generation so that it is ready to be used for the genetic algorithm.
        /// </summary>
        /// <param name="ga">The genetic algorithm that is running.</param>
        /// <param name="generation">The generation to initialise.</param>
        void InitialiseGeneration(TGA ga, TGeneration generation);

        /// <summary>
        /// This initialises the population so that it is ready to be used for the genetic algorithm.
        /// </summary>
        /// <param name="ga">The genetic algorithm that is running.</param>
        /// <param name="population">The population to initialise.</param>
        void InitialisePopulation(TGA ga, TPopulation population);

        void RandomiseIndividual(TGA ga, TIndividual individual);

        void BeforeIndividualUpdated(TGA ga, TIndividual individual);
        void AfterIndividualUpdated(TGA ga, TIndividual individual);

        void BeforeGenerationUpdated(TGA ga, TGeneration generation);
        void AfterGenerationUpdated(TGA ga, TGeneration generation);

        void BeforePopulationUpdated(TGA ga, TPopulation population);
        void AfterPopulationUpdated(TGA ga, TPopulation population);

        double CalculateFitness(TGA ga, TIndividual individual);

        void CloneIndividualValues(TIndividual from, TIndividual to);

        /// <summary>
        /// This selects an individual from the population for the given generation.
        /// </summary>
        /// <param name="ga">The genetic algorithm that is running.</param>
        /// <param name="generation">The generation to select the individual from.</param>
        /// <returns>The selected individual.</returns>
        TIndividual SelectIndividual(TGA ga, TGeneration generation);

        /// <summary>
        /// This crosses over two parents to create two children.
        /// </summary>
        /// <param name="ga">The genetic algorithm that is running.</param>
        /// <param name="parentsGeneration">The generation that the parent individuals belong to.</param>
        /// <param name="childsGeneration">The generation that the child individuals belong to.</param>
        /// <param name="parent1">The first parent to cross over.</param>
        /// <param name="parent2">The second parent to cross over.</param>
        /// <param name="child">The child that must be updated.</param>
        void CrossOver(TGA ga, TGeneration parentsGeneration, TIndividual parent1, TIndividual parent2, TGeneration childsGeneration, TIndividual child);

        /// <summary>
        /// This mutates the given individual.
        /// </summary>
        /// <param name="ga">The genetic algorithm that is running.</param>
        /// <param name="generation">The individuals generation.</param>
        /// <param name="individual">The individual to mutate.</param>
        void Mutate(TGA ga, TGeneration generation, TIndividual individual);

        /// <summary>
        /// This gets the size of the next generation to create.
        /// Typically, this is the same size as the current generation.
        /// </summary>
        /// <param name="ga">The genetic algorithm that is running.</param>
        /// <param name="currentGeneration">The current generation.</param>
        /// <returns>The size of the next generation to create.</returns>
        int GetNextGenerationSize(TGA ga, TGeneration currentGeneration);


        /// <summary>
        /// This gets whether a cross over should be performed when creating a child from this individual.
        /// </summary>
        /// <param name="ga">The genetic algorithm that is running.</param>
        /// <param name="currentGeneration">The current generation.</param>
        /// <param name="individual">The individual to determine whether it needs a cross over.</param>
        /// <returns>True to perform a cross over. False to allow the individual through to the next generation un-altered.</returns>
        bool ShouldPerformCrossOver(TGA ga, TGeneration generation, TIndividual individual);

        /// <summary>
        /// This gets whether a mutation should be performed when creating a child from this individual.
        /// </summary>
        /// <param name="ga">The genetic algorithm that is running.</param>
        /// <param name="currentGeneration">The current generation.</param>
        /// <param name="individual">The individual to determine whether it needs a mutation.</param>
        /// <returns>True to perform a mutation. False to allow the individual through to the next generation un-altered.</returns>
        bool ShouldPerformMutation(TGA ga, TGeneration generation, TIndividual individual);
    }

適切なアダプターを作成するだけで、さまざまな問題のドメインに対してGA実装を簡単に再利用できるため、このアプローチがうまく機能することがわかりました。さまざまな選択、クロスオーバー、またはミューテーションの実装に関して、アダプターは関心のある実装を呼び出すことができます。私が通常行うことは、適切な戦略を調査している間、アダプターのさまざまなアイデアをコメントアウトすることです。

お役に立てれば。必要に応じて、より多くのガイダンスを提供できます。このようなデザインの正義を行うのは難しいです。

于 2009-12-19T09:34:53.017 に答える
1

アルゴリズム全体をカプセル化する1つの大きなクラスではなく、多くのオブジェクトのコラボレーションとしてGAにアプローチします。基本的に、バリエーションの大きなポイントごとに抽象クラスを作成し、必要な実装の選択ごとに具象クラスを作成することができます。次に、必要な具象クラスをさまざまなGAに結合します。

また、戦略パターンをよく理解しておくことをお勧めします:http: //en.wikipedia.org/wiki/Strategy_pattern

于 2009-11-27T18:02:05.590 に答える
1

私はあなたがあなたのアプローチで物事を複雑にしすぎていると思います。GAlibパッケージをダウンロードすることをお勧めします。htmlまたはpdf形式のドキュメントのみをプルする場合でも。これらのライブラリはしばらく前から存在しており、GAlibでどのように行われているかを確認することで、ライブラリを構造化する方法を学ぶことができると確信しています。

于 2009-11-27T18:02:33.433 に答える
1

私の部分からのいくつかのランダムなビット:

  • (アプローチとして)チェックすべきプロジェクトは時計職人です
  • GAを構築する上で最も難しいのは、問題の適切な遺伝的表現を見つけ、特定の母集団に対する適応度の分布が良好な適応度関数を構築することです。
  • (m)任意のハード制約を処理する場合、(可能性のある)ジャンクDNAとわずかなパフォーマンスを犠牲にして、ハード制約を処理するTranslatorクラスを導入することを検討できます。
于 2009-11-27T21:50:22.187 に答える
0

実装はデコレータパターンのように見えます。

于 2009-11-27T17:58:46.843 に答える
0

人々が言うように、それを1つの巨大なクラスにしないでください。それは恐ろしいでしょう。さまざまなクラスで動作をカプセル化します。戦略は解決策です。例が必要な場合は、ソースとJGAP
の例をダウンロードしてください。遺伝的プログラミングと遺伝的アルゴリズムをサポートしています。あなたはそこに素敵な素敵なデザインが表示されます。Mutation、Crossover、Selection、Population、Gene-これらはすべて別個のクラスです。使用する実装で定義済みのインターフェイスを開始し、適切なアルゴリズムパラメータを渡して、それを実行する構成オブジェクトを設定するだけです。本当にパッケージは巨大で、javadocは素晴らしいです、そしてあなたはいつでもソースを調べるか、いくつかの答えのためにメールグループをチェックすることができます。GAパッケージを探していたときにGAlibなどを見ましたが、これは本当に素敵なデザインで最も完成度が高いと思います。

于 2009-11-27T22:42:45.037 に答える