文章 "遗传算法 - 很简单!" - 页 9

 

我建议应计算人口数量:

  ChromosomeCount=GeneCount*11;                                      //菌落中染色体的数量
取自:http://habrahabr.ru/blogs/algorithm/122222/
Генетический алгоритм: боремся с преждевременной сходимостью
  • habrahabr.ru
В предыдущем очерке (Выбор размера популяции для генетического алгоритма) был определен минимальный размер популяции необходимый для работоспособности генетического алгоритма: N = 1 + LOG2(1/(1-P1^(1/L))), где P1 — требуемая вероятность того, что случайный набор хромосом будет содержать все необходимые элементы для каждого локуса; L — длина...
 

非常感谢你的文章!要不是这篇文章,我还不知道什么是遗传方法呢 :)

但有一个问题!当我们从数据库中检查染色体时,如果匹配,则会从数据库中的染色体索引中减去一个单位。为什么?如果指数为零呢?

//在数据库中搜索染色体,找到相同的染色体。
    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 个个体!而这 11000 次 FF 运行只需要 1 个历元!你也可以使用随机基因生成法,结果也不会比直接搜索差多少。给定的数据源 "赌 "的是,在一个庞大的群体中,会有足够的遗传物质来进一步发展群体,使其在每个纪元中都有所改进。我正试图实现同样的目标,不过是在不增加 FF 运行总数的情况下,利用基因运算符进行概率运算。

 
MigVRN:

非常感谢你的文章!要不是这篇文章,我还不知道什么是遗传方法呢 :)

但有一个问题!当我们从数据库中检查染色体时,如果匹配,则会从数据库中的染色体索引中减去一个单位。为什么?如果指数为零呢?

我哪里说错了?

  //如果数据库中存储了任何染色体
  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++;
  }

只有当数据库中至少有一条染色体时,才会对数据库进行检查。你没有引用数据库搜索代码的整个部分。

因此,数据库中没有染色体但检查了沟槽的情况是不可能出现的。

 
joo:

只有当数据库中至少有一条染色体时,才会进行数据库检查。您没有给出按碱基搜索的整段代码。

因此,不可能出现数据库中没有染色体,但却进行了沟槽检查的情况。

感谢您如此及时的回复!我的意思和你说的不太一样!

1) 假设数据库中确实有一条染色体(ChrCountInHistory = 1 - 即数组维数 等于 1),那么它在数据库中的索引为 0!(默认情况下 ChrCountInHistory 为零,即数组中元素 的索引为零)。

我们从这个索引中减去 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:

你说得对,谢谢。

这才是王道 That's the way to go:

嗯。

现在,HistoryHromosomes[0][Ch1]上的"Array out of range"(数组超出范围),尽管一切似乎都是正确的...

 

joo:

你说得对,谢谢。

不客气!最重要的是现在比以前更好用了:)

joo

嗯。

现在,HistoryHromosomes[0][Ch1]上出现了 "Array out of range(数组超出范围)",尽管一切看起来都是正确的...

很难说原因--我们分析的代码不同。也许是 "position "变量的问题--文章中的类似变量是 "chromos"。我大概把文章中的代码看了 10 遍--我不明白错误出在哪里:( 我稍后会检查文章中的示例--也许有些东西会变得更清楚。

附注:如果一个变量由 ~150 个值组成,使用内存库是 合理的。历史记录中有 100000 个个体。 也许 在这种情况下,计算比检查(搜索)更快? 你没有 检查过吗

 
MigVRN:

附注:如果变量由 ~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
//|版权所有 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]);
}
//+------------------------------------------------------------------+

//------------------------------------------------------------------------------
//Checking a chromosome against a chromosome database(对照染色体数据库检查染色体)。
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;
}