Algoritmo do Restaurateur de Sucesso — Successful Restaurateur Algorithm (SRA)
Conteúdo
Introdução
Sempre me fascinaram os paralelos entre problemas de otimização e cenários da vida real. Ao explorar novos caminhos para algoritmos meta-heurísticos, percebi semelhanças entre a otimização populacional e a evolução de um restaurante. Essa ideia se tornou a inspiração para o que chamo de "Algoritmo do Restaurateur de Sucesso" (SRA).
Imagine o dono de um restaurante que busca constantemente melhorar seu cardápio para aumentar sua popularidade e atrair novos clientes. Em vez de simplesmente eliminar os pratos menos pedidos, ele segue uma estratégia mais refinada: identifica o item menos popular e o combina cuidadosamente com elementos dos pratos mais apreciados. Às vezes, as mudanças são conservadoras; em outras ocasiões, incluem novos ingredientes ousados. O objetivo, porém, é sempre o mesmo: transformar a opção menos pedida em algo capaz de se tornar o novo favorito do cardápio.
Essa metáfora culinária define a base do SRA. Ao contrário dos algoritmos evolucionários tradicionais, que geralmente descartam soluções malsucedidas, o SRA foca na recuperação dos piores desempenhos, incorporando a eles elementos de sucesso. Essa estratégia mantém a diversidade no espaço de soluções enquanto eleva gradualmente a qualidade geral da população.
Neste artigo, analisaremos os principais mecanismos do SRA, sua implementação e como parâmetros, como "temperatura" e "intensidade dos experimentos culinários", regulam o equilíbrio entre intensificação e diversificação. Apresentarei também os resultados dos testes que comparam o SRA com outros algoritmos reconhecidos em um ranking de diferentes funções de teste.
O que começou como um experimento mental criativo se transformou em uma abordagem promissora com características únicas. Convido você a descobrir como esse algoritmo, inspirado no ramo da restauração, oferece soluções de otimização com um sabor especial.
Implementação do algoritmo
Vamos destrinchar o funcionamento do algoritmo por meio de analogias simples. Imagine que eu sou o dono de um restaurante. Tenho um cardápio com vários pratos e percebo que alguns são muito populares, enquanto outros quase não são pedidos pelos clientes. O que eu faço? Eu não retiro imediatamente os pratos impopulares do cardápio (o que reduziria a variedade disponível), mas pego o menos popular e tento melhorá-lo. Como? Eu observo os itens de maior sucesso do restaurante e extraio deles algumas ideias ou ingredientes. Por exemplo, suponha que um prato de peixe esteja com vendas fracas, mas a salada seja extremamente popular. Então, incorporo ao prato de peixe algum elemento dessa salada de sucesso (talvez um molho especial ou uma forma de apresentação) e crio algo novo.
Às vezes, faço pequenas mudanças; outras vezes, arrisco experimentos ousados. No início, quando acabei de abrir o restaurante, eu fazia muitas experiências, mas, depois de encontrar alguns pratos de grande sucesso, passei a refinar mais cuidadosamente as combinações de ingredientes e suas proporções. Com o tempo, até mesmo os pratos mais fracos do cardápio ficam cada vez melhores. E, em certos casos, aquele antigo "azarão" pode se transformar em um novo sucesso! Dessa forma, a popularidade geral do restaurante aumenta, pois todos os itens acabam tendo boa aceitação.
É exatamente assim que meu algoritmo funciona: não descartamos as más soluções, mas as melhoramos continuamente com ideias das melhores soluções. E, quanto mais o processo avança, menos experimentamos de forma radical e mais refinamos o que já foi descoberto. A figura 1 mostra o diagrama de funcionamento do algoritmo.

Figura 1. Diagrama de funcionamento do algoritmo SRA
O diagrama tem início no bloco "Inicialização", onde o cardápio inicial é criado. Em seguida, ocorre o ciclo principal do algoritmo, cujo centro é o cardápio atual do restaurante, ordenado pela qualidade dos pratos. Esse cardápio é representado por um gradiente de cores, que vai do verde (melhores pratos) ao vermelho (piores pratos). Abaixo, estão quatro etapas sequenciais: a primeira é a escolha dos pratos a serem melhorados, na qual o pior prato e um doador de alta qualidade são selecionados, e essa seleção é influenciada por uma probabilidade crescente de acordo com a lei quadrática; a segunda é a criação de novas versões por meio da combinação de receitas e da mutação de ingredientes (quanto maior a temperatura, mais ousados os experimentos); a terceira é a avaliação dos novos pratos pelo cálculo da função de adaptabilidade; e a quarta é a redução da temperatura para diminuir a intensidade dos experimentos. À esquerda, uma seta tracejada indica que o processo se repete até atingir a convergência ou satisfazer o critério de parada. À direita, as marcações: A (círculo verde) — melhores pratos, B (círculo vermelho) — piores pratos. Todo o esquema ilustra o processo que remete ao trabalho do restaurateur, que melhora sistematicamente os pontos fracos do cardápio aproveitando elementos dos pratos de maior sucesso.
Agora vamos passar à escrita do pseudocódigo do algoritmo SRA.
//Inicialização
Criar uma população de popSize agentes (pratos do cardápio)
Para cada agente:
Inicializar aleatoriamente todas as coordenadas dentro dos limites permitidos
Definir a temperatura inicial = 1.0
Definir o coeficiente de resfriamento = 0.98
Definir a intensidade dos experimentos culinários = 0.3
//Ciclo principal do algoritmo
ENQUANTO não for satisfeito o critério de parada:
//Etapa 1: Avaliação de todos os agentes
Para cada agente:
Calcular o valor da função de adaptabilidade
// Combinar a população atual e a anterior
Formar o cardápio geral com os agentes atuais e os anteriores
Ordenar o cardápio geral pelo valor da função de adaptabilidade do melhor para o pior
//Etapa 2: Criação de novas variantes
Para cada agente na nova população:
// Pegamos o pior elemento da primeira metade da população ordenada
Copiar as coordenadas do agente com índice (popSize-1)
// Escolha entre melhoria e experimento
Se (número_aleatório < (1.0 - menuInnovationRate * temperatura)):
// Escolha do "doador" pelo método da roleta quadrática
r = número aleatório entre 0 e 1
r = r²
donorIndex = escalar r entre 0 e (popSize-1)
// Para cada coordenada
Para cada coordenada c:
// Com probabilidade de 0.8, copiar coordenada do doador
Se (número_aleatório < 0.8):
agente_atual.c = doador.c
// Mutação adaptativa
mutationRate = 0.1 + 0.4 * temperatura * (índice_agente / popSize)
Se (número_aleatório < mutationRate):
// Escolha do tipo de mutação
Se (número_aleatório < 0.5):
agente_atual.c = distribuição gaussiana(agente_atual.c)
Caso contrário:
agente_atual.c = valor aleatório no intervalo
// Garantir que o valor esteja dentro dos limites permitidos
agente_atual.c = arredondar para o valor válido mais próximo
Caso contrário:
// Criação de um novo "prato"
Para cada coordenada c:
Se (número_aleatório < 0.7):
agente_atual.c = valor aleatório no intervalo
Caso contrário:
agente_atual.c = distribuição gaussiana(melhor_solucao.c)
// Garantir que o valor esteja dentro dos limites permitidos
agente_atual.c = arredondar para o valor válido mais próximo
// Elitismo — às vezes é útil simplesmente adicionar elementos da melhor solução
Se (número_aleatório < 0.1):
numEliteCoords = número aleatório entre 1 e (coords * 0.3)
Para i de 1 até numEliteCoords:
c = índice aleatório da coordenada
agente_atual.c = melhor_solucao.c
// Etapa 3: Atualização da melhor solução
Para cada agente:
Se agente.fitness > melhor_solucao.fitness:
melhor_solucao = agente
// Etapa 4: Redução da temperatura
temperatura = temperatura * taxa_de_resfriamento
Se temperatura < 0.1:
temperatura = 0.1
Retornar melhor_solucao
Agora podemos começar a escrever o código do algoritmo. Vamos implementar a classe "C_AO_SRA", que herda da classe principal "C_AO" e realiza a lógica do SRA. Vamos detalhar como ela funciona.
Construtor e destrutor: popSize, temperature, coolingRate, menuInnovationRate definem as principais características do algoritmo, como o número de agentes e os parâmetros de controle do processo de busca.
Método SetParams: atualiza os parâmetros da classe com base nos valores armazenados no array "params", parâmetros estes que foram previamente inicializados no construtor.
Método Init: responsável pela inicialização do algoritmo. Ele recebe os valores mínimos e máximos, o passo de variação dos parâmetros e o número de épocas, preparando o algoritmo para executar a tarefa de busca.
Métodos Moving e Revision: implementam as etapas principais do algoritmo, ligadas ao movimento (ou atualização) do estado dos agentes e ao "Revision", que trata da revisão e adaptação dos parâmetros.
Membros da classe:
- temperature — a temperatura atual, ligada ao controle da diversificação e ao cronograma de resfriamento do algoritmo.
- coolingRate — a taxa de resfriamento, usada para definir a velocidade de redução da temperatura.
- menuInnovationRate — a intensidade dos experimentos culinários, que indica até que ponto os agentes são estimulados a buscar novas soluções.
- S_AO_Agent menu [] — array de agentes, representando o "cardápio" no contexto do algoritmo SRA.
- S_AO_Agent menuT [] — array de agentes usado para armazenamento temporário de variações dos pratos.
//—————————————————————————————————————————————————————————————————————————————— class C_AO_SRA : public C_AO { public: //-------------------------------------------------------------------- ~C_AO_SRA () { } C_AO_SRA () { ao_name = "SRA"; ao_desc = "Successful Restaurateur Algorithm (joo)"; ao_link = "https://www.mql5.com/ru/articles/17380"; popSize = 50; // число агентов (размер "меню") temperature = 1.0; // начальная "температура" для управления исследованием coolingRate = 0.98; // скорость охлаждения menuInnovationRate = 0.3; // интенсивность кулинарных экспериментов ArrayResize (params, 4); params [0].name = "popSize"; params [0].val = popSize; params [1].name = "temperature"; params [1].val = temperature; params [2].name = "coolingRate"; params [2].val = coolingRate; params [3].name = "menuInnovationRate"; params [3].val = menuInnovationRate; } void SetParams () { popSize = (int)params [0].val; temperature = params [1].val; coolingRate = params [2].val; menuInnovationRate = params [3].val; } bool Init (const double &rangeMinP [], // минимальные значения const double &rangeMaxP [], // максимальные значения const double &rangeStepP [], // шаг изменения const int epochsP = 0); // количество эпох void Moving (); void Revision (); //---------------------------------------------------------------------------- double temperature; // текущая "температура" double coolingRate; // скорость охлаждения double menuInnovationRate; // интенсивность кулинарных экспериментов private: //------------------------------------------------------------------- S_AO_Agent menu []; S_AO_Agent menuT []; }; //——————————————————————————————————————————————————————————————————————————————
O método "Init" da classe "C_AO_SRA" realiza a inicialização do algoritmo:
Verificação da inicialização padrão: o método chama "StandardInit" com os valores mínimos e máximos dos intervalos e os passos. Caso falhe, retorna "false".
Inicialização dos arrays:
- Distribui os tamanhos dos arrays "menu" e "menuT" de acordo com a quantidade de agentes.
- Inicializa cada agente no array "menu".
Reinício da temperatura: define o valor inicial de "temperature" como "1.0".
Conclusão bem-sucedida: retorna "true" caso a inicialização seja realizada corretamente.
//—————————————————————————————————————————————————————————————————————————————— //--- Инициализация bool C_AO_SRA::Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP = 0) { if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; //---------------------------------------------------------------------------- ArrayResize (menu, popSize * 2); ArrayResize (menuT, popSize * 2); for (int p = 0; p < popSize * 2; p++) menu [p].Init (coords); temperature = 1.0; // сброс температуры при инициализации return true; } //——————————————————————————————————————————————————————————————————————————————
O método "Moving" da classe "C_AO_SRA" implementa a etapa principal do algoritmo. Ele possui duas partes principais: a inicialização dos agentes e sua adaptação através de mutação e criação de novas soluções.
Inicialização inicial (quando "revision" é igual a "false"):- Cada agente é inicializado com valores aleatórios dentro dos limites definidos (rangeMin, rangeMax), aplicando os passos (rangeStep). Os valores são armazenados em "c" e "cB" para cada agente.
- Define "revision" como "true" e encerra o método.
Redução da temperatura: a temperatura é multiplicada pelo coeficiente de resfriamento (coolingRate), o que influencia as probabilidades de mudanças subsequentes.
Ciclo principal dos agentes: para cada agente, seleciona-se o pior elemento da primeira metade da população ordenada (a partir do array menu).
Classificação das ações: com uma probabilidade dependente da temperatura, o agente pode:
- modificar a solução atual (usando uma "receita-doador" de um prato de melhor qualidade), aplicando mutação com probabilidade variável.
- criar uma nova solução (valores aleatórios).
Elitismo: com determinada probabilidade, ao novo resultado podem ser adicionados elementos da melhor solução encontrada.
//—————————————————————————————————————————————————————————————————————————————— //--- Основной шаг алгоритма void C_AO_SRA::Moving () { //---------------------------------------------------------------------------- // Начальная инициализация if (!revision) { for (int p = 0; p < popSize; p++) { for (int c = 0; c < coords; c++) { a [p].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]); a [p].c [c] = u.SeInDiSp (a [p].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); a [p].cB [c] = a [p].c [c]; } } revision = true; return; } //---------------------------------------------------------------------------- // Снижаем температуру temperature *= coolingRate; // Основной цикл по агентам популяции for (int p = 0; p < popSize; p++) { // Берем худший элемент из первой половины отсортированной популяции (с индексом popSize-1) // Помним, что в menu элементы отсортированы от лучшего к худшему ArrayCopy (a [p].c, menu [popSize - 1].c, 0, 0, WHOLE_ARRAY); // Решаем, создавать ли гибрид или экспериментировать с новым "блюдом" // Вероятность эксперимента зависит от температуры - в начале больше экспериментов if (u.RNDprobab () < (1.0 - menuInnovationRate * temperature)) { // Выбираем "рецепт-донор" с вероятностью пропорциональной успешности блюда double r = u.RNDprobab (); r = pow (r, 2); // Усиление предпочтения к лучшим блюдам int menuIND = (int)u.Scale (r, 0, 1.0, 0, popSize - 1); // Лучшие в начале массива // Для каждой координаты for (int c = 0; c < coords; c++) { // С вероятностью, зависящей от температуры, берем параметр из успешного блюда if (u.RNDprobab () < 0.8) { a [p].c [c] = menu [menuIND].c [c]; } // Мутация с адаптивной вероятностью - чем дальше от лучшего решения и выше температура, тем больше мутаций double mutationRate = 0.1 + 0.4 * temperature * (double)(p) / popSize; if (u.RNDprobab () < mutationRate) { // Комбинация различных типов мутаций if (u.RNDprobab () < 0.5) a [p].c [c] = u.GaussDistribution (a [p].c [c], rangeMin [c], rangeMax [c], 2); else a [p].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]); // Иногда полностью новое значение // Убедимся, что значение в допустимых пределах a [p].c [c] = u.SeInDiSp (a [p].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } } else // Создаем абсолютно новое "блюдо" { for (int c = 0; c < coords; c++) { // Вариация 1: полностью случайное значение if (u.RNDprobab () < 0.7) { a [p].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]); } // Вариация 2: основано на лучшем найденном решении с большим отклонением else { a [p].c [c] = u.GaussDistribution (cB [c], rangeMin [c], rangeMax [c], 1); } a [p].c [c] = u.SeInDiSp (a [p].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } // Иногда добавляем элементы из лучшего решения напрямую (элитизм) if (u.RNDprobab () < 0.1) { int numEliteCoords = u.RNDintInRange (1, coords / 3); // Берем от 1 до 30% координат for (int i = 0; i < numEliteCoords; i++) { int c = u.RNDminusOne (coords); a [p].c [c] = cB [c]; // Берем значение из лучшего решения } } } } //——————————————————————————————————————————————————————————————————————————————
O método "Revision" da classe "C_AO_SRA" é responsável por atualizar a melhor solução encontrada e por gerenciar o "cardápio" geral de soluções durante a execução do algoritmo:
Busca do melhor agente: percorre todos os agentes da população atual e identifica aquele com o maior valor da função de adaptabilidade (f). Se for encontrado um novo melhor agente, atualiza "fB" e o índice "bestIND".
Atualização da melhor solução: se for identificado um melhor agente (isto é, se bestIND for diferente de -1), copia seus parâmetros de solução (c) para a variável cB, que representa a solução atual de maior qualidade.
Atualização do cardápio geral: adiciona os parâmetros atuais de todos os agentes ao "cardápio", permitindo armazenar os experimentos realizados.
Ordenação do cardápio: organiza o array "menu" pela função de adaptabilidade, do melhor para o pior, garantindo que as melhores soluções permaneçam na primeira metade. Isso será utilizado na próxima iteração do algoritmo.
Controle de temperatura: estabelece um limite inferior para a temperatura, assegurando que ela não caia abaixo de "0.1", evitando assim uma convergência prematura.//—————————————————————————————————————————————————————————————————————————————— //--- Обновление лучшего решения с учетом жадного выбора и вероятности принятия худших решений void C_AO_SRA::Revision () { int bestIND = -1; // Находим лучшего агента в текущей популяции for (int p = 0; p < popSize; p++) { if (a [p].f > fB) { fB = a [p].f; bestIND = p; } } // Если нашли лучшее решение, обновляем cB if (bestIND != -1) ArrayCopy (cB, a [bestIND].c, 0, 0, WHOLE_ARRAY); // Добавляем текущий набор блюд в общее "меню" for (int p = 0; p < popSize; p++) { menu [popSize + p] = a [p]; } // Сортируем всё "меню" от лучших к худшим решениям // После сортировки, первая половина menu будет содержать лучшие решения, // которые будут использоваться на следующей итерации u.Sorting (menu, menuT, popSize * 2); // Не позволяем температуре упасть ниже определенного порога if (temperature < 0.1) temperature = 0.1; } //——————————————————————————————————————————————————————————————————————————————
Resultados dos testes
Agora podemos observar como o algoritmo SRA funciona. Abaixo está a saída dos resultados de teste:
SRA|Successful Restaurateur Algorithm|50.0|1.0|0.98|0.3|
=============================
5 Hilly's; Func runs: 10000; result: 0.9688326305968623
25 Hilly's; Func runs: 10000; result: 0.6345483084017249
500 Hilly's; Func runs: 10000; result: 0.292167027537253
=============================
5 Forest's; Func runs: 10000; result: 0.946368863880973
25 Forest's; Func runs: 10000; result: 0.5550607959254661
500 Forest's; Func runs: 10000; result: 0.19124225531141872
=============================
5 Megacity's; Func runs: 10000; result: 0.7492307692307693
25 Megacity's; Func runs: 10000; result: 0.4403076923076923
500 Megacity's; Func runs: 10000; result: 0.12526153846153956
=============================
All score: 4.90302 (54.48%)
A visualização do funcionamento do algoritmo SRA no ambiente de teste permite tirar conclusões sobre as características de sua estratégia de busca. Nesse caso, observa-se uma ampla diversificação do espaço de busca, com os agentes distribuídos de maneira relativamente uniforme e explorando até mesmo as regiões mais distantes. Ao mesmo tempo, não há sinais significativos de agrupamento em extremos locais e os movimentos dos agentes parecem caóticos.
Entretanto, apesar da boa capacidade de diversificação, o algoritmo apresenta certas limitações no refinamento das soluções, o que se reflete em uma precisão relativamente baixa de convergência. Também vale destacar uma pequena variação nos resultados obtidos durante os testes.

SRA na função de teste Hilly

SRA na função de teste Forest

SRA na função de teste Megacity
Com base nos testes realizados, o algoritmo ocupa a 20ª posição no ranking dos algoritmos populacionais de otimização mais fortes. Atualmente, a tabela inclui nove algoritmos autorais de otimização (joo), entre os quais está o novo algoritmo SRA.
| № | 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 | 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 | 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 |
| 13 | 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 |
| 14 | 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 |
| 15 | 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 |
| 16 | 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 |
| 17 | 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 |
| 18 | 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 |
| 19 | 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 |
| 20 | 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 |
| 21 | 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 |
| 22 | 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 |
| 23 | 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 |
| 24 | 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 |
| 25 | 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 |
| 26 | 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 |
| 27 | 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 |
| 28 | (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 |
| 29 | 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 |
| 30 | 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 |
| 31 | 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 |
| 32 | 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 |
| 33 | 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 |
| 34 | 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 |
| 35 | 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 |
| 36 | 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 |
| 37 | 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 |
| 38 | 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 |
| 39 | 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 |
| 40 | CGO | chaos game optimization | 0,57256 | 0,37158 | 0,32018 | 1,26432 | 0,61176 | 0,61931 | 0,62161 | 1,85267 | 0,37538 | 0,21923 | 0,19028 | 0,78490 | 3,902 | 43,35 |
| 41 | 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 |
| 42 | 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 |
| 43 | 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 |
| 44 | 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 |
| 45 | CSA | circle search algorithm | 0,66560 | 0,45317 | 0,29126 | 1,41003 | 0,68797 | 0,41397 | 0,20525 | 1,30719 | 0,37538 | 0,23631 | 0,10646 | 0,71815 | 3,435 | 38,17 |
| 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
Após desenvolver e testar o Algoritmo do Restaurateur de Sucesso (SRA), afirmo com segurança que ele apresentou um desempenho respeitável. No momento, ele ocupa a 20ª posição no ranking, o que, para uma nova abordagem, é um resultado bastante positivo. Analisando os resultados, percebi algumas particularidades em seu comportamento. Em problemas de baixa dimensionalidade, os resultados apresentam maior variação. Isso é especialmente evidente na função discreta "Megacity", em que o algoritmo apresenta uma dispersão ainda maior dos valores. Essa função é extremamente desafiadora para algoritmos de otimização e o aprisionamento em extremos locais é mais regra do que exceção.
Em problemas de alta dimensionalidade, o SRA apresenta resultados um pouco abaixo do esperado. Isso provavelmente se deve ao fato de que, em espaços multidimensionais, é necessário um ajuste mais preciso dos parâmetros de temperatura e de taxa de resfriamento para melhorar as soluções mais fracas.
Ainda assim, considero o SRA um algoritmo promissor, com potencial para evoluir. Sua metáfora culinária não apenas torna o conceito intuitivo, mas também possibilita modificações criativas, como o aprimoramento do mecanismo de mutação adaptativa e a realização de experimentos com diferentes esquemas de seleção de "pratos-doadores".
Ao criar o Algoritmo do Restaurateur de Sucesso, não foi minha intenção superar os métodos já existentes, mas sim revelar novos horizontes conceituais através de uma metáfora de vida original. Os resultados obtidos demonstram de forma convincente que esta abordagem merece um lugar no ecossistema dos algoritmos meta-heurísticos.
Surpreendentemente, a ideia de se focar na pior solução da população e de a usar como base para experimentos mostrou-se bastante produtiva, apesar de, à primeira vista, poder parecer absurda. No entanto, é precisamente este princípio de "reabilitação dos azarões" que revela um potencial notável para a otimização. Tal como um restaurador experiente consegue transformar um prato pouco popular num futuro sucesso, o algoritmo consegue converter soluções fracas em versões mais eficazes, aproveitando os "ingredientes" fornecidos pelas soluções líderes.
Esta experiência confirma uma regra valiosa no campo da investigação científica: mesmo as ideias menos ortodoxas, quando bem implementadas, podem proporcionar vantagens práticas. As abordagens fora do padrão frequentemente revelam aspetos de um problema que permanecem invisíveis sob metodologias tradicionais.

Figura 2. Gradação de cores dos algoritmos conforme os testes correspondentes

Figura 3. 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 está o script para cálculo da tabela de classificação)
Prós e contras do algoritmo SRA:
Prós:
- Implementação simples.
- Bons resultados.
Contras:
- Sem desvantagens relevantes.
Está anexado ao artigo um arquivo com as versões atualizadas dos códigos dos algoritmos. O autor não se responsabiliza pela descrição absolutamente fiel dos algoritmos canônicos, já que muitos deles foram modificados para ampliar sua capacidade de busca. As conclusões e opiniões apresentadas baseiam-se nos resultados obtidos durante os experimentos.
Programas utilizados no artigo
| # | Nome | Tipo | Descrição |
|---|---|---|---|
| 1 | C_AO.mqh | Arquivo incluído | Classe principal 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 calcular resultados e gerar a tabela comparativa |
| 7 | Testing AOs.mq5 | Script | Ambiente unificado de testes 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_SRA.mq5 | Script | Ambiente de testes específico para o SRA |
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/17380
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.
Gerente de risco profissional remoto para Forex em Python
Negociando com o Calendário Econômico MQL5 (Parte 4): Implementando Atualizações de Notícias em Tempo Real no Painel
Arbitragem Forex: painel de avaliação de correlações
Utilizando o modelo de Machine Learning CatBoost como Filtro para Estratégias de Seguimento de Tendência
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso