記事「母集団最適化アルゴリズム:Shuffled Frog-Leaping (SFL) アルゴリズム」についてのディスカッション

 

新しい記事「母集団最適化アルゴリズム:Shuffled Frog-Leaping (SFL) アルゴリズム」はパブリッシュされました:

本稿では、Shuffled Frog-Leaping (SFL)アルゴリズムの詳細な説明と、最適化問題を解く上でのその能力を紹介します。SFLアルゴリズムは、自然環境におけるカエルの行動から着想を得ており、関数最適化への新しいアプローチを提供します。SFLアルゴリズムは、効率的で柔軟なツールであり、様々な種類のデータを処理し、最適解を得ることができます。

Shuffled Frog Leaping Algorithm (SFL)は、М.Eusuffらによって2003年に提案されました。このアルゴリズムは、Memeticアルゴリズムと粒子群アルゴリズムの原理を組み合わせたもので、その設計は、採食過程におけるカエルの集団の行動にヒントを得たものです。

SFLアルゴリズムは、もともと組合せ最適化問題を解くためのメタヒューリスティクス手法として開発されました。これは数学的関数の使用と、情報に基づいたヒューリスティックな探索に基づいています。

SFLアルゴリズムは、ミームプレックスと呼ばれるカエルの複数の相互作用する仮想集団で構成されます。仮想のカエルはミームの宿主またはキャリアとして機能し、ミームは文化的進化の単位を表します。各ミームプレックスは、粒子群最適化に似た手法を用いて、独立した局所探索をおこないますが、局所探索に重点が置かれています。

大域的探索をサポートするため、シャッフル複合進化アルゴリズムに似た方法で、仮想カエルは定期的にシャッフルされ、新しいミームプレックスに再編成されます。さらに、改良された情報がランダムに生成されるように、ランダムな仮想カエルが生成され、集団の中で入れ替わります。

Shuffled Frog-Leapingは、複雑な最適化問題を解くのに有効な方法です。様々な応用領域で最適解を得ることができます。この記事では、このアルゴリズムの基本原理と応用、そして利点と限界について見ていきます。

作者: Andrey Dik

 
К каждой статье я прикрепляю архив, содержащий обновленные актуальные версии кодов алгоритмов, описанных в предыдущих статьях.

素晴らしい仕事をしてくれた作者に感謝し、無償で使わせてもらった!


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));
  }
}

ちょっとコードを見ている。そして、この美しさをこのような恐怖に置き換えた。

#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;
  }
}
 
fxsaber #:

コードを少し見てみよう。

私の理解が正しければ、クラスの形をした最適化アルゴリズムの実装はすべて、書式なしの共通インターフェースをいくつか持っている。特に、サーチクラウドの設定。

  public: double rangeMax  []; //maximum search range
  public: double rangeMin  []; //manimum search range
  public: double rangeStep []; //step search

これを使いやすい形に定式化することは可能でしょうか?大雑把に言えば、基本クラスがあり、そこからすべてのアルゴリズムの実装を継承し、仮想関数を通して同じように使用する。

 
fxsaber #:

素晴らしい仕事をしてくれた作者に感謝するとともに、ありがたく使わせてもらう機会を与えてくれたことに感謝する!

ありがとうございます。)

fxsaber#:

コードを少し見てみる。そして、この美しさをこのような恐怖に置き換えた。

面白い

fxsaber#:

私の理解が正しければ、クラスとしての最適化アルゴリズムの実装はすべて、ある種のフォーマットされていない共通インターフェースを持っている。具体的には、サーチクラウドの仕様だ。

これを使いやすい形に定式化することは可能でしょうか?大雑把に言えば、ベースクラスがあり、そこからすべてのアルゴリズムの実装を継承し、仮想関数を通して同じように使う。

1. はい、私は単純な方法を取り、アルゴリズムの境界条件をオープンメンバー、つまり配列の形にしました。

2.一般的に、最適化アルゴリズムには、その動作のロジックという点で、非常に多くの種類がありますが、私はそれらをすべて統一しようとしました。

3. すべてのアルゴリズムを一般的なクラスの子オブジェクトにするアイデアを持っていましたが、これでは記事の教育目的には使えません。

4.しかし、2.で行った作業のおかげで、すべてのアルゴリズムを統一し、統一性を持たせることができるのは事実です。


rangeMaxやその他の境界条件はInitメソッドの引数であるべきである。

 
fxsaber #:


ちょっとコードを見ているんだ。この美しさを、こんな恐ろしいものに置き換えてみた。

リクエストに応じた関数の作成は、(文字列のダンスや、クラス名や列挙要素のマッチするフラグメントでの「抱き合わせ」なしで)クラスそのもので行われるべきだ。そこに著者の変種がある。もうひとつ、こんなものもある:

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;
  }
  ...
};
...

このようなスクリプトで使用する:

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
  }
}
 
Stanislav Korotky #:

リクエストに応じて関数を作成するのは、ぜひともクラス自体にあるべきだ(文字列の踊りや、クラス名と列挙要素の一致する断片に「結びつける」ことなく)。そこには著者のバリエーションがある。もうひとつ、こんなものもある:

Functions.mqhファイル:

このようなスクリプトで使用します:

このオプションに対する2つの反論。

  1. 文字列による関数の指定を拒否する - iniファイルによるロボット設定の指定を拒否する。
  2. シングルトン - 異なる設定を持つ複数の同一ロボットの並列作業を拒否する。
 
fxsaber #:

この選択肢には2つの反論がある。

  1. 文字列による関数指定の拒否 - iniファイルによるロボット設定の指定の拒否。
  2. シングルトン - 異なる設定を持つ複数の同一ロボットの並列作業の拒否。

文字列検索(!)を使ったループの使い方に「はまった」のだが、大きなプログラムでは超非効率的になりかねない。

iniファイルの文字列パラメータだけでなく、他の型(テキストで表現されるが)も同様だ。

ファクトリーでのシングルトンは問題ない。関数オブジェクトでのシングルトン - この場合は例の操作性のためだけだが、多重性を実装できる。

 
Stanislav Korotky #:

文字列検索(!)でループを使うことに "はまった "のだが、大きなプログラムでは超非効率的になる可能性がある。

iniファイルには文字列パラメーターだけでなく、他のタイプのパラメーターも含まれている(テキストで表現されているが)。

ファクトリーでのシングルトンは問題ない。関数オブジェクトでのシングルトン - この場合は例の操作性のためだけですが - 多重性を実装できます。

私は初期化の段階で文字列解決を使います。ミリ秒もかからないと思います。正直なところ、潜在的な問題は感じなかった。

 
fxsaber #:

素晴らしい仕事をしてくれた作者に感謝するとともに、ありがたく使わせてもらう機会を与えてくれたことに感謝する!



ちょっとコードを見ている。そして、この美しさをこのような恐怖に置き換えた。

このゲインは何だ?本当に恐ろしい。何かあればすみません))

 
Stanislav Korotky #:

語句の語句の語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句語句そこには著者のバリエーションがある。もうひとつ、こんなものもある:

Functions.mqhファイル:

このようなスクリプトで使用します:

申し訳ないが、私はもちろん間違っている:

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>()};
 

各タイプのオブジェクトを作成しないのですか?

......では、どのように、1つのタイプは、プログラムの全体の時間の間に使用されます。

 
Dmitry Fedoseev #:

ゲインは?というか、本当にひどい。何かあったら謝ります)))

難しい質問だね。分からないよ。

理由: