記事"遺伝的アルゴリズム - とても簡単です!"についてのディスカッション - ページ 9

 

人口規模を計算することを提案する:

  ChromosomeCount=GeneCount*11;                                      //コロニー内の染色体数
検索元:http://habrahabr.ru/blogs/algorithm/122222/
Генетический алгоритм: боремся с преждевременной сходимостью
  • habrahabr.ru
В предыдущем очерке (Выбор размера популяции для генетического алгоритма) был определен минимальный размер популяции необходимый для работоспособности генетического алгоритма: N = 1 + LOG2(1/(1-P1^(1/L))), где P1 — требуемая вероятность того, что случайный набор хромосом будет содержать все необходимые элементы для каждого локуса; L — длина...
 

記事をありがとう!もしこの記事がなかったら、遺伝的手法とは何かを学ぶことはなかったでしょう :)

しかし、一つ疑問があります!データベースから染色体をチェックする際、一致した場合、データベースの染色体インデックスから1単位が減算されます。なぜですか?また、インデックスがゼロの場合はどうなるのでしょうか?

//データベース内の染色体を検索し、同じものを見つける。
    for (Ch1=0;Ch1<ChrCountInHistory && cnt<GeneCount;Ch1++)
    {
      cnt=0;
      //遺伝子インデックスが遺伝子数より少なく、同じ遺伝子が見つかる限り、遺伝子をチェックする。
      for (Ge=1;Ge<=GeneCount;Ge++)
      {
        if (Colony[Ge][chromos]!=historyHromosomes[Ge][Ch1])
          break;
        cnt++;
      }
    }
    //同一遺伝子の数が同じなら、データベースから既成の解決策を取ることができる。
    if (cnt==GeneCount)
      Colony[0][chromos]=historyHromosomes[0][Ch1-1];

どこが間違っているのでしょうか?

 
Rich:

人口規模を計算することを提案する:

引用されたソースの能力に異議を唱えるつもりはないが、同意しかねる。

最適化問題でGAを使うことの実現可能性は、直接探索に比べて最適を決定するのに必要なFFの実行回数を減らすことにある。

その推奨に従えば

ChromosomeCount=GeneCount*11

1000個の引数を持つ問題は、11000個の個体数を必要とする!そしてそれは、たった1エポックで11000回のFFを実行することになる!ランダムな遺伝子生成を使っても、最適を見つけるという点ではそれほど劣らないだろう。このソースは、大規模な集団の中に、各エポックにおいて集団を改善に向けてさらに発展させるのに十分な遺伝物質が存在するという「賭け」を行っている。私は同じことを達成しようとしているが、FFの実行回数を増やすことなく、遺伝的演算子で確率を操作している。

 
MigVRN:

記事にしてくれてありがとう!もしこの記事がなかったら、遺伝的手法とは何かを学ぶことはなかったでしょう :)

しかし、一つ疑問があります!データベースから染色体をチェックする際、一致した場合、データベースの染色体インデックスから1単位が減算されます。なぜですか?また、インデックスがゼロの場合はどうなるのでしょうか?

どこが間違っているのでしょうか?

  // データベースに染色体が保存されている場合
  if (ChrCountInHistory>0)
  {
    //データベース内の染色体を検索し、同じものを見つける。
    for (Ch1=0;Ch1<ChrCountInHistory && cnt<GeneCount;Ch1++)
    {
      cnt=0;
      //遺伝子インデックスが遺伝子数より小さく、かつ、以下の条件を満たす限り、遺伝子をチェックする。 
      //...同じ遺伝子を得る。
      for (Ge=1;Ge<=GeneCount;Ge++)
      {
        if (Colony[Ge][position]!=HistoryHromosomes[Ge][Ch1])
          break;
        cnt++;
      }
    }
    //同じ遺伝子が同じ数だけある場合、我々は次のように考えることができる。 
    //データベースからの既製ソリューション
    if (cnt==GeneCount)
      Colony[0][position]=HistoryHromosomes[0][Ch1-1];
    //データベースにそのような染色体がなければ、FFを計算する。
    else
    {
      FitnessFunction();
      //... データベースに空きがあれば、それを保存します。
      if (ChrCountInHistory<10000)
      {
        for (Ge=0;Ge<=GeneCount;Ge++)
          HistoryHromosomes[Ge][ChrCountInHistory]=Colony[Ge][position];
        ChrCountInHistory++;
      }
    }
  }
  //ベースが空の場合、染色体のFFを計算してベースに格納
  else
  {
    FitnessFunction();
    for (Ge=0;Ge<=GeneCount;Ge++)
      HistoryHromosomes[Ge][ChrCountInHistory]=Colony[Ge][position];
    ChrCountInHistory++;
  }

データベースに少なくとも1本の染色体がある場合のみチェックします。データベース検索コードの全セクションを引用していません。

したがって、データベースに染色体がないにもかかわらず、溝がチェックされるケースはありえません。

 
joo:

データベース・チェックは、データベースに少なくとも1本の染色体がある場合にのみ実行されます。塩基で検索するコードの全セクションが与えられていません。

したがって、データベースに染色体がないにもかかわらず、溝チェックを行うというケースはありえません。

迅速なご回答ありがとうございます!おっしゃっているような正確な意味ではありません!

1) 仮に、データベースに染色体が1本(ChrCountInHistory = 1、つまり配列の次元が 1)あったとします!(ChrCountInHistoryはデフォルトで0-配列の要素の インデックスは0)。

そして、このインデックスから1を引く:

Colony[0][position]=HistoryHromosomes[0][Ch1-1]; 

その上、検索はCh1=0から 始まります

2)HistoryHromosomes[Ge][Ch1]と比較し、HistoryHromosomes[0][Ch1-1]を代入する。

Документация по MQL5: Операции с массивами / ArrayRange
Документация по MQL5: Операции с массивами / ArrayRange
  • www.mql5.com
Операции с массивами / ArrayRange - Документация по MQL5
 

その通りだ。

その通りだ:

Colony[0][position]=HistoryHromosomes[0][Ch1]; 
 
joo:

その通りだ。

それでいいんだ:

うーん。

現在、HistoryHromosomes[0][Ch1]で"Array out of range"となっています。

 

joo:

ありがとう。

どういたしまして!前よりうまく動くようになったことが大きいよ :)

joo

うーん。

HistoryHromosomes[0][Ch1]で "Array out of range "となっています。

解析するコードが違うので、理由はわかりません。たぶん "position "変数のせいでしょう。記事のコードを10回くらい見たけど、どこにバグがあるのか理解できなかったよ。

P.S. : 変数が~150個の値で構成されている場合、メモリバンクを 使用することは正当化されます。そして、履歴には100000の個体があります。そのような場合、すべてをチェック(検索)するよりも、計算した方が 速いかもしれませんね チェックし てないの

 
MigVRN:

P.S. : 変数が~150個の値で構成されている場合、メモリーバンクを使用することは正当化されます。そして履歴には100000の個体がある。このような場合、すべてをチェック(再チェック)するよりも、カウントした方が 早いかもしれませんね チェックし てないの

すべてはFFを計算するのに必要な時間によります。もしFFが単なる数学的関数であれば、銀行は合理的ではありません。しかし、FFがヒストリーラン(ニューロン学習など)やその他のリソース集約的なタスクを使用するのであれば、バンクは必要であり、最適化時間を大幅に短縮することができる。

また、遺伝子の精度にもよる。遺伝子が "粗く "なればなるほど、繰り返しの頻度が高くなり、染色体バンクを使うことが合理的になります。

 
MigVRN:
....

:)

それでもエラーは出ません。テストスクリプトを作ってみたので、試してみてください。

for (Ge=1;Ge<=GeneCount;Ge++)
      {
        if (Colony[Ge][position]!=HistoryHromosomes[Ge][Ch1])
          break;
        cnt++;
      }

ここで、染色体をCh1の位置と比較していますが、上のループでは+1が代入されているので、その後に-1を引いています。

そうですね、ちょっと曲がっていますね。

これをチェックするスクリプトを以下に示します:

//+------------------------------------------------------------------+
//|チェックmq5|チェックする。
//|Copyright 2011, JQS aka Joo |
//|https://www.mql5.com/ru/users/joo
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, JQS aka Joo"
#property link      "https://www.mql5.com/ru/users/joo"
#property version   "1.00"
//+------------------------------------------------------------------+
//| スクリプト番組開始機能|
//+------------------------------------------------------------------+

double Colony[][5];
double HistoryHromosomes[][3];

int ChrCountInHistory=5;
int GeneCount=5;
int position=0;

void OnStart()
{
  ArrayResize(Colony,GeneCount+1);            ArrayInitialize(Colony,0.0);
  ArrayResize(HistoryHromosomes,GeneCount+1); ArrayInitialize(HistoryHromosomes,0.0);

  Colony[1][0]=7.0;
  Colony[2][0]=8.0;
  Colony[3][0]=9.0;
  Colony[4][0]=3.0;
  Colony[5][0]=2.0;

  HistoryHromosomes[0][0]=8.0;
  //-------------------------
  HistoryHromosomes[1][0]=7.0;
  HistoryHromosomes[2][0]=8.0;
  HistoryHromosomes[3][0]=9.0;
  HistoryHromosomes[4][0]=3.0;
  HistoryHromosomes[5][0]=1.0;//別の遺伝子


  HistoryHromosomes[0][1]=7.0;
  //-------------------------
  HistoryHromosomes[1][1]=7.0;
  HistoryHromosomes[2][1]=8.0;
  HistoryHromosomes[3][1]=6.0;//別の遺伝子
  HistoryHromosomes[4][1]=3.0;
  HistoryHromosomes[5][1]=2.0;

  HistoryHromosomes[0][2]=11.0;
  //-------------------------
  HistoryHromosomes[1][2]=7.0;
  HistoryHromosomes[2][2]=8.0;
  HistoryHromosomes[3][2]=9.0;
  HistoryHromosomes[4][2]=3.0;
  HistoryHromosomes[5][2]=2.0;

  CheckHistoryChromosomes();

  Print(Colony[0][0]);
}
//+------------------------------------------------------------------+

//------------------------------------------------------------------------------
//染色体を染色体データベースと照合する。
void CheckHistoryChromosomes()
{
  //----------------------------------------------------------------------------
  int   Ch1=0;  //データベースからの染色体インデックス
  int   Ge =0;  //遺伝子インデックス
  int   cnt=0;  //ユニークな遺伝子のカウンタ。いずれかの遺伝子が異なる場合 
                //- 染色体は一意であると認識される
  //----------------------------------------------------------------------------
  // データベースに染色体が保存されている場合
  if (ChrCountInHistory>0)
  {
    //データベース内の染色体を検索し、同じものを見つける。
    for (Ch1=0;Ch1<ChrCountInHistory && cnt<GeneCount;Ch1++)
    {
      cnt=0;
      //遺伝子インデックスが遺伝子数より小さく、かつ、以下の条件を満たす限り、遺伝子をチェックする。 
      //...同じ遺伝子を得る。
      for (Ge=1;Ge<=GeneCount;Ge++)
      {
        if (Colony[Ge][position]!=HistoryHromosomes[Ge][Ch1])
          break;
        cnt++;
      }
    }
    //同じ遺伝子が同じ数だけある場合、我々は次のように考えることができる。 
    //データベースからの既製ソリューション
    if (cnt==GeneCount)
    {
      Colony[0][position]=HistoryHromosomes[0][Ch1-1];
    }
    //データベースにそのような染色体がなければ、FFを計算する。
    else
    {
      FitnessFunction();
      //... データベースに空きがあれば、それを保存します。
      if (ChrCountInHistory<5)
      {
        for (Ge=0;Ge<=GeneCount;Ge++)
          HistoryHromosomes[Ge][ChrCountInHistory]=Colony[Ge][position];
        ChrCountInHistory++;
      }
    }
  }
  //ベースが空の場合、染色体のFFを計算してベースに格納
  else
  {
    FitnessFunction();
    for (Ge=0;Ge<=GeneCount;Ge++)
      HistoryHromosomes[Ge][ChrCountInHistory]=Colony[Ge][position];
    ChrCountInHistory++;
  }
}
//------------------------------------------------------------------------------

void FitnessFunction()
{
  Colony[0][position]=20.0;
}