Keyword: 大域的最適化
概要
本サンプルは大域的最適化を行うC言語によるサンプルプログラムです。 本サンプルは以下に示される2次元におけるpeaks関数の大域的最小値を求めて出力します。
※本サンプルはnAG Cライブラリに含まれる関数 nag_glopt_bnd_mcs_solve() のExampleコードです。本サンプル及び関数の詳細情報は nag_glopt_bnd_mcs_solve のマニュアルページをご参照ください。
ご相談やお問い合わせはこちらまで
入力データ
(本関数の詳細はnag_glopt_bnd_mcs_solve のマニュアルページを参照)このデータをダウンロード |
nag_glopt_bnd_mcs_solve (e05jbc) Example Program Data 3 : sdlist Nag_Bounds : bound -3.0 -3.0 : Lower bounds bl 3.0 3.0 : Upper bounds bu Nag_SimpleBdry : initmethod 0 : plot
- 1行目はタイトル行で読み飛ばされます。
- 2行目に変数の数(n)と初期化リストに従って分割が行われる座標の点の数の最大値(sdlist)を指定しています。
- 3行目には境界値を処理するための機能が使用されるか(bound)を指定しています。"Nag_Bounds"は下限と上限をそれぞれ与えることを意味します。
- 4行目には下限(bl)を指定しています。
- 5行目には上限(bu)を指定しています。
- 6行目にはどの初期化の手法が使用されるか(initmethod)を指定しています。"Nag_SimpleBdry"は簡易な初期化(境界法と中点法)を意味しています。
- 7行目には現在の検索ボックス(領域)に情報を表示させるかどうか(plot)を指定しています。"0"の場合は検索ボックス(領域)には表示されません。
出力結果
(本関数の詳細はnag_glopt_bnd_mcs_solve のマニュアルページを参照)この出力例をダウンロード |
nag_glopt_bnd_mcs_solve (e05jbc) Example Program Results (User-supplied callback objfun, first invocation.) (objfun was just called for the first time) (User-supplied callback monit, first invocation.) *** Begin monitoring information *** Values controlling initial splitting of a box: ** In dimension 1 Extent of initialization list in this dimension = 3 Initialization points in this dimension: LIST(i, 1:numpts[i - 1]) = -3.00000 0.00000 3.00000 Initial point in this dimension: LIST(i, 2) ** In dimension 2 Extent of initialization list in this dimension = 3 Initialization points in this dimension: LIST(i, 1:numpts[i - 1]) = -3.00000 0.00000 3.00000 Initial point in this dimension: LIST(i, 2) Total sub-boxes = 228 Total function evaluations (rounded to nearest 20) = 200 Total function evaluations used in local search (rounded to nearest 15) = 90 Total points used in local search = 13 Total sweeps through levels = 12 Total splits by init. list = 5 Lowest level with nonsplit boxes = 7 Number of candidate minima in the 'shopping basket' = 2 Shopping basket: xbaskt( 1,:) = -1.34740 0.22828 xbaskt( 2,:) = 0.20452 -1.62553 Best point: xbest = 0.22828 -1.62553 *** End monitoring information *** Final objective value = -6.55113 Global optimum x = 0.22828 -1.62553
- 7〜17行目に以下に示すモニタリング情報が出力されています。
- サブボックス(下位領域)の数
- 関数objfunの呼び出しの累積数
- 局所検索での関数objfunの呼び出しの累積数
- 局所検索の開始点として使用される座標点の数
- 分割のレベルを通じたスイープ(sweep)の累積数
- 初期化リストによる分割の累積数
- 分割していないボックス(領域)を含む、最も低い分割のレベル
- ショッピングバスケット(最小値の候補の格納場所)の最小値の候補の座標点の数
- 最小値の候補が格納されているショッピングバスケットの内容
- 21行目に最終的な関数値が出力されています。
- 22行目に大域的最適解xの値が出力されています。
ソースコード
(本関数の詳細はnag_glopt_bnd_mcs_solve のマニュアルページを参照)
※本サンプルソースコードはnAG数値計算ライブラリ(Windows, Linux, MAC等に対応)の関数を呼び出します。
サンプルのコンパイル及び実行方法
このソースコードをダウンロード |
/* nag_glopt_bnd_mcs_solve (e05jbc) Example Program. * * CLL6I261D/CLL6I261DL Version. * * Copyright 2017 Numerical Algorithms Group. * * Mark 26.1, 2017. */ #include <stdio.h> #include <math.h> #include <nag.h> #include <nag_stdlib.h> #include <nage05.h> #ifdef __cplusplus extern "C" { #endif static void nAG_CALL objfun(Integer n, const double x[], double *f, Integer nstate, Nag_Comm *comm, Integer *inform); static void nAG_CALL monit(Integer n, Integer ncall, const double xbest[], const Integer icount[], Integer sdlist, const double list[], const Integer numpts[], const Integer initpt[], Integer nbaskt, const double xbaskt[], const double boxl[], const double boxu[], Integer nstate, Nag_Comm *comm, Integer *inform); static void nAG_CALL output_current_box(const double boxl[], const double boxu[]); #ifdef __cplusplus } #endif int main(void) { /* Scalars */ double obj; Integer exit_status = 0, i, n = 2, plot, sdlist; Nag_BoundType boundenum; Nag_MCSInitMethod initmethodenum; /* Arrays */ static double ruser[2] = { -1.0, -1.0 }; char bound[16], initmethod[18]; double *bl = 0, *bu = 0, *list = 0, *x = 0; Integer *initpt = 0, *numpts = 0; Integer iuser[1]; /* Nag Types */ Nag_E05State state; NagError fail; Nag_Comm comm; INIT_FAIL(fail); printf("nag_glopt_bnd_mcs_solve (e05jbc) Example Program Results\n"); /* For communication with user-supplied functions: */ comm.iuser = iuser; comm.user = ruser; /* Skip heading in data file */ scanf("%*[^\n] "); /* Read sdlist from data file */ scanf("%ld%*[^\n] ", &sdlist); if (n <= 0 || sdlist <= 0) goto END; if (!(bl = nAG_ALLOC(n, double)) || !(bu = nAG_ALLOC(n, double)) || !(list = nAG_ALLOC(n * sdlist, double)) || !(x = nAG_ALLOC(n, double)) || !(initpt = nAG_ALLOC(n, Integer)) || !(numpts = nAG_ALLOC(n, Integer))) { printf("Allocation failure\n"); exit_status = -1; goto END; } /* Read in bound (and bl and bu if necessary) */ scanf("%15s%*[^\n] ", bound); /* nag_enum_name_to_value (x04nac). * Converts nAG enum member name to value */ boundenum = (Nag_BoundType) nag_enum_name_to_value(bound); if (boundenum == Nag_Bounds) /* Read in the whole of each bound */ { for (i = 0; i < n; ++i) scanf("%lf", &bl[i]); scanf("%*[^\n] "); for (i = 0; i < n; ++i) scanf("%lf", &bu[i]); scanf("%*[^\n] "); } else if (boundenum == Nag_BoundsEqual) /* Bounds are uniform: read in only the first entry of each */ { scanf("%lf%*[^\n] ", &bl[0]); scanf("%lf%*[^\n] ", &bu[0]); } /* Read in initmethod */ scanf("%17s%*[^\n] ", initmethod); /* nag_enum_name_to_value (x04nac). * Converts nAG enum member name to value */ initmethodenum = (Nag_MCSInitMethod) nag_enum_name_to_value(initmethod); /* Read in plot. Its value determines whether monit displays * information on the current search box */ scanf("%ld%*[^\n] ", &plot); /* Communicate plot through to monit */ iuser[0] = plot; /* Call nag_glopt_bnd_mcs_init (e05jac) to initialize * nag_glopt_bnd_mcs_solve (e05jbc). */ /* Its first argument is a legacy argument and has no significance. */ nag_glopt_bnd_mcs_init(0, &state, &fail); if (fail.code != NE_NOERROR) { printf("Initialization of nag_glopt_bnd_mcs_solve (e05jbc) failed.\n%s\n", fail.message); exit_status = 1; goto END; } /* Solve the problem. */ /* nag_glopt_bnd_mcs_solve (e05jbc). * Global optimization by multilevel coordinate search, simple bounds. */ nag_glopt_bnd_mcs_solve(n, objfun, boundenum, initmethodenum, bl, bu, sdlist, list, numpts, initpt, monit, x, &obj, &state, &comm, &fail); if (fail.code != NE_NOERROR) { printf("Error message from nag_glopt_bnd_mcs_solve (e05jbc).\n%s\n", fail.message); exit_status = 1; goto END; } printf("Final objective value = %11.5f\n", obj); printf("Global optimum x = "); for (i = 0; i < n; ++i) printf("%9.5f", x[i]); printf("\n"); END: nAG_FREE(bl); nAG_FREE(bu); nAG_FREE(list); nAG_FREE(x); nAG_FREE(initpt); nAG_FREE(numpts); return exit_status; } static void nAG_CALL objfun(Integer n, const double x[], double *f, Integer nstate, Nag_Comm *comm, Integer *inform) { /* Routine to evaluate objective function */ if (comm->user[0] == -1.0) { printf("(User-supplied callback objfun, first invocation.)\n"); comm->user[0] = 0.0; } /* This is a two-dimensional objective function. * As an example of using the inform mechanism, * terminate if any other problem size is supplied. */ if (n != 2) { *inform = -1; return; } *inform = 0; if (*inform >= 0) /* Here we're prepared to evaluate objfun at the current x */ { if (nstate == 1) /* This is the first call to objfun */ { printf("\n(objfun was just called for the first time)\n"); } *f = (3.0 * pow((1.0 - x[0]), 2) * exp(-pow(x[0], 2) - pow((x[1] + 1), 2)) - (10.0 * (x[0] / 5.0 - pow(x[0], 3) - pow(x[1], 5)) * exp(-pow(x[0], 2) - pow(x[1], 2))) - 1.0 / 3.0 * exp(-pow((x[0] + 1.0), 2) - pow(x[1], 2)) ); } } static void nAG_CALL monit(Integer n, Integer ncall, const double xbest[], const Integer icount[], Integer sdlist, const double list[], const Integer numpts[], const Integer initpt[], Integer nbaskt, const double xbaskt[], const double boxl[], const double boxu[], Integer nstate, Nag_Comm *comm, Integer *inform) { /* Scalars */ Integer i, j; Integer plot; #define LIST(I, J) list[(I-1)*sdlist + (J-1)] #define XBASKT(I, J) xbaskt[(I-1)*nbaskt + (J-1)] if (comm->user[1] == -1.0) { printf("(User-supplied callback monit, first invocation.)\n"); comm->user[1] = 0.0; } *inform = 0; if (*inform >= 0) /* We are going to allow the iterations to continue */ { /* Extract plot from the communication structure */ plot = comm->iuser[0]; if (nstate == 0 || nstate == 1) /* When nstate == 1, monit is called for the first time. * When nstate == 0, monit is called for the first AND last time. * Display a welcome message */ { printf("\n*** Begin monitoring information ***\n\n"); printf("Values controlling initial splitting of a box:\n"); for (i = 1; i <= n; ++i) { printf("**\n"); printf("In dimension %5ld\n", i); printf("Extent of initialization list in this dimension =" "%5ld\n", numpts[i - 1]); printf("Initialization points in this dimension:\n"); printf("LIST(i, 1:numpts[i - 1]) ="); for (j = 1; j <= numpts[i - 1]; ++j) printf("%9.5f", LIST(i, j)); printf("\n"); printf("Initial point in this dimension: LIST(i,%5ld)\n", initpt[i - 1]); } if (plot != 0 && n == 2) printf("<Begin displaying search boxes>\n\n"); } if (plot != 0 && n == 2) { /* Display the coordinates of the edges of the current search box */ output_current_box(boxl, boxu); } if (nstate <= 0) /* monit is called for the last time */ { if (plot != 0 && n == 2) printf("<End displaying search boxes>\n\n"); printf("Total sub-boxes = %5ld\n", icount[0]); printf("Total function evaluations (rounded to nearest 20) = " "%5ld\n", 20*((ncall+10)/20)); printf("Total function evaluations used in local search (rounded\n" " to nearest 15) = %5ld\n", 15*((icount[1]+7)/15)); printf("Total points used in local search = %5ld\n", icount[2]); printf("Total sweeps through levels = %5ld\n", icount[3]); printf("Total splits by init. list = %5ld\n", icount[4]); printf("Lowest level with nonsplit boxes = %5ld\n", icount[5]); printf("Number of candidate minima in the 'shopping basket'" " = %5ld\n", nbaskt); printf("Shopping basket:\n"); for (i = 1; i <= n; ++i) { printf("xbaskt(%3ld,:) =", i); for (j = 1; j <= nbaskt; ++j) printf("%9.5f", XBASKT(i, j)); printf("\n"); } printf("Best point:\n"); printf("xbest ="); for (i = 0; i < n; ++i) printf("%9.5f", xbest[i]); printf("\n"); printf("\n*** End monitoring information ***\n\n"); } } } static void nAG_CALL output_current_box(const double boxl[], const double boxu[]) { printf("%20.15f %20.15f\n", boxl[0], boxl[1]); printf("%20.15f %20.15f\n\n", boxl[0], boxu[1]); printf("%20.15f %20.15f\n", boxl[0], boxl[1]); printf("%20.15f %20.15f\n\n", boxu[0], boxl[1]); printf("%20.15f %20.15f\n", boxl[0], boxu[1]); printf("%20.15f %20.15f\n\n", boxu[0], boxu[1]); printf("%20.15f %20.15f\n", boxu[0], boxl[1]); printf("%20.15f %20.15f\n\n", boxu[0], boxu[1]); }