Русский
preview
Busca dialética — Dialectic Search (DA)

Busca dialética — Dialectic Search (DA)

MetaTrader 5Sistemas de negociação |
83 0
Andrey Dik
Andrey Dik

Conteúdo

  1. Introdução
  2. Implementação do algoritmo
  3. Resultados dos testes


Introdução

O materialismo dialético baseia-se no princípio da unidade e da luta dos opostos na natureza, na sociedade e no pensamento. Seu fundamento está na ideia de que o desenvolvimento ocorre por meio do conflito entre forças e tendências opostas, onde cada fenômeno contém contradições internas. O princípio-chave dessa abordagem é a transição de mudanças quantitativas em qualitativas, quando mudanças graduais se acumulam e resultam em saltos qualitativos abruptos. O processo de desenvolvimento segue a lei da "negação da negação", em que uma tese é sucedida por uma antítese, gerando uma síntese como nova qualidade que preserva o melhor dos estados anteriores.

No mundo dos algoritmos de otimização, onde a precisão matemática se encontra com a sabedoria filosófica, surgiu um método único inspirado no materialismo dialético, o Dialectical Algorithm (DA). Este algoritmo, apresentado como uma síntese entre a dialética clássica e os métodos modernos de otimização, reformula o processo de busca por soluções ótimas através da lente do confronto filosófico entre tese e antítese. A essência do DA está na ideia de que toda solução (tese) contém em si o potencial de ser aprimorada por meio da interação com sua contraposição (antítese).

Na implementação algorítmica, esse princípio se manifesta na interação entre pensadores especulativos, que buscam novas soluções se afastando das conhecidas, e pensadores práticos, que se concentram em soluções já verificadas. O aspecto materialista do materialismo dialético se revela na confiança em critérios objetivos para avaliar soluções e na verificação prática dos resultados. O desenvolvimento ocorre de forma cíclica: as soluções encontradas geram novas contradições, o que leva ao próximo ciclo de busca, refletindo a continuidade do processo de conhecimento e aprimoramento.

O algoritmo implementa esse princípio por meio de três momentos-chave: compreensão, onde ocorre a avaliação e ordenação das soluções; interação dialética, em que as soluções encontram suas antíteses; e o momento de síntese, onde se formam novas soluções aprimoradas. A particularidade do algoritmo está na divisão da população em dois tipos de pensadores: especulativos (k1), que exploram o espaço de soluções com grandes saltos (por meio da interação de soluções semelhantes em qualidade, mas distantes entre si no espaço de busca), e práticos (p-k1), que realizam uma busca local (soluções diferentes em qualidade, mas próximas no espaço). Essa divisão reflete o princípio filosófico da unidade e luta dos opostos, em que cada grupo traz uma contribuição única ao processo de otimização.

A busca dialética (Dialectic Search, DA) foi apresentada por Serdar Kadioglu e Meinolf Sellmann em 2009. Esse método adota a abordagem dialética para resolver tarefas de otimização com restrições, dando continuidade às tradições estabelecidas pelo materialismo dialético na investigação e busca por novas soluções.


Implementação do algoritmo

Na base do algoritmo está uma população com p soluções (geralmente 50), cada uma representando um vetor de coordenadas no espaço de busca. Essa população é dividida em dois grupos: k1 pensadores especulativos (as melhores soluções) e (p-k1) pensadores práticos.

A primeira etapa é o Momento de Compreensão. Aqui ocorre a avaliação de todas as soluções através da função objetivo f(x). As soluções são classificadas por qualidade, e as melhores k1 tornam-se pensadores especulativos, enquanto as demais tornam-se práticos. Nesta etapa também ocorre a aceitação ou rejeição de novas soluções, com base em sua qualidade em relação às iterações anteriores (a melhor solução individual para cada pensador).

A segunda etapa é o Momento Dialético. Nesta fase, cada solução busca sua antítese, o oposto com o qual irá interagir. Para os pensadores especulativos, a busca pela antítese baseia-se na maximização da distância com manutenção da qualidade da solução (dialética idealista). Para a primeira solução, a antítese é a segunda melhor; para a última, é a penúltima; para as demais, escolhe-se o vizinho com a maior distância. Já os pensadores práticos buscam a antítese minimizando a distância, desde que haja diferença suficiente na qualidade (dialética materialista).

A terceira etapa é o Momento Especulativo/Prático (Momento de Atualização). Aqui ocorre a atualização das posições de todas as soluções usando as antíteses encontradas. Os pensadores especulativos usam uma distribuição uniforme, que garante uma ampla exploração do espaço de soluções. Os pensadores práticos utilizam uma distribuição normal. Meus experimentos mostraram que, para ambos os tipos de pensadores, a distribuição uniforme oferece os melhores resultados.

A fórmula de atualização das posições é a mesma para todos: X(i) = X(i) + μ⊙(Xanti(i) - X(i)), onde μ é um vetor aleatório do respectivo tipo de distribuição, e ⊙ representa a multiplicação elemento a elemento. Isso garante um equilíbrio entre a exploração do espaço de soluções pelos pensadores especulativos e o refinamento das soluções encontradas pelos pensadores práticos.

O Algoritmo Dialético (DA) possui semelhanças com o algoritmo de evolução diferencial DE, no que diz respeito à fórmula de atualização das soluções. No DE, um novo vetor é criado adicionando-se ao vetor alvo a diferença escalada entre dois outros vetores (x_new = x_target + F(x_r1 - x_r2)), enquanto o DA usa um princípio semelhante, mas com uma antítese e um coeficiente adaptativo (x_new = x + μ(x_anti - x)).

No entanto, a principal diferença está no modo como os vetores são escolhidos para gerar novas soluções. O DE depende da seleção aleatória de vetores para formar a diferença, o que caracteriza sua natureza estocástica. O DA, por outro lado, adota uma abordagem determinística na escolha das antíteses, baseada na distância entre as soluções e sua qualidade, ao mesmo tempo em que divide a população entre pensadores especulativos e práticos, cada qual com estratégias de busca distintas. O algoritmo DA apresenta uma complexidade computacional ligeiramente maior (devido ao cálculo de distância euclidiana), mas mostra uma eficiência mais elevada em diversas tarefas de otimização.

Na Figura 1 é ilustrado o princípio de escolha das antíteses para as teses especulativas (vermelhas, as melhores) e materiais (azuis). Os especulativos escolhem antíteses vizinhas em qualidade, mas distantes no espaço de busca; já os materiais escolhem soluções distantes em qualidade, mas próximas no espaço de busca. 

dialectical-search

Imagem 1. Representação esquemática do princípio de funcionamento do algoritmo DA. Linhas contínuas - interação com antíteses preferenciais, diferente das menos preferenciais, indicadas por linhas tracejadas


dialectical-algo-flow

Imagem 2. Etapas da lógica do algoritmo DA

Prosseguimos agora com a escrita do pseudocódigo do algoritmo:

Na primeira iteração: os agentes são posicionados aleatoriamente: position[i] = random(min, max)

A população é ordenada com base nas melhores soluções individuais

Cria-se uma população com três tipos de agentes:

  • Melhor pensador (1 agente)
  • Pensadores especulativos (k1 = 3 agentes)
  • Pensadores práticos (os demais dos 50 agentes)
Nas iterações seguintes:

    A. O melhor pensador move-se em direção ao segundo melhor:

    position[0] = best[0] + rand(0,1) * (position[1] - position[0])

    B. Pensadores especulativos:

    • Identificam os vizinhos mais distantes com base na distância euclidiana:

    distance = √Σ(x₁-x₂)²

    • Atualizam a posição em relação ao mais distante:

    position[i] = best[i] + rand(0,1) * (position[furthest] - position[i])

    C. Pensadores práticos:

    • Selecionam dois pensadores especulativos aleatórios
    • Movem-se em direção ao mais próximo:

    position[i] = best[i] + rand(0,1) * (position[nearest] - position[i])

    Após cada movimento:

      • Atualizamos as melhores soluções individuais
      • Atualizamos a melhor solução global
      • Ordenamos os agentes com base na qualidade de suas soluções individuais

      O processo se repete até que o critério de parada seja atingido

      Após a análise completa do algoritmo, passamos à implementação em código. Vamos escrever a classe "C_AO_DA" do algoritmo dialético de otimização, herdando a funcionalidade da classe base "C_AO".

      Parâmetros do algoritmo:

      • Tamanho da população— as antíteses determinam a quantidade de agentes que participarão do processo de otimização.
      • Pensadores especulativos — indica a quantidade de melhores agentes capazes de realizar uma busca mais livre por soluções.
      • Vizinhos para análise — define quantos vizinhos mais próximos cada pensador especulativo (agente) irá considerar para trocar informações e aprimorar sua estratégia.

      Métodos:

      • C_AO_DA () — o construtor inicializa os parâmetros principais e também cria um array para armazenar os parâmetros.
      • SetParams () — a definição de parâmetros permite atualizar os valores dos parâmetros do algoritmo durante a execução.
      • Moving () e Revision () — funções responsáveis pelo deslocamento dos agentes no espaço de busca e pela revisão das soluções encontradas.
      • EuclideanDistance () — cálculo da distância no espaço de busca entre dois vetores, necessário para escolher o vizinho mais próximo (para os especulativos) e o mais distante (para os práticos), de acordo com a semelhança entre as soluções encontradas pelos agentes.
      //——————————————————————————————————————————————————————————————————————————————
      // Класс реализующий диалектический алгоритм оптимизации
      class C_AO_DA : public C_AO
      {
        public: //--------------------------------------------------------------------
        ~C_AO_DA () { }
        C_AO_DA ()
        {
          ao_name = "DA";
          ao_desc = "Dialectical Algorithm";
          ao_link = "https://www.mql5.com/ru/articles/16999";
      
          popSize = 50;       // размер популяции
          k1      = 3;        // спекулятивные мыслители
          k2      = 10;       // соседи
      
          ArrayResize (params, 3);
          params [0].name = "popSize"; params [0].val = popSize;
          params [1].name = "k1";      params [1].val = k1;
          params [2].name = "k2";      params [2].val = k2;
        }
      
        // Установка параметров алгоритма
        void SetParams ()
        {
          popSize = (int)params [0].val;
          k1      = (int)params [1].val;
          k2      = (int)params [2].val;
        }
      
        bool Init (const double &rangeMinP  [], // минимальный диапазон поиска
                   const double &rangeMaxP  [], // максимальный диапазон поиска
                   const double &rangeStepP [], // шаг поиска
                   const int     epochsP = 0);  // количество эпох
      
        void Moving   ();    // Перемещение агентов в пространстве поиска
        void Revision ();    // Пересмотр и обновление лучших найденных решений
      
        //----------------------------------------------------------------------------
        int k1;       // количество спекулятивных мыслителей
        int k2;       // количество соседей для анализа
      
        private: //-------------------------------------------------------------------
        // Вычисление евклидового расстояния между двумя векторами
        double EuclideanDistance (const double &vec1 [], const double &vec2 [], const int dim)
        {
          double sum  = 0;
          double diff = 0.0;
      
          for (int i = 0; i < dim; i++)
          {
            diff = vec1 [i] - vec2 [i];
            sum += diff * diff;
          }
          return MathSqrt (sum);
        }
      };
      //——————————————————————————————————————————————————————————————————————————————

      O método "Init" da classe "C_AO_DA" é destinado à inicialização dos parâmetros do algoritmo de otimização. Ele recebe arrays com os valores mínimos e máximos do intervalo de busca, os passos de busca e, opcionalmente, o número de épocas para executar a otimização. O método realiza primeiro a inicialização padrão dos parâmetros; se essa inicialização falhar, ele retorna "false". Caso a inicialização seja bem-sucedida, o método retorna "true", confirmando que o algoritmo está pronto para ser executado.

      //——————————————————————————————————————————————————————————————————————————————
      bool C_AO_DA::Init (const double &rangeMinP  [], // минимальный диапазон поиска
                          const double &rangeMaxP  [], // максимальный диапазон поиска
                          const double &rangeStepP [], // шаг поиска
                          const int     epochsP = 0)   // количество эпох
      {
        if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;
      
        //----------------------------------------------------------------------------
        return true;
      }
      //——————————————————————————————————————————————————————————————————————————————

      O método "Moving" implementa o deslocamento dos agentes no espaço de busca. Abaixo está uma descrição detalhada do funcionamento do método:

      Inicialização:

      • No início (!revision), as posições iniciais dos agentes são definidas aleatoriamente, usando os limites mínimos e máximos definidos para cada coordenada. Cada agente "a[i]" recebe coordenadas aleatórias dentro dos intervalos especificados e de acordo com o passo definido.
      • Após a inicialização, "revision" é definido como "true", o que impede nova inicialização nas próximas chamadas ao método "Moving".

      Atualização da posição do melhor pensador:

      • O melhor pensador (agente) atualiza suas coordenadas com base em sua melhor posição anterior e uma probabilidade aleatória, utilizando o vizinho mais próximo "a[1]" para realizar a atualização.

      Atualização das posições dos pensadores especulativos:

      • Para cada pensador especulativo (agente) no intervalo de "k2" até "k1", o método procura o vizinho anterior mais distante (antiPrevIND) e o vizinho seguinte mais distante (antiNextIND).
      • Em seguida, a coordenada do pensador especulativo é atualizada com base no vizinho mais distante considerado como antítese.

      Atualização das posições dos pensadores práticos:

      • Os pensadores práticos (agentes) estão no intervalo de "k1" até "popSize".
      • O código seleciona aleatoriamente dois pensadores especulativos e calcula a distância até eles. O pensador prático escolhe o mais próximo (entre os dois selecionados) para atualizar sua posição.
      • Cada coordenada é atualizada com base no vizinho escolhido.

      Funções auxiliares

      • EuclideanDistance — função que calcula a distância euclidiana entre dois pontos "a" e "b" em um espaço multidimensional.
      • u.RNDfromCI — retorna um número aleatório dentro de um intervalo especificado.
      • u.SeInDiSp — ajusta o "value" ao passo adequado de acordo com o intervalo.
      • u.RNDprobab — retorna um número aleatório com distribuição uniforme de probabilidade.
      //——————————————————————————————————————————————————————————————————————————————
      // Реализация движения агентов в пространстве поиска
      void C_AO_DA::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 c = 0; c < coords; c++)
        {
          a [0].c [c] = a [0].cB [c] + u.RNDprobab () * (a [1].c [c] - a [0].c [c]);
          a [0].c [c] = u.SeInDiSp (a [0].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
        }
      
        //----------------------------------------------------------------------------
        double dist_next   = -DBL_MAX;  // максимальное расстояние до следующего соседа
        double dist_prev   = -DBL_MAX;  // максимальное расстояние до предыдущего соседа
        double dist        = 0.0;       // текущее расстояние
        int    antiNextIND = 0;         // индекс наиболее удаленного следующего соседа
        int    antiPrevIND = 0;         // индекс наиболее удаленного предыдущего соседа
        int    antiIND     = 0;         // выбранный индекс для обновления позиции
      
        // Обновление позиций спекулятивных мыслителей -------------------------------
        for (int i = k2; i < k1; i++)
        {
          // Поиск наиболее удаленного предыдущего соседа
          for (int j = 1; j <= k2; j++)
          {
            dist = EuclideanDistance (a [i].cB, a [i - j].cB, coords);
            if (dist > dist_prev)
            {
              dist_prev   = dist;
              antiPrevIND = i - j;
            }
          }
      
          // Поиск наиболее удаленного следующего соседа
          for (int j = 1; j <= k2; j++)
          {
            dist = EuclideanDistance (a [i].cB, a [i + j].cB, coords);
            if (dist > dist_next)
            {
              dist_next = dist;
              antiNextIND  = i + j;
            }
          }
      
          // Выбор наиболее удаленного соседа для обновления позиции
          if (dist_prev > dist_next) antiIND = antiPrevIND;
          else                       antiIND = antiNextIND;
      
          // Обновление координат спекулятивного мыслителя
          for (int c = 0; c < coords; c++)
          {
            a [i].c [c] = a [i].cB [c] + u.RNDbool () * (a [antiIND].c [c] - a [i].c [c]);
            //a [i].c [c] = a [i].cB [c] + u.RNDprobab () * (a [antiIND].c [c] - a [i].c [c]);
            a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
          }
        }
      
        // Обновление позиций практических мыслителей --------------------------------
        for (int i = k1; i < popSize; i++)
        {
          // Случайный выбор двух спекулятивных мыслителей
          antiNextIND = u.RNDintInRange (0, k1 - 1);
          antiPrevIND = u.RNDintInRange (0, k1 - 1);
      
          if (antiNextIND == antiPrevIND) antiNextIND = antiPrevIND + 1;
      
          // Расчет расстояний до выбранных мыслителей
          dist_next = EuclideanDistance (a [i].cB, a [antiNextIND].cB, coords);
          dist_prev = EuclideanDistance (a [i].cB, a [antiPrevIND].cB, coords);
      
          // Выбор ближайшего мыслителя для обновления позиции
          if (dist_prev < dist_next) antiIND = antiPrevIND;
          else                       antiIND = antiNextIND;
      
          // Обновление координат практического мыслителя
          for (int c = 0; c < coords; c++)
          {
            a [i].c [c] = a [i].cB [c] + u.RNDprobab () * (a [antiIND].c [c] - a [i].c [c]);
            a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
          }
        }
      }
      //——————————————————————————————————————————————————————————————————————————————

      O método "Revision" é responsável pela revisão e atualização das melhores soluções encontradas pelos agentes. Abaixo está uma análise detalhada do funcionamento deste método:

      Atualização das melhores soluções encontradas: no laço "for", o método percorre cada agente na população. Para cada agente, o valor atual da função de adaptabilidade "a[i].f" é comparado:

      • Melhor solução global — se o valor da função "f" do agente for maior do que o atual melhor valor global "fB", então a solução global é atualizada e o índice do agente (ind) que encontrou essa melhor solução é armazenado.
      • Melhor solução pessoal — cada valor "f" do agente também é comparado com seu melhor valor pessoal "fB". Se o valor atual for melhor, o valor pessoal é atualizado e suas coordenadas atuais "c" são copiadas para as coordenadas pessoais "cB".

      Atualização das coordenadas da melhor solução global: se foi encontrado o índice de um agente que passou a representar a melhor solução global (ind != -1), então as coordenadas desse agente são copiadas para as coordenadas globais "cB".

      Ordenação dos agentes: No final do método, é criado um array "aT" e seu tamanho é ajustado ao tamanho da população. Em seguida, a função "u.Sorting_fB" é chamada para ordenar os agentes com base em suas melhores soluções encontradas (valores de fB).

      //——————————————————————————————————————————————————————————————————————————————
      // Пересмотр и обновление лучших найденных решений
      void C_AO_DA::Revision ()
      {
        int ind = -1;
      
        // Обновление лучших найденных решений для каждого агента
        for (int i = 0; i < popSize; i++)
        {
          // Обновление глобального лучшего решения
          if (a [i].f > fB)
          {
            fB = a [i].f;
            ind = i;
          }
      
          // Обновление личного лучшего решения агента
          if (a [i].f > a [i].fB)
          {
            a [i].fB = a [i].f;
            ArrayCopy (a [i].cB, a [i].c, 0, 0, WHOLE_ARRAY);
          }
        }
      
        // Обновление координат глобального лучшего решения
        if (ind != -1) ArrayCopy (cB, a [ind].c, 0, 0, WHOLE_ARRAY);
      
        // Сортировка агентов по их лучшим найденным решениям
        static S_AO_Agent aT []; ArrayResize (aT, popSize);
        u.Sorting_fB (a, aT, popSize);
      }
      //——————————————————————————————————————————————————————————————————————————————


      Resultados dos testes

      Chegou o momento de conhecer os resultados dos testes com o DA. Ainda mais, vamos destacar o método "Moving", onde a linha que deveria estar conforme a proposta dos autores está destacada em verde e comentada no código. Pois bem, os resultados foram os seguintes:

      DA|Dialectical Algorithm|50.0|30.0|1.0|
      =============================
      5 Hilly's; Func runs: 10000; result: 0.749254786734898
      25 Hilly's; Func runs: 10000; result: 0.36669693350810206
      500 Hilly's; Func runs: 10000; result: 0.2532075139007539
      =============================
      5 Forest's; Func runs: 10000; result: 0.7626421292861323
      25 Forest's; Func runs: 10000; result: 0.4144802592253075
      500 Forest's; Func runs: 10000; result: 0.2006796312431603
      =============================
      5 Megacity's; Func runs: 10000; result: 0.36
      25 Megacity's; Func runs: 10000; result: 0.15969230769230774
      500 Megacity's; Func runs: 10000; result: 0.0952000000000008
      =============================
      All score: 3.36185 (37.35%)

      Esses resultados estão longe de serem os melhores, mas poderiam ter entrado na tabela de classificação. Ocorre que cometi um erro, e em vez de usar números aleatórios no intervalo [0.0;1.0], inseri no código uma função de geração de valores booleanos aleatórios (destacado em vermelho).

      A lógica da mudança aleatória consiste no seguinte: com 50% de probabilidade, a coordenada correspondente permanece a mesma, ou será substituída pela coordenada da antítese. Na minha opinião, isso se alinha até mais com a ideia dos autores sobre o confronto entre tese e antítese. No caso dos pensadores práticos, tudo permanece como antes — seus teses finais são um híbrido entre a tese atual e a antítese, retirados dos pensadores especulativos. Assim, por um feliz acaso, obtive os seguintes resultados:

      DA|Dialectical Algorithm|50.0|40.0|1.0|
      =============================
      5 Hilly's; Func runs: 10000; result: 0.8618313952293774
      25 Hilly's; Func runs: 10000; result: 0.700333708747176
      500 Hilly's; Func runs: 10000; result: 0.3372386732170054
      =============================
      5 Forest's; Func runs: 10000; result: 0.9816317765399738
      25 Forest's; Func runs: 10000; result: 0.7277214130784131
      500 Forest's; Func runs: 10000; result: 0.28717629901518305
      =============================
      5 Megacity's; Func runs: 10000; result: 0.7030769230769229
      25 Megacity's; Func runs: 10000; result: 0.4529230769230769
      500 Megacity's; Func runs: 10000; result: 0.16366923076923204
      =============================
      All score: 5.21560 (57.95%)

      São resultados realmente impressionantes! Como essa melhora significativa nos indicadores ocorreu de forma não intencional, não posso atribuir à versão modificada o índice "m". Na nossa tabela de classificação, o algoritmo permanecerá com o nome "DA". Dessa forma, o algoritmo dialético demonstra excelente desempenho, atingindo um índice de eficiência geral de 57,95%. A característica central do algoritmo é sua capacidade de equilibrar com eficácia a busca global e a busca local, graças à divisão entre pensadores especulativos e práticos.

      Na visualização, é possível perceber que o algoritmo encontra rapidamente ótimos locais relevantes, embora careça de precisão na convergência para ser considerado ideal. Ainda assim, os resultados são, de qualquer forma, bastante sólidos.

      Hilly

        DA na função de teste Hilly

      Forest

      DA na função de teste Forest

      Megacity

      DA na função de teste Megacity

      De acordo com os resultados dos testes, o algoritmo DA ficou na 12ª posição da nossa tabela de classificação — um resultado bom e estável.

      AO Description Hilly Hilly final Forest Forest final Megacity (discrete) Megacity final Final result % of 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 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
      9 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
      10 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
      11 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
      12 DA dialectical 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
      13 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
      14 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
      15 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
      16 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
      17 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
      18 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
      19 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
      20 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
      21 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
      22 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
      23 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
      24 (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
      25 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
      26 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
      27 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
      28 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
      29 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
      30 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
      31 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
      32 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
      33 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
      34 ACMO atmospheric cloud 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
      35 ADAMm adaptive moment estimation M 0,88635 0,44766 0,26613 1,60014 0,84497 0,38493 0,16889 1,39880 0,66154 0,27046 0,10594 1,03794 4,037 44,85
      36 ATAm artificial tribe algorithm M 0,71771 0,55304 0,25235 1,52310 0,82491 0,55904 0,20473 1,58867 0,44000 0,18615 0,09411 0,72026 3,832 42,58
      37 ASHA artificial showering algorithm 0,89686 0,40433 0,25617 1,55737 0,80360 0,35526 0,19160 1,35046 0,47692 0,18123 0,09774 0,75589 3,664 40,71
      38 ASBO adaptive social behavior optimization 0,76331 0,49253 0,32619 1,58202 0,79546 0,40035 0,26097 1,45677 0,26462 0,17169 0,18200 0,61831 3,657 40,63
      39 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
      40 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
      41 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
      42 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
      43 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
      44 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
      45 BBBC big bang-big crunch algorithm 0,60531 0,45250 0,31255 1,37036 0,52323 0,35426 0,20417 1,08166 0,39769 0,19431 0,11286 0,70486 3,157 35,08
      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


      Considerações finais

      O algoritmo dialético representa uma abordagem inovadora de otimização, fundamentada no conceito filosófico da dialética, onde a melhoria das soluções é alcançada por meio da interação entre opostos. O algoritmo combina com sucesso conceitos de busca global e local através da divisão única da população entre pensadores especulativos e práticos, o que garante um equilíbrio eficaz entre diversificação e intensificação do espaço de soluções.

      A estrutura do algoritmo, composta por três etapas-chave, garante uma abordagem sistemática para a otimização. Durante a execução, os pensadores especulativos realizam uma busca ampla no espaço de soluções (ainda que, em geral, algoritmos de otimização tendam a refinar as melhores soluções em vez de “espalhá-las” pelo espaço de busca), enquanto os pensadores práticos concentram-se na otimização local de regiões promissoras. Essa divisão permite que o algoritmo explore eficientemente o espaço de soluções e evite ficar preso em ótimos locais, ainda mais considerando que, devido a um erro acidental que cometi, a lógica do algoritmo acabou se aproximando ainda mais da ideia de opostos dialéticos.

      Os resultados dos testes confirmam a alta eficiência do algoritmo com capacidades de busca equilibradas, que se mantêm em bom nível em diferentes tipos de tarefas. Em comparação com outros algoritmos, o DA não apresenta desvios acentuados nem para pior nem para melhor, mantendo um desempenho estável e uniforme conforme a gradação de cores na tabela. O indicador geral de eficiência demonstra a competitividade do algoritmo em relação aos métodos de otimização existentes. Essa combinação de princípios filosóficos com métodos matemáticos forma uma ferramenta poderosa para resolver problemas complexos de otimização.

      Tab

      Imagem 3. Graduação de cores dos algoritmos conforme os respectivos testes

      Chart

      Imagem 4. Histograma dos resultados de teste dos algoritmos (em uma escala de 0 a 100, quanto maior, melhor, onde 100 é o resultado teórico máximo possível, no arquivo compactado está o script para cálculo da tabela de classificação)


      Pontos positivos e negativos do algoritmo DA:

      Pontos positivos:

      1. Poucos parâmetros externos, apenas dois além do tamanho da população.
      2. Implementação simples.
      3. Bastante rápido.
      4. Indicadores equilibrados e bons em tarefas de baixa e alta dimensionalidade.

      Pontos negativos:

      1. Variação dos resultados.

      Um arquivo compactado com as versões atuais dos códigos dos algoritmos está anexado ao artigo. O autor do artigo não se responsabiliza pela exatidão absoluta na descrição dos algoritmos canônicos, pois muitos deles foram modificados para melhorar as capacidades de busca. As conclusões e julgamentos apresentados nos artigos baseiam-se nos resultados dos experimentos realizados.

      Programas utilizados no artigo

      # Nome Tipo Descrição
      1 C_AO.mqh
      Arquivo incluído
      Classe pai dos algoritmos populacionais de otimização
      2 C_AO_enum.mqh
      Arquivo incluído
      Enumeração dos algoritmos populacionais de otimização
      3 TestFunctions.mqh
      Arquivo incluído
      Biblioteca de funções de teste
      4
      TestStandFunctions.mqh
      Arquivo incluído
      Biblioteca de funções do ambiente de teste
      5
      Utilities.mqh
      Arquivo incluído
      Biblioteca de funções auxiliares
      6
      CalculationTestResults.mqh
      Arquivo incluído
      Script para cálculo dos resultados na tabela comparativa
      7
      Testing AOs.mq5
      Script Ambiente de teste unificado para todos os algoritmos populacionais de otimização
      8
      Simple use of population optimization algorithms.mq5
      Script
      Exemplo simples de uso dos algoritmos populacionais de otimização sem visualização
      9
      Test_AO_DA.mq5
      Script Ambiente de teste para o DA

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

      Arquivos anexados |
      DA.ZIP (156.94 KB)
      Redes neurais em trading: Transformador hierárquico de duas torres (Hidformer) Redes neurais em trading: Transformador hierárquico de duas torres (Hidformer)
      Apresentamos o framework do transformador hierárquico de duas torres (Hidformer), desenvolvido para previsão de séries temporais e análise de dados. Os autores do framework propuseram diversas melhorias na arquitetura Transformer, o que permitiu aumentar a precisão das previsões e reduzir o consumo de recursos computacionais.
      Neurônio biológico para previsão de séries temporais financeiras Neurônio biológico para previsão de séries temporais financeiras
      Estamos construindo um sistema de neurônios biologicamente fiel para prever séries temporais. A introdução de um meio semelhante ao plasma na arquitetura da rede neural criou uma espécie de "inteligência coletiva", onde cada neurônio influencia o funcionamento do sistema não apenas por meio de conexões diretas, mas também por meio de interações eletromagnéticas de longo alcance. Como esse sistema neural modelando o cérebro irá se comportar no mercado?
      Redes neurais em trading: Transformador hierárquico com duas torres (Conclusão) Redes neurais em trading: Transformador hierárquico com duas torres (Conclusão)
      Continuamos a desenvolver o modelo transformador hierárquico com duas torres, o Hidformer, projetado para análise e previsão de séries temporais multivariadas complexas. Neste artigo, levaremos o trabalho iniciado anteriormente até sua conclusão lógica, com testes do modelo em dados históricos reais.
      Indicador de previsão de volatilidade usando Python Indicador de previsão de volatilidade usando Python
      Vamos prever a volatilidade extrema futura com ajuda da classificação binária. Criamos um indicador de previsão de volatilidade extrema com uso de aprendizado de máquina.