English Русский Português
preview
Optimización por comunidad de científicos — Community of Scientist Optimization (CoSO): Práctica

Optimización por comunidad de científicos — Community of Scientist Optimization (CoSO): Práctica

MetaTrader 5Trading |
20 0
Andrey Dik
Andrey Dik

Índice:

  1. Implementación del algoritmo
  2. Resultados de las pruebas
  3. Conclusiones


Implementación del algoritmo

Hoy continuaremos con la descripción de la implementación del algoritmo, que iniciamos en la primera parte del artículo, y presentaremos también los resultados de las pruebas experimentales realizadas con funciones de prueba especializadas.

La función «AssignFunds» describe el mecanismo de distribución de los «fondos» disponibles entre los investigadores en el algoritmo CoSO. Estos fondos representan oportunidades de aprendizaje, desplazamiento o participación en procesos posteriores, y su distribución influye en la dinámica de la evolución de las soluciones. La función recibe un único parámetro: «availableFunds», es decir, la cantidad total de fondos que hay que distribuir. Este proceso se divide en varias fases.

División de los fondos en dos partes. Se calcula «outsiderFunds», es decir, la parte de los fondos destinada a los investigadores «outsiders». La cantidad de estos fondos se determina como una fracción del total de «availableFunds», donde «omegaCurrent» (parámetro que controla la proporción de fondos destinados a los outsiders) actúa como coeficiente. Los fondos restantes, «existingFunds», se destinan a su distribución entre los investigadores activos.

    Distribución de fondos entre los investigadores existentes. Esta parte solo se ejecuta si existe un «informe global» (globalReport) y si su tamaño es mayor que cero; entonces se calcula «totalRank», la suma de todos los rangos en una progresión aritmética desde «1» hasta «reportSize». En esencia, se trata de la suma de los coeficientes de ponderación que se utilizarán para el reparto proporcional de los fondos. A continuación, los fondos («existingFunds») se distribuyen unidad por unidad: para cada unidad de fondos se genera un número aleatorio, que se multiplica por «totalRank», y ese valor se utilizará para seleccionar al investigador. Después se itera sobre «globalReport».

    Para cada entrada de «globalReport» se calcula la suma acumulada «cumSum», a la que se suma un «peso» igual a (reportSize - i). Esto significa que a los investigadores con posiciones más altas en el informe se les asigna un mayor peso y, por lo tanto, tienen más posibilidades de obtener fondos. Si el número aleatorio cae en el intervalo asociado al investigador actual (es decir, rnd <= cumSum), los fondos de dicho investigador aumentan en una unidad. A continuación, se interrumpe el ciclo de distribución del fondo actual y se pasa a la distribución del siguiente fondo.

    Creación de outsiders. Para finalizar, se llama a la función «CreateOutsiders», a la que se le pasa «outsiderFunds». Esta función utiliza los fondos reservados para outsiders para crear nuevos investigadores o, en otras palabras, para iniciar nuevas vías de investigación.

      De este modo, «AssignFunds» implementa una estrategia de gestión de fondos que premia a los investigadores que han mostrado buenos resultados (a través de «existingFunds» y la distribución por rango) y, al mismo tiempo, fomenta la aparición de nuevas ideas o agentes (a través de «outsiderFunds»).

      //———————————————————————————————————————————————————————————————————— 
      void C_AO_CoSO::AssignFunds (int availableFunds)
      {
        // Fondos para los outsiders
        int outsiderFunds = (int)(availableFunds * omegaCurrent);
        int existingFunds = availableFunds - outsiderFunds;
      
        int reportSize = ArraySize (globalReport);
      
        // Asignación de fondos a los investigadores existentes
        if (reportSize > 0)
        {
          int totalRank = reportSize * (reportSize + 1) / 2;
      
          for (int f = 0; f < existingFunds; f++)
          {
            double rnd = u.RNDprobab () * totalRank;
            double cumSum = 0;
      
            for (int i = 0; i < reportSize; i++)
            {
              cumSum += reportSize - i;
              if (rnd <= cumSum)
              {
                researchers [globalReport [i].index].m++;
                break;
              }
            }
          }
        }
      
        // Creación de outsiders
        CreateOutsiders (outsiderFunds);
      }
      //————————————————————————————————————————————————————————————————————

      La función «CreateOutsiders» describe el proceso de creación de nuevos «investigadores» en el marco del modelo CoSO, utilizando los fondos asignados específicamente a los «outsiders». Estos nuevos investigadores representan una diversidad potencial o nuevas ideas introducidas en el sistema. La función admite un único parámetro: «outsiderFunds», que es la cantidad de fondos destinados a la creación de «outsiders». Si «outsiderFunds» es menor o igual a cero, la función interrumpe inmediatamente su ejecución, ya que no hay fondos para crear «outsiders».

      Determinación del número de nuevos investigadores. A continuación, se establece «maxNew»: el número máximo de nuevos outsiders que se pueden crear en este momento. Este valor depende del tamaño actual de la población. Si la población es grande (más de 100 elementos), «maxNew» es igual a 2 (para ralentizar el crecimiento). De lo contrario, «maxNew» es igual a 5. Se trata de un mecanismo de control del crecimiento de la población. Se determina el número real de nuevos investigadores que se crearán. Luego se selecciona aleatoriamente dentro de un rango que va desde uno hasta el valor mínimo entre «outsiderFunds» y «maxNew». Esto garantiza que el número de nuevos investigadores no supere los fondos disponibles ni el límite establecido; a continuación, se calcula la cantidad de fondos que recibirá cada nuevo investigador (simple división del total de «outsiderFunds» entre «newResearchers»).

      Ciclo de creación de nuevos investigadores. La función ejecuta el ciclo «newResearchers» veces: primero se busca un espacio «libre» en el array existente de investigadores (researchers). Si se encuentra un espacio libre (idx != -1), se utiliza. Si no hay espacio libre, pero el tamaño actual de la población es inferior al tamaño máximo permitido (maxPopSize), se añade un nuevo espacio al final del array (idx = actualPopSize).

      Ampliación del array (si es necesario). Si no hay espacio libre y «actualPopSize» ya es igual o superior a «maxPopSize», se comprueba si es posible aumentar el tamaño del array de investigadores. Si «actualPopSize» ya alcanza «maxPopSize», se calcula un nuevo tamaño máximo (newMaxSize) como «maxPopSize + 50», pero sin superar los 500. Este es otro mecanismo que limita el crecimiento de la población. Si se alcanza el límite absoluto de 500, se omite la iteración actual (no se crean nuevos outsiders). De lo contrario, «maxPopSize» se actualiza a «newMaxSize». Tras las comprobaciones, «idx» se establece en «actualPopSize» para utilizar el primer espacio nuevo. Si, por cualquier motivo, «idx» sigue siendo «-1» después de todos los intentos de buscar o crear un espacio, se omite la creación del investigador actual.

      Inicialización de un nuevo investigador. Si el espacio «idx» se encuentra o se crea correctamente, «researchers [idx]. alive» se establece en «true», haciendo que el investigador sea marcado como activo; la cantidad de fondos, o «motivación», se establece en «fundsPerNew», y la «fuerza», o el valor inicial de otro parámetro, se inicializa con un número aleatorio.

      Inicialización de las coordenadas (posición en el espacio de soluciones). Para cada coordenada «c» («coords»: número de dimensiones), la posición se inicializa con un número aleatorio dentro del intervalo especificado. A continuación, «researchers [idx]. x [c]» se ajusta considerando el paso de discretización mediante la función «SeInDiSp», y la «mejor» posición, que inicialmente es igual a la actual, también se establece en «researchers [idx]. x [c]». La velocidad o el vector de variación se inicializa con un número aleatorio extraído de una distribución normal con los parámetros especificados.

      Inicialización de las probabilidades de las revistas científicas (de publicación). Para cada revista científica «j» («journalsNum»: número de revistas científicas), la probabilidad de publicación en la revista «j» se inicializa con un número aleatorio. A continuación, se llama a «NormalizeProbabilities» para «researchers [idx]. rho», con el fin de garantizar que la suma de todos los «rho» de ese investigador sea igual a uno.

      Actualización del tamaño de la población. Si se ha añadido un nuevo investigador al final del array, «actualPopSize» se actualiza a «idx + 1».

        De este modo, «CreateOutsiders» añade dinámicamente nuevos investigadores a la población, garantizando su inicialización aleatoria en el espacio de soluciones y distribuyendo entre ellos los fondos asignados. Los mecanismos de limitación «maxNew» y «maxPopSize» sirven para controlar el tamaño de la población, evitando que crezca indefinidamente.

        //————————————————————————————————————————————————————————————————————
        void C_AO_CoSO::CreateOutsiders (int outsiderFunds)
        {
          if (outsiderFunds <= 0) return;
        
          // Limitamos el número de nuevos outsiders, sobre todo si la población ya es numerosa
          int maxNew = (actualPopSize > 100) ? 2 : 5;
          int newResearchers = (int)(u.RNDfromCI (1, MathMin (outsiderFunds, maxNew)));
          int fundsPerNew = outsiderFunds / newResearchers;
        
          for (int i = 0; i < newResearchers; i++)
          {
            // Buscamos un espacio libre
            int idx = -1;
            for (int j = 0; j < actualPopSize; j++)
            {
              if (!researchers [j].alive)
              {
                idx = j;
                break;
              }
            }
        
            if (idx == -1 && actualPopSize < maxPopSize)
            {
              idx = actualPopSize;
            }
        
            if (idx == -1) // No hay espacio, ampliamos el array
            {
              if (actualPopSize >= maxPopSize)
              {
                // Limitamos el crecimiento de la población
                int newMaxSize = MathMin (maxPopSize + 50, 500);
                if (newMaxSize == maxPopSize) continue; // Se ha alcanzado el límite, omitimos la creación
        
                maxPopSize = newMaxSize;
                ArrayResize (researchers, maxPopSize);
                for (int j = actualPopSize; j < maxPopSize; j++)
                {
                  researchers [j].Init (coords, journalsNum);
                  researchers [j].alive = false;
                }
                idx = actualPopSize;
              }
            }
        
            if (idx == -1) continue; // No se ha podido crear
        
            researchers [idx].alive = true;
            researchers [idx].m = fundsPerNew;
            researchers [idx].s = u.RNDprobab ();
        
            // Inicialización aleatoria
            for (int c = 0; c < coords; c++)
            {
              researchers [idx].x [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
              researchers [idx].x [c] = u.SeInDiSp (researchers [idx].x [c], rangeMin [c], rangeMax [c], rangeStep [c]);
              researchers [idx].b [c] = researchers [idx].x [c];
              researchers [idx].v [c] = u.GaussDistribution (0.0, -0.01, 0.01, 1);
            }
        
            // Inicialización de las probabilidades de las revistas científicas
            for (int j = 0; j < journalsNum; j++)
            {
              researchers [idx].rho [j] = u.RNDprobab ();
            }
            NormalizeProbabilities (researchers [idx].rho);
        
            if (idx >= actualPopSize) actualPopSize = idx + 1;
          }
        }
        //————————————————————————————————————————————————————————————————————

        La función «HireResearchers» describe el proceso de «contratación» de nuevos investigadores por parte de un investigador ya existente que cuenta con una cantidad suficiente de subvenciones. Se trata de un mecanismo para crear nuevos elementos (soluciones) teniendo en cuenta las características de los ya existentes, lo que constituye una forma de reproducción o diversificación. La función admite un único parámetro: el índice del «supervisor», es decir, el investigador que se encargará de contratar a los nuevos. Si el investigador con ese índice dispone de una unidad de fondos o menos, la función interrumpe inmediatamente su ejecución. Esto significa que, para la contratación, es necesario disponer de fondos suficientes.

        División de los fondos del supervisor. Se calcula la parte de los fondos que el supervisor conserva para sí. Se trata de los fondos totales del supervisor, multiplicados por «researchers[idx].s». Se calculan los fondos disponibles para la contratación. Son los fondos restantes. Se actualizan los fondos del supervisor. Si «hireFunds» es menor o igual que 0, la contratación no es posible y la función interrumpe su ejecución.

        Determinación del número de investigadores que se van a contratar. Se establece el número máximo de nuevos investigadores que se pueden contratar. Si la población actual es grande (más de 100), «maxNew» es igual a 1. De lo contrario, «maxNew» es igual a 3. Se trata de un mecanismo de control del crecimiento de la población. Primero se determina el número real de nuevos investigadores que se crearán. Luego se selecciona aleatoriamente en el rango de 1 hasta el valor mínimo entre «hireFunds» y «maxNew». Después se calcula la cantidad de fondos que recibirá cada nuevo investigador contratado (división simple de «hireFunds» entre «newCount»).

        Ciclo de creación de nuevos investigadores (contratación). La función ejecuta este proceso «newCount» veces: primero se busca un «espacio libre» en el array existente de investigadores. Se considera espacio libre el índice cuyo indicador de actividad está establecido en «false» y, si se encuentra un espacio libre, este se utiliza. Si no hay espacio libre, pero el tamaño actual de la población es inferior al tamaño máximo permitido, se añade un nuevo espacio al final del array.

        Comprobación de la posibilidad de contratación (al alcanzar los límites). Si no hay espacio libre y, además, «actualPopSize» ya es igual o superior a «maxPopSize», o si «actualPopSize» ya es igual o superior al límite absoluto de 500, se omite la creación del investigador actual (el ciclo pasa a la siguiente iteración o finaliza). Si «newIdx» sigue siendo -1, significa que no es posible encontrar ni crear un espacio para un nuevo investigador, por lo que se omite la iteración actual del ciclo.

        Inicialización de un nuevo investigador. Si se encuentra un espacio correctamente, «researchers [newIdx]. alive» se establece en «true», lo que hace que el nuevo investigador se marque como activo, y los fondos del nuevo investigador se establecen en «fundsPerNew». El parámetro de «tendencia» del nuevo investigador se inicializa con un número aleatorio extraído de una distribución gaussiana. El valor medio de esta distribución se toma de «researchers [idx]. s» (parámetro del supervisor) y significa que el nuevo investigador será similar a su «supervisor». El valor de «s» queda limitado al intervalo de «0» a «1».

        Herencia de características del supervisor. La mejor posición encontrada o el «conocimiento» de un nuevo investigador se copia directamente de la mejor posición del supervisor y permite a los nuevos investigadores heredar esa «experiencia».

        Inicialización de la posición (coordenadas). Para cada coordenada «c» (coords — número de dimensiones), la posición del nuevo investigador se inicializa como la posición del supervisor, más una perturbación aleatoria extraída de una distribución gaussiana. Esto significa que los nuevos investigadores aparecen «cerca» de su supervisor, pero no exactamente en el mismo lugar. La posición se restringe a los límites establecidos. A continuación, «researchers [newIdx]. x [c]» se ajusta teniendo en cuenta el paso de discretización mediante la función «SeInDiSp», y la velocidad o el vector de variación también se inicializa de forma aleatoria a partir de una distribución normal.

        Inicialización de las probabilidades de las revistas científicas (publicación). Para cada revista científica «j» (journalsNum: número de revistas científicas), la probabilidad de publicación en la revista científica «j» se inicializa con un número aleatorio extraído de una distribución gaussiana. El valor medio de esta distribución se obtiene a partir de la probabilidad del supervisor. Esto permite a los nuevos investigadores heredar las preferencias del supervisor en cuanto a las revistas científicas, aunque con cierta variación aleatoria. Los valores negativos de «rho» se recortan a 0. A continuación, se llama a «NormalizeProbabilities» para «researchers [newIdx]. rho», con el fin de garantizar que la suma de todos los «rho» de ese investigador sea igual a uno.

        Actualización del tamaño de la población. Si se ha añadido un nuevo investigador al final del array («newIdx» es igual o mayor que «actualPopSize»), entonces «actualPopSize» se actualiza a «newIdx + 1».

          De este modo, «HireResearchers» permite a los investigadores de éxito «reproducirse», creando nuevas instancias que heredan parte de sus características, pero con cierta variación aleatoria. Esto favorece la exploración de las zonas adyacentes en el espacio de búsqueda y la difusión de estrategias exitosas, al tiempo que se controla el tamaño total de la población.

          //————————————————————————————————————————————————————————————————————
          void C_AO_CoSO::HireResearchers (int idx)
          {
            if (researchers [idx].m <= 1) return;
          
            int keepFunds = (int)(researchers [idx].m * researchers [idx].s);
            int hireFunds = researchers [idx].m - keepFunds;
            researchers [idx].m = keepFunds;
          
            if (hireFunds <= 0) return;
          
            // Limitamos el número de investigadores contratados, sobre todo cuando la población es numerosa
            int maxNew = (actualPopSize > 100) ? 1 : 3;
            int newCount = (int)(u.RNDfromCI (1, MathMin (hireFunds, maxNew)));
            int fundsPerNew = hireFunds / newCount;
          
            for (int i = 0; i < newCount; i++)
            {
              // Buscamos un espacio libre
              int newIdx = -1;
              for (int j = 0; j < actualPopSize; j++)
              {
                if (!researchers [j].alive)
                {
                  newIdx = j;
                  break;
                }
              }
          
              if (newIdx == -1 && actualPopSize < maxPopSize)
              {
                newIdx = actualPopSize;
              }
          
              if (newIdx == -1) // No hay espacio disponible
              {
                if (actualPopSize >= maxPopSize || actualPopSize >= 500) continue; // Se omite la creación al alcanzar el límite
              }
          
              if (newIdx == -1) continue; // No se pudo encontrar un espacio libre
          
              researchers [newIdx].alive = true;
              researchers [newIdx].m = fundsPerNew;
              researchers [newIdx].s = u.GaussDistribution (researchers [idx].s, 0, 1, 1);
              if (researchers [newIdx].s < 0) researchers [newIdx].s = 0;
              if (researchers [newIdx].s > 1) researchers [newIdx].s = 1;
          
              // Herencia a partir del supervisor
              ArrayCopy (researchers [newIdx].b, researchers [idx].b, 0, 0, WHOLE_ARRAY);
          
              // Posición cerca del supervisor
              for (int c = 0; c < coords; c++)
              {
                researchers [newIdx].x [c] = researchers [idx].x [c] + u.GaussDistribution (0.0, -0.01, 0.01, 1);
          
                // Control de límites
                if (researchers [newIdx].x [c] < rangeMin [c]) researchers [newIdx].x [c] = rangeMin [c];
                if (researchers [newIdx].x [c] > rangeMax [c]) researchers [newIdx].x [c] = rangeMax [c];
          
                researchers [newIdx].x [c] = u.SeInDiSp (researchers [newIdx].x [c], rangeMin [c], rangeMax [c], rangeStep [c]);
                researchers [newIdx].v [c] = u.GaussDistribution (0.0, -0.01, 0.01, 1);
              }
          
              // Probabilidades perturbadas de las revistas científicas
              for (int j = 0; j < journalsNum; j++)
              {
                researchers [newIdx].rho [j] = u.GaussDistribution (researchers [idx].rho [j], 0, 1, 1);
                if (researchers [newIdx].rho [j] < 0) researchers [newIdx].rho [j] = 0;
              }
              NormalizeProbabilities (researchers [newIdx].rho);
          
              if (newIdx >= actualPopSize) actualPopSize = newIdx + 1;
            }
          }
          //————————————————————————————————————————————————————————————————————

          La función «ComputeStdDev» sirve para calcular la desviación estándar de los valores de la función objetivo para todos los investigadores activos de la población. Es una medida de la dispersión de los datos en torno al valor medio y, en el contexto de la optimización, puede indicar la diversidad de soluciones en la población actual.

          Cálculo de la media (Mean):
          • Se inicializan las variables «mean» (para acumular la suma de los valores de «f») y «count» (para contar el número de investigadores activos).
          • La función itera por todos los investigadores del array «researchers», desde «0» hasta «actualPopSize - 1».
          • Dentro del ciclo se comprueba si el investigador «researchers [i]» está «activo», ya que solo los investigadores activos deben tenerse en cuenta en los cálculos.
          • Si el investigador está activo, su valor «f» se suma a «mean» y «count» aumenta en «1».
          • Una vez finalizado el primer ciclo, si «count» sigue siendo igual a «0» (no se ha encontrado ningún investigador activo), la función devuelve «0».
          • Por último, «mean» se divide entre «count» para obtener la media aritmética de «f» para todos los investigadores activos.
          Cálculo de la varianza (Variance):
          • Se inicializa la variable «variance» con el valor «0».
          • La función vuelve a recorrer todos los investigadores del array «researchers».
          • Se vuelve a comprobar la condición de investigador activo.
          • Para cada investigador activo se calcula el cuadrado de la diferencia entre su valor «f» y el valor «mean» ya calculado. Esta diferencia al cuadrado se suma a «variance».
          • Una vez finalizado el segundo ciclo, «variance» se divide entre «count». Esto da como resultado la varianza de los valores de «f» para los investigadores activos.
          Cálculo y devolución de la desviación estándar. La función devuelve la raíz cuadrada de la «variance» calculada. Esto es precisamente la desviación estándar.
          //————————————————————————————————————————————————————————————————————
          double C_AO_CoSO::ComputeStdDev ()
          {
            if (actualPopSize == 0) return 0;
          
            double mean = 0;
            int count = 0;
          
            for (int i = 0; i < actualPopSize; i++)
            {
              if (researchers [i].alive)
              {
                mean += researchers [i].f;
                count++;
              }
            }
          
            if (count == 0) return 0;
            mean /= count;
          
            double variance = 0;
            for (int i = 0; i < actualPopSize; i++)
            {
              if (researchers [i].alive)
              {
                variance += MathPow (researchers [i].f - mean, 2);
              }
            }
            variance /= count;
          
            return MathSqrt (variance);
          }
          //————————————————————————————————————————————————————————————————————

          La función «UpdateOmega» ajusta dinámicamente el parámetro «omegaCurrent», que representa la proporción de outsiders o la probabilidad de seleccionar a un outsider en el comportamiento del algoritmo. El objetivo de esta función es gestionar de forma adaptativa la estrategia de exploración/explotación según el estado actual de la población de investigadores, es decir, de su dispersión en el espacio de búsqueda.

          En primer lugar, la función llama a «ComputeStdDev()» para determinar «currentSigma», es decir, la desviación estándar actual de los valores de la función objetivo para los investigadores activos. Un valor alto de «currentSigma» indica una gran diversidad de soluciones, mientras que un valor bajo indica su convergencia.

          Caso 1: Convergencia de la población (currentSigma &lt; sigma0). Si la desviación estándar actual es inferior a un umbral «sigma0» predeterminado, esto indica que los investigadores comienzan a converger o a agruparse en torno a determinadas soluciones. En este caso, el algoritmo pasa a la fase de explotación (refinamiento) de las soluciones encontradas. Para evitar una convergencia prematura hacia un óptimo local y fomentar una mayor exploración, así como la búsqueda de mejores soluciones, se aumenta la proporción de outsiders (omegaCurrent). El incremento se calcula como (omegaMax - omegaMin) / 2.0 * epsilonPlus. Aquí, «omegaMax» y «omegaMin» definen los límites superior e inferior de «omegaCurrent», mientras que «epsilonPlus» es un coeficiente positivo que controla la velocidad de aumento. El objetivo es dar mayor peso a aquellos elementos que puedan «desviarse» de la tendencia general o que representen enfoques completamente nuevos.

          Caso 2: Divergencia o falta de convergencia de la población (currentSigma &gt;= sigma0). Si la desviación estándar es mayor o igual que el umbral «sigma0», esto significa que la población sigue estando muy dispersa o se encuentra en las primeras fases de exploración. En este caso la proporción de outsiders (omegaCurrent) disminuye. La reducción se calcula como (omegaMax - omegaMin) / 2.0 * epsilonMinus, donde «epsilonMinus» es un coeficiente negativo que controla la velocidad de reducción. Esto se hace para que el algoritmo no dedique demasiados recursos a la exploración aleatoria cuando la población ya es lo suficientemente diversa, y pueda empezar a centrarse en áreas más prometedoras.

          Limitación del rango (omegaCurrent). Tras modificar «omegaCurrent», la función garantiza que su valor se mantenga dentro del rango establecido; si «omegaCurrent» desciende por debajo de «omegaMin», se fija en «omegaMin», y si supera «omegaMax», se fija en «omegaMax», lo que evita que el parámetro se salga de unos límites operativos razonables.

          En general, la función «UpdateOmega» aplica una estrategia adaptativa. Cuando la población de investigadores muestra signos de convergencia rápida (baja desviación estándar), el algoritmo aumenta la probabilidad de seleccionar «outsiders» (o elementos que puedan alterar la estructura actual), con el fin de evitar los óptimos locales y estimular una nueva búsqueda o la exploración de un espacio más amplio. A la inversa, cuando la población sigue estando ampliamente distribuida, el algoritmo reduce el énfasis en los outsiders para centrarse en una exploración o explotación más sistemática de las áreas prometedoras ya identificadas.

          //————————————————————————————————————————————————————————————————————
          void C_AO_CoSO::UpdateOmega ()
          {
            double currentSigma = ComputeStdDev ();
          
            if (currentSigma < sigma0)
            {
              // Aumentamos la proporción de outsiders cuando hay convergencia
              omegaCurrent += (omegaMax - omegaMin) / 2.0 * epsilonPlus;
            }
            else
            {
              // Reducimos la proporción de outsiders
              omegaCurrent -= (omegaMax - omegaMin) / 2.0 * epsilonMinus;
            }
          
            // Limitamos el rango
            if (omegaCurrent < omegaMin) omegaCurrent = omegaMin;
            if (omegaCurrent > omegaMax) omegaCurrent = omegaMax;
          }
          //————————————————————————————————————————————————————————————————————

          La función «NormalizeProbabilities» está diseñada para transformar el array de valores numéricos «probs» de tal forma que representen una distribución de probabilidades correcta. Es decir, tras ejecutar la función, la suma de todos los elementos del array «probs» será igual a uno. Se inicializa la variable «sum» con el valor 0; se utilizará para acumular la suma de todos los elementos del array «probs». Se inicia un ciclo que recorre todos los elementos de este array. Dentro del ciclo, cada valor de «probs [i]» se suma a la variable «sum».

          Si el valor calculado de «sum» es positivo, se inicia un segundo ciclo que también recorre todos los elementos del array «probs». Dentro de este ciclo, cada elemento del array se divide entre «sum». Como resultado de esta división, cada valor de «probs [i]» pasa a ser la fracción correspondiente del total, y la suma de todos los elementos del array es igual a «1». Se trata de un procedimiento estándar de normalización.

          Si «sum» es igual a «0» o es negativa —aunque esto no suele esperarse en el caso de las probabilidades, la función también contempla este caso—, significa que no hay base sobre la que normalizar los valores iniciales. Por ejemplo, todas las probabilidades iniciales eran cero. En este caso, la función pasa a una «distribución uniforme». El valor «val» se calcula como (1.0 / size). Esto significa que cada elemento del array tendrá la misma probabilidad, de modo que su suma sea «1». Se inicia el tercer ciclo, que recorre todos los elementos del array «probs». Dentro de este ciclo, a cada elemento se le asigna el valor calculado «val». De este modo, cada elemento del array pasa a ser igual a (1 / size), y su suma será «1».

          Esta función es un método de utilidad general que garantiza que un conjunto de pesos o probabilidades «en bruto» pueda utilizarse como una distribución de probabilidades válida (donde «válida» significa que la suma de todas las probabilidades es igual a 1). Esto es importante en muchos algoritmos, como los métodos de selección basados en probabilidades, la selección por ruleta o el método de Monte Carlo, en los que una normalización adecuada evita errores y garantiza un comportamiento estadístico correcto.

          //————————————————————————————————————————————————————————————————————
          void C_AO_CoSO::NormalizeProbabilities (double &probs [])
          {
            double sum = 0;
            int size = ArraySize (probs);
          
            for (int i = 0; i < size; i++)
            {
              sum += probs [i];
            }
          
            if (sum > 0)
            {
              for (int i = 0; i < size; i++)
              {
                probs [i] /= sum;
              }
            }
            else
            {
              // Distribución uniforme
              double val = 1.0 / size;
              for (int i = 0; i < size; i++)
              {
                probs [i] = val;
              }
            }
          }
          //————————————————————————————————————————————————————————————————————

          La función «CompactPopulation» se encarga de gestionar el tamaño y la composición de la población de investigadores en el algoritmo. El objetivo principal es eliminar a los investigadores menos eficaces y, si es necesario, reducir la población a un tamaño manejable para mantener la eficiencia y el rendimiento del algoritmo.

          Recuento de investigadores «activos». Se inicializa la variable «aliveCount» (número de supervivientes) con el valor «0». A continuación, en un ciclo se recorren todos los investigadores de la población actual (desde 0 hasta actualPopSize - 1). Se comprueba el estado de cada investigador (researchers [i]. alive). Si el investigador está «activo» (su propiedad «alive» es verdadera), «aliveCount» se incrementa en uno.

            Condición para la compactación/reducción. Después de contar los investigadores activos, la función comprueba si es necesario llevar a cabo la compactación. Esto ocurre si se cumple una de estas dos condiciones: el número de investigadores activos «aliveCount» es inferior al 75 % del tamaño total actual de la población «actualPopSize», o si el tamaño actual de la población «actualPopSize» supera los 200 (aunque la mayoría de ellos estén activos, la población se considera demasiado grande y debe reducirse).

            Primera fase de compactación (eliminación de los «inactivos»). Si se cumple una de las condiciones para la compactación, se inicia el proceso. Se inicializa un nuevo índice con el valor «0». Este índice indicará el siguiente espacio libre al principio del array «researchers», al que se trasladarán los investigadores «activos». Luego se inicia un ciclo que recorre a todos los investigadores (del 0 al actualPopSize - 1). Dentro del ciclo, si el investigador actual está «activo», se comprueba si ya se encuentra en la posición correcta; de no ser así, significa que hay que desplazarlo hacia delante en el array.

            El investigador se copia en la posición «newIdx». Normalmente, en estos casos, se establece (researchers [i]. alive = false) para marcar al investigador original como «eliminado» o inactivo, aunque ya se haya copiado. Se trata de una limpieza: «newIdx» se incrementa en uno para indicar el siguiente espacio para el siguiente investigador activo. Una vez finalizado este ciclo, todos los investigadores «activos» se encontrarán al principio del array «researchers». El tamaño de la población se actualiza a «aliveCount».

            Segunda fase de compactación (reducción de una población grande). Tras la primera fase (en la que se eliminaron los inactivos y se desplazaron los activos), la función comprueba si «actualPopSize» aún supera los 150. Esta condición está anidada, es decir, solo se cumple si la población ya se ha compactado o contaba con muchos investigadores inactivos. Si «actualPopSize» es mayor que 150, significa que, incluso tras eliminar los investigadores inactivos, la población sigue siendo demasiado grande y es necesario reducirla aún más hasta el tamaño máximo permitido, que es 150. Para ello, se realiza una clasificación según el indicador «fitness». Después de esto, los investigadores con mejor «fitness» quedarán al principio del array.

            Eliminación de los «peores» investigadores. Todos los investigadores a partir del elemento 150 (es decir, los que quedaron en la «cola» tras la clasificación) se marcan como «inactivos» (researchers [i]. alive = false). Su parámetro «m» también se pone a cero. Por último, «actualPopSize» se establece en 150, con lo que en la práctica se recorta la población al tamaño máximo deseado. Esta función garantiza que la población:
            1. No acumula individuos no utilizados que podrían ocupar memoria y ralentizar el procesamiento.
            2. No crezca de forma descontrolada, lo que también puede afectar negativamente al rendimiento y la eficiencia, además de provocar un estancamiento prematuro.
            3. Mantenga un determinado nivel de calidad, descartando a los individuos menos aptos cuando el tamaño de la población alcanza un nivel crítico.
            //————————————————————————————————————————————————————————————————————
            void C_AO_CoSO::CompactPopulation ()
            {
              // Contamos los investigadores activos
              int aliveCount = 0;
              for (int i = 0; i < actualPopSize; i++)
              {
                if (researchers [i].alive) aliveCount++;
              }
            
              // Si hay demasiados inactivos, compactamos
              if (aliveCount < actualPopSize * 0.75 || actualPopSize > 200)
              {
                int newIdx = 0;
                for (int i = 0; i < actualPopSize; i++)
                {
                  if (researchers [i].alive)
                  {
                    if (i != newIdx)
                    {
                      // Copiamos el investigador activo a una nueva ubicación
                      researchers [newIdx] = researchers [i];
                      researchers [i].alive = false;
                    }
                    newIdx++;
                  }
                }
                actualPopSize = aliveCount;
            
                // Si la población sigue siendo demasiado grande, la limitamos
                if (actualPopSize > 150)
                {
                  // Clasificamos por aptitud (fitness) y nos quedamos con los mejores
                  for (int i = 0; i < actualPopSize - 1; i++)
                  {
                    for (int j = i + 1; j < actualPopSize; j++)
                    {
                      if (researchers [i].f < researchers [j].f)
                      {
                        S_Researcher temp = researchers [i];
                        researchers [i] = researchers [j];
                        researchers [j] = temp;
                      }
                    }
                  }
            
                  // Desactivamos a los peores
                  for (int i = 150; i < actualPopSize; i++)
                  {
                    researchers [i].alive = false;
                    researchers [i].m = 0;
                  }
                  actualPopSize = 150;
                }
              }
            }
            //————————————————————————————————————————————————————————————————————

            El método «Revision» restante del algoritmo CoSO. Se inicia un ciclo que recorre todos los individuos del array «a», desde el índice «0» hasta «aSize - 1». Dentro del ciclo, para cada individuo «a [i]» se comprueba la condición: «if (a [i]. f > fB)». Si el valor de la función objetivo del individuo actual resulta ser mayor que el mejor valor global actual, «fB» se actualiza con el nuevo mejor valor: «fB = a [i]. f». Luego se guarda el índice de este mejor individuo.

            Una vez finalizado el ciclo que ha recorrido todos los individuos del array «a», se comprueba la condición «if (bestIND != -1)». Esta condición se cumple si se ha encontrado al menos un individuo cuya función objetivo fuera mejor que el valor anterior de «fB». Si se ha encontrado un nuevo mejor individuo (bestIND es distinto de -1), se llama a la función «ArrayCopy», que copia los parámetros «c» del mejor individuo encontrado en el array global «cB».

            El objetivo principal de este método es mantener actualizado el estado de la mejor solución global encontrada por el algoritmo hasta ese momento. En los algoritmos evolutivos, como CoSO, el concepto de «mejor global» (global best) se sigue y se actualiza constantemente a medida que se encuentran mejores soluciones. Este resultado «mejor global» se utiliza después para orientar la búsqueda. En esencia, esta función implementa el paso de «memorizar la mejor solución» en cada iteración del algoritmo.

            //————————————————————————————————————————————————————————————————————
            void C_AO_CoSO::Revision ()
            {
              int bestIND = -1;
              int aSize = ArraySize (a);
            
              for (int i = 0; i < aSize; i++)
              {
                if (a [i].f > fB)
                {
                  fB = a [i].f;
                  bestIND = i;
                }
              }
            
              if (bestIND != -1)
              {
                ArrayCopy (cB, a [bestIND].c, 0, 0, WHOLE_ARRAY);
              }
            }
            //————————————————————————————————————————————————————————————————————


            Resultados de las pruebas

            El algoritmo CoSO funciona bastante bien y muestra resultados bastante buenos; por supuesto, quienes lo deseen pueden seguir experimentando con los parámetros.
            CoSO|Community of Scientist Optimization|10,0|150,0|3,0|10,0|0,7|
            =============================
            5 Hilly's; Func runs: 10000; result: 0,8047081198587067
            25 Hilly's; Func runs: 10000; result: 0,5429326559833119
            500 Hilly's; Func runs: 10000; result: 0,30916988715342353
            =============================
            5 Forest's; Func runs: 10000; result: 0,7383405771205314
            25 Forest's; Func runs: 10000; result: 0,38224371519203115
            500 Forest's; Func runs: 10000; result: 0,20600693936217676
            =============================
            5 Megacity's; Func runs: 10000; result: 0.553846153846154
            25 Megacity's; Func runs: 10000; result: 0.2550769230769231
            500 Megacity's; Func runs: 10000; result: 0.11129230769230862
            =============================
            Total score: 3,90362 (43,37%)

            Es la primera vez que me encuentro con una visualización tan inusual del algoritmo; esto se debe a la lógica de implementación multicapa.

            Hilly

            CoSO en la función de prueba Hilly

            Forest

            CoSO en la función de prueba Forest

            Megacity

            CoSO en la función de prueba Megacity

            Según los resultados del trabajo, el algoritmo se presenta con fines informativos en la tabla de clasificación de CoSO. Quiero señalar que nuestra tabla se está compactando, y los resultados inferiores al 45 % ya quedan fuera de sus límites.

            N.º AO Descripción Hilly Hilly
            Final
            Forest Forest
            Final
            Megacity (discrete) Megacity
            Final
            Final
            Resultado
            % 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 ANS across neighbourhood search 0,94948 0,84776 0,43857 2,23581 1,00000 0,92334 0,39988 2,32323 0,70923 0,63477 0,23091 1,57491 6.134 68,15
            2 CLA code lock algorithm (joo) 0,95345 0,87107 0,37590 2,20042 0,98942 0,91709 0,31642 2,22294 0,79692 0,69385 0,19303 1,68380 6.107 67,86
            3 AMOm animal migration ptimization M 0,90358 0,84317 0,46284 2,20959 0,99001 0,92436 0,46598 2,38034 0,56769 0,59132 0,23773 1,39675 5 987 66,52
            4 (P+O)ES (P+O) evolution strategies 0,92256 0,88101 0,40021 2,20379 0,97750 0,87490 0,31945 2,17185 0,67385 0,62985 0,18634 1,49003 5.866 65,17
            5 CTA comet tail algorithm (joo) 0,95346 0,86319 0,27770 2,09435 0,99794 0,85740 0,33949 2,19484 0,88769 0,56431 0,10512 1,55712 5.846 64,96
            6 TETA time evolution travel algorithm (joo) 0,91362 0,82349 0,31990 2,05701 0,97096 0,89532 0,29324 2,15952 0,73462 0,68569 0,16021 1,58052 5.797 64,41
            7 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
            8 BOAm billiards optimization algorithm M 0,95757 0,82599 0,25235 2,03590 1,00000 0,90036 0,30502 2,20538 0,73538 0,52523 0,09563 1,35625 5 598 62,19
            9 AAm archery algorithm M 0,91744 0,70876 0,42160 2,04780 0,92527 0,75802 0,35328 2,03657 0,67385 0,55200 0,23738 1,46323 5.548 61,64
            10 ESG evolution of social groups (joo) 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
            11 SIA simulated isotropic annealing (joo) 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
            12 EOm extremal_optimization_M 0,76166 0,77242 0,31747 1,85155 0,99999 0,76751 0,23527 2,00277 0,74769 0,53969 0,14249 1,42987 5 284 58,71
            13 BBO biogeography based optimization 0,94912 0,69456 0,35031 1,99399 0,93820 0,67365 0,25682 1,86867 0,74615 0,48277 0,17369 1,40261 5 265 58,50
            14 ACS artificial cooperative search 0,75547 0,74744 0,30407 1,80698 1,00000 0,88861 0,22413 2,11274 0,69077 0,48185 0,13322 1,30583 5.226 58,06
            15 DA dialectic algorithm 0,86183 0,70033 0,33724 1,89940 0,98163 0,72772 0,28718 1,99653 0,70308 0,45292 0,16367 1,31967 5.216 57,95
            16 BHAm black hole algorithm M 0,75236 0,76675 0,34583 1,86493 0,93593 0,80152 0,27177 2,00923 0,65077 0,51646 0,15472 1,32195 5.196 57,73
            17 ASO anarchy society optimization 0,84872 0,74646 0,31465 1,90983 0,96148 0,79150 0,23803 1,99101 0,57077 0,54062 0,16614 1,27752 5 178 57,54
            18 RFO royal flush optimization (joo) 0,83361 0,73742 0,34629 1,91733 0,89424 0,73824 0,24098 1,87346 0,63154 0,50292 0,16421 1,29867 5.089 56,55
            19 AOSm atomic orbital search M 0,80232 0,70449 0,31021 1,81702 0,85660 0,69451 0,21996 1,77107 0,74615 0,52862 0,14358 1,41835 5.006 55,63
            20 TSEA turtle shell evolution algorithm (joo) 0,96798 0,64480 0,29672 1,90949 0,99449 0,61981 0,22708 1,84139 0,69077 0,42646 0,13598 1,25322 5.004 55,60
            21 BSA backtracking search algorithm 0,97309 0,54534 0,29098 1,80941 0,99999 0,58543 0,21747 1,80289 0,84769 0,36953 0,12978 1,34700 4.959 55,10
            22 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
            23 SRA successful restaurateur algorithm (joo) 0,96883 0,63455 0,29217 1,89555 0,94637 0,55506 0,19124 1,69267 0,74923 0,44031 0,12526 1,31480 4.903 54,48
            24 CRO chemical reaction optimisation 0,94629 0,66112 0,29853 1,90593 0,87906 0,58422 0,21146 1,67473 0,75846 0,42646 0,12686 1,31178 4.892 54,36
            25 BIO blood inheritance optimization (joo) 0,81568 0,65336 0,30877 1,77781 0,89937 0,65319 0,21760 1,77016 0,67846 0,47631 0,13902 1,29378 4.842 53,80
            26 BSA bird swarm algorithm 0,89306 0,64900 0,26250 1,80455 0,92420 0,71121 0,24939 1,88479 0,69385 0,32615 0,10012 1,12012 4.809 53,44
            27 DEA dolphin_echolocation_algorithm 0,75995 0,67572 0,34171 1,77738 0,89582 0,64223 0,23941 1,77746 0,61538 0,44031 0,15115 1,20684 4 762 52,91
            28 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
            29 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
            30 BCOm bacterial chemotaxis optimization M 0,75953 0,62268 0,31483 1,69704 0,89378 0,61339 0,22542 1,73259 0,65385 0,42092 0,14435 1,21912 4.649 51,65
            31 ABO african buffalo optimization 0,83337 0,62247 0,29964 1,75548 0,92170 0,58618 0,19723 1,70511 0,61000 0,43154 0,13225 1,17378 4.634 51,49
            32 (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
            33 FBA fractal-based algorithm 0,79000 0,65134 0,28965 1,73099 0,87158 0,56823 0,18877 1,62858 0,61077 0,46062 0,12398 1,19537 4 555 50,61
            34 TSm tabu search M 0,87795 0,61431 0,29104 1,78330 0,92885 0,51844 0,19054 1,63783 0,61077 0,38215 0,12157 1,11449 4.536 50,40
            35 BSO brain storm optimization 0,93736 0,57616 0,29688 1,81041 0,93131 0,55866 0,23537 1,72534 0,55231 0,29077 0,11914 0,96222 4.498 49,98
            36 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
            37 AEFA artificial electric field algorithm 0,87700 0,61753 0,25235 1,74688 0,92729 0,72698 0,18064 1,83490 0,66615 0,11631 0,09508 0,87754 4.459 49,55
            38 AEO artificial ecosystem-based optimization algorithm 0,91380 0,46713 0,26470 1,64563 0,90223 0,43705 0,21400 1,55327 0,66154 0,30800 0,28563 1,25517 4.454 49,49
            39 CAm camel algorithm M 0,78684 0,56042 0,35133 1,69859 0,82772 0,56041 0,24336 1,63149 0,64846 0,33092 0,13418 1,11356 4.444 49,37
            40 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
            41 CMAES covariance_matrix_adaptation_evolution_strategy 0,76258 0,72089 0,00000 1,48347 0,82056 0,79616 0,00000 1,61672 0,75846 0,49077 0,00000 1,24923 4.349 48,33
            42 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
            43 SOA simple optimization algorithm 0,91520 0,46976 0,27089 1,65585 0,89675 0,37401 0,16984 1,44060 0,69538 0,28031 0,10852 1,08422 4 181 46,45
            44 ABHA artificial bee hive algorithm 0,84131 0,54227 0,26304 1,64663 0,87858 0,47779 0,17181 1,52818 0,50923 0,33877 0,10397 0,95197 4.127 45,85
            45 ACMO atmosphere clouds model optimization 0,90321 0,48546 0,30403 1,69270 0,80268 0,37857 0,19178 1,37303 0,62308 0,24400 0,10795 0,97503 4.041 44,90

            CoSO community_of_scientist_optimization 0,80471 0,54293 0,30917 1,65681 0,73834 0,38224 0,20600 1,32658 0,55384 0,25507 0,11129 0,92020 3.904 43,37

            RW random walk 0,48754 0,32159 0,25781 1,06694 0,37554 0,21944 0,15877 0,75375 0,27969 0,14917 0,09847 0,52734 2.348 26,09


            Conclusiones

            El algoritmo CoSO obtiene resultados medios en las funciones de prueba, alcanzando el 43 % del rendimiento máximo posible. Por supuesto, esperaba unos resultados más impresionantes. El banco de pruebas ofrece un conjunto ampliado de funciones, incluidas funciones estándar y ampliamente conocidas, con el que cualquier interesado puede seguir experimentando tanto con la selección de parámetros como con la elección de funciones para aprovechar mejor las posibilidades del algoritmo.

            El principal inconveniente de la implementación actual es su elevada complejidad computacional. La arquitectura multicapa con revistas científicas, la asignación dinámica de fondos y la gestión adaptativa de la población generan una carga considerable. Este algoritmo es notablemente más lento que otros métodos poblacionales, lo que limita su aplicabilidad en problemas que requieren soluciones rápidas.

            Sin embargo, el marco conceptual de CoSO reviste un gran interés. El modelado de la comunidad científica aporta mecanismos únicos que se han aplicado: la población dinámica adapta automáticamente los recursos computacionales a la complejidad del problema, el sistema de revistas garantiza un intercambio eficaz de información sin perder las mejores soluciones, la financiación competitiva genera una selección natural sin reglas rígidas, y el mecanismo de contratación intenta resolver el dilema entre la búsqueda local y la global.

            El potencial de mejora es evidente. CoSO no debe considerarse una solución definitiva, sino una plataforma de investigación con gran potencial. El algoritmo abre una nueva vía en la optimización evolutiva, en la que los mecanismos sociales de las comunidades humanas se convierten en fuente de estrategias computacionales. Con el perfeccionamiento adecuado, CoSO podría encontrar su nicho en problemas en los que sean importantes la adaptabilidad y la robustez frente a los cambios, y el tiempo de cálculo no sea un factor crítico.

            tab

            Figura 1. Gradación por colores de los algoritmos según las pruebas correspondientes

            gráfico

            Figura 2. Histograma de los resultados de las pruebas de los algoritmos (en una escala de 0 a 100; cuanto mayor sea el valor, mejor, donde 100 es el resultado teórico máximo posible; en el archivo comprimido se incluye el script para calcular la tabla de clasificación)

            Ventajas y desventajas del algoritmo CoSO:

            Ventajas:

            1. una buena base para desarrollar derivaciones de nuevas variantes.

            Desventajas:

            1. una gran cantidad de parámetros externos;
            2. propensión a estancarse en los problemas;
            3. lento.

            Se adjunta al artículo un archivo comprimido con las versiones actualizadas de los códigos de los algoritmos. El autor del artículo no se hace responsable de la exactitud absoluta en la descripción de los algoritmos canónicos, ya que en muchos de ellos se han introducido modificaciones para mejorar las capacidades de búsqueda. Las conclusiones y consideraciones que figuran en los artículos se basan en los resultados de los experimentos realizados.


            Programas utilizados en el artículo

            # Nombre Tipo Descripción
            1 #C_AO.mqh
            Archivo de inclusión
            Clase padre de los algoritmos de optimización poblacional
            2 #C_AO_enum.mqh
            Archivo de inclusión
            Enumeración de algoritmos de optimización poblacional
            3 TestFunctions.mqh
            Archivo de inclusión
            Biblioteca de funciones de prueba
            4
            TestStandFunctions.mqh
            Archivo de inclusión
            Biblioteca de funciones del banco de pruebas
            5
            Utilities.mqh
            Archivo de inclusión
            Biblioteca de funciones auxiliares
            6
            CalculationTestResults.mqh
            Archivo de inclusión
            Script para calcular los resultados destinados a la tabla comparativa
            7
            Testing AOs.mq5
            Script Banco de pruebas unificado para todos los algoritmos de optimización poblacional
            8
            Simple use of population optimization algorithms.mq5
            Script
            Ejemplo sencillo de uso de algoritmos de optimización poblacional sin visualización
            9
            Test_AO_CoSO.mq5
            Script Banco de pruebas para CoSO

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

            Archivos adjuntos |
            CoSO.ZIP (325.17 KB)
            Utilizando redes neuronales en MetaTrader Utilizando redes neuronales en MetaTrader
            En el artículo se muestra la aplicación de las redes neuronales en los programas de MQL, usando la biblioteca de libre difusión FANN. Usando como ejemplo una estrategia que utiliza el indicador MACD se ha construido un experto que usa el filtrado con red neuronal de las operaciones. Dicho filtrado ha mejorado las características del sistema comercial.
            Redes neuronales en el trading: Desentrañando los componentes estructurados (SCNN) Redes neuronales en el trading: Desentrañando los componentes estructurados (SCNN)
            Le invitamos a conocer el innovador framework SCNN, que lleva el análisis de series temporales a un nuevo nivel gracias a una separación clara de los datos en componentes de largo plazo, estacionales, de corto plazo y residuales. Este enfoque mejora considerablemente la precisión de la predicción y permite que el modelo se adapte a la compleja y cambiante dinámica del mercado.
            Particularidades del trabajo con números del tipo double en MQL4 Particularidades del trabajo con números del tipo double en MQL4
            En estos apuntes hemos reunido consejos para resolver los errores más frecuentes al trabajar con números del tipo double en los programas en MQL4.
            Automatización de estrategias de trading en MQL5 (Parte 22): Desarrollo de un sistema de recuperación por zonas para trading de tendencia con Envelopes Automatización de estrategias de trading en MQL5 (Parte 22): Desarrollo de un sistema de recuperación por zonas para trading de tendencia con Envelopes
            En este artículo, desarrollamos un sistema de recuperación por zonas integrado con una estrategia de trading de tendencias basada en envolventes en MQL5. Describimos la arquitectura para utilizar los indicadores RSI y Envelopes para activar operaciones y gestionar zonas de recuperación con el fin de mitigar las pérdidas. Mediante la implementación y las pruebas retrospectivas, mostramos cómo construir un sistema de negociación automatizado eficaz para mercados dinámicos.