user_eval.c

来自「sqp程序包。用sqp算法实现非线性约束的优化求解」· C语言 代码 · 共 282 行

C
282
字号
#include "o8para.h"              void user_eval(DOUBLE xvar[],INTEGER mode) {    /* ************************************************************************ */    /* called only if bloc = TRUE                                               */    /* interface to a users evaluation code of functions                        */    /* which define the optimization problem                                    */    /* mode = -1 : evaluate function values at xvar only, store them in fu      */    /* mode = 0  : evaluate inequality constraints and                          */    /*             equality constraints with gunit[1][.] = 1 only at xvar       */    /* mode = 1  : evaluate function and gradient values at xvar and store      */    /*             them in  fu and fugrad                                       */    /* mode = 2  : evaluate gradients only at xvar and store them in fugrad     */    /* The users evaluation routine                                             */    /*             eval_extern(mode)                                            */    /* is called with three settings of its mode only:                           */    /* mode = 0: evaluate constraints which depend linearly                     */    /* on one variable only (gunit[1][i] = 1).                                  */    /* mode = 1: set function value                                             */    /* fu using xtr, mode = 2 set function values fu and gradients fugrad using */    /* xtr                                                                      */    /* Since donlp2 uses internally a scaled value of x, the external value xtr */    /* is obtained by multiplying with xsc. In evaluating the gradients,        */    /* the user must not take care of this scaling. Scaling of the gradients    */    /* is done by donlp2 internally.                                            */    /* If the user has set analyt = TRUE, he is responsible for computing       */    /* the gradients himself correctly                                          */    /* otherwise, if analyt = FALSE, then this routine does numerical           */    /* differentiation according to the method defined by difftype:             */    /* difftype = 1   ordinary forward difference quotient, using               */    /*                min(0.1*sqrt(epsfcn),1.e-2) as stepsize                   */    /*                epsfcn is the assumed precision of function values        */    /*                and must be set by the user in setup0                     */    /* difftype = 2   central difference quotient with stepsize                 */    /*                min(0.1*pow(epsfcn,2/3),1.e-2) as stepsize                */    /* difftype = 3   6-th order Richardson extrapolation method using          */    /*                6 function values for each component of grad,             */    /*                with stepsize min(0.1*pow(epsfcn,1/7),0.01)              */    /* This is done by several calls of eval_extern                             */    /* xtr is the current design to be used by the external routine             */    /* Values must be returned in the arrays fu (and fugrad).                   */    /*  The order of information is as follows:                                 */    /* fu[0]  objective function value                                          */    /* fugrad[i][0] : objective function gradient, i = 1,...,n the components   */    /* fu[1],...,fu[nh]  equality constraints (if any)                          */    /* fugrad[i][1],.., fugrad[i][nh] gradients of equality constraints         */    /* fu[nh+1],...,fu[ng+nh] inequality constraints                            */    /* fugrad[i][nh+1],...,fugrad[i][nh+ng] the gradients of the inequality     */    /*               constraints, wtih component i = 1,..,n                     */    /* If there are bound constraints or fixed variables as described           */    /* by the array gunit in setup0, these must be evaluated here too.          */    /* Their gradients however need not to be computed.                         */    /* The method uses the parameters                                           */    /*      epsfcn  =  relative accuracy of function values                     */    /*      taubnd  =  amount by which bound constraints may be violated        */    /*                 during finite differencing                               */    /*      difftype   (see above)                                              */    /*      analyt     (see above)                                              */    /* These must be set prior in setup0                                        */        /* ************************************************************************ */        #define  X extern    #include "o8comm.h"    #include "o8fint.h"    #undef   X    #include "o8cons.h"        void    eval_extern(INTEGER mode);    static DOUBLE   fusave[NRESM+1],xhelp,xincr,sd1,sd2,sd3,d1,d2,d3;    static INTEGER  i,j;    static LOGICAL  changed;        if ( mode < -1 || mode  > 2 ) {         fprintf(stderr,"donlp2: call of user_eval with undefined mode\n");        exit(1);    }    if ( mode == 0 ) {        for (i = 1 ; i <= n ; i++) {            xtr[i] = xsc[i]*xvar[i];        }        eval_extern(0);                valid = TRUE;    }    if ( mode == -1 ) {        changed = FALSE;        for (i = 1 ; i <= n ; i++) {            if ( xtr[i] != xsc[i]*xvar[i] ) changed = TRUE;        }        if ( changed || ! valid ) {            for (i = 1 ; i <= n ; i++) {                xtr[i] = xsc[i]*xvar[i];            }            eval_extern(1);                        valid = TRUE;        }        return;    }    if ( mode >= 1 ) {            /* evaluate functions and its gradients */                for (i = 1 ; i <= n ; i++) {            xtr[i] = xsc[i]*xvar[i];        }        /* even if xtr did not change we must evaluate externally, since now */        /* gradients are required                                            */                if ( analyt ) {                    eval_extern(2);                        valid = TRUE;                        return;                    } else {            if ( mode == 1 ) eval_extern(1);        }        /* continue with computing the gradients : mode = 1 or mode = 2 */        /* require gradients                                            */                if ( difftype == 1 ) {            deldif = min(tm1*sqrt(epsfcn),tm2);                        if ( mode == 2 ) eval_extern(1);                        for (j = 0 ; j <= nres ; j++) {                fusave[j] = fu[j];            }            for (i = 1 ; i <= n ; i++) {                xhelp = xtr[i];                xincr = min(min(tm2,deldif*fabs(xhelp)+deldif),taubnd);                if ( xhelp >= zero ) {                    xtr[i] = xhelp+xincr;                } else {                    xtr[i] = xhelp-xincr;                }                eval_extern(1);                                for (j = 0 ; j <= nres ; j++) {                    fugrad[i][j] = (fu[j]-fusave[j])/(xtr[i]-xhelp);                }                xtr[i] = xhelp;            }            for (j = 0 ; j <= nres ; j++) {                fu[j] = fusave[j];            }            valid = TRUE;                        return;                    } else if ( difftype == 2 ) {            deldif = min(tm1*pow(epsfcn,one/three),tm2);            for (j = 0 ; j <= nres ; j++) {                fusave[j] = fu[j];            }            for (i = 1 ; i <= n ; i++) {                xhelp  = xtr[i];                xincr  = min(min(tm2,deldif*fabs(xhelp)+deldif),taubnd);                xtr[i] = xhelp+xincr;                                eval_extern(1);                                for (j = 0 ; j <= nres ; j++) {                    fud[j][1] = fu[j];                }                xtr[i] = xhelp-xincr;                                eval_extern(1);                                for (j = 0 ; j <= nres ; j++) {                    fud[j][2] = fu[j];                }                for (j = 0 ; j <= nres ; j++) {                    fugrad[i][j] = (fud[j][1]-fud[j][2])/(xincr+xincr);                }                xtr[i] = xhelp;            }            for (j = 0 ; j <= nres ; j++) {                fu[j] = fusave[j];            }            valid = TRUE;                        return;                    } else {            deldif = min(tm1*pow(epsfcn,one/seven),tm2);            for (j = 0 ; j <= nres ; j++) {                fusave[j] = fu[j];            }            for (i = 1 ; i <= n ; i++) {                xhelp  = xtr[i];                xincr  = min(min(tm2,deldif*fabs(xhelp)+deldif),taubnd/four);                xtr[i] = xhelp-xincr;                                eval_extern(1);                        for (j = 0 ; j <= nres ; j++) {                    fud[j][1] = fu[j];                }                xtr[i] = xhelp+xincr;                                eval_extern(1);                                for (j = 0 ; j <= nres ; j++) {                    fud[j][2] = fu[j];                }                xincr  = xincr+xincr;                d1     = xincr;                xtr[i] = xhelp-xincr;                                eval_extern(1);                                for (j = 0 ; j <= nres ; j++) {                    fud[j][3] = fu[j];                }                xtr[i] = xhelp+xincr;                                eval_extern(1);                                for (j = 0 ; j <= nres ; j++) {                    fud[j][4] = fu[j];                }                xincr  = xincr+xincr;                d2     = xincr;                xtr[i] = xhelp-xincr;                                eval_extern(1);                                for (j = 0 ; j <= nres ; j++) {                    fud[j][5] = fu[j];                }                xtr[i] = xhelp+xincr;                                eval_extern(1);                                for (j = 0 ; j <= nres ; j++) {                    fud[j][6] = fu[j];                }                xtr[i] = xhelp;                d3     = xincr+xincr;                for (j = 0 ; j <= nres ; j++) {                    sd1 = (fud[j][2]-fud[j][1])/d1;                    sd2 = (fud[j][4]-fud[j][3])/d2;                    sd3 = (fud[j][6]-fud[j][5])/d3;                    sd3 = sd2-sd3;                    sd2 = sd1-sd2;                    sd3 = sd2-sd3;                    fugrad[i][j] = sd1+p4*sd2+sd3/c45;                }            }            for (j = 0 ; j <= nres ; j++) {                fu[j] = fusave[j];            }            valid = TRUE;                        return;        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?