最優化程式c++的方法(GSL)
解決的問題 最優化問題的一般形式 minf(paras) minf(paras) s.t.paras∈[paras_lower,paras_upper] s.t.paras∈[paras_lower,paras_upper]
這個是數學上的一般形式,當求函式的最大值時候只要加上一個負號就可以 在程式中我們面對的問題一般是離散的即 f(paras)f(paras)一般情況下是關於XiXi的一個離散變數的。而此時問題會轉化為 valueType errorfunc(valueType* paras,valueType* X)//誤差函式輸入要求的引數和具體的X的值因為多個以陣列的形式傳值。 { sum(f(paras,X_i))//求得函式關於每個X_i的函式和 } 我們通過調節要求得引數paras來使得errorfunc返回的值最小
exp=min_value//收斂的最小值 while(errorfunc( paras, X)>exp)//當誤差函式的變化大於最小值時候 { adjust(paras);//調整引數,繼續判斷其收斂與否 } 解決的方法 當問題是線性的時候 AX=b 利用SVD分解就可以求得最後的解,這種方法比較簡單,網上也有很多的程式碼,下次有機會在補上。
當問題非線性的時候 如果不採用函式庫的方法的話,就只能具體問題具體分析了。 在這裡我們採用GNU GSL函式庫 [ 下載地址 ] [ 具體的配置方法 1] [ 具體的配置方法 ,為了防止原網頁不能用轉載了一下。。。。哈哈哈] [ 這是一個已經生成好的gsl,可以直接將lib和include在vs中設定好,將bin的設定成系統變數,就可以了 。。。。。哈哈哈]
下面就是我們的函式程式碼
void my_df (const gsl_vector *params, void *xandcval)//paras是需要傳入的數值,可以是X和一些固定引數,也可以用全域性變數的方法,para是我們最後需要調整的引數 { double x, y; double *Xandcval = (double *)xandcval;//
x = gsl_vector_get(params, 0);//將要求得paras讀取出來 y = gsl_vector_get(params, 1); return errorfunc(...);
} void optim1() { size_t np = 30;//paras的大小 double Xandcval[2] = { 1, 2 };//這裡假設只有引數,當有很多X時候需要構造 const gsl_multimin_fminimizer_type *T_min = gsl_multimin_fminimizer_nmsimplex; gsl_multimin_fminimizer *s = NULL; gsl_vector *ss, *x; gsl_multimin_function minex_func;
size_t iter = 0, i; int status; double size;
/* Initial vertex size vector */ ss = gsl_vector_alloc(np);
/* Set all step sizes to 1 */ gsl_vector_set_all(ss, 0.00001);//這裡的0.00001指的是exp
/* Starting point */ paras = gsl_vector_alloc(np); //對需要求得引數賦予初始值12 123 gsl_vector_set(paras , 0,12);//引數表,序號,值 gsl_vector_set(paras , 1, 123);
/* Initialize method and iterate */ minex_func.f = &my_f1;//誤差函式的名稱 minex_func.n = np; minex_func.params = (void *)∥ char szbuffer[1000]; s = gsl_multimin_fminimizer_alloc(T_min, np); gsl_multimin_fminimizer_set(s, &minex_func, x, ss);
do { iter++; status = gsl_multimin_fminimizer_iterate(s);
if (status) break;
size = gsl_multimin_fminimizer_size(s); status = gsl_multimin_test_size(size, 1e-12);
if (status == GSL_SUCCESS)//收斂了 {
printf("f() = %12.11f size = %.3f\n", s->fval, size); ; }
// printf("%5d ", iter); for (i = 0; i < np; i++) { ;//printf("%10.3e ", gsl_vector_get(s->x, i)); } optim1<<"f() = "<<s->fval<<"size="<<size<<"\n"; // sprintf(szbuffer,"f() = %12.11f size = %.3f\n", s->fval, size); //MessageBox(NULL,(TCHAR*)szbuffer,TEXT("長度優化"),MB_OK); //printf("f() = %12.11f size = %.3f\n", s->fval, size);
fcf<<"fc[0]="<<fc[0]<<";\t"<<"fc[1]="<<fc[1]<<";\t"<<"cc[0]="<<cc[0]<<";\t"<<"cc[1]="<<cc[1]<<";\n"; } while (status == GSL_CONTINUE && iter < 15622);//此處設定最大迭代次數,此處為15622
///
x = gsl_vector_get(s->paras, 0);//將函式值傳回來 y = gsl_vector_get(s->paras, 1);//