English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
preview
Algoritmos de otimização populacionais: Algoritmo de otimização de cuco (COA)

Algoritmos de otimização populacionais: Algoritmo de otimização de cuco (COA)

MetaTrader 5Exemplos | 20 fevereiro 2023, 08:54
546 0
Andrey Dik
Andrey Dik

Conteúdo

1. Introdução
2. Descrição do algoritmo, árvore de decisão e voo de Levy
3. Revisão do código COA
4. Resultado dos testes


1. Introdução

O cuco é uma ave fascinante, não apenas pelo seu canto melífluo, mas também pela sua estratégia agressiva de reprodução. O cuco põe seus ovos em ninhos de outras aves, deixando a responsabilidade de criação de sua descendência para os pais adotivos. Cada espécie de cuco tem uma postura de ovos específica em termos de tamanho e cor para melhor corresponder aos ovos dos pais adotivos. Os filhotes de cuco, quando colocados em ninhos de outras espécies, geralmente são maiores e mais fortes do que os filhotes dos donos do ninho, exigindo, portanto, mais comida. Durante o desenvolvimento, os filhotes de cuco de Hodgson desenvolvem um padrão especial em suas asas em forma de bico aberto, o que lhes permite receber mais comida dos pais adotivos, devido a essa ilusão. No entanto, o parasitismo de ninhada não é exclusivo do cuco, sendo encontrado em pelo menos 80 espécies de aves. Além disso, esse fenômeno também é comum em algumas espécies de insetos sociais, como zangões, abelhas e formigas, cujas fêmeas penetram em colônias estrangeiras, matam a rainha e põem seus ovos. O parasitismo de ninhada também é encontrado em peixes, como o bagre do lago africano Tanganyika, que coloca seus ovos em outros peixes que estão incubando ovos em suas bocas.


O algoritmo de busca de cuco é um dos algoritmos heurísticos mais recentes, inspirados na natureza, desenvolvido por Yang e Deb em 2009. Esse algoritmo é baseado no parasitismo encontrado em algumas espécies de cucos. Desde então, o algoritmo foi aprimorado com o uso de "voos de Levy" em vez de métodos simples de caminhada aleatória isotrópica.Esses voos de Levy permitem que o algoritmo explore mais efetivamente o espaço de busca em questão, fornecendo uma maneira mais eficiente e precisa de encontrar soluções ótimas.


2. Descrição do algoritmo

O algoritmo de otimização de cuco (Cuckoo Optimization Algorithm, COA) é um método utilizado para otimização não linear contínua. Ele é inspirado no estilo de vida dos cuculídeos, suas características de oviposição e reprodução, que fundamentam o desenvolvimento do algoritmo de otimização. Como outras abordagens evolutivas, o COA começa com uma população inicial de indivíduos que competem pela sobrevivência. Ao longo do tempo, os cucos menos aptos são eliminados, e os sobreviventes se deslocam para locais mais favoráveis e começam a reproduzir e a pôr ovos. Eventualmente, os cucos sobreviventes convergem para formar uma sociedade com valores de adaptação semelhantes.
Uma das principais vantagens do COA é a sua simplicidade. O algoritmo requer apenas quatro parâmetros compreensíveis, o que torna o ajuste do método fácil e intuitivo.

O algoritmo de busca de cuco é baseado na estratégia reprodutiva dos cucos, onde os ovos colocados em ninhos alheios são interpretados como possíveis soluções para o problema de otimização. Cada ovo do cuco representa uma nova solução em potencial que pode ser utilizada para substituir a solução atual no ninho. O objetivo do algoritmo é usar essas novas soluções de ovos de cuco parasitas, que podem ser potencialmente melhores, para substituir a solução de ninho de ovos atual. Esse processo de substituição é realizado de forma iterativa, permitindo que as novas soluções sejam avaliadas e refinadas ao longo do tempo, levando eventualmente à solução ótima do problema de otimização.

Os professores Yang e Deb propuseram que o algoritmo teria os seguintes três conjuntos de estados ideais:
1. Cada cuco põe um ovo e o coloca em um ninho selecionado aleatoriamente.
2. Os melhores ninhos com ovos de alta qualidade serão passados para as próximas gerações.
3. O número de ninhos disponíveis é fixo e o ninho pode detectar um ovo forasteiro com probabilidade pa. Nesse caso, a ave hospedeira pode jogar fora o ovo ou deixar o ninho e o ovo morrerá.

Para simplificar, a terceira proposição pode ser aproximada pela fração pa de n ninhos. Para um problema de maximização, a qualidade ou ajuste da solução pode ser simplesmente proporcional à função objetivo. Entretanto, outras expressões (mais complexas) para a função de adaptação podem ser definidas.

Em cada iteração g do algoritmo, um ovo de cuco i é escolhido aleatoriamente e utilizado para gerar novas soluções xi (g + 1) através de um voo de Levy. Esse processo envolve a realização de um passeio aleatório com passos determinados dentro de limites de comprimentos de passo que seguem uma distribuição de probabilidade específica, enquanto as direções dos passos são aleatórias e isotrópicas. A estratégia de usar voos de Levy é considerada superior a outros tipos de passeios aleatórios por seus melhores resultados. A equação geral de voo de Levy é expressa como

xi(g + 1) = xi(g) + α ⊕ levy(λ),

onde g representa a geração atual e α > 0 determina o tamanho do passo, relacionado com a escala do problema em questão. O símbolo ⊕ é usado para indicar multiplicação elementar. Essa equação segue uma cadeia de Markov, já que a próxima localização na geração g + 1 depende apenas da localização atual na geração g e da probabilidade de transição dada pelos primeiros e segundos termos. A probabilidade de transição é regulada pela distribuição de Levy, que é modulada assim: 

levy(λ) ∼ g−λ, (1 < λ ≤ 3),

que tem média e variância infinitas, e a prática tem mostrado que um grau fixo de 2,0 produz os melhores resultados. Aqui a distribuição de Levy, que apresenta uma cauda pesada de lei de potência, leva a um processo de passeio aleatório nas etapas do algoritmo. O modelo consiste em escolher uma direção aleatória de acordo com uma distribuição uniforme e gerar etapas com a distribuição de Levy. A nova solução é avaliada e comparada com a atual, substituindo-a se for mais adequada. Algumas soluções são abandonadas para aumentar a exploração do espaço de busca. A taxa de substituição é determinada pelo parâmetro pa, que deve ser ajustado para otimizar o desempenho. O algoritmo é executado iterativamente até que um critério de parada seja atingido, como encontrar uma solução satisfatória, alcançar um número fixo de gerações ou não obter mais resultados melhores em iterações sucessivas.

Vamos aprofundar no processo de postura dos ovos do cuco. Um ninho é selecionado aleatoriamente para que o ovo do cuco seja depositado. Como a qualidade do ovo é uma representação da solução, se o ovo do cuco for de qualidade superior ao ovo pai, o ovo pai será substituído. Caso contrário, o ovo pai permanecerá no ninho, e a evolução continuará a partir do filhote que sobreviveu. Isso significa que, se o filhote do ovo pai sobreviver, a evolução continuará do mesmo lugar. No entanto, se o ovo do cuco for mais viável, a busca pela solução do problema prosseguirá em um novo local. A Figura 1 esquematiza a árvore de decisão do processo.


decision tree

Figura 1. Árvore de decisão. O ponto vermelho é o começo, o ponto verde é a decisão final.


O segundo componente do algoritmo é o voo de Levy, que é um passeio aleatório (um processo estatístico de Markov) no qual o comprimento dos saltos muda em etapas, a direção muda aleatoriamente e a distribuição de probabilidade é um caso especial da distribuição de Pareto, caracterizada por caudas pesadas. Esse voo é definido como um salto no espaço e ocorre isotropicamente em direções aleatórias. O voo de Levy é uma ferramenta para descrever processos estocásticos anômalos em que a dispersão é infinita (saltos de grande comprimento são possíveis), os comprimentos dos saltos são auto-similares em todos os níveis (saltos curtos são intercalados com voos longos). Às vezes, o termo voo de Levy é estendido para incluir um passeio aleatório que ocorre em uma grade discreta em vez de em um espaço contínuo.

O voo de Levy é uma ferramenta poderosa no algoritmo de cuco, especialmente em problemas de otimização com um parâmetro. Para ilustrar isso, consideremos uma função hipotética (a linha preta na Figura 2) que é predominantemente horizontal (y=x) em seu domínio de definição, mas tem um único pico em uma pequena área. Se iniciarmos a busca pelo máximo a partir do ponto laranja na Figura 2 e gerarmos um valor aleatório x com a distribuição de Levy, nos afastaremos do ponto inicial, mantendo a função inalterada. No entanto, com um forte salto na cauda da distribuição, podemos obter um ponto verde que representa uma solução melhor do que o ponto laranja original. A partir desse ponto verde, podemos melhorar ainda mais o resultado e nos aproximar do máximo da função. Este exemplo mostra claramente como o voo de Levy pode aumentar drasticamente a capacidade de busca do algoritmo.

levy flight

Figura 2. Exemplo de busca de solução para uma função unidimensional hipotética usando o voo de Levy.

O conceito de voo de Lévy é amplamente utilizado na teoria do caos para modelar fenômenos naturais aleatórios ou pseudoaleatórios, como o voo de um albatroz, que combina trajetórias longas e curtas. Esse conceito tem sido aplicado em diversas áreas, incluindo a análise de dados de terremotos, matemática financeira, criptografia, análise de sinais, movimento turbulento e em muitas aplicações em astronomia, biologia e física.

Pseudocódigo do algoritmo COA (Figura 3):

1. Inicialização de cucos com valores aleatórios.
2. Definição de adaptação.
3. Postura de ovos em ninhos aleatórios.
4. Esvaziamento do ninho com uma determinada probabilidade.
5. Envio de cucos da posição atual para uma direção aleatória dentro da distância de voo de Levi.
6. Definição de adaptação.
7. Postura de ovos em ninhos aleatórios.
8. Esvaziamento do ninho com uma determinada probabilidade.
9. Repetição do passo 5 até que o critério de parada seja atingido.

scheme

Figura 3. Diagrama de blocos do algoritmo COA. 


3. Revisão de código

Comecemos com o código do algoritmo. A solução do problema é representada pelo cuco, que é também o ovo. Essa representação é composta pelas coordenadas no espaço de busca e pelo valor da função de adaptação, que indica a qualidade do ovo.

//——————————————————————————————————————————————————————————————————————————————
struct S_Cuckoo
{
  double c []; //coordinates (egg parameters)
  double e;    //egg quality 
};
//——————————————————————————————————————————————————————————————————————————————

Podemos descrever o ninho como uma estrutura que contém coordenadas no espaço e o valor de função de adaptação, semelhante à estrutura de um ovo. "Colocar o ovo no ninho" consiste em copiar a estrutura do ovo na estrutura do ninho. Além disso, ao usar o parâmetro probabilístico pa, o ovo pode ser ejetado do ninho se um número aleatório entre 0,0 e pa cair no intervalo [0,0;1,0]. Nesse caso, o valor de e é definido como -DBL_MAX, indicando que o ninho está vazio.

//——————————————————————————————————————————————————————————————————————————————
struct S_Nest
{
  void Init (int coordinates)
  {
    ArrayResize (c, coordinates);
    e = -DBL_MAX;
  }
  double c []; //coordinates (egg parameters)
  double e;    //egg quality
};
//——————————————————————————————————————————————————————————————————————————————

Na classe do algoritmo são declarados os métodos de inicialização públicos e os dois principais métodos de chamada no programa do usuário, os intervalos de valores dos argumentos do problema de otimização e métodos privados adicionais que executam funções de serviço.

//——————————————————————————————————————————————————————————————————————————————
class C_AO_COA
{
  //============================================================================
  public: double rangeMax  []; //maximum search range
  public: double rangeMin  []; //manimum search range
  public: double rangeStep []; //step search
  public: S_Cuckoo cuckoos []; //all the cuckoos
  public: double cB        []; //best coordinates (egg parameters)
  public: double eB;           //best eggs quality

  public: void Init (const int    coordinatesP, //number of opt. parameters
                     const int    cuckoosP,     //number of cuckoos
                     const int    nestsP,       //number of cuckoo nests
                     const double koef_paP,     //probability of detection of cuckoo eggs
                     const double koef_alphaP); //step control value

  public: void CuckooFlight ();
  public: void LayEggs      ();


  //============================================================================
  private: double SeInDiSp       (double In, double InMin, double InMax, double Step);
  private: double RNDfromCI      (double Min, double Max);
  private: double Scale          (double In, double InMIN, double InMAX, double OutMIN, double OutMAX,  bool Revers);

  private: S_Nest nests [];      //nests
  private: int    cuckoosNumber; //number of cuckoos
  private: int    nestsNumber;   //number of cuckoo nests
  private: double koef_pa;       //probability of detection of cuckoo eggs
  private: double koef_alpha;    //step control value
  private: double v     [];
  private: int    coordinates;   //coordinates number
  private: bool   clutchEggs;    //clutch of eggs
};
//——————————————————————————————————————————————————————————————————————————————

Método público Init(). Aqui, os valores das variáveis são zerados e a memória dos arrays é alocada.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_COA::Init (const int    coordinatesP,  //number of opt. parameters
                     const int    cuckoosP,     //number of cuckoos
                     const int    nestsP,       //number of cuckoo nests
                     const double koef_paP,     //probability of detection of cuckoo eggs
                     const double koef_alphaP)  //step control value
{
  MathSrand (GetTickCount ());
  clutchEggs = false;
  eB         = -DBL_MAX;

  coordinates   = coordinatesP;
  cuckoosNumber = cuckoosP;
  nestsNumber   = nestsP;
  koef_pa       = koef_paP;
  koef_alpha    = koef_alphaP;

  ArrayResize (nests, nestsNumber);
  for (int i = 0; i < nestsNumber; i++)
  {
    nests  [i].Init (coordinates);
  }

  ArrayResize (rangeMax,  coordinates);
  ArrayResize (rangeMin,  coordinates);
  ArrayResize (rangeStep, coordinates);
  ArrayResize (cB,        coordinates);

  ArrayResize (v, coordinates);

  ArrayResize (cuckoos, cuckoosNumber);
  for (int i = 0; i < cuckoosNumber; i++)
  {
    ArrayResize (cuckoos [i].c, coordinates);
  }
}
//——————————————————————————————————————————————————————————————————————————————

Durante cada iteração do algoritmo de busca cuco, o primeiro método público chamado é o "voo do cuco". Se a variável clutchEggs estiver desativada, os cucos são enviados aleatoriamente em uma direção, gerando números aleatórios dentro do intervalo correspondente a cada coordenada. Caso a variável esteja ativada, o voo do cuco ocorre de acordo com a distribuição de Levy, dentro do alcance do vetor v. Esse vetor é pré-calculado na função Init() para cada coordenada, visto que elas podem ter diferentes faixas de valores.

A expressão "cucos[i].c[c] = cucos[i].c[c] + r1 * v[c] * pow(r2, -2.0)" representa a adição do deslocamento "r1 * v[c] * pow(r2, -2.0)" à coordenada atual do cuco na dimensão "c". O valor de "r1" é -1 ou 1, o que determina a direção do deslocamento em relação à posição original. O vetor de deslocamento é representado por "v", enquanto o valor de "r2" é um número aleatório no intervalo de 0,0 a 20,0 elevado à potência de -2,0. Essa função de voo de Levy é usada para gerar movimentos aleatórios dos cucos, e seu gráfico pode ser visualizado na Figura 2.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_COA::CuckooFlight ()
{
  //----------------------------------------------------------------------------
  if (!clutchEggs)
  {
    for (int i = 0; i < coordinates; i++) v [i] = (rangeMax [i] - rangeMin [i]) * koef_alpha;

    for (int i = 0; i < cuckoosNumber; i++)
    {
      for (int c = 0; c < coordinates; c++)
      {
        cuckoos [i].c [c] = RNDfromCI (rangeMin [c], rangeMax [c]);
        cuckoos [i].c [c] = SeInDiSp (cuckoos [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }

    clutchEggs = true;
  }
  else
  {
    double r1 = 0.0;
    double r2 = 0.0;

    for (int i = 0; i < cuckoosNumber; i++)
    {
      for (int c = 0; c < coordinates; c++)
      {
        r1 = RNDfromCI (0.0, 1.0);
        r1 = r1 > 0.5 ? 1.0 : -1.0;
        r2 = RNDfromCI (1.0, 20.0);

        cuckoos [i].c [c] = cuckoos [i].c [c] + r1 * v [c] * pow (r2, -2.0);
        cuckoos [i].c [c] = SeInDiSp (cuckoos [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

Durante cada iteração, o segundo método público é chamado "colocar ovos". Nessa etapa, é reproduzida algoritmicamente a simulação de um ovo de cuco sendo colocado em um ninho. O processo se inicia com a escolha aleatória de um ninho dentre todos os existentes, seguida da comparação da qualidade do ovo de cuco com aquele que já está no ninho. Se o ovo de cuco for mais apto, ele substitui o ovo anterior. É interessante notar que o algoritmo também considera a possibilidade do ovo morrer após a postura, mesmo sendo o mais apto, assim como na natureza. Existe uma chance, representada por koef_pade, de qualquer ovo morrer ou ser jogado fora do ninho. Se isso ocorrer, o ninho fica disponível para uma nova postura, mesmo que seja um ovo de aptidão ainda menor, o que, algoritmicamente, significa uma pesquisa em um novo local.

Assim, em poucas linhas de código, pode-se implementar um dos métodos da evolução natural, o parasitismo de ninhos. Embora muitos autores recomendem inicializar o ninho com novos valores aleatórios após retirar o ovo, esta abordagem pode não resultar em um aumento significativo na capacidade exploratória do algoritmo. Com base em minha própria pesquisa, é mais vantajoso deixar o ninho vazio e permitir que um dos cucos o use para depositar um ovo, independentemente da qualidade do mesmo. Isso é mais eficiente do que simplesmente atribuir valores aleatórios, e a variabilidade no estudo é fornecida pelos saltos aleatórios em direções aleatórias das coordenadas atuais. Dessa forma, o número de iterações necessárias para encontrar a melhor solução é reduzido, aumentando assim a taxa de convergência do algoritmo como um todo.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_COA::LayEggs ()
{
  int ind = 0;

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  for (int i = 0; i < cuckoosNumber; i++)
  {
    ind = (int)round (RNDfromCI (0.0, nestsNumber - 1));

    if (cuckoos [i].e > nests [ind].e)
    {
      nests [ind].e = cuckoos [i].e;
      ArrayCopy (nests [ind].c, cuckoos [i].c, 0, 0, WHOLE_ARRAY);

      if (cuckoos [i].e > eB)
      {
        eB = cuckoos [i].e;
        ArrayCopy (cB, cuckoos [i].c, 0, 0, WHOLE_ARRAY);
      }
    }
    else
    {
      ArrayCopy (cuckoos [i].c, nests [ind].c, 0, 0, WHOLE_ARRAY);
    }
  }
  //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  for (int n = 0; n < nestsNumber; n++)
  {
    if (RNDfromCI (0.0, 1.0) < koef_pa)
    {
      nests [ind].e = -DBL_MAX;
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————


4. Resultado dos testes

Impressão dos resultados do teste:

2022.11.30 11:31:54.490    Test_AO_COA_fast (EURUSD,M1)    =============================
2022.11.30 11:31:54.507    Test_AO_COA_fast (EURUSD,M1)    1 Skin's; Func runs 10000 result: 4.918379100238852
2022.11.30 11:31:54.507    Test_AO_COA_fast (EURUSD,M1)    Score: 1.00000
2022.11.30 11:31:54.854    Test_AO_COA_fast (EURUSD,M1)    20 Skin's; Func runs 10000 result: 4.257477577760983
2022.11.30 11:31:54.854    Test_AO_COA_fast (EURUSD,M1)    Score: 0.84220
2022.11.30 11:32:02.346    Test_AO_COA_fast (EURUSD,M1)    500 Skin's; Func runs 10000 result: 1.3521208312080903
2022.11.30 11:32:02.346    Test_AO_COA_fast (EURUSD,M1)    Score: 0.14849
2022.11.30 11:32:02.346    Test_AO_COA_fast (EURUSD,M1)    =============================
2022.11.30 11:32:02.368    Test_AO_COA_fast (EURUSD,M1)    1 Forest's; Func runs 10000 result: 1.7600394018343262
2022.11.30 11:32:02.368    Test_AO_COA_fast (EURUSD,M1)    Score: 0.99557
2022.11.30 11:32:02.775    Test_AO_COA_fast (EURUSD,M1)    20 Forest's; Func runs 10000 result: 0.4968964923017033
2022.11.30 11:32:02.775    Test_AO_COA_fast (EURUSD,M1)    Score: 0.28107
2022.11.30 11:32:13.125    Test_AO_COA_fast (EURUSD,M1)    500 Forest's; Func runs 10000 result: 0.07638950254648778
2022.11.30 11:32:13.125    Test_AO_COA_fast (EURUSD,M1)    Score: 0.04321
2022.11.30 11:32:13.125    Test_AO_COA_fast (EURUSD,M1)    =============================
2022.11.30 11:32:13.148    Test_AO_COA_fast (EURUSD,M1)    1 Megacity's; Func runs 10000 result: 12.0
2022.11.30 11:32:13.148    Test_AO_COA_fast (EURUSD,M1)    Score: 1.00000
2022.11.30 11:32:13.584    Test_AO_COA_fast (EURUSD,M1)    20 Megacity's; Func runs 10000 result: 2.69
2022.11.30 11:32:13.584    Test_AO_COA_fast (EURUSD,M1)    Score: 0.22417
2022.11.30 11:32:24.379    Test_AO_COA_fast (EURUSD,M1)    500 Megacity's; Func runs 10000 result: 0.40800000000000003
2022.11.30 11:32:24.379    Test_AO_COA_fast (EURUSD,M1)    Score: 0.03400
2022.11.30 11:32:24.379    Test_AO_COA_fast (EURUSD,M1)    =============================
2022.11.30 11:32:24.379    Test_AO_COA_fast (EURUSD,M1)    All score for C_AO_COA: 0.507633670637353

O algoritmo de busca de cuco usando o voo de Levy apresentou um desempenho impressionante, superando a maioria dos outros algoritmos de otimização em vários testes. Por exemplo, o algoritmo alcançou 100% de convergência na função suave Skin com duas variáveis e na função discreta Megacity com duas variáveis. Além disso, demonstrou excelente escalabilidade na função discreta e, em outros testes, foi apenas ligeiramente inferior ao algoritmo da formiga. Neste momento, entre todos os algoritmos de otimização considerados, o algoritmo de busca de cuco usando o voo de Levy se destaca como o líder na tabela de classificação.

Gostaria de esclarecer que todos os algoritmos possuem parâmetros de ajuste que afetam os resultados finais em maior ou menor grau, o que significa que é possível que existam parâmetros ótimos adicionais para alguns desses algoritmos, alterando a tabela de classificação. Apresentei apenas os resultados dos testes com os parâmetros que foram encontrados para fornecer os melhores resultados. Se algum dos leitores descobrir parâmetros ótimos adicionais que resultem em melhores resultados, posso atualizar a tabela de classificação com base nessas descobertas. Acredita-se que o algoritmo da formiga possa competir com o líder atual com sucesso, pois supera o algoritmo de busca de cuco em algumas medidas e fica minimamente atrás em outros resultados. Além disso, na função Skin com 1000 variáveis, o GWO ainda se mostra o mais forte. Em qualquer caso, qualquer pessoa que pretenda utilizar esses algoritmos em seus projetos para resolver problemas de otimização pode navegar na tabela e selecionar o algoritmo mais adequado para suas necessidades específicas.


Skin

COA na função de teste Pele.

Forest

  COA na função de teste Forest.

Megacity

  ACO na função de teste Megacity.

Na visualização da bancada de testes, o comportamento do algoritmo difere dos modelos anteriores, mas há algumas características em comum com algoritmos que dividem tarefas em áreas de estudo, como o algoritmo de colônia de abelhas. Isso demonstra que o algoritmo não se concentra apenas em um extremo, mas explora várias áreas promissoras, o que lhe confere resistência a ficar preso em extremos locais. Para melhorar o algoritmo, foi proposta a ideia de ordenar os ninhos e escolher o ninho pelo cuco proporcionalmente à sua qualidade, em vez de selecionar aleatoriamente. No entanto, os resultados não melhoraram e praticamente mostraram a insignificância da escolha aleatória dos ninhos. Isso pode ser semelhante ao que acontece na natureza, pois substituir um ovo em hospedeiros mais inteligentes é mais difícil do que em hospedeiros selecionados aleatoriamente.

O algoritmo também possui uma característica de se comportar como um passeio aleatório em funções com muitas variáveis. Visualmente, ele se assemelha a um ruído branco ou a uma tela de TV antiga, sendo perceptível alguma concentração de coordenadas nos extremos locais apenas no final das iterações. No entanto, gostaria de obter uma "cristalização" mais clara dos parâmetros, como no algoritmo de colônia de formigas. Esse é um problema geral enfrentado por todos os algoritmos de otimização, que não possuem uma solução universal. Vários autores de algoritmos clássicos e relativamente novos têm tentado resolvê-lo.

O problema central é que não se sabe qual dos parâmetros otimizados da função em estudo possui prioridade ou força, nem até que ponto e como cada um desses parâmetros afeta o resultado. Por exemplo, mesmo que o algoritmo já tenha encontrado o conjunto correto de parâmetros, é difícil identificar qual deles é o responsável pelo resultado ideal. Como resultado, o algoritmo continua a tentar ajustar todos os parâmetros, embora apenas alguns precisem ser modificados para atingir o extremo global. Esse problema se torna ainda mais complexo em funções com muitas variáveis, tornando o problema mais acentuado. Visualmente, o problema se assemelha a um ruído branco na tela. 

Fiz uma tentativa de solucionar esse problema, pelo menos parcialmente, embora não seja uma solução fundamental. Quando não se sabe a priori qual parâmetro deve ser modificado e qual deve permanecer inalterado, é possível abordar isso de forma probabilística. Ou seja, supõe-se que apenas uma parte dos parâmetros precisa ser alterada, e não todos de uma só vez. O algoritmo PSO se comporta de forma característica, formando uma nuvem que não se concentra quando há um grande número de parâmetros (argumentos) na função otimizada. Para lidar com isso, introduzi um novo parâmetro no algoritmo que define a probabilidade de alteração de cada coordenada. Caso contrário, a coordenada permanecerá inalterada.

No final... funcionou!!! Os resultados dos testes melhoraram. Funções com muitas variáveis mostraram a «cristalização» que queríamos alcançar.

Impressão da bancada de teste:

2022.12.03 16:01:26.256    Test_AO_COAm (EURUSD,M1)    =============================
2022.12.03 16:01:27.511    Test_AO_COAm (EURUSD,M1)    1 Skin's; Func runs 10000 result: 4.918367945334852
2022.12.03 16:01:27.511    Test_AO_COAm (EURUSD,M1)    Score: 1.00000
2022.12.03 16:01:30.291    Test_AO_COAm (EURUSD,M1)    20 Skin's; Func runs 10000 result: 4.328327964103814
2022.12.03 16:01:30.291    Test_AO_COAm (EURUSD,M1)    Score: 0.85911
2022.12.03 16:01:59.306    Test_AO_COAm (EURUSD,M1)    500 Skin's; Func runs 10000 result: 1.3297901702583084
2022.12.03 16:01:59.306    Test_AO_COAm (EURUSD,M1)    Score: 0.14316
2022.12.03 16:01:59.306    Test_AO_COAm (EURUSD,M1)    =============================
2022.12.03 16:02:00.511    Test_AO_COAm (EURUSD,M1)    1 Forest's; Func runs 10000 result: 1.755200932219688
2022.12.03 16:02:00.511    Test_AO_COAm (EURUSD,M1)    Score: 0.99283
2022.12.03 16:02:03.566    Test_AO_COAm (EURUSD,M1)    20 Forest's; Func runs 10000 result: 0.5089243656052672
2022.12.03 16:02:03.566    Test_AO_COAm (EURUSD,M1)    Score: 0.28787
2022.12.03 16:02:35.468    Test_AO_COAm (EURUSD,M1)    500 Forest's; Func runs 10000 result: 0.08044934398920801
2022.12.03 16:02:35.468    Test_AO_COAm (EURUSD,M1)    Score: 0.04551
2022.12.03 16:02:35.468    Test_AO_COAm (EURUSD,M1)    =============================
2022.12.03 16:02:36.628    Test_AO_COAm (EURUSD,M1)    1 Megacity's; Func runs 10000 result: 12.0
2022.12.03 16:02:36.628    Test_AO_COAm (EURUSD,M1)    Score: 1.00000
2022.12.03 16:02:39.628    Test_AO_COAm (EURUSD,M1)    20 Megacity's; Func runs 10000 result: 2.9899999999999998
2022.12.03 16:02:39.628    Test_AO_COAm (EURUSD,M1)    Score: 0.24917
2022.12.03 16:03:11.892    Test_AO_COAm (EURUSD,M1)    500 Megacity's; Func runs 10000 result: 0.4244
2022.12.03 16:03:11.892    Test_AO_COAm (EURUSD,M1)    Score: 0.03537
2022.12.03 16:03:11.892    Test_AO_COAm (EURUSD,M1)    =============================
2022.12.03 16:03:11.892    Test_AO_COAm (EURUSD,M1)    All score for C_AO_COAm: 0.5125572342985216

A 'cristalização' é lindamente visível, a tela, que inicialmente parece ruído branco, clareia, as coordenadas começam a se concentrar, os centros de concentração se movem:

cristal

COAm na função de testeMegacity. O efeito de "cristalização" é mais pronunciado.

Por um lado, o algoritmo busca por novas áreas, garantindo a variabilidade na busca por soluções, enquanto por outro lado, aprimora as coordenadas dos extremos já alcançados, permitindo a exploração de áreas promissoras. Para fins de comparação, pode-se observar que o desempenho do algoritmo da colônia de formigas é semelhante a uma cristalização, ou seja, há um processo de refinamento gradual em torno de uma solução encontrada, em vez de uma busca mais exploratória por novas soluções.

cristACO

  ACOm na função de teste Forest.

4. Resultado dos testes

AO

Descrição

Skin

Forest

Megacity (discrete)

Final result

2 params (1 F)

40 params (20 F)

1000 params (500 F)

2 params (1 F)

40 params (20 F)

1000 params (500 F)

2 params (1 F)

40 params (20 F)

1000 params (500 F)

COAm

algoritmo de otimização de cuco

1,00000

0,85911

0,14316

0,99283

0,28787

0,04551

1,00000

0,24917

0,03537

0,51255778

ACOm

otimização de colônia de formigas

0,98229

0,79108

0,12602

1,00000

0,62077

0,11521

0,38333

0,44000

0,02377

0,49805222

ABCm

colônia artificial de abelhas M

1,00000

0,63922

0,08076

0,99908

0,20112

0,03785

1,00000

0,16333

0,02823

0,46106556

ABC

colônia artificial de abelhas

0,99339

0,73381

0,11118

0,99934

0,21437

0,04215

0,85000

0,16833

0,03130

0,46043000

GWO

otimizador lobo-cinzento

0,99900

0,48033

0,18924

0,83844

0,08755

0,02555

1,00000

0,10000

0,02187

0,41577556

PSO

otimização de enxame de partículas

0,99627

0,38080

0,05089

0,93772

0,14540

0,04856

1,00000

0,09333

0,02233

0,40836667

RND

aleatório

0,99932

0,44276

0,06827

0,83126

0,11524

0,03048

0,83333

0,09000

0,02403

0,38163222


O algoritmo de busca de cuco possui uma vantagem em relação a outros algoritmos de busca global, pois utiliza voos ou um processo de Levy em vez de caminhadas aleatórias convencionais. Como os voos de Levy possuem média e variância infinitas, o algoritmo COA consegue explorar o espaço de busca com maior eficiência do que os algoritmos de processo gaussiano padrão. O Levy flight é um processo de passeio aleatório caracterizado por uma série de saltos instantâneos selecionados a partir de uma função de densidade de probabilidade que possui uma cauda de lei de potência.

No momento, o algoritmo de busca do cuco está liderando a tabela, superando significativamente outros algoritmos em testes individuais e não ficando muito atrás em outras áreas. Ele alcançou excelentes resultados na função discreta Megacity, com 1000 argumentos, tornando-o uma ferramenta ideal para tarefas de otimização discreta, como aquelas encontradas na negociação. Além disso, obteve resultados excelentes, embora não os melhores, na função Skin, com 1000 argumentos, o que sugere que o algoritmo é apropriado para o treinamento de redes neurais, em particular, e para aprendizado de máquina, em geral.

Prós:
1. Rápido.
2. Versatilidade. Pode ser usado em uma grande variedade de tarefas de otimização.
3. É capaz de não focar apenas em extremos locais.
4. Alta convergência para funções suaves e discretas.
5. Escalabilidade.

Contras:
1. Muitos parâmetros.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/11786

Arquivos anexados |
MQL5 — Você também pode se tornar um mestre nesta linguagem MQL5 — Você também pode se tornar um mestre nesta linguagem
Neste artigo, será algo como uma entrevista comigo, de como comecei no MQL5. Irei lhe mostrar, como você pode se tornar um grande programador de MQL5. Mostrarei as bases necessárias para você conseguir alcançar tal feito. O único requisito é ter vontade de aprender.
Algoritmos de otimização populacionais: Otimizador lobo-cinzento (GWO) Algoritmos de otimização populacionais: Otimizador lobo-cinzento (GWO)
Vamos falar sobre um dos algoritmos de otimização mais recentes e modernos: o "Packs of grey wolves" (manada de lobos-cinzentos). Devido ao seu comportamento distinto em funções de teste, este algoritmo se torna um dos mais interessantes em comparação com outros considerados anteriormente. Ele é um dos principais candidatos para treinamento de redes neurais e para otimizar funções suaves com muitas variáveis.
Integrando modelos de ML ao Testador de estratégias  (Parte 3): Gerenciamento de Arquivos CSV(II) Integrando modelos de ML ao Testador de estratégias (Parte 3): Gerenciamento de Arquivos CSV(II)
Este artigo fornece uma visão detalhada sobre como construir uma classe em MQL5 para gerenciamento eficiente de arquivos CSV. Ele explica como os métodos de abertura, escrita, leitura e conversão de dados são implementados e como eles podem ser utilizados para armazenar e carregar dados. Além disso, o artigo também discute as limitações e considerações importantes ao usar essa classe. É uma leitura valiosa para aqueles interessados em aprender a trabalhar com arquivos CSV em MQL5.
Aprendendo a construindo um Expert Advisor que opera de forma automática (Parte 15): Automação (VII) Aprendendo a construindo um Expert Advisor que opera de forma automática (Parte 15): Automação (VII)
Para coroar esta sequencia de automação. Vamos complementar o que foi visto no artigo anterior. Este definitivamente mostra como tudo irá se encaixar, fazendo o Expert Advisor, funcionar como um relógio.