C#、数値計算 - 1次元の黄金分割探索の計算方法とソースプログラム

 

1 黄金分割探索法

今日は黄金分割検索法を導き出しました。 授業ノートも参照してください。

区間 [a,b] にわたる関数 f(x) の最小値を見つけるための黄金分割検索の方法の導出。

想定します

  • f(x) は [a,b] にわたって連続であり、
  • f(x) は [a,b] に対して「単峰性」です。これは、f(x) が [a,b] 内で最小値を 1 つだけ持つことを意味します。

この方法は最大値を求める場合にも適用されることに注意してください。

上記の条件は二分法を思い出させます。同様のアイデアを適用します。つまり、最小の比較関数値を含む区間を狭めます。
このメソッドを設計する際に、次の 2 つの目標を満たすように努めます。

  1. 検索間隔の最適な削減係数。
  2. 関数呼び出しの最小数。

これらの目標を念頭に置いて、関数を評価する場所を決定します。

二分法にヒントを得た選択肢の 1 つは、中点 m = (a+b)/2 を計算し、x1 = m - eps/2 および x2 = m + eps/2 で定義される x1 および x2 で評価することです。 f(x1) /= f(x2) となる小さな値の eps。f(x1) < f(x2) の場合は [a,x1] が残り、それ以外の場合は [x2,b] が新しい検索間隔になります。これにより各ステップの検索間隔が半分になりますが、各ステップで 2 つの新しい関数評価を行う必要があります。これは最適ではありません。

したがって、各ステップで新しい関数の評価を 1 つだけ実行する必要があります。さらに、間隔のサイズに対して一定の縮小係数 (たとえば c) が必要です。

今日、黄金分割検索メソッドを導き出しました。クラスノートも参照してください。

黄金分割探索法を導出して、区間 [a,b] 上の関数 f(x) の最小値を見つけます。

仮定してみましょう

f(x) は [a,b] 上で連続であり、

f(x) は [a,b] 上で「単峰性」です。これは、f(x) が [a,b] 内に最小値を 1 つだけ持つことを意味します。

この方法は最大値を見つける場合にも機能することに注意してください。

上記の条件は二分法を使用することを思い出させます。同様のアイデアを適用します。つまり、比較関数の最小値を含む区間を狭めます。

メソッドを設計するときは、次の 2 つの目標を満たすように努めます。

検索間隔の最適な削減係数。

関数呼び出しの最小数。

これらの目標を念頭に置いて、関数をどこで評価するかを決定します。

二等分にヒントを得たオプションの 1 つは、中点 m=(a+b)/2 を計算し、評価するいくつかの小さな値 eps について f(x1 )/=f(x2) を比較することです。f(x1) < f(x2) の場合は [a,x1] が残り、それ以外の場合は [x2,b] が新しい検索間隔になります。これにより各ステップの検索間隔が半分になりますが、各ステップで 2 つの新しい関数評価を行う必要があります。これは最適ではありません。

したがって、各ステップで新しい機能の評価のみを実行する必要があります。また、間隔のサイズについては、一定の縮小係数、たとえば c が必要です。

2 C# ソースコード

システムを使用する;

namespace Legalsoft.Truffer
{     /// <summary>     /// 1 次元のゴールデン セクション検索     /// </summary>     public class Golden : Bracketmethod     {         //public delegateFunc func { get; セット; } = null;





        public double xmin { 取得; セット; パブリック
        ダブルfmin {取得; セット; public
        double tol {get; セット; }

        public Golden(double toll = 3.0e-8)
        {             this.tol = toll;         }

        public double minimum(UniVarRealValueFun func)
        {             const double R = 0.61803399;             ダブル C = 1.0 - R;             ダブルx1。             ダブルx2。             ダブル x0 = 斧;             ダブル x3 = cx;             if (Math.Abs​​(cx - bx) > Math.Abs​​(bx - ax))             {                 x1 = bx;                 x2 = bx + C * (cx - bx);             }             else             {                 x2 = bx;                 x1 = bx - C * (bx - ax);             ダブル             f1 = func.funk(x1);             double f2 = func.funk(x2);


















            while (Math.Abs​​(x3 - x0) > tol * (Math.Abs​​(x1) + Math.Abs​​(x2)))
            {                 if (f2 < f1)                 {                     shft3(ref x0, ref x1, ref x2, R * x2 + C * x3);                     shft2(ref f1, ref f2, func.funk(x2));                 }                 else                 {                     shft3(ref x3, ref x2, ref x1, R * x1 + C * x0);                     shft2(ref f2, ref f1, func.funk(x1));             if (f1 < f2)             {                 xmin = x1;             }                 }                 fmin = f1;             }
















            else
            {                 xmin = x2;                 fmin = f2;             xminを返し             ます。         } }     }







 

おすすめ

転載: blog.csdn.net/beijinghorn/article/details/132286385