Discussing the article: "Population optimization algorithms: Shuffled Frog-Leaping algorithm (SFL)"
Thanks to the author for doing a great job and for the gratuitous opportunity to use it!
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)); } }
I'm looking at the code a bit. And replaced this beauty with such a horror.
#property script_show_inputs #include <Math\Functions.mqh> // https://www.mql5.com/en/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; } }
If I understand correctly, all implementations of optimisation algorithms in the form of classes have some unformatted common interface. In particular, setting the search cloud.
public: double rangeMax []; //maximum search range public: double rangeMin []; //manimum search range public: double rangeStep []; //step search
Is it possible to formalise it in the form of some easy-to-use variant? Roughly speaking, there is a base class, we inherit implementations of all algorithms from it, and then use them in the same way through virtual functions.
Thanks, glad my work is useful)))
interesting
If I understand correctly, all implementations of optimisation algorithms as classes have some kind of unformatted common interface. Specifically, the search cloud specification.
Is it possible to formalise it in some easy-to-use variant? Roughly speaking, there is a base class, we inherit implementations of all algorithms from it, and then use them in the same way through virtual functions.
1. yes, I took the simple way and made the boundary conditions of algorithms in the form of open members - arrays.
2. in general, while there is a huge variety of optimisation algorithms in terms of the logic of their work, I tried to make them all uniform, they all have three steps: initialisation, moving agents to new positions and revision, and between the last two, calculation of FF, this allows flexible application of algorithms in user applications.
3. i had the idea to make all algorithms as child objects of a generic class, but this prevents for teaching purposes of the articles, variables are named and commented specific to each algorithm and help to understand the logic better.
4. however, it is true that all algorithms can be unified and brought to uniformity thanks to the work done in point 2.
The rangeMax and other boundary conditions should be arguments in the Init method.
The creation of a function on request should be done in the class itself (without string dances and "tying" on matching fragments of class names and enumeration elements). There's a variant of the author there. Here is another one - something like this:
Functions.mqh file:
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 in a script like this:
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 } }
By all means, creating a function on request should be in the class itself (without string dances and "tying" on matching fragments of class names and enumeration elements). There's a variant of the author there. Here is another one - something like this:
Functions.mqh file:
Use in a script like this:
Two arguments against this option.
- Refuse to specify a function by a string - refuse to specify robot settings via ini-file.
- Singleton - refusal of parallel work of several identical robots with different settings.
Two arguments against this option.
- Refusal to specify a function by a string - refusal to specify robot settings via an ini-file.
- Singleton - refusal of parallel work of several identical robots with different settings.
I sketched it just because if I'm going to create some contrivances, then without potential problems - I was "hooked" by the use of loop with string search (!) - it can be super inefficient in bigger programmes.
Not only string parameters in the ini file, but also other types (though represented by text).
Singleton at a factory is fine. Singleton at function object - in this case just for the operability of the example - you can implement multiplicity.
I just sketched it out because if I'm going to build some contrivances, it should be without potential problems - I was "hooked" by the use of a loop with string search (!) - it can be super inefficient in bigger programmes.
The ini-file does not only contain string parameters, but also other types of parameters (although they are represented by text).
A singleton at a factory is fine. Singleton at function object - in this case just for the operability of the example - you can implement multiplicity.
I use string-resolution at the initialisation stage. I think it takes less than a millisecond. Honestly, I didn't feel any potential problems.
By all means, creating a function on request should be in the class itself (without string dances and "tying" on matching fragments of class names and enumeration elements). There's a variant of the author there. Here is another one - something like this:
Functions.mqh file:
Use in a script like this:
Sorry, but I'm wrong of course, right there in that line of code:
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>()};
will not create an object of each type?
...then how, only one type will be used during the whole time of the programme.

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Check out the new article: Population optimization algorithms: Shuffled Frog-Leaping algorithm (SFL).
The article presents a detailed description of the shuffled frog-leaping (SFL) algorithm and its capabilities in solving optimization problems. The SFL algorithm is inspired by the behavior of frogs in their natural environment and offers a new approach to function optimization. The SFL algorithm is an efficient and flexible tool capable of processing a variety of data types and achieving optimal solutions.
The Shuffled Frog Leaping Algorithm (SFL) was proposed by М. Eusuff and other authors in 2003. This algorithm combines the principles of the memetic algorithm and the particle swarm algorithm, and its design was inspired by the behavior of a group of frogs during the foraging process.
The SFL algorithm was originally developed as a metaheuristic method for solving combinatorial optimization problems. It is based on the use of mathematical functions and informed heuristic search.
The SFL algorithm consists of several interacting virtual populations of frogs called memeplexes. Virtual frogs act as hosts or carriers of memes, where a meme represents a unit of cultural evolution. Each memeplex undergoes an independent local search using a method similar to particle swarm optimization, but with an emphasis on local search.
To support global exploration, virtual frogs are periodically shuffled and reorganized into new memeplexes using a method similar to the shuffled complex evolution algorithm. In addition, random virtual frogs are generated and replaced in the population to allow improved information to be generated randomly.
The shuffled frog-leaping is an effective method for solving complex optimization problems. It can achieve optimal solutions in various application domains. In this article, we will look at the basic principles and applications of this algorithm, as well as its advantages and limitations.
Author: Andrey Dik