int main(int argc, char **argv)
{
    lmstate state;
    lmreport rep;
    int i;
    ap::real_1d_array s;
    ap::real_1d_array x;
    ap::real_1d_array y;
    double fi;
    int n;
    int m;

    
    //
    // Example of solving polynomial approximation task using FJ scheme.
    //
    // Data points:
    //     xi are random numbers from [-1,+1],
    //
    // Function being fitted:
    //     yi = exp(xi) - sin(xi) - x^3/3
    //
    // Function being minimized:
    //     F(a,b,c) =
    //         (a + b*x0 + c*x0^2 - y0)^2 +
    //         (a + b*x1 + c*x1^2 - y1)^2 + ...
    //
    n = 3;
    s.setlength(n);
    for(i = 0; i <= n-1; i++)
    {
        s(i) = ap::randomreal()-0.5;
    }
    m = 100;
    x.setlength(m);
    y.setlength(m);
    for(i = 0; i <= m-1; i++)
    {
        x(i) = double(2*i)/double(m-1)-1;
        y(i) = exp(x(i))-sin(x(i))-x(i)*x(i)*x(i)/3;
    }
    
    //
    // Now S stores starting point, X and Y store points being fitted.
    //
    minlmfj(n, m, s, 0.0, 0.001, 0, state);
    while(minlmiteration(state))
    {
        if( state.needf )
        {
            state.f = 0;
        }
        for(i = 0; i <= m-1; i++)
        {
            
            //
            // "a" is stored in State.X[0]
            // "b" - State.X[1]
            // "c" - State.X[2]
            //
            fi = state.x(0)+state.x(1)*x(i)+state.x(2)*ap::sqr(x(i))-y(i);
            if( state.needf )
            {
                
                //
                // F is equal to sum of fi squared.
                //
                state.f = state.f+ap::sqr(fi);
            }
            if( state.needfij )
            {
                
                //
                // Fi
                //
                state.fi(i) = fi;
                
                //
                // dFi/da
                //
                state.j(i,0) = 1;
                
                //
                // dFi/db
                //
                state.j(i,1) = x(i);
                
                //
                // dFi/dc
                //
                state.j(i,2) = ap::sqr(x(i));
            }
        }
    }
    minlmresults(state, s, rep);
    
    //
    // output results
    //
    printf("A = %4.2lf\n",
        double(s(0)));
    printf("B = %4.2lf\n",
        double(s(1)));
    printf("C = %4.2lf\n",
        double(s(2)));
    printf("TerminationType = %0ld (should be 2 - stopping when step is small enough)\n",
        long(rep.terminationtype));
    return 0;
}
Пример #2
0
bool testminlm(bool silent)
{
    bool result;
    bool waserrors;
    bool referror;
    bool lin1error;
    bool lin2error;
    bool eqerror;
    bool converror;
    bool scerror;
    int rkind;
    int nset;
    int n;
    int m;
    ap::real_1d_array x;
    ap::real_1d_array xe;
    ap::real_1d_array b;
    int i;
    int j;
    double v;
    ap::real_2d_array a;
    lmstate state;
    lmreport rep;

    waserrors = false;
    referror = false;
    lin1error = false;
    lin2error = false;
    eqerror = false;
    converror = false;
    scerror = false;
    
    //
    // Reference problem.
    // RKind is a algorithm selector:
    // * 0 = FJ
    // * 1 = FGJ
    // * 2 = FGH
    //
    x.setbounds(0, 2);
    n = 3;
    m = 3;
    for(rkind = 0; rkind <= 2; rkind++)
    {
        x(0) = 100*ap::randomreal()-50;
        x(1) = 100*ap::randomreal()-50;
        x(2) = 100*ap::randomreal()-50;
        if( rkind==0 )
        {
            minlmfj(n, m, x, 0.0, 0.0, 0, state);
        }
        if( rkind==1 )
        {
            minlmfgj(n, m, x, 0.0, 0.0, 0, state);
        }
        if( rkind==2 )
        {
            minlmfgh(n, x, 0.0, 0.0, 0, state);
        }
        while(minlmiteration(state))
        {
            
            //
            // (x-2)^2 + y^2 + (z-x)^2
            //
            state.f = ap::sqr(state.x(0)-2)+ap::sqr(state.x(1))+ap::sqr(state.x(2)-state.x(0));
            if( state.needfg||state.needfgh )
            {
                state.g(0) = 2*(state.x(0)-2)+2*(state.x(0)-state.x(2));
                state.g(1) = 2*state.x(1);
                state.g(2) = 2*(state.x(2)-state.x(0));
            }
            if( state.needfij )
            {
                state.fi(0) = state.x(0)-2;
                state.fi(1) = state.x(1);
                state.fi(2) = state.x(2)-state.x(0);
                state.j(0,0) = 1;
                state.j(0,1) = 0;
                state.j(0,2) = 0;
                state.j(1,0) = 0;
                state.j(1,1) = 1;
                state.j(1,2) = 0;
                state.j(2,0) = -1;
                state.j(2,1) = 0;
                state.j(2,2) = 1;
            }
            if( state.needfgh )
            {
                state.h(0,0) = 4;
                state.h(0,1) = 0;
                state.h(0,2) = -2;
                state.h(1,0) = 0;
                state.h(1,1) = 2;
                state.h(1,2) = 0;
                state.h(2,0) = -2;
                state.h(2,1) = 0;
                state.h(2,2) = 2;
            }
            scerror = scerror||!rkindvsstatecheck(rkind, state);
        }
        minlmresults(state, x, rep);
        referror = referror||rep.terminationtype<=0||ap::fp_greater(fabs(x(0)-2),0.001)||ap::fp_greater(fabs(x(1)),0.001)||ap::fp_greater(fabs(x(2)-2),0.001);
    }
    
    //
    // end
    //
    waserrors = referror||lin1error||lin2error||eqerror||converror||scerror;
    if( !silent )
    {
        printf("TESTING LEVENBERG-MARQUARDT OPTIMIZATION\n");
        printf("REFERENCE PROBLEM:                        ");
        if( referror )
        {
            printf("FAILED\n");
        }
        else
        {
            printf("OK\n");
        }
        printf("1-D PROBLEM #1:                           ");
        if( lin1error )
        {
            printf("FAILED\n");
        }
        else
        {
            printf("OK\n");
        }
        printf("1-D PROBLEM #2:                           ");
        if( lin2error )
        {
            printf("FAILED\n");
        }
        else
        {
            printf("OK\n");
        }
        printf("LINEAR EQUATIONS:                         ");
        if( eqerror )
        {
            printf("FAILED\n");
        }
        else
        {
            printf("OK\n");
        }
        printf("CONVERGENCE PROPERTIES:                   ");
        if( converror )
        {
            printf("FAILED\n");
        }
        else
        {
            printf("OK\n");
        }
        printf("STATE FIELDS CONSISTENCY:                 ");
        if( scerror )
        {
            printf("FAILED\n");
        }
        else
        {
            printf("OK\n");
        }
        if( waserrors )
        {
            printf("TEST FAILED\n");
        }
        else
        {
            printf("TEST PASSED\n");
        }
        printf("\n\n");
    }
    result = !waserrors;
    return result;
}
Пример #3
0
/*************************************************************************
Nonlinear least squares fitting. Algorithm iteration.

Called after inialization of the State structure with  LSFitNonlinearXXX()
subroutine. See HTML docs for examples.

INPUT PARAMETERS:
    State   -   structure which stores algorithm state between  subsequent
                calls and which is used for reverse communication. Must be
                initialized with LSFitNonlinearXXX() call first.

RESULT
1. If subroutine returned False, iterative algorithm has converged.
2. If subroutine returned True, then if:
* if State.NeedF=True,      function value F(X,C) is required
* if State.NeedFG=True,     function value F(X,C) and gradient  dF/dC(X,C)
                            are required
* if State.NeedFGH=True     function value F(X,C), gradient dF/dC(X,C) and
                            Hessian are required

One and only one of this fields can be set at time.

Function, its gradient and Hessian are calculated at  (X,C),  where  X  is
stored in State.X[0..M-1] and C is stored in State.C[0..K-1].

Results are stored:
* function value            -   in State.F
* gradient                  -   in State.G[0..K-1]
* Hessian                   -   in State.H[0..K-1,0..K-1]

  -- ALGLIB --
     Copyright 17.08.2009 by Bochkanov Sergey
*************************************************************************/
bool lsfitnonlineariteration(lsfitstate& state)
{
    bool result;
    int n;
    int m;
    int k;
    int i;
    int j;
    double v;
    double relcnt;

    
    //
    // Reverse communication preparations
    // I know it looks ugly, but it works the same way
    // anywhere from C++ to Python.
    //
    // This code initializes locals by:
    // * random values determined during code
    //   generation - on first subroutine call
    // * values from previous call - on subsequent calls
    //
    if( state.rstate.stage>=0 )
    {
        n = state.rstate.ia(0);
        m = state.rstate.ia(1);
        k = state.rstate.ia(2);
        i = state.rstate.ia(3);
        j = state.rstate.ia(4);
        v = state.rstate.ra(0);
        relcnt = state.rstate.ra(1);
    }
    else
    {
        n = -983;
        m = -989;
        k = -834;
        i = 900;
        j = -287;
        v = 364;
        relcnt = 214;
    }
    if( state.rstate.stage==0 )
    {
        goto lbl_0;
    }
    if( state.rstate.stage==1 )
    {
        goto lbl_1;
    }
    if( state.rstate.stage==2 )
    {
        goto lbl_2;
    }
    if( state.rstate.stage==3 )
    {
        goto lbl_3;
    }
    if( state.rstate.stage==4 )
    {
        goto lbl_4;
    }
    
    //
    // Routine body
    //
    
    //
    // check params
    //
    if( state.n<1||state.m<1||state.k<1||ap::fp_less(state.epsf,0)||ap::fp_less(state.epsx,0)||state.maxits<0 )
    {
        state.repterminationtype = -1;
        result = false;
        return result;
    }
    
    //
    // init
    //
    n = state.n;
    m = state.m;
    k = state.k;
    state.x.setlength(m);
    state.g.setlength(k);
    if( state.havehess )
    {
        state.h.setlength(k, k);
    }
    
    //
    // initialize LM optimizer
    //
    if( state.havehess )
    {
        
        //
        // use Hessian.
        // transform stopping conditions.
        //
        minlmcreatefgh(k, state.c, state.optstate);
    }
    else
    {
        
        //
        // use one of gradient-based schemes (depending on gradient cost).
        // transform stopping conditions.
        //
        if( state.cheapfg )
        {
            minlmcreatefgj(k, n, state.c, state.optstate);
        }
        else
        {
            minlmcreatefj(k, n, state.c, state.optstate);
        }
    }
    minlmsetcond(state.optstate, 0.0, state.epsf, state.epsx, state.maxits);
    minlmsetstpmax(state.optstate, state.stpmax);
    
    //
    // Optimize
    //
lbl_5:
    if( !minlmiteration(state.optstate) )
    {
        goto lbl_6;
    }
    if( !state.optstate.needf )
    {
        goto lbl_7;
    }
    
    //
    // calculate F = sum (wi*(f(xi,c)-yi))^2
    //
    state.optstate.f = 0;
    i = 0;
lbl_9:
    if( i>n-1 )
    {
        goto lbl_11;
    }
    ap::vmove(&state.c(0), 1, &state.optstate.x(0), 1, ap::vlen(0,k-1));
    ap::vmove(&state.x(0), 1, &state.taskx(i, 0), 1, ap::vlen(0,m-1));
    state.pointindex = i;
    lsfitclearrequestfields(state);
    state.needf = true;
    state.rstate.stage = 0;
    goto lbl_rcomm;
lbl_0:
    state.optstate.f = state.optstate.f+ap::sqr(state.w(i)*(state.f-state.tasky(i)));
    i = i+1;
    goto lbl_9;
lbl_11:
    goto lbl_5;
lbl_7:
    if( !state.optstate.needfg )
    {
        goto lbl_12;
    }
    
    //
    // calculate F/gradF
    //
    state.optstate.f = 0;
    for(i = 0; i <= k-1; i++)
    {
        state.optstate.g(i) = 0;
    }
    i = 0;
lbl_14:
    if( i>n-1 )
    {
        goto lbl_16;
    }
    ap::vmove(&state.c(0), 1, &state.optstate.x(0), 1, ap::vlen(0,k-1));
    ap::vmove(&state.x(0), 1, &state.taskx(i, 0), 1, ap::vlen(0,m-1));
    state.pointindex = i;
    lsfitclearrequestfields(state);
    state.needfg = true;
    state.rstate.stage = 1;
    goto lbl_rcomm;
lbl_1:
    state.optstate.f = state.optstate.f+ap::sqr(state.w(i)*(state.f-state.tasky(i)));
    v = ap::sqr(state.w(i))*2*(state.f-state.tasky(i));
    ap::vadd(&state.optstate.g(0), 1, &state.g(0), 1, ap::vlen(0,k-1), v);
    i = i+1;
    goto lbl_14;
lbl_16:
    goto lbl_5;
lbl_12:
    if( !state.optstate.needfij )
    {
        goto lbl_17;
    }
    
    //
    // calculate Fi/jac(Fi)
    //
    i = 0;
lbl_19:
    if( i>n-1 )
    {
        goto lbl_21;
    }
    ap::vmove(&state.c(0), 1, &state.optstate.x(0), 1, ap::vlen(0,k-1));
    ap::vmove(&state.x(0), 1, &state.taskx(i, 0), 1, ap::vlen(0,m-1));
    state.pointindex = i;
    lsfitclearrequestfields(state);
    state.needfg = true;
    state.rstate.stage = 2;
    goto lbl_rcomm;
lbl_2:
    state.optstate.fi(i) = state.w(i)*(state.f-state.tasky(i));
    v = state.w(i);
    ap::vmove(&state.optstate.j(i, 0), 1, &state.g(0), 1, ap::vlen(0,k-1), v);
    i = i+1;
    goto lbl_19;
lbl_21:
    goto lbl_5;
lbl_17:
    if( !state.optstate.needfgh )
    {
        goto lbl_22;
    }
    
    //
    // calculate F/grad(F)/hess(F)
    //
    state.optstate.f = 0;
    for(i = 0; i <= k-1; i++)
    {
        state.optstate.g(i) = 0;
    }
    for(i = 0; i <= k-1; i++)
    {
        for(j = 0; j <= k-1; j++)
        {
            state.optstate.h(i,j) = 0;
        }
    }
    i = 0;
lbl_24:
    if( i>n-1 )
    {
        goto lbl_26;
    }
    ap::vmove(&state.c(0), 1, &state.optstate.x(0), 1, ap::vlen(0,k-1));
    ap::vmove(&state.x(0), 1, &state.taskx(i, 0), 1, ap::vlen(0,m-1));
    state.pointindex = i;
    lsfitclearrequestfields(state);
    state.needfgh = true;
    state.rstate.stage = 3;
    goto lbl_rcomm;
lbl_3:
    state.optstate.f = state.optstate.f+ap::sqr(state.w(i)*(state.f-state.tasky(i)));
    v = ap::sqr(state.w(i))*2*(state.f-state.tasky(i));
    ap::vadd(&state.optstate.g(0), 1, &state.g(0), 1, ap::vlen(0,k-1), v);
    for(j = 0; j <= k-1; j++)
    {
        v = 2*ap::sqr(state.w(i))*state.g(j);
        ap::vadd(&state.optstate.h(j, 0), 1, &state.g(0), 1, ap::vlen(0,k-1), v);
        v = 2*ap::sqr(state.w(i))*(state.f-state.tasky(i));
        ap::vadd(&state.optstate.h(j, 0), 1, &state.h(j, 0), 1, ap::vlen(0,k-1), v);
    }
    i = i+1;
    goto lbl_24;
lbl_26:
    goto lbl_5;
lbl_22:
    goto lbl_5;
lbl_6:
    minlmresults(state.optstate, state.c, state.optrep);
    state.repterminationtype = state.optrep.terminationtype;
    
    //
    // calculate errors
    //
    if( state.repterminationtype<=0 )
    {
        goto lbl_27;
    }
    state.reprmserror = 0;
    state.repavgerror = 0;
    state.repavgrelerror = 0;
    state.repmaxerror = 0;
    relcnt = 0;
    i = 0;
lbl_29:
    if( i>n-1 )
    {
        goto lbl_31;
    }
    ap::vmove(&state.c(0), 1, &state.c(0), 1, ap::vlen(0,k-1));
    ap::vmove(&state.x(0), 1, &state.taskx(i, 0), 1, ap::vlen(0,m-1));
    state.pointindex = i;
    lsfitclearrequestfields(state);
    state.needf = true;
    state.rstate.stage = 4;
    goto lbl_rcomm;
lbl_4:
    v = state.f;
    state.reprmserror = state.reprmserror+ap::sqr(v-state.tasky(i));
    state.repavgerror = state.repavgerror+fabs(v-state.tasky(i));
    if( ap::fp_neq(state.tasky(i),0) )
    {
        state.repavgrelerror = state.repavgrelerror+fabs(v-state.tasky(i))/fabs(state.tasky(i));
        relcnt = relcnt+1;
    }
    state.repmaxerror = ap::maxreal(state.repmaxerror, fabs(v-state.tasky(i)));
    i = i+1;
    goto lbl_29;
lbl_31:
    state.reprmserror = sqrt(state.reprmserror/n);
    state.repavgerror = state.repavgerror/n;
    if( ap::fp_neq(relcnt,0) )
    {
        state.repavgrelerror = state.repavgrelerror/relcnt;
    }
lbl_27:
    result = false;
    return result;
    
    //
    // Saving state
    //
lbl_rcomm:
    result = true;
    state.rstate.ia(0) = n;
    state.rstate.ia(1) = m;
    state.rstate.ia(2) = k;
    state.rstate.ia(3) = i;
    state.rstate.ia(4) = j;
    state.rstate.ra(0) = v;
    state.rstate.ra(1) = relcnt;
    return result;
}