Agradeço ao autor por ter feito um ótimo trabalho e pela oportunidade gratuita de usá-lo!
enum EFunc { Skin, Forest, Megacity, Rastrigin, Universe }; C_Function *SelectFunction (EFunc f) { C_Function *func; switch (f) { case Skin: func = new C_Skin (); return (GetPointer (func)); case Forest: func = new C_Forest (); return (GetPointer (func)); case Megacity: func = new C_Megacity (); return (GetPointer (func)); case Rastrigin: func = new C_Rastrigin (); return (GetPointer (func)); case Universe: func = new C_Universe (); return (GetPointer (func)); default: func = new C_Skin (); return (GetPointer (func)); } }
Estou analisando um pouco o código. E substituí essa beleza por um horror.
#property script_show_inputs #include <Math\Functions.mqh> // https://www.mql5.com/ru/articles/13366 template <typename T> C_Function* New( const string &ClassName ) { return((typename(T) == ClassName) ? new T : NULL); } C_Function* New2( string ClassName ) { typedef C_Function* (*TNew)( const string& ); static const TNew FuncNew[] = {New<C_Skin>, New<C_Forest>, New<C_Megacity>, New<C_Rastrigin>, New<C_Universe>}; C_Function* Res = NULL; ClassName = "class " + ClassName; for (uint i = ArraySize(FuncNew); (Res == NULL) && (bool)i--;) Res = FuncNew[i](ClassName); return(Res); } C_Function* SelectFunction2( const EFunc f ) { return(New2("C_" + EnumToString(f))); } input EFunc inFunc = Skin; void OnStart() { C_Function* Func = SelectFunction2(inFunc); if (Func != NULL) { Print(Func.GetNamFun()); delete Func; } }
Se entendi corretamente, todas as implementações de algoritmos de otimização na forma de classes têm alguma interface comum não formatada. Em particular, a configuração da nuvem de pesquisa.
public: double rangeMax []; //maximum search range public: double rangeMin []; //manimum search range public: double rangeStep []; //step search
É possível formalizar isso na forma de alguma variante fácil de usar? Em termos gerais, há uma classe base, herdamos as implementações de todos os algoritmos dela e as usamos da mesma forma por meio de funções virtuais.
Obrigado, fico feliz que meu trabalho seja útil)))
interessante
Se entendi corretamente, todas as implementações de algoritmos de otimização como classes têm algum tipo de interface comum não formatada. Especificamente, a especificação da nuvem de pesquisa.
É possível formalizá-la em alguma variante fácil de usar? Em termos gerais, há uma classe base, herdamos as implementações de todos os algoritmos dela e as usamos da mesma forma por meio de funções virtuais.
1. sim, adotei a maneira mais simples e criei as condições de limite dos algoritmos na forma de membros abertos - matrizes.
2. em geral, embora haja uma enorme variedade de algoritmos de otimização em termos da lógica de seu trabalho, tentei torná-los uniformes; todos eles têm três etapas: inicialização, movimentação de agentes para novas posições e revisão e, entre as duas últimas, o cálculo do FF, o que permite a aplicação flexível de algoritmos em aplicativos de usuários.
3. eu tive a ideia de fazer todos os algoritmos como objetos filhos de uma classe genérica, mas isso impede que, para fins didáticos dos artigos, as variáveis sejam nomeadas e comentadas especificamente para cada algoritmo e ajudem a entender melhor a lógica.
4. Entretanto, é verdade que todos os algoritmos podem ser unificados e uniformizados graças ao trabalho realizado no ponto 2.
O rangeMax e outras condições de limite devem ser argumentos no método Init.
A criação de uma função sob solicitação deve ser feita na própria classe (sem danças de string e "amarração" em fragmentos correspondentes de nomes de classe e elementos de enumeração). Há uma variante do autor aqui. Aqui está outra - algo como isto:
Arquivo Functions.mqh:
class C_Function; // forward declaration for use in FunctionInstance base class class FunctionInstance // common parent for all fabrics to be used in unified manner, for example listed in an array { protected: C_Function *instance; public: FunctionInstance(): instance(NULL) { } ~FunctionInstance() // destructor provides garbage collection { if(CheckPointer(instance) == POINTER_DYNAMIC) delete instance; } virtual C_Function *create() = 0; }; template<typename T> class FunctionFabric: public FunctionInstance // specific fabric { public: virtual T *create() override { if(instance == NULL) instance = new T; // here dynamic "singleton" pattern is implemeted for simplicity only (could be a collection of objects or no references at all) return instance; } }; //—————————————————————————————————————————————————————————————————————————————— class C_Function { public: template<typename T> static FunctionFabric<T> *fabric() { static FunctionFabric<T> singleton; // here static "singleton" is implemeted as most appropriate for fabric (no need to have more than 1 fabric per class) return &singleton; } ... }; ...
Use em um script como este:
C_Function* NewX(const EFunc elem) { // order of initialization corresponds to EFunc enumeration static FunctionInstance *pointers[] = {C_Function::fabric<C_Skin>(), C_Function::fabric<C_Forest>(), C_Function::fabric<C_Megacity>(), C_Function::fabric<C_Rastrigin>(), C_Function::fabric<C_Universe>()}; return pointers[elem].create(); } void OnStart() { C_Function* Func = NewX(inFunc); if (Func != NULL) { Print(Func.GetNamFun()); // delete Func; // not needed anymore, fabric will do itself } }
De qualquer forma, a criação de uma função sob solicitação deve estar na própria classe (sem danças de string e "amarração" em fragmentos correspondentes de nomes de classe e elementos de enumeração). Há uma variante do autor aqui. Aqui está outra - algo parecido com isto:
Arquivo Functions.mqh:
Use em um script como este:
Dois argumentos contra essa opção.
- Recusar-se a especificar uma função por uma string - recusar-se a especificar as configurações do robô por meio do arquivo ini.
- Singleton - recusa de trabalho paralelo de vários robôs idênticos com configurações diferentes.
Dois argumentos contra essa opção.
- Recusa de especificar uma função por meio de uma string - recusa de especificar as configurações do robô por meio de um arquivo ini.
- Singleton - recusa de trabalho paralelo de vários robôs idênticos com configurações diferentes.
Eu a esbocei apenas porque, se for criar alguns truques, sem problemas em potencial - fui "fisgado" pelo uso de loop com pesquisa de string (!) - ela pode ser muito ineficiente em programas maiores.
Não apenas os parâmetros de string no arquivo ini, mas também outros tipos (embora representados por texto).
Um singleton em uma fábrica não tem problema. Singleton em um objeto de função - nesse caso, apenas para a operacionalidade do exemplo - você pode implementar a multiplicidade.
Eu apenas o esbocei porque, se vou criar algum truque, ele deve ser feito sem problemas em potencial - fui "fisgado" pelo uso de um loop com pesquisa de string (!) - ele pode ser muito ineficiente em programas maiores.
O arquivo ini não contém apenas parâmetros de cadeia de caracteres, mas também outros tipos de parâmetros (embora eles sejam representados por texto).
Um singleton em uma fábrica é aceitável. Singleton em um objeto de função - nesse caso, apenas para a operacionalidade do exemplo - você pode implementar a multiplicidade.
Eu uso a resolução de strings no estágio de inicialização. Acho que isso leva menos de um milissegundo. Sinceramente, não senti nenhum problema em potencial.
De qualquer forma, a criação de uma função sob solicitação deve estar na própria classe (sem danças de string e "amarração" em fragmentos correspondentes de nomes de classe e elementos de enumeração). Há uma variante do autor aqui. Aqui está outra - algo parecido com isto:
Arquivo Functions.mqh:
Use em um script como este:
Desculpe, mas é claro que estou errado, bem ali naquela linha de código:
static FunctionInstance *pointers[] = {C_Function::fabric<C_Skin>(), C_Function::fabric<C_Forest>(), C_Function::fabric<C_Megacity>(), C_Function::fabric<C_Rastrigin>(), C_Function::fabric<C_Universe>()};
não criará um objeto de cada tipo?
...então como, apenas um tipo será usado durante todo o tempo do programa.
![MQL5 - Linguagem para estratégias de negociação inseridas no terminal do cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- 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
Novo artigo Algoritmos de otimização populacionais: salto de sapo embaralhado foi publicado:
O artigo apresenta uma descrição detalhada do algoritmo salto de sapo embaralhado (Shuffled Frog Leaping Algorithm, SFL) e suas capacidades na solução de problemas de otimização. O algoritmo SFL é inspirado no comportamento dos sapos em seu ambiente natural e oferece uma nova abordagem para a otimização de funções. O algoritmo SFL é uma ferramenta eficaz e flexível, capaz de lidar com diversos tipos de dados e alcançar soluções ótimas.
O algoritmo salto de sapo embaralhado (Shuffled Frog Leaping Algorithm, SFL) foi proposto por M. Eusuff e outros autores em 2003. Este algoritmo combina princípios do algoritmo memético e do algoritmo enxame de partículas, e seu desenvolvimento foi inspirado no comportamento de um grupo de sapos na busca por alimento.
Originalmente, o algoritmo SFL foi desenvolvido como um método metaheurístico para resolver problemas de otimização combinatória. Ele é baseado no uso de funções matemáticas e busca heurística informada.
O algoritmo SFL consiste em várias populações virtuais interativas de sapos, chamadas memplexos. Os sapos virtuais desempenham o papel de hospedeiros ou portadores de memes, aqui um meme representa uma unidade de evolução cultural. Em cada memplexo, ocorre uma busca local independente usando um método semelhante à otimização por enxame de partículas, mas com foco na busca local.
Para facilitar as explorações globais, os sapos virtuais são periodicamente embaralhados e reorganizados em novos memplexos usando um método semelhante ao algoritmo de evolução complexa embaralhada. Além disso, sapos virtuais aleatórios são gerados e substituídos na população para permitir a geração aleatória de informações aprimoradas.
O algoritmo salto de sapo embaralhado é um método eficaz para resolver problemas complexos de otimização e permite alcançar soluções ótimas em várias áreas de aplicação. Neste artigo, examinaremos os princípios fundamentais e a aplicação deste algoritmo, bem como suas vantagens e limitações.
Autor: Andrey Dik