mskefile,データ例,プログラム
-------------------------i_data------------------------- // 関数 a 関数 1 変数の数 2 最大試行回数 1000 初期値設定係数 1.0 許容誤差 1.0e-20 縮小比率 0.7 拡大比率 1.5 初期値 0.0 0.0 // 関数 b 関数 2 変数の数 2 最大試行回数 1000 初期値設定係数 1.0 許容誤差 1.0e-20 縮小比率 0.7 拡大比率 1.5 初期値 0.0 0.0 // 関数 c 関数 3 変数の数 2 最大試行回数 1000 初期値設定係数 1.0 許容誤差 1.0e-20 縮小比率 0.7 拡大比率 1.5 初期値 0.0 0.0 -------------------------program------------------------- /**************************************/ /* シンプレックス法による最小値の計算 */ /* coded by Y.Suganuma */ /**************************************/ #include <stdio.h> double snx1(double *); double snx2(double *); double snx3(double *); int simplex(int, int, double, double, double, double, double *, double *, double (*)(double *)); int main() { double eps, r1, r2, *x, y, k; int fun, i1, max, n, sw = 0; // データの入力 scanf("%*s %d %*s %d %*s %d %*s %lf", &fun, &n, &max, &k); scanf("%*s %lf %*s %lf %*s %lf", &eps, &r1, &r2); x = new double [n]; scanf("%*s"); for (i1 = 0; i1 < n; i1++) scanf("%lf", &x[i1]); // 実行 switch (fun) { case 1: sw = simplex(max, n, k, eps, r1, r2, &y, x, snx1); break; case 2: sw = simplex(max, n, k, eps, r1, r2, &y, x, snx2); break; case 3: sw = simplex(max, n, k, eps, r1, r2, &y, x, snx3); break; } // 結果の出力 if (sw < 0) printf(" 収束しませんでした!"); else { printf(" 結果="); for (i1 = 0; i1 < n; i1++) printf("%f ", x[i1]); printf(" 最小値=%f 回数=%d\n", y, sw); } delete [] x; return 0; } /******************************************/ /* シンプレックス法 */ /* max : 最大繰り返し回数 */ /* n : 次元 */ /* k : 初期値設定係数 */ /* r1 : 縮小比率 */ /* r2 : 拡大比率 */ /* y : 最小値 */ /* x : x(初期値と答え) */ /* snx : 関数値を計算する関数名 */ /* return : >=0 : 正常終了(収束回数) */ /* =-1 : 収束せず */ /******************************************/ #include <math.h> int simplex(int max, int n, double k, double eps, double r1, double r2, double *y, double *x, double (*snx)(double *)) { double **xx, *yy, *xg, *xr, *xn, yr, yn, e; int i1, i2, fh = -1, fg = -1, fl = -1, count = 0, sw = -1; // 初期値の設定 yy = new double [n+1]; xg = new double [n]; xr = new double [n]; xn = new double [n]; xx = new double * [n+1]; for (i1 = 0; i1 < n+1; i1++) xx[i1] = new double [n]; for (i1 = 0; i1 < n+1; i1++) { for (i2 = 0; i2 < n; i2++) xx[i1][i2] = x[i2]; if (i1 > 0) xx[i1][i1-1] += k; yy[i1] = snx(xx[i1]); } // 最大値,最小値の計算 for (i1 = 0; i1 < n+1; i1++) { if (fh < 0 || yy[i1] > yy[fh]) fh = i1; if (fl < 0 || yy[i1] < yy[fl]) fl = i1; } for (i1 = 0; i1 < n+1; i1++) { if (i1 != fh && (fg < 0 || yy[i1] > yy[fg])) fg = i1; } // 最小値の計算 while (count < max && sw < 0) { count++; // 重心の計算 for (i1 = 0; i1 < n; i1++) xg[i1] = 0.0; for (i1 = 0; i1 < n+1; i1++) { if (i1 != fh) { for (i2 = 0; i2 < n; i2++) xg[i2] += xx[i1][i2]; } } for (i1 = 0; i1 < n; i1++) xg[i1] /= n; // 最大点の置き換え for (i1 = 0; i1 < n; i1++) xr[i1] = 2.0 * xg[i1] - xx[fh][i1]; yr = snx(xr); if (yr >= yy[fh]) { // 縮小 for (i1 = 0; i1 < n; i1++) xr[i1] = (1.0 - r1) * xx[fh][i1] + r1 * xr[i1]; yr = snx(xr); } else if (yr < (yy[fl]+(r2-1.0)*yy[fh])/r2) { // 拡大 for (i1 = 0; i1 < n; i1++) xn[i1] = r2 * xr[i1] - (r2 - 1.0) * xx[fh][i1]; yn = snx(xn); if (yn <= yr) { for (i1 = 0; i1 < n; i1++) xr[i1] = xn[i1]; yr = yn; } } for (i1 = 0; i1 < n; i1++) xx[fh][i1] = xr[i1]; yy[fh] = yr; // シンプレックス全体の縮小 if (yy[fh] >= yy[fg]) { for (i1 = 0; i1 < n+1; i1++) { if (i1 != fl) { for (i2 = 0; i2 < n; i2++) xx[i1][i2] = 0.5 * (xx[i1][i2] + xx[fl][i2]); yy[i1] = snx(xx[i1]); } } } // 最大値,最小値の計算 fh = -1; fg = -1; fl = -1; for (i1 = 0; i1 < n+1; i1++) { if (fh < 0 || yy[i1] > yy[fh]) fh = i1; if (fl < 0 || yy[i1] < yy[fl]) fl = i1; } for (i1 = 0; i1 < n+1; i1++) { if (i1 != fh && (fg < 0 || yy[i1] > yy[fg])) fg = i1; } // 収束判定 e = 0.0; for (i1 = 0; i1 < n+1; i1++) { if (i1 != fl) { yr = yy[i1] - yy[fl]; e += yr * yr; } } if (e < eps) sw = 0; } if (sw == 0) { sw = count; *y = yy[fl]; for (i1 = 0; i1 < n; i1++) x[i1] = xx[fl][i1]; } delete [] yy; delete [] xg; delete [] xr; delete [] xn; for (i1 = 0; i1 < n+1; i1++) delete [] xx[i1]; delete [] xx; return sw; } /*******************/ /* 関数値の計算 */ /* y = f(x) */ /* return : y */ /*******************/ // 関数1 double snx1(double *x) { double x1, y1, y; x1 = x[0] - 1.0; y1 = x[1] - 2.0; y = x1 * x1 + y1 * y1; return y; } // 関数2 double snx2(double *x) { double x1, y1, y; x1 = x[1] - x[0] * x[0]; y1 = 1.0 - x[0]; y = 100.0 * x1 * x1 + y1 * y1; return y; } // 関数3 double snx3(double *x) { double x1, y1, z1, y; x1 = 1.5 - x[0] * (1.0 - x[1]); y1 = 2.25 - x[0] * (1.0 - x[1] * x[1]); z1 = 2.625 - x[0] * (1.0 - x[1] * x[1] * x[1]); y = x1 * x1 + y1 * y1 + z1 * z1; return y; }