/*********************************************/
/* 多項式近似によるy=x^4+3x^3+2x^2+1の最小値 */
/* coded by Y.Suganuma */
/*********************************************/
import java.io.*;
public class Test {
public static void main(String args[]) throws IOException
{
double eps, x, d, val[] = new double [1];
int max, ind[] = new int [1];
x = -2.0;
d = 0.1;
eps = 1.0e-10;
max = 100;
Kansu kn = new Kansu();
x = kn.approx(x, d, eps, val, ind, max);
System.out.println("x " + x + " val " + val[0] + " ind " + ind[0]);
}
}
/****************/
/* 関数値の計算 */
/****************/
class Kansu extends Approximation
{
double snx(double x)
{
double y = x * x * x * x + 3.0 * x * x * x + 2.0 * x * x + 1.0;
return y;
}
}
abstract class Approximation {
/************************************************/
/* 多項式近似(関数の最小値) */
/* x0 : 初期値 */
/* d0 : 初期ステップ */
/* eps : 許容誤差 */
/* val : 間数値 */
/* ind : 計算状況 */
/* >= 0 : 正常終了(収束回数) */
/* = -1 : 収束せず */
/* max : 最大試行回数 */
/* return : 結果 */
/************************************************/
abstract double snx(double x);
double approx(double x0, double d0, double eps, double val[], int ind[], int max)
{
double f[] = new double [4];
double x[] = new double [4];
double xx = 0.0, d, dl;
int i1, k = 0, count = 0, min, sw = 0;
d = d0;
x[1] = x0;
f[1] = snx(x0);
ind[0] = -1;
while (count < max && ind[0] < 0) {
x[3] = x[1] + d;
f[3] = snx(x[3]);
while (k < max && f[3] <= f[1]) {
k++;
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] = snx(x[3]);
}
// 初期値が不適当
if (k >= max)
count = max;
else {
// 3点の選択
sw = 0;
if (k > 0) {
x[2] = x[3] - 0.5 * d;
f[2] = snx(x[2]);
min = -1;
for (i1 = 0; i1 < 4; i1++) {
if (min < 0 || f[i1] < f[min])
min = i1;
}
if (min >= 2) {
for (i1 = 0; i1 < 3; i1++) {
x[i1] = x[i1+1];
f[i1] = f[i1+1];
}
}
sw = 1;
}
else {
x[0] = x[1] - d0;
f[0] = snx(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;
}
}
// 収束?
if (sw > 0) {
count++;
dl = 0.5 * d * (f[2] - f[0]) / (f[0] - 2.0 * f[1] + f[2]);
xx = x[1] - dl;
val[0] = snx(xx);
if (Math.abs(dl) < 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];
}
}
}
}
}
return xx;
}
}