English Русский 中文 Deutsch 日本語 Português
preview
Algoritmos de optimización de la población: Algoritmo de enjambre de aves (Bird Swarm Algorithm, BSA)

Algoritmos de optimización de la población: Algoritmo de enjambre de aves (Bird Swarm Algorithm, BSA)

MetaTrader 5Ejemplos |
693 6
Andrey Dik
Andrey Dik

Contenido:

1. Introducción
2. Descripción del algoritmo
3. Resultados de las pruebas


1. Introducción

Las aves son criaturas asombrosas que ocupan un lugar esencial en la naturaleza y el ecosistema. Se cree que las aves descienden de los dinosaurios, sus parientes más cercanos. Uno de los ejemplos más famosos sería el Archaeopteryx, el ave más antigua conocida, que vivió hace unos 150 millones de años. Con frecuencia actúan como indicadores de la salud del medio ambiente porque los cambios en su número y su comportamiento pueden indicar problemas en el ecosistema, como la contaminación, la pérdida de hábitat y el cambio climático. Existen más de 10 000 especies conocidas de aves en la Tierra, y cada una tiene adaptaciones únicas a su estilo de vida.

Algunas aves pueden volar grandes distancias, otras sumergirse en las aguas a gran profundidad, otras poseen una voz con asombrosas capacidades. Las aves desempeñan un papel importante en el ecosistema, esparcen semillas de plantas, controlan las poblaciones de insectos y otros animales y suponen una fuente de alimento para los depredadores. Muchas especies de aves realizan largas migraciones, se reúnen e interactúan con otros miembros de su especie en una bandada, recorriendo miles de kilómetros juntos en busca de alimento o zonas de cría. Este excepcional fenómeno pone de relieve sus extraordinarias habilidades de navegación, de resistencia, interacción en grupo y cooperación. Las aves son una parte increíblemente diversa e importante de nuestro planeta.

El Bird Swarm Algorithm (BSA) es un apasionante algoritmo evolutivo bioinspirado que utiliza la inteligencia de enjambre, y se basa en las interacciones sociales y el comportamiento de las bandadas de pájaros. Desarrollado por Meng y sus colegas en 2015, el BSA supone un enfoque de optimización único que integra tres aspectos clave del comportamiento de las aves: el vuelo, la búsqueda de alimento y la vigilancia. Entre las bandadas electrónicas, donde cada "pájaro" posee tácticas y estrategias individuales, generando un sistema único de interacción colectiva, lleno de inteligencia algorítmica y creatividad. Aquí no solo resultan importantes los esfuerzos personales, sino también la capacidad de cooperar, compartir y apoyarse mutuamente en la persecución de un objetivo común de optimización.  

Los distintos individuos del BSA pueden tener estrategias de búsqueda diferentes. Las aves pueden alternar de forma aleatoria entre el comportamiento de vuelo, la vigilancia y la búsqueda de alimento. El algoritmo de diseño biónico consiste en buscar alimentos basándose en la adaptación global e individual. Las aves también intentan desplazarse al centro de la población, lo cual puede provocar competencia con otras aves, o bien alejarse de la bandada. El comportamiento de las aves incluye el vuelo habitual y la migración, así como el cambio entre los papeles de «productor» y «mendigo». En el mundo de BSA, cada individuo en esa iteración concreta tiene su propia estrategia de búsqueda, lo cual hace que este algoritmo sea multidimensional y pueda exhibir su potencia.

Sin embargo, como muchos algoritmos de inteligencia de enjambre, el BSA puede sufrir de convergencia prematura y quedarse atascado en óptimos locales. Para lograr una convergencia más rápida con una gran precisión de los algoritmos de optimización basados en enjambres, se han usado varios métodos para equilibrar la explotación y la exploración.

El algoritmo BSA basado en el comportamiento de las aves se inspira en las interacciones colectivas en bandada de las aves en la naturaleza, cuyo comportamiento constituye la base de este algoritmo:

  • Comportamiento de la bandada. Muchas aves, como los estorninos, las golondrinas y los gansos, muestran un comportamiento de bandada cuando vuelan juntos. Este comportamiento les ayuda a reducir la resistencia del aire y ahorrar energía durante las migraciones o la búsqueda de alimento.
  • Comunicación. Las aves usan distintos tipos de comunicación, como sonidos, gestos y posturas, para comunicarse entre sí. Esto les permite coordinar sus acciones, advertir sobre peligros a sus congéneres y coordinar su búsqueda de alimento.
  • Adaptabilidad. Las aves tienen un alto grado de adaptabilidad a las cambiantes condiciones del entorno. Pueden reaccionar rápidamente ante el peligro, los cambios meteorológicos y la disponibilidad de alimentos, y también adaptar su comportamiento y sus rutas migratorias según las circunstancias.
  • Liderazgo y seguimiento. En una bandada de pájaros, suele haber un líder que define la dirección del vuelo y los demás pájaros le siguen. Esto demuestra el principio de liderazgo y seguimiento, que también se tiene en cuenta en el algoritmo BSA para encontrar eficientemente soluciones óptimas.

El algoritmo BSA usa estos principios del comportamiento de las aves para desarrollar una técnica de optimización eficaz que imite el comportamiento colectivo de las bandadas de pájaros para resolver diversos problemas de optimización. El BSA no es solo un algoritmo, también supone un fascinante viaje al mundo de la optimización, donde las interacciones sociales de las aves se convierten en fuente de inspiración para resolver problemas complejos con eficacia.


2. Descripción del algoritmo

Veamos a echar un vistazo más de cerca a la lógica del algoritmo BSA, que puede parecer compleja y confusa a primera vista. Antes de empezar a escribir el código, desarrollaremos el pseudocódigo del algoritmo que servirá de base para su implementación. Así resultará mucho más fácil entender cómo funciona el BSA.

El Pseudocódigo del Algoritmo de Enjambre de Pájaros (Bird Swarm Algorithm, BSA), es una descripción de alto nivel de un algoritmo que modela el comportamiento de una bandada de pájaros:

1. Inicialización de N soluciones y parámetros asociados
2. Generación de nuevas soluciones:
3. Si el pájaro está volando:
    4. Si el pájaro es productor:
        5. Búsqueda de un nuevo sector de alimentación
    6. De lo contrario:
        7. El pájaro mendigo sigue la pista del productor
8. De lo contrario:
    9. Si el ave está buscando comida:
        10. El pájaro se alimenta
    11. De lo contrario:
        12. El pájaro se mantiene alerta (vigilante)
13. Evaluación de la idoneidad de las nuevas soluciones
14. Actualización de la solución
15. Si se alcanza el criterio de parada:
    16. Finalización del algoritmo
17. De lo contrario:
    18. Volver al paso 2


La fórmula del punto 5 para un ave que busca un nuevo sector de alimentación será:

 xn = RNDg (min, max, producerPower)

donde:

  • xn - nuevo valor de las coordenadas
  • RNDg - número aleatorio con distribución normal con el centro de distribución en la coordenada actual
  • min y max - límites de la distribución
  • producerPower - valor de la desviación típica del productor

La fórmula implica que un ave-productora podrá migrar en cualquier dirección a lo largo del espacio de búsqueda, con una probabilidad mayor en las proximidades de su posición actual. Esto garantizará que las aves exploren nuevas zonas en busca de alimento.

La fórmula del punto 7 para un pájaro mendigo que siga al productor será:

xn = x + (xK - x) * FL * RNDg (-1.0, 1.0, scroungerPower)

donde:

  • xn - nuevo valor de las coordenadas
  • x - mejor coordenada del mendigo en la historia.
  • xK - mejor coordenada del productor en la historia, donde un ave aleatoria con la posición K en la población es elegida como productor
  • RNDg - número aleatorio con distribución normal con el centro de la distribución en 0 y los límites "-1.0" y "1.0".
  • scroungerPower - valor de la desviación estándar del mendigo

La fórmula muestra que el ave mendiga se orienta hacia sus mejores coordenadas y hacia las mejores coordenadas del mejor individuo de la bandada (el productor no se orientará hacia sus mejores coordenadas, sino hacia las coordenadas actuales). Esto modelará el comportamiento de seguimiento al líder en una manada.

La fórmula del punto 10 aplicable a un ave durante el periodo de alimentación fuera de vuelo será:

xn = x + (p - x) * C * r1 + (g - x) * S * r2

donde:

  • xn - nuevo valor de las coordenadas
  • x - coordenada actual
  • p - mejor coordenada en la historia del ave que toma alimentos
  • g - mejores coordenadas demográficas en la historia (mejor solución global)
  • r1 - número aleatorio uniforme en el rango [0.0 ... 1.0]
  • r2 - número aleatorio uniforme en el intervalo [0.0 ... 1.0]
  • C - coeficiente cognitivo, parámetro externo
  • S - coeficiente social, parámetro externo

La fórmula describe un momento de ingestión de alimento en el que el comportamiento del ave se basa en su propia experiencia (posición actual y mejor posición en el pasado) y en la experiencia de la bandada.

La fórmula del punto 12 para un ave vigilante será:

xn = x + A1 * (mean [c] - x) * r1 + A2 * (xK - x) * r2

donde:

  • xn - nuevo valor de las coordenadas
  • x - mejor coordenada de ave vigilante en la historia.
  • r1 - número aleatorio uniforme en el rango [0.0 ... 1.0]
  • r2 - número aleatorio uniforme en el rango [-1.0 ... 1.0]
  • mean [c] - valor medio de la coordenada c-ésima basado en las mejores coordenadas de todas las aves de la bandada

A1 - coeficiente corrector de influencia de las coordenadas promediadas del centro de la bandada:

A1 = a1 * exp (-pFit * N / (sumFit + e)) 

donde:

  • a1 - coeficiente, parámetro externo
  • e = DBL_MIN, para evitar la división por 0
  • pFit - mejor adaptación de ave vigilante
  • sumFit - suma de las mejores adaptaciones de las aves de la bandada
  • N - número de aves de la manada

A2 - factor de corrección que considera el efecto de la posición del ave seleccionada para la observación (en el campo de visión del ave vigilante) sobre el comportamiento de esta última. Fórmula para A2:

A2 = a2 * exp (((pFit - pFitK) / (|pFitK - pFit| + e)) * (N * pFitK / (sumFit + e)))

donde:

  • a2 - coeficiente, parámetro externo
  • e = DBL_MIN, para evitar la división por 0
  • pFit - mejor adaptación de ave vigilante
  • pFitK - mejor aptitud de un ave K seleccionada al azar en la población (el ave que ha estado a la vista del ave vigilante)
  • sumFit - suma de las mejores adaptaciones de las aves de la bandada
  • N - número de aves de la manada

De este modo, el ave vigilante observa su entorno, lo cual le permite advertir a tiempo a sus congéneres del peligro. Se trata del comportamiento más complejo de todos los descritos en el algoritmo, pues tiene en cuenta la aptitud de todas las aves de la población, así como la aptitud del propio ave vigilante y del individuo seleccionado para la observación. En esencia, el ave vigilante se desplazará hacia la aptitud general de la población, dada la posición de un congénere que haya entrado en su campo de visión.

El texto resaltado con color en el pseudocódigo corresponde a los elementos lógicos del BSA mostrados en el esquema de la figura 1.

BSA

Figura 1. Esquema lógico del algoritmo BSA.

El esquema de la figura 1 supone una visualización del algoritmo BSA y modela el comportamiento de una bandada de pájaros. Las principales características de este algoritmo son:

  1. La inicialización de las soluciones. El algoritmo comienza inicializando un conjunto de soluciones y sus parámetros vinculados. Esto incluye la distribución inicial de las aves (o soluciones) en el espacio de búsqueda.
  2. El comportamiento de vuelo. Durante el proceso del algoritmo, cada ave puede "volar" o "no volar". Esta condición influye en la capacidad del ave para descubrir nuevas soluciones. 
  3. El comportamiento de búsqueda de alimentos. Si un ave está "volando" puede convertirse en "productora" y empezar a buscar un nuevo sector de alimento, o puede convertirse en "mendiga", siguiendo al productor.
  4. El comportamiento de alimentación. Si un ave "no vuela", o bien se está alimentando o bien permanece vigilante. Puede representar un estado de espera, o bien de observación del entorno.
  5. La evaluación y actualización de las soluciones. Una vez generadas las nuevas soluciones, se evaluará su adaptabilidad o calidad.
  6. El criterio de parada. El algoritmo continuará el ciclo de generación y actualización de soluciones hasta que se alcance un determinado criterio de parada. Puede tratarse de un determinado número de iteraciones, del alcance de un determinado nivel de calidad de la solución o de cualquier otro criterio.

Me gustaría destacar que el BSA es un algoritmo dinámico que se adapta y evoluciona en el proceso de búsqueda de la solución óptima.

Vamos a escribir el código del algoritmo BSA. Para cada agente, definiremos la estructura "S_BSA_Agent", que supondrá una solución independiente al problema de la optimización, así como la descripción de un ave en la bandada.

La estructura contendrá los siguientes campos:

  • cBest[] - array para almacenar las mejores coordenadas del agente.
  • fBest - variable para almacenar la mejor estimación de aptitud del agente.
  • Init - método de la estructura "S_BSA_Agent" que inicializa los campos de la estructura. Tomará el argumento entero "coords", el número de coordenadas que se utiliza para redimensionar el array "cBest" usando la función "ArrayResize".

Estableceremos un valor inicial de la variable "fBest" igual al valor mínimo posible de un número de tipo double, lo que significará la peor adaptación posible.

//——————————————————————————————————————————————————————————————————————————————
struct S_BSA_Agent
{
    double cBest []; //best coordinates
    double fBest;    //best fitness

    void Init (int coords)
    {
      ArrayResize (cBest, coords);
      fBest = -DBL_MAX;
    }
};
//——————————————————————————————————————————————————————————————————————————————

Vamos a definir ahora la clase "C_AO_BSA" del algoritmo BSA, que será la sucesora de la clase básica de los algoritmos de población "C_AO" y contendrá los siguientes campos y métodos:

1. Campos públicos:

  • ao_name - nombre del algoritmo de optimización.
  • ao_desc - descripción del algoritmo de optimización.
  • popSize - tamaño de la población.
  • params - array de parámetros del algoritmo.
  • flyingProb - probabilidad de vuelo.
  • producerProb - probabilidad de producción.
  • foragingProb - probabilidad de recolección.
  • a1 - constante a1 [0...2].
  • a2 - constante a2 [0...2].
  • C - coeficiente cognitivo.
  • S - coeficiente social.
  • FL - FL constante [0...2].
  • producerPower - desviación estándar en el comportamiento de los productores.
  • scroungerPower - desviación estándar en el comportamiento de los mendigos.

2. Métodos:

  • C_AO_BSA - constructor de clase que inicializa los campos de la clase.
  • SetParams - método para establecer los parámetros del algoritmo.
  • Init - método para inicializar el algoritmo. Admite rangos de búsqueda mínimo y máximo, paso de búsqueda y número de épocas.
  • Moving - método para desplazar a los agentes.
  • Revision - método para revisar a los agentes.

//——————————————————————————————————————————————————————————————————————————————
class C_AO_BSA : public C_AO
{
  public: //--------------------------------------------------------------------
  ~C_AO_BSA () { }
  C_AO_BSA ()
  {
    ao_name = "BSA";
    ao_desc = "Bird Swarm Algorithm";

    popSize        = 20;  //population size

    flyingProb     = 0.8;  //Flight probability
    producerProb   = 0.25; //Producer probability
    foragingProb   = 0.55; //Foraging probability
    a1             = 0.6;  //a1 constant [0...2]
    a2             = 0.05; //a2 constant [0...2]
    C              = 0.05; //Cognitive coefficient
    S              = 1.1;  //Social coefficient
    FL             = 1.75; //FL constant [0...2]
    producerPower  = 7.05; //Producer power
    scroungerPower = 2.60; //Scrounger power

    ArrayResize (params, 11);

    params [0].name = "popSize";         params [0].val  = popSize;

    params [1].name  = "flyingProb";     params [1].val  = flyingProb;
    params [2].name  = "producerProb";   params [2].val  = producerProb;
    params [3].name  = "foragingProb";   params [3].val  = foragingProb;
    params [4].name  = "a1";             params [4].val  = a1;
    params [5].name  = "a2";             params [5].val  = a2;
    params [6].name  = "C";              params [6].val  = C;
    params [7].name  = "S";              params [7].val  = S;
    params [8].name  = "FL";             params [8].val  = FL;
    params [9].name  = "producerPower";  params [9].val  = producerPower;
    params [10].name = "scroungerPower"; params [10].val = scroungerPower;
  }

  void SetParams ()
  {
    popSize        = (int)params [0].val;

    flyingProb     = params [1].val;
    producerProb   = params [2].val;
    foragingProb   = params [3].val;
    a1             = params [4].val;
    a2             = params [5].val;
    C              = params [6].val;
    S              = params [7].val;
    FL             = params [8].val;
    producerPower  = params [9].val;
    scroungerPower = params [10].val;
  }

  bool Init (const double &rangeMinP  [], //minimum search range
             const double &rangeMaxP  [], //maximum search range
             const double &rangeStepP [], //step search
             const int     epochsP = 0);  //number of epochs

  void Moving   ();
  void Revision ();
  void Injection (const int popPos, const int coordPos, const double value);

  //----------------------------------------------------------------------------
  double flyingProb;      //Flight probability
  double producerProb;    //Producer probability
  double foragingProb;    //Foraging probability
  double a1;              //a1 constant [0...2]
  double a2;              //a2 constant [0...2]
  double C;               //Cognitive coefficient
  double S;               //Social coefficient
  double FL;              //FL constant [0...2]
  double producerPower;   //Producer power
  double scroungerPower;  //Scrounger power

  S_BSA_Agent agent [];


  private: //-------------------------------------------------------------------
  double mean [];  //represents the element of the average position of the whole bird’s swarm
  double N;
  double e;        //epsilon

  void BirdProducer  (int pos);
  void BirdScrounger (int pos);
  void BirdForaging  (int pos);
  void BirdVigilance (int pos);
};
//——————————————————————————————————————————————————————————————————————————————

El método "Init" de la clase "C_AO_BSA" se utilizará para inicializar las variables de la clase basándose en los parámetros transmitidos. Este método realiza una inicialización estándar usando el método "StandardInit", que admite los rangos de búsqueda mínimo y máximo, así como el paso de búsqueda.

Si la inicialización estándar se ha realizado correctamente, el método continuará inicializando las variables "N" y "e". El valor de "N" se establecerá igual al tamaño de la población "popSize", mientras que "e"-épsilon se inicializará con el valor mínimo de un número de tipo double.

A continuación, el método redimensiona el array "agent" a "popSize". Para cada elemento del "agente", se llama al método "Init" con el parámetro "coords". El array "mean" también se redimensionará a "coords", este array se utilizará para almacenar las coordenadas de las aves promediadas según la población.

El método retornará "true" si la inicialización se ha realizado correctamente y "false" en caso contrario.

Este método realizará la configuración inicial del algoritmo de optimización BSA con los parámetros especificados y lo preparará para realizar la optimización.

//——————————————————————————————————————————————————————————————————————————————
bool C_AO_BSA::Init (const double &rangeMinP  [], //minimum search range
                     const double &rangeMaxP  [], //maximum search range
                     const double &rangeStepP [], //step search
                     const int     epochsP = 0)  //number of epochs
{
  if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;

  //----------------------------------------------------------------------------
  ArrayResize (agent, popSize);
  for (int i = 0; i < popSize; i++) agent [i].Init (coords);

  ArrayResize (mean, coords);

  N = popSize;
  e = DBL_MIN;

  return true;
}
//——————————————————————————————————————————————————————————————————————————————

El método "Moving" de la clase "C_AO_BSA" se utilizará para desplazar agentes durante el proceso de optimización. El método ejecutará las siguientes acciones:

  • Si "revision" es "false", las coordenadas de los agentes "a[i].c[c]" se inicializarán utilizando valores aleatorios dentro de los rangos dados. A continuación, la bandera "revisión" se establecerá en "true" y el método finalizará.
  • Si "revision" no es igual a "false", se calcularán las nuevas coordenadas para cada agente utilizando fórmulas y probabilidades.

En la segunda y siguientes épocas, el método llamará a las funciones que determinarán el comportamiento de cada ave de la bandada según las probabilidades ejecutadas: 

  • Si la probabilidad de vuelo - "flyingProb" se ha ejecutado, el agente "volará". En este caso, hay dos comportamientos posibles:

  1. Si la probabilidad es menor que "producerProb", entonces el agente será un "productor" y estará buscando un nuevo lugar para comer.
  2. De lo contrario, el agente será un "mendigo" y seguirá al productor.
  • Si "no vuela", serán posibles los dos comportamientos siguientes:
  1. Si la probabilidad es menor que "foragingProb", entonces el agente "recolectará" la comida. 
  2. En caso contrario, el agente se encontrará en estado de "vigilancia".

Este método se encarga de actualizar las coordenadas de los agentes en el algoritmo de optimización BSA según la época actual, los valores aleatorios y las probabilidades.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_BSA::Moving ()
{
  //----------------------------------------------------------------------------
  if (!revision)
  {
    for (int i = 0; i < popSize; i++)
    {
      for (int c = 0; c < coords; c++)
      {
        a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
        a [i].c [c] = u.SeInDiSp  (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }

    revision = true;
    return;
  }

  //----------------------------------------------------------------------------
  for (int i = 0; i < popSize; i++)
  {
    //bird is flying------------------------------------------------------------
    if (u.RNDprobab () < flyingProb)
    {
      //bird producer
      if (u.RNDprobab () < producerProb) BirdProducer  (i); //bird is looking for a new place to eat
      //bird is not a producer
      else                               BirdScrounger (i); //scrounger follows the  producer
    }
    //bird is not flying--------------------------------------------------------
    else
    {
      //bird foraging
      if (u.RNDprobab () < foragingProb) BirdForaging  (i); //bird feeds
      //bird is not foraging
      else                               BirdVigilance (i); //bird vigilance
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

El método "BirdProducer" de la clase "C_AO_BSA" se utiliza para modelar el comportamiento del "productor" en el algoritmo BSA. El método ejecutará las siguientes acciones:

  • Inicializa la variable "x", que se usará para almacenar la posición actual del ave.
  • A continuación, se realizarán los siguientes pasos para cada coordenada del agente:
    • El valor "x" se establecerá igual a la coordenada actual del agente.
    • El valor "x" se actualizará usando una distribución gaussiana en la que la media será igual a la coordenada actual y el rango y la desviación típica estarán definidos por "rangeMin", "rangeMax" y "producerPower".
    • El nuevo valor de la coordenada del agente se establecerá mediante el método "SeInDiSp", que ajustará el valor "x" según el rango y el paso de búsqueda.

Este método modelará el comportamiento del "productor" en el algoritmo BSA, que busca nuevas ubicaciones de fuentes de alimento (es decir, nuevas soluciones potenciales) usando una distribución gaussiana para explorar el espacio de búsqueda.

//——————————————————————————————————————————————————————————————————————————————
void  C_AO_BSA::BirdProducer  (int pos)
{
  double x = 0.0; //bird position

  for (int c = 0; c < coords; c++)
  {
    x = a [pos].c [c];
    x = u.GaussDistribution (x, rangeMin [c], rangeMax [c], producerPower);

    a [pos].c [c] = u.SeInDiSp (x, rangeMin [c], rangeMax [c], rangeStep [c]);
  }
}
//——————————————————————————————————————————————————————————————————————————————

El método que modela el comportamiento del "mendigo" será la función "BirdScrounger" de la clase "C_AO_BSA". Realizará las siguientes acciones:

  • 1. Inicializará las variables "K", "x" y "xK". "K" será la posición de un ave seleccionada al azar en la bandada, "x" será la mejor posición del ave y "xK" será la mejor posición actual de un ave seleccionada al azar en la bandada.
  • 2. Ejecutará un ciclo a través de todas las coordenadas.
    • Seleccionará un ave al azar que no será el ave actual.
    • Actualizará "x" y "xK" basándose en las mejores posiciones del ave actual y de un ave seleccionada al azar.
    • Actualizará "x" utilizando una distribución gaussiana.
    • Por último, actualizará la posición actual del ave mediante el método "SeInDiSp", y además ajustará el valor "x" según el rango de búsqueda y el paso.

Este método modelará el comportamiento del "mendigo" en el algoritmo BSA, utilizando una distribución gaussiana que seguirá al "productor" (es decir, afinará su propia ubicación con respecto a la posición del productor).

//——————————————————————————————————————————————————————————————————————————————
void  C_AO_BSA::BirdScrounger (int pos)
{
  int    K  = 0;   //position of a randomly selected bird in a swarm
  double x  = 0.0; //best bird position
  double xK = 0.0; //current best position of a randomly selected bird in a swarm

  for (int c = 0; c < coords; c++)
  {
    do K = u.RNDminusOne (popSize);
    while (K == pos);

    x  = agent [pos].cBest [c];
    xK = agent   [K].cBest [c];

    x = x + (xK - x) * FL * u.GaussDistribution (0, -1.0, 1.0, scroungerPower);

    a [pos].c [c] = u.SeInDiSp (x, rangeMin [c], rangeMax [c], rangeStep [c]);
  }
}
//——————————————————————————————————————————————————————————————————————————————

Para un ave que no vuela en ese momento y está ocupada comiendo, se ha previsto el método "BirdForaging" de la clase "C_AO_BSA". Dentro de un ciclo a través de todas las coordenadas, el método hará lo siguiente:

  • Actualizará "x", "p" y "g" en función de la posición actual y la mejor posición del ave, así como de la mejor posición global.
  • Generará dos números aleatorios "r1" y "r2".
  • Actualizará "x" utilizando estos números aleatorios, así como las constantes "C" y "S".
  • Corregirá la posición del ave obtenida usando la función "SeInDiSp".
//——————————————————————————————————————————————————————————————————————————————
void  C_AO_BSA::BirdForaging  (int pos)
{
  double x  = 0.0; //current bird position
  double p  = 0.0; //best bird position
  double g  = 0.0; //best global position
  double r1 = 0.0; //uniform random number [0.0 ... 1.0]
  double r2 = 0.0; //uniform random number [0.0 ... 1.0]

  for (int c = 0; c < coords; c++)
  {
    x = a     [pos].c     [c];
    p = agent [pos].cBest [c];
    g = cB                [c];

    r1 = u.RNDprobab ();
    r2 = u.RNDprobab ();

    x = x + (p - x) * C * r1 + (g - x) * S * r2;

    a [pos].c [c] = u.SeInDiSp (x, rangeMin [c], rangeMax [c], rangeStep [c]);
  }
}
//——————————————————————————————————————————————————————————————————————————————

El último y más complejo método que modelará el comportamiento de un ave vigilante es "BirdVigilance". Realizará las siguientes acciones:

  • Calculará la suma de los mejores valores de adaptación de todas las aves de la bandada.
  • Calculará el valor medio de cada coordenada para todas las aves de la bandada.
  • Seleccionará un ave al azar que no será el ave actual.
  • Actualizará "pFit" y "pFitK" basándose en los mejores valores de adaptación del ave actual y de un ave seleccionada al azar.
  • Calculará "A1" y "A2" utilizando una función exponencial que dependerá de "pFit", "pFitK", "N", "sumFit" y "e".
  • Ejecutará un ciclo a través de todas las coordenadas: 
    • Generará dos números aleatorios "r1" y "r2".
    • Actualizará "x" y "xK" basándose en las mejores posiciones del ave actual y de un ave seleccionada al azar.
    • Actualizará "x" utilizando "A1", "A2", "r1" y "r2".
    • Corregirá la posición actual del ave mediante la función "SeInDiSp".
//——————————————————————————————————————————————————————————————————————————————
void  C_AO_BSA::BirdVigilance (int pos)
{
  int    K      = 0;   //position of a randomly selected bird in a swarm
  double sumFit = 0.0; //best birds fitness sum
  double pFitK  = 0.0; //best fitness of a randomly selected bird
  double pFit   = 0.0; //best bird fitness
  double A1     = 0.0;
  double A2     = 0.0;
  double r1     = 0.0; //uniform random number [ 0.0 ... 1.0]
  double r2     = 0.0; //uniform random number [-1.0 ... 1.0]
  double x      = 0.0; //best bird position
  double xK     = 0.0; //best position of a randomly selected bird in a swarm

  ArrayInitialize (mean, 0.0);

  for (int i = 0; i < popSize; i++) sumFit += agent [i].fBest;

  for (int c = 0; c < coords; c++)
  {
    for (int i = 0; i < popSize; i++) mean [c] += a [i].c [c];

    mean [c] /= popSize;
  }

  do K = u.RNDminusOne (popSize);
  while (K == pos);

  pFit  = agent [pos].fBest;
  pFitK = agent   [K].fBest;

  A1 = a1 * exp (-pFit * N / (sumFit + e));
  A2 = a2 * exp (((pFit - pFitK) / (fabs (pFitK - pFit) + e)) * (N * pFitK / (sumFit + e)));

  for (int c = 0; c < coords; c++)
  {
    r1 = u.RNDprobab ();
    r2 = u.RNDfromCI (-1, 1);

    x  = agent [pos].cBest [c];
    xK = agent   [K].cBest [c];

    x = x + A1 * (mean [c] - x) * r1 + A2 * (xK - x) * r2;

    a [pos].c [c] = u.SeInDiSp (x, rangeMin [c], rangeMax [c], rangeStep [c]);
  }
}
//——————————————————————————————————————————————————————————————————————————————

Finalmente, se utilizará el método "Revision" de la clase "C_AO_BSA" para actualizar la mejor solución global y actualizar las mejores posiciones de los agentes. El método ejecutará las siguientes acciones:

  • Actualizará la mejor solución global.
  • Actualizará los mejores valores anteriores de la función de adaptación y de las coordenadas del agente.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_BSA::Revision ()
{
  //----------------------------------------------------------------------------
  int ind = -1;

  for (int i = 0; i < popSize; i++)
  {
    if (a [i].f > fB) ind = i;
  }

  if (ind != -1)
  {
    fB = a [ind].f;
    ArrayCopy (cB, a [ind].c, 0, 0, WHOLE_ARRAY);
  }

  //----------------------------------------------------------------------------
  for (int i = 0; i < popSize; i++)
  {
    if (a [i].f > agent [i].fBest)
    {
      agent [i].fBest = a [i].f;
      ArrayCopy (agent [i].cBest, a [i].c, 0, 0, WHOLE_ARRAY);
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————


3. Resultados de las pruebas

Me gustaría profundizar en los resultados del algoritmo BSA con diferentes conjuntos de características. La puntuación total del BSA en todas las funciones de la prueba ha sido de 4,80947, lo que se corresponde con el 53,44% de la puntuación máxima posible. Este resultado indica la eficacia global del algoritmo, por lo que podemos concluir que el algoritmo BSA tiene potencial para resolver con éxito una gran variedad de problemas de optimización de diferentes funciones.

BSA|Bird Swarm Algorithm|20.0|0.8|0.25|0.55|0.6|0.05|0.05|1.1|1.75|7.05|2.6|
=============================
5 Hilly's; Func runs: 10000; result: 0.8930600046782612
25 Hilly's; Func runs: 10000; result: 0.6489975525320968
500 Hilly's; Func runs: 10000; result: 0.262496551797822
=============================
5 Forest's; Func runs: 10000; result: 0.9241962617798402
25 Forest's; Func runs: 10000; result: 0.7112057472851052
500 Forest's; Func runs: 10000; result: 0.24938963509983267
=============================
5 Megacity's; Func runs: 10000; result: 0.6938461538461538
25 Megacity's; Func runs: 10000; result: 0.3261538461538461
500 Megacity's; Func runs: 10000; result: 0.1001230769230778
=============================
All score: 4.80947 (53.44%)

La visualización del rendimiento del algoritmo permite observar una variación significativa de los resultados con diferentes funciones de prueba. A pesar de explorar con éxito las superficies localizadas, el algoritmo puede atascarse en trampas localizadas. Esto limita su capacidad para alcanzar un óptimo global y puede provocar una falta de estabilidad en la búsqueda de una solución óptima.

La visualización del rendimiento con la función de prueba Skin supone solo un ejemplo del rendimiento del algoritmo y no participa en la tabla de clasificación.

Hilly

  BSA en la función de prueba Hilly.

Forest

  BSA en la función de prueba Forest.

Megacity

BSA en la función de prueba Megacity.

Skin

BSA en función de la prueba Skin.

Es importante señalar que en la prueba de la función suave Hilly con un elevado número de variables, el algoritmo ha tenido un rendimiento extremadamente ineficiente, mostrando el resultado más bajo en la tabla de clasificación entre todos los algoritmos considerados, aunque, eso sí, en las funciones Forest y Megacity discreta de alta dimensionalidad, el BSA muestra resultados decentes en comparación con otros algoritmos, incluidos los anteriores en la tabla.

AO Description Hilly Hilly final Forest Forest final Megacity (discrete) Megacity final Final result % de MAX
10 p (5 F) 50 p (25 F) 1000 p (500 F) 10 p (5 F) 50 p (25 F) 1000 p (500 F) 10 p (5 F) 50 p (25 F) 1000 p (500 F)
1 BGA binary genetic algorithm 0,99992 0,99484 0,50483 2,49959 1,00000 0,99975 0,32054 2,32029 0,90667 0,96400 0,23035 2,10102 6,921 76,90
2 (P+O)ES (P+O) evolution strategies 0,99934 0,91895 0,56297 2,48127 1,00000 0,93522 0,39179 2,32701 0,83167 0,64433 0,21155 1,68755 6,496 72,18
3 SDSm stochastic diffusion search M 0,93066 0,85445 0,39476 2,17988 0,99983 0,89244 0,19619 2,08846 0,72333 0,61100 0,10670 1,44103 5,709 63,44
4 ESG evolution of social groups 0,99906 0,79654 0,35056 2,14616 1,00000 0,82863 0,13102 1,95965 0,82333 0,55300 0,04725 1,42358 5,529 61,44
5 SIA simulated isotropic annealing 0,95784 0,84264 0,41465 2,21513 0,98239 0,79586 0,20507 1,98332 0,68667 0,49300 0,09053 1,27020 5,469 60,76
6 DE differential evolution 0,95044 0,61674 0,30308 1,87026 0,95317 0,78896 0,16652 1,90865 0,78667 0,36033 0,02953 1,17653 4,955 55,06
7 BSA bird swarm algorithm 0,90857 0,73661 0,25767 1,90285 0,90437 0,81619 0,16401 1,88457 0,61692 0,54154 0,10951 1,26797 5,055 56,17
8 HS harmony search 0,86509 0,68782 0,32527 1,87818 0,99999 0,68002 0,09590 1,77592 0,62000 0,42267 0,05458 1,09725 4,751 52,79
9 SSG saplings sowing and growing 0,77839 0,64925 0,39543 1,82308 0,85973 0,62467 0,17429 1,65869 0,64667 0,44133 0,10598 1,19398 4,676 51,95
10 (PO)ES (PO) evolution strategies 0,79025 0,62647 0,42935 1,84606 0,87616 0,60943 0,19591 1,68151 0,59000 0,37933 0,11322 1,08255 4,610 51,22
11 WOAm wale optimization algorithm M 0,84521 0,56298 0,26263 1,67081 0,93100 0,52278 0,16365 1,61743 0,66308 0,41138 0,11357 1,18803 4,476 49,74
12 ACOm ant colony optimization M 0,88190 0,66127 0,30377 1,84693 0,85873 0,58680 0,15051 1,59604 0,59667 0,37333 0,02472 0,99472 4,438 49,31
13 BFO-GA bacterial foraging optimization - ga 0,89150 0,55111 0,31529 1,75790 0,96982 0,39612 0,06305 1,42899 0,72667 0,27500 0,03525 1,03692 4,224 46,93
14 MEC mind evolutionary computation 0,69533 0,53376 0,32661 1,55569 0,72464 0,33036 0,07198 1,12698 0,52500 0,22000 0,04198 0,78698 3,470 38,55
15 IWO invasive weed optimization 0,72679 0,52256 0,33123 1,58058 0,70756 0,33955 0,07484 1,12196 0,42333 0,23067 0,04617 0,70017 3,403 37,81
16 Micro-AIS micro artificial immune system 0,79547 0,51922 0,30861 1,62330 0,72956 0,36879 0,09398 1,19233 0,37667 0,15867 0,02802 0,56335 3,379 37,54
17 COAm cuckoo optimization algorithm M 0,75820 0,48652 0,31369 1,55841 0,74054 0,28051 0,05599 1,07704 0,50500 0,17467 0,03380 0,71347 3,349 37,21
18 SDOm spiral dynamics optimization M 0,74601 0,44623 0,29687 1,48912 0,70204 0,34678 0,10944 1,15826 0,42833 0,16767 0,03663 0,63263 3,280 36,44
19 NMm Nelder-Mead method M 0,73807 0,50598 0,31342 1,55747 0,63674 0,28302 0,08221 1,00197 0,44667 0,18667 0,04028 0,67362 3,233 35,92
20 FAm firefly algorithm M 0,58634 0,47228 0,32276 1,38138 0,68467 0,37439 0,10908 1,16814 0,28667 0,16467 0,04722 0,49855 3,048 33,87
21 GSA gravitational search algorithm 0,64757 0,49197 0,30062 1,44016 0,53962 0,36353 0,09945 1,00260 0,32667 0,12200 0,01917 0,46783 2,911 32,34
22 BFO bacterial foraging optimization 0,61171 0,43270 0,31318 1,35759 0,54410 0,21511 0,05676 0,81597 0,42167 0,13800 0,03195 0,59162 2,765 30,72
23 ABC artificial bee colony 0,63377 0,42402 0,30892 1,36671 0,55103 0,21874 0,05623 0,82600 0,34000 0,14200 0,03102 0,51302 2,706 30,06
24 BA bat algorithm 0,59761 0,45911 0,35242 1,40915 0,40321 0,19313 0,07175 0,66810 0,21000 0,10100 0,03517 0,34617 2,423 26,93
25 SA simulated annealing 0,55787 0,42177 0,31549 1,29513 0,34998 0,15259 0,05023 0,55280 0,31167 0,10033 0,02883 0,44083 2,289 25,43
26 IWDm intelligent water drops M 0,54501 0,37897 0,30124 1,22522 0,46104 0,14704 0,04369 0,65177 0,25833 0,09700 0,02308 0,37842 2,255 25,06
27 PSO particle swarm optimisation 0,59726 0,36923 0,29928 1,26577 0,37237 0,16324 0,07010 0,60572 0,25667 0,08000 0,02157 0,35823 2,230 24,77
28 MA monkey algorithm 0,59107 0,42681 0,31816 1,33604 0,31138 0,14069 0,06612 0,51819 0,22833 0,08567 0,02790 0,34190 2,196 24,40
29 SFL shuffled frog-leaping 0,53925 0,35816 0,29809 1,19551 0,37141 0,11427 0,04051 0,52618 0,27167 0,08667 0,02402 0,38235 2,104 23,38
30 FSS fish school search 0,55669 0,39992 0,31172 1,26833 0,31009 0,11889 0,04569 0,47467 0,21167 0,07633 0,02488 0,31288 2,056 22,84
31 RND random 0,52033 0,36068 0,30133 1,18234 0,31335 0,11787 0,04354 0,47476 0,25333 0,07933 0,02382 0,35648 2,014 22,37
32 GWO grey wolf optimizer 0,59169 0,36561 0,29595 1,25326 0,24499 0,09047 0,03612 0,37158 0,27667 0,08567 0,02170 0,38403 2,009 22,32
33 CSS charged system search 0,44252 0,35454 0,35201 1,14907 0,24140 0,11345 0,06814 0,42299 0,18333 0,06300 0,02322 0,26955 1,842 20,46
34 EM electroMagnetism-like algorithm 0,46250 0,34594 0,32285 1,13129 0,21245 0,09783 0,10057 0,41085 0,15667 0,06033 0,02712 0,24412 1,786 19,85


Conclusiones

El algoritmo de enjambre de aves (BSA) es una fascinante herramienta de investigación que cautiva la imaginación con su rica lógica que encarna los diversos estados y estrategias de las bandadas de pájaros. Trabajar en este algoritmo ha resultado interesante por la compleja dinámica que encierra, en la que las acciones individuales y grupales de las aves están sujetas a diferentes condiciones y combinaciones.

La complejidad del BSA también se manifiesta en el gran número de parámetros que requieren un cuidadoso ajuste para conseguir resultados óptimos. Para optimizar los parámetros del algoritmo hemos tenido que escribir un asesor experto para trabajar en el modo de cálculos matemáticos del simulador estándar MetaTrader 5, que ha servido de ayuda para encontrar buenos parámetros externos que han conseguido al algoritmo el 7º lugar en la clasificación. Quizá exista potencial para mejorar aún más los resultados, así que animo a los lectores que deseen experimentar con el algoritmo a poner manos a la obra, con la confianza de saber que aún no se han explotado plenamente todas las posibilidades para obtener los mejores resultados, ya que hay muchas variaciones en el orden de ejecución y la combinación de secuencias de comportamiento de las aves (en el artículo se dan a conocer 4 tipos de comportamiento). 

tab

Figura 2. Gradación por colores de los algoritmos según sus respectivas pruebas. Los resultados superiores o iguales a 0,99 aparecen resaltados en blanco.

chart

Figura 3. Histograma con los resultados de las pruebas de los algoritmos (en una escala de 0 a 100, cuanto mayor, mejor),

donde 100 es el máximo resultado teórico posible; hay un script para calcular la tabla de puntuación en el archivo).

Ventajas y desventajas del algoritmo del enjambre de pájaros (BSA):

Ventajas:

  1. Buenos resultados en la función Forest aguda y Megacity discreta de alta dimensionalidad.

Desventajas:

  1. Difícil implementación.
  2. Baja convergencia.
  3. Baja escalabilidad en funciones suaves como Hilly (problemas con tareas de alta dimensionalidad).

Adjunto al artículo encontrará un archivo con las versiones actuales de los códigos. El autor de este artículo no se responsabiliza de la exactitud absoluta de la descripción de los algoritmos canónicos, muchos de ellos han sido modificados para mejorar las capacidades de búsqueda. Las conclusiones y juicios presentados en los artículos se basan en los resultados de los experimentos realizados.

Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/14491

Archivos adjuntos |
BSA.zip (28.34 KB)
Andrey Dik
Andrey Dik | 3 abr 2024 en 11:45
fxsaber #:
¿Qué AO converge más rápido (número de cálculos FF)? No importa hacia dónde converja. Siempre que haya un mínimo de pasos.
Cualquiera de los 5 primeros converge muy rápido.
fxsaber
fxsaber | 3 abr 2024 en 11:50
Andrey Dik #:
Cualquiera de los 5 primeros, muy rápido para converger.

Lástima que no haya un valor numérico para rápido.

Andrey Dik
Andrey Dik | 3 abr 2024 en 11:58
fxsaber #:

Lástima que no exista un valor numérico para la rapidez.

Podrías hacerlo, hacer varias series de pruebas, guardar los valores de FF en cada época, calcular la mejora media en cada época correspondiente. Por supuesto, habrá valores diferentes para cada número de variables. Esto si te pones muy quisquilloso con los indicadores numéricos de "velocidad de convergencia".

En cada primera prueba para las tres funciones de prueba (10 parámetros), el Top 5 de la lista estará muy cerca del máximo teórico ya alrededor de la 100ª época (con una población de 50).

fxsaber
fxsaber | 3 abr 2024 en 12:02
Andrey Dik #:

Por supuesto, puede hacerlo, hacer varias series de pruebas, guardar los valores FF en cada época, calcular la mejora media en cada época correspondiente. Por supuesto, para cada número de variables habrá diferentes indicadores. Eso si eres muy quisquilloso con los indicadores numéricos de "velocidad de convergencia".

En cada primera prueba para las tres funciones de prueba (10 parámetros), el Top 5 de la lista estará muy cerca del máximo teórico ya alrededor de la 100ª época (con una población de 50).

~¿5000 FF?

Andrey Dik
Andrey Dik | 3 abr 2024 en 12:08
fxsaber #:

~¿5000 FF?

Sí. Incluso en 50th epoch ya será de alrededor de 70-80% del máximo teórico.

Bueno, esto es, por supuesto, con el parámetro paso 0 (como se hace por mí cuando las pruebas). Si el paso es diferente de 0, la convergencia es aún mayor.

Red neuronal en la práctica: Pseudo inversa (II) Red neuronal en la práctica: Pseudo inversa (II)
Por esta razón, dado que estos artículos tienen un propósito didáctico y no están enfocados en mostrar cómo implementar una funcionalidad específica, haremos algo un poco diferente aquí. En lugar de mostrar cómo implementar la factorización para obtener la inversa de una matriz, nos centraremos en cómo factorizar la pseudo inversa. El motivo es que no tiene sentido mostrar cómo factorizar algo de forma genérica si podemos hacerlo de manera especializada. Y mejor aún, será algo que podrás entender mucho más profundamente, comprendiendo por qué las cosas son como son. Así que veamos por qué, con el tiempo, un hardware sustituye a un software.
Algoritmos de optimización de la población: Algoritmo Boids, o algoritmo de comportamiento de bandada (Algoritmo Boids, Boids) Algoritmos de optimización de la población: Algoritmo Boids, o algoritmo de comportamiento de bandada (Algoritmo Boids, Boids)
En este artículo, realizamos un estudio del algoritmo Boids, que se basa en ejemplos únicos del comportamiento de enjambre o bandada de animales. El algoritmo Boids, a su vez, ha servido de base para la creación de toda una clase de algoritmos agrupados bajo el nombre de "inteligencia de enjambre".
Regresiones espurias en Python Regresiones espurias en Python
Las regresiones espurias ocurren cuando dos series de tiempo exhiben un alto grado de correlación puramente por casualidad, lo que conduce a resultados engañosos en el análisis de regresión. En tales casos, aunque las variables parezcan estar relacionadas, la correlación es casual y el modelo puede no ser confiable.
Características del Wizard MQL5 que debe conocer (Parte 18): Búsqueda de arquitectura neural con vectores propios Características del Wizard MQL5 que debe conocer (Parte 18): Búsqueda de arquitectura neural con vectores propios
Búsqueda de arquitectura neuronal, un enfoque automatizado para determinar la configuración ideal de la red neuronal, puede ser una ventaja cuando se enfrentan muchas opciones y grandes conjuntos de datos de prueba. Analizamos cómo, cuando se combinan vectores propios, este proceso puede resultar aún más eficiente.