/* golden.c */
#include <stdio.h>
#include <math.h>
#define R 0.61803399 /* 黄金分割比 golden section ratio */
#define C (1.0 - R)
#define SHFT2(a,b,c) (a)=(b); (b)=(c);
#define SHFT3(a,b,c,d) (a)=(b); (b)=(c); (c)=(d);
/*
関数 f と、極小を囲い込む2点のx座標 ax,bx とを与えると、黄金分割法で極小を
与える。戻り値は極小値で、そのx座標は xmin に入る。xmin の相対精度はほぼ
tol になる。
*/
double golden(double ax, double bx, double (*f)(double), double tol, double *xmin)
{
double f1, f2, x0, x1, x2, x3;
x0 = ax; /* 4点 x0,x1,x2,x3 を更新していく */
x1 = ax + C * (bx - ax);
x2 = ax + R * (bx - ax);
x3 = bx;
f1 = (*f)(x1); /* 関数の最初の評価 */
f2 = (*f)(x2);
while(fabs(x3 - x0) > tol * (fabs(x1) + fabs(x2))) /* 収束判定 */
{
if(f2 < f1) /* 場合分けの一方 */
{
SHFT3(x0, x1, x2, R * x1 + C * x3) /* 各点の更新 */
SHFT2(f1, f2, (*f)(x2)) /* 関数を評価 */
}
else /* 場合分けのもう一方 */
{
SHFT3(x3, x2, x1, R * x2 + C * x0)
SHFT2(f2, f1, (*f)(x1)) /* 関数を評価 */
}
}
if(f1 < f2) /* 完成。最新の2点のうち良い方を返す */
{
*xmin = x1;
return f1;
}
else
{
*xmin = x2;
return f2;
}
}
double f(double x)
{
return 5. + fabs((x - 1.6)*(x - 10.)*(x + 8.));
}
int main(void)
{
double ax, bx, fmin, xmin, tol;
ax = 1.0;
bx = 2.0;
tol = 1.e-6;
printf("f(x)=|(x-1.6)(x-10)(x+8)|\n");
printf("極小点 x=1.6,10,-8\n");
printf("[ input ]\n");
printf("start point : ax=%f, bx=%f\n", ax, bx);
printf("tolerance = %e\n", tol);
fmin = golden(ax, bx, f, tol, &xmin);
printf("[ output ]\n");
printf("xmin=%f, fmin=%f\n", xmin, fmin);
return 1;
}
|