1変数関数の極小値求解プログラム1



[ 簡単な説明 ]

黄金分割法による1変数関数の極小値求解プログラムです。

出力例 1 〜 4 は、極小値を囲い込む範囲を変えて、関数
f (x) = 5 + |(x−1.6)(x−10)(x+8)|
の極小を求めています。

極小値求解プログラムは、与える関数の符号を変えれば、極大値求解に使用できます。


プログラム・ソース("golden.c")           top (トップに戻る)
/*		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;
}

出力例 1           top (トップに戻る)
f(x)=|(x-1.6)(x-10)(x+8)|
極小点 x=1.6,10,-8
[ input ]
start point : ax=1.000000, bx=2.000000
tolerance = 1.000000e-06
[ output ]
xmin=1.600000, fmin=5.000017

出力例 2           top (トップに戻る)
f(x)=|(x-1.6)(x-10)(x+8)|
極小点 x=1.6,10,-8
[ input ]
start point : ax=-10.000000, bx=20.000000
tolerance = 1.000000e-06
[ output ]
xmin=1.600000, fmin=5.000008

出力例 3           top (トップに戻る)
f(x)=|(x-1.6)(x-10)(x+8)|
極小点 x=1.6,10,-8
[ input ]
start point : ax=-10.000000, bx=0.000000
tolerance = 1.000000e-06
[ output ]
xmin=-7.999999, fmin=5.000186

出力例 4           top (トップに戻る)
f(x)=|(x-1.6)(x-10)(x+8)|
極小点 x=1.6,10,-8
[ input ]
start point : ax=5.000000, bx=20.000000
tolerance = 1.000000e-06
[ output ]
xmin=9.999999, fmin=5.000157