#********************************************/ # 黄金分割法による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 } #*****************************************/ # 黄金分割法(関数の最小値) */ # a,b : 初期区間 a < b */ # eps : 許容誤差 */ # val : 間数値 */ # ind : 計算状況 */ # >= 0 : 正常終了(収束回数) */ # = -1 : 収束せず */ # max : 最大試行回数 */ # fun : 関数値を計算する関数の名前 */ # return : 結果 */ #*****************************************/ def gold(a, b, eps, val, ind, max, &fun) x = 0.0 tau = (Math.sqrt(5.0) - 1.0) / 2.0 count = 0 ind[0] = -1 x1 = b - tau * (b - a) x2 = a + tau * (b - a) f1 = fun.call(x1) f2 = fun.call(x2) while count < max && ind[0] < 0 count += 1 if f2 > f1 if (b-a).abs() < eps && (b-a).abs() < eps*b.abs() ind[0] = 0 x = x1 val[0] = f1 else b = x2 x2 = x1 x1 = a + (1.0 - tau) * (b - a) f2 = f1 f1 = fun.call(x1) end else if (b-a).abs() < eps && (b-a).abs() < eps*b.abs() ind[0] = 0 x = x2 val[0] = f2 f1 = f2 else a = x1 x1 = x2 x2 = b - (1.0 - tau) * (b - a) f1 = f2 f2 = fun.call(x2) end end end if ind[0] == 0 ind[0] = count fa = fun.call(a) fb = fun.call(b) if fb < fa a = b fa = fb end if fa < f1 x = a val[0] = fa end end return x end ind = Array.new(1) val = Array.new(1) a = -2.0 b = -1.0 eps = 1.0e-10 max = 100 x = gold(a, b, eps, val, ind, max, &snx) printf("x %f val %f ind %d\n", x, val[0], ind[0])