Discusión sobre el artículo "Algoritmos Genéticos: ¡Es fácil!" - página 9

 

Sugiero que se calcule el tamaño de la población:

  ChromosomeCount=GeneCount*11;                                      //Número de cromosomas en la colonia
Extraído de: http: //habrahabr.ru/blogs/algorithm/122222/
Генетический алгоритм: боремся с преждевременной сходимостью
  • habrahabr.ru
В предыдущем очерке (Выбор размера популяции для генетического алгоритма) был определен минимальный размер популяции необходимый для работоспособности генетического алгоритма: N = 1 + LOG2(1/(1-P1^(1/L))), где P1 — требуемая вероятность того, что случайный набор хромосом будет содержать все необходимые элементы для каждого локуса; L — длина...
 

Muchas gracias por el artículo. Si no fuera por él, nunca me habría enterado de lo que son los métodos genéticos :)

¡Pero hay una pregunta! Cuando comprobamos los cromosomas de la base de datos - en caso de coincidencia - se restará una unidad del índice del cromosoma de la base de datos. ¿Por qué? ¿Y si el índice es cero?

//Busca los cromosomas en la base de datos para encontrar el mismo.
    for (Ch1=0;Ch1<ChrCountInHistory && cnt<GeneCount;Ch1++)
    {
      cnt=0;
      //Comprueba los genes siempre que el índice de genes sea menor que el número de genes y siempre que se encuentren los mismos genes
      for (Ge=1;Ge<=GeneCount;Ge++)
      {
        if (Colony[Ge][chromos]!=historyHromosomes[Ge][Ch1])
          break;
        cnt++;
      }
    }
    //Si el número de genes idénticos es el mismo, puede tomar una solución ya hecha de la base de datos
    if (cnt==GeneCount)
      Colony[0][chromos]=historyHromosomes[0][Ch1-1];

¿En qué me equivoco?

 
Rich:

Sugiero que se calcule el tamaño de la población:

No voy a discutir la competencia de la fuente citada, pero tengo que discrepar.

La viabilidad del uso de AG en problemas de optimización reside en la reducción del número de ejecuciones de FF necesarias para determinar el óptimo en comparación con la búsqueda directa.

Si seguimos la recomendación

ChromosomeCount=GeneCount*11

el problema con 1000 argumentos requerirá una población de 11000 individuos. ¡Y eso son 11000 ejecuciones FF en sólo 1 epoch! También se puede utilizar la generación aleatoria de genes y el resultado no será muy inferior a la hora de encontrar el óptimo. La fuente dada hace una "apuesta" de que en una población grande habrá suficiente material genético para seguir desarrollando la población hacia la mejora en cada época. Estoy tratando de lograr lo mismo, pero jugando probabilidades con los operadores genéticos sin aumento total de FF se ejecuta.

 
MigVRN:

Muchas gracias por el artículo. Si no fuera por él, nunca me habría enterado de lo que son los métodos genéticos :)

¡Pero hay una pregunta! Cuando comprobamos los cromosomas de la base de datos - en caso de coincidencia - se restará una unidad del índice del cromosoma de la base de datos. ¿Por qué? ¿Y si el índice es cero?

¿En qué me equivoco?

  //Si algún cromosoma está almacenado en la base de datos
  if (ChrCountInHistory>0)
  {
    //Busca los cromosomas en la base de datos para encontrar el mismo.
    for (Ch1=0;Ch1<ChrCountInHistory && cnt<GeneCount;Ch1++)
    {
      cnt=0;
      //Comprueba los genes siempre que el índice de genes sea menor que el número de genes y siempre que 
      //...obtener los mismos genes.
      for (Ge=1;Ge<=GeneCount;Ge++)
      {
        if (Colony[Ge][position]!=HistoryHromosomes[Ge][Ch1])
          break;
        cnt++;
      }
    }
    //Si hay tantos genes idénticos como hay, podemos tomar 
    //...solución lista a partir de la base de datos
    if (cnt==GeneCount)
      Colony[0][position]=HistoryHromosomes[0][Ch1-1];
    //Si no existe tal cromosoma en la base de datos, calcularemos FF para él....
    else
    {
      FitnessFunction();
      //... y si hay sitio en la base de datos, lo guardaremos.
      if (ChrCountInHistory<10000)
      {
        for (Ge=0;Ge<=GeneCount;Ge++)
          HistoryHromosomes[Ge][ChrCountInHistory]=Colony[Ge][position];
        ChrCountInHistory++;
      }
    }
  }
  //Si la base está vacía, calcula FF para el cromosoma y lo almacena en la base
  else
  {
    FitnessFunction();
    for (Ge=0;Ge<=GeneCount;Ge++)
      HistoryHromosomes[Ge][ChrCountInHistory]=Colony[Ge][position];
    ChrCountInHistory++;
  }

Sólo se comprueba si hay al menos un cromosoma en la base de datos. No has citado toda la sección del código de búsqueda en la base de datos.

Por lo tanto, el caso de que no haya cromosomas en la base de datos pero se compruebe el surco es imposible.

 
joo:

La comprobación de la base de datos sólo se realiza cuando hay al menos un cromosoma en la base de datos. Usted no ha dado toda la sección del código para la búsqueda por base.

Por lo tanto, el caso en el que no hay cromosomas en la base de datos, pero se realiza la comprobación del surco es imposible.

Gracias por una respuesta tan rápida. No me refería exactamente a lo que usted dice.

1) Supongamos que efectivamente hay un cromosoma en la base de datos (ChrCountInHistory = 1 - es decir, la dimensión del array es igual a uno) - ¡entonces su índice en la base de datos es cero! (ChrCountInHistory es cero por defecto - el índice de un elemento en el array es cero).

Y restamos uno de este índice:

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

además, la búsqueda comienza desde Ch1=0.

2) Comparamos con HistoriaHromosomas [Ge][Ch1 ], y asignamos HistoriaHromosomas[0][Ch1-1].

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

Tienes razón, gracias.

Así se hace:

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

Tienes razón, gracias.

Ese es el camino a seguir:

Hmm.

Ahora"Array out of range" en HistoryHromosomes[0][Ch1], aunque todo parece correcto...

 

joo:

Tienes razón, gracias.

De nada. Lo principal es que ahora funciona incluso mejor que antes :)

joo:

Hmm.

Ahora "Array out of range" en HistoryHromosomes[0][Ch1], aunque todo parece correcto...

Es difícil decir por qué - tenemos diferente código para analizar. Quizás sea la variable "position" - su análoga en el artículo es "chromos". He mirado el código en el artículo probablemente 10 veces - no podía entender dónde está el error :( Voy a comprobar más tarde en los ejemplos en el artículo - tal vez algo se aclarará.

P.D. : está justificado utilizar un banco de memoria si una variable consta de ~150 valores. Y hay 100000 individuos en el historial. ¿Tal vez en tal caso sería más rápido calcular que comprobar (buscar) todo? ¿No lo has comprobado?

 
MigVRN:

P.D. : está justificado utilizar un banco de memoria si una variable consta de ~150 valores. Y hay 100000 individuos en el historial. ¿Tal vez en tal caso sería más rápido contar que comprobar (volver a comprobar) todo? ¿No lo ha comprobado?

Todo depende del tiempo necesario para calcular el FF. Si la FF es sólo alguna función matemática, entonces el banco no es razonable. Pero si el FF utiliza recorridos históricos (aprendizaje neuronal, etc.) y otras tareas que requieren muchos recursos, entonces el banco es necesario y puede reducir significativamente el tiempo de optimización.

También depende de la precisión de los genes. Cuanto más "gruesos" sean los genes, más a menudo se producirán repeticiones, y más razonable es utilizar un banco de cromosomas.

 
MigVRN:
....

:)

Aún así, no hay ningún error, me has confundido mucho. Aquí, he hecho un script de prueba, pruébalo, te quedará más claro.

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

Aquí, aunque el cromosoma se compara con la posición de Ch1, pero en el bucle superior se le asigna +1, así que después le resto -1.

Estoy de acuerdo, está un poco torcido, se podría hacer mejor.

Aquí tienes un script para comprobarlo:

//+------------------------------------------------------------------+
//|Comprobar.mq5
//|Copyright 2011, JQS alias 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"
//+------------------------------------------------------------------+
//| Función de inicio del programa de script|
//+------------------------------------------------------------------+

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;//otro gen


  HistoryHromosomes[0][1]=7.0;
  //-------------------------
  HistoryHromosomes[1][1]=7.0;
  HistoryHromosomes[2][1]=8.0;
  HistoryHromosomes[3][1]=6.0;//otro gen
  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]);
}
//+------------------------------------------------------------------+

//------------------------------------------------------------------------------
//Comprobar un cromosoma con una base de datos de cromosomas.
void CheckHistoryChromosomes()
{
  //----------------------------------------------------------------------------
  int   Ch1=0;  //Índice cromosómico de la base de datos
  int   Ge =0;  //Índice genético
  int   cnt=0;  //Contador de genes únicos. Si algún gen es diferente 
                //- un cromosoma se reconoce como único
  //----------------------------------------------------------------------------
  //Si algún cromosoma está almacenado en la base de datos
  if (ChrCountInHistory>0)
  {
    //Busca los cromosomas en la base de datos para encontrar el mismo.
    for (Ch1=0;Ch1<ChrCountInHistory && cnt<GeneCount;Ch1++)
    {
      cnt=0;
      //Comprueba los genes siempre que el índice de genes sea menor que el número de genes y siempre que 
      //...obtener los mismos genes.
      for (Ge=1;Ge<=GeneCount;Ge++)
      {
        if (Colony[Ge][position]!=HistoryHromosomes[Ge][Ch1])
          break;
        cnt++;
      }
    }
    //Si hay tantos genes idénticos como hay, podemos tomar 
    //...solución lista a partir de la base de datos
    if (cnt==GeneCount)
    {
      Colony[0][position]=HistoryHromosomes[0][Ch1-1];
    }
    //Si no existe tal cromosoma en la base de datos, calcularemos FF para él....
    else
    {
      FitnessFunction();
      //... y si hay sitio en la base de datos, lo guardaremos.
      if (ChrCountInHistory<5)
      {
        for (Ge=0;Ge<=GeneCount;Ge++)
          HistoryHromosomes[Ge][ChrCountInHistory]=Colony[Ge][position];
        ChrCountInHistory++;
      }
    }
  }
  //Si la base está vacía, calcula FF para el cromosoma y lo almacena en la base
  else
  {
    FitnessFunction();
    for (Ge=0;Ge<=GeneCount;Ge++)
      HistoryHromosomes[Ge][ChrCountInHistory]=Colony[Ge][position];
    ChrCountInHistory++;
  }
}
//------------------------------------------------------------------------------

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