1. 程式人生 > >最優化程式c++的方法(GSL)

最優化程式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);//