#********************************************/ # 多項式近似によるy=x^4+3x^3+2x^2+1の最小値 */ # coded by Y.Suganuma */ #********************************************/ #***************/ # 関数値の計算 */ #***************/ snx = Proc.new { |x| x * x * x * x + 3.0 * x * x * x + 2.0 * x * x + 1.0 } #*****************************************/ # 多項式近似(関数の最小値) */ # x0 : 初期値 */ # d0 : 初期ステップ */ # eps : 許容誤差 */ # val : 関数値 */ # ind : 計算状況 */ # >= 0 : 正常終了(収束回数) */ # = -1 : 収束せず */ # max : 最大試行回数 */ # fun : 関数値を計算する関数の名前 */ # return : 結果 */ #*****************************************/ def approx(x0, d0, eps, val, ind, max, &fun) f = Array.new(4) x = Array.new(4) xx = 0.0 d = d0 x[1] = x0 f[1] = fun.call(x0) k = 0 count = 0 ind[0] = -1 while count < max && ind[0] < 0 x[3] = x[1] + d f[3] = fun.call(x[3]) while k < max && f[3] <= f[1] k += 1 d *= 2.0 x[0] = x[1] f[0] = f[1] x[1] = x[3] f[1] = f[3] x[3] = x[1] + d f[3] = fun.call(x[3]) end # 初期値が不適当 if k >= max count = max else # 3点の選択 sw = 0 if k > 0 x[2] = x[3] - 0.5 * d f[2] = fun.call(x[2]) min = -1 for i1 in 0 ... 4 if min < 0 || f[i1] < f[min] min = i1 end end if min >= 2 for i1 in 0 ... 3 x[i1] = x[i1+1] f[i1] = f[i1+1] end end sw = 1 else x[0] = x[1] - d0 f[0] = fun.call(x[0]) if f[0] > f[1] x[2] = x[3] f[2] = f[3] sw = 1 else x[1] = x[0] f[1] = f[0] d0 = -d0 d = 2.0 * d0 k = 1 end end # 収束? if sw > 0 count += 1 dl = 0.5 * d * (f[2] - f[0]) / (f[0] - 2.0 * f[1] + f[2]) xx = x[1] - dl val[0] = fun.call(xx) if dl.abs() < eps ind[0] = count else k = 0 d0 = 0.5 * d d = d0 if val[0] < f[1] x[1] = xx f[1] = val[0] end end end end end return xx end ind = Array.new(1) val = Array.new(1) x = -3.0 d = 0.1 eps = 1.0e-7 max = 100 x = approx(x, d, eps, val, ind, max, &snx) printf("x %f val %f ind %d\n", x, val[0], ind[0])