Ejemplo n.º 1
0
        /*************************************************************************
        *  Least squares fitting by polynomial.
        *
        *  This subroutine is "lightweight" alternative for more complex and feature-
        *  rich PolynomialFitWC().  See  PolynomialFitWC() for more information about
        *  subroutine parameters (we don't duplicate it here because of length)
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 12.10.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfit(ref double[] x,
                                         ref double[] y,
                                         int n,
                                         int m,
                                         ref int info,
                                         ref ratint.barycentricinterpolant p,
                                         ref polynomialfitreport rep)
        {
            int i = 0;

            double[] w  = new double[0];
            double[] xc = new double[0];
            double[] yc = new double[0];
            int[]    dc = new int[0];

            if (n > 0)
            {
                w = new double[n];
                for (i = 0; i <= n - 1; i++)
                {
                    w[i] = 1;
                }
            }
            polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 0, m, ref info, ref p, ref rep);
        }
Ejemplo n.º 2
0
        /*************************************************************************
        Weighted  fitting by polynomials in barycentric form, with constraints  on
        function values or first derivatives.

        Small regularizing term is used when solving constrained tasks (to improve
        stability).

        Task is linear, so linear least squares solver is used. Complexity of this
        computational scheme is O(N*M^2), mostly dominated by least squares solver

        SEE ALSO:
            PolynomialFit()

        INPUT PARAMETERS:
            X   -   points, array[0..N-1].
            Y   -   function values, array[0..N-1].
            W   -   weights, array[0..N-1]
                    Each summand in square  sum  of  approximation deviations from
                    given  values  is  multiplied  by  the square of corresponding
                    weight. Fill it by 1's if you don't  want  to  solve  weighted
                    task.
            N   -   number of points, N>0.
                    * if given, only leading N elements of X/Y/W are used
                    * if not given, automatically determined from sizes of X/Y/W
            XC  -   points where polynomial values/derivatives are constrained,
                    array[0..K-1].
            YC  -   values of constraints, array[0..K-1]
            DC  -   array[0..K-1], types of constraints:
                    * DC[i]=0   means that P(XC[i])=YC[i]
                    * DC[i]=1   means that P'(XC[i])=YC[i]
                    SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
            K   -   number of constraints, 0<=K<M.
                    K=0 means no constraints (XC/YC/DC are not used in such cases)
            M   -   number of basis functions (= polynomial_degree + 1), M>=1

        OUTPUT PARAMETERS:
            Info-   same format as in LSFitLinearW() subroutine:
                    * Info>0    task is solved
                    * Info<=0   an error occured:
                                -4 means inconvergence of internal SVD
                                -3 means inconsistent constraints
            P   -   interpolant in barycentric form.
            Rep -   report, same format as in LSFitLinearW() subroutine.
                    Following fields are set:
                    * RMSError      rms error on the (X,Y).
                    * AvgError      average error on the (X,Y).
                    * AvgRelError   average relative error on the non-zero Y
                    * MaxError      maximum error
                                    NON-WEIGHTED ERRORS ARE CALCULATED

        IMPORTANT:
            this subroitine doesn't calculate task's condition number for K<>0.

        NOTES:
            you can convert P from barycentric form  to  the  power  or  Chebyshev
            basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions  from
            POLINT subpackage.

        SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:

        Setting constraints can lead  to undesired  results,  like ill-conditioned
        behavior, or inconsistency being detected. From the other side,  it allows
        us to improve quality of the fit. Here we summarize  our  experience  with
        constrained regression splines:
        * even simple constraints can be inconsistent, see  Wikipedia  article  on
          this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
        * the  greater  is  M (given  fixed  constraints),  the  more chances that
          constraints will be consistent
        * in the general case, consistency of constraints is NOT GUARANTEED.
        * in the one special cases, however, we can  guarantee  consistency.  This
          case  is:  M>1  and constraints on the function values (NOT DERIVATIVES)

        Our final recommendation is to use constraints  WHEN  AND  ONLY  when  you
        can't solve your task without them. Anything beyond  special  cases  given
        above is not guaranteed and may result in inconsistency.

          -- ALGLIB PROJECT --
             Copyright 10.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfitwc(double[] x,
            double[] y,
            double[] w,
            int n,
            double[] xc,
            double[] yc,
            int[] dc,
            int k,
            int m,
            ref int info,
            ratint.barycentricinterpolant p,
            polynomialfitreport rep)
        {
            double xa = 0;
            double xb = 0;
            double sa = 0;
            double sb = 0;
            double[] xoriginal = new double[0];
            double[] yoriginal = new double[0];
            double[] y2 = new double[0];
            double[] w2 = new double[0];
            double[] tmp = new double[0];
            double[] tmp2 = new double[0];
            double[] bx = new double[0];
            double[] by = new double[0];
            double[] bw = new double[0];
            int i = 0;
            int j = 0;
            double u = 0;
            double v = 0;
            double s = 0;
            int relcnt = 0;
            lsfitreport lrep = new lsfitreport();

            x = (double[])x.Clone();
            y = (double[])y.Clone();
            w = (double[])w.Clone();
            xc = (double[])xc.Clone();
            yc = (double[])yc.Clone();
            info = 0;

            alglib.ap.assert(n>0, "PolynomialFitWC: N<=0!");
            alglib.ap.assert(m>0, "PolynomialFitWC: M<=0!");
            alglib.ap.assert(k>=0, "PolynomialFitWC: K<0!");
            alglib.ap.assert(k<m, "PolynomialFitWC: K>=M!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "PolynomialFitWC: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "PolynomialFitWC: Length(Y)<N!");
            alglib.ap.assert(alglib.ap.len(w)>=n, "PolynomialFitWC: Length(W)<N!");
            alglib.ap.assert(alglib.ap.len(xc)>=k, "PolynomialFitWC: Length(XC)<K!");
            alglib.ap.assert(alglib.ap.len(yc)>=k, "PolynomialFitWC: Length(YC)<K!");
            alglib.ap.assert(alglib.ap.len(dc)>=k, "PolynomialFitWC: Length(DC)<K!");
            alglib.ap.assert(apserv.isfinitevector(x, n), "PolynomialFitWC: X contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "PolynomialFitWC: Y contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(w, n), "PolynomialFitWC: X contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(xc, k), "PolynomialFitWC: XC contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(yc, k), "PolynomialFitWC: YC contains infinite or NaN values!");
            for(i=0; i<=k-1; i++)
            {
                alglib.ap.assert(dc[i]==0 || dc[i]==1, "PolynomialFitWC: one of DC[] is not 0 or 1!");
            }
            
            //
            // Scale X, Y, XC, YC.
            // Solve scaled problem using internal Chebyshev fitting function.
            //
            lsfitscalexy(ref x, ref y, ref w, n, ref xc, ref yc, dc, k, ref xa, ref xb, ref sa, ref sb, ref xoriginal, ref yoriginal);
            internalchebyshevfit(x, y, w, n, xc, yc, dc, k, m, ref info, ref tmp, lrep);
            if( info<0 )
            {
                return;
            }
            
            //
            // Generate barycentric model and scale it
            // * BX, BY store barycentric model nodes
            // * FMatrix is reused (remember - it is at least MxM, what we need)
            //
            // Model intialization is done in O(M^2). In principle, it can be
            // done in O(M*log(M)), but before it we solved task with O(N*M^2)
            // complexity, so it is only a small amount of total time spent.
            //
            bx = new double[m];
            by = new double[m];
            bw = new double[m];
            tmp2 = new double[m];
            s = 1;
            for(i=0; i<=m-1; i++)
            {
                if( m!=1 )
                {
                    u = Math.Cos(Math.PI*i/(m-1));
                }
                else
                {
                    u = 0;
                }
                v = 0;
                for(j=0; j<=m-1; j++)
                {
                    if( j==0 )
                    {
                        tmp2[j] = 1;
                    }
                    else
                    {
                        if( j==1 )
                        {
                            tmp2[j] = u;
                        }
                        else
                        {
                            tmp2[j] = 2*u*tmp2[j-1]-tmp2[j-2];
                        }
                    }
                    v = v+tmp[j]*tmp2[j];
                }
                bx[i] = u;
                by[i] = v;
                bw[i] = s;
                if( i==0 || i==m-1 )
                {
                    bw[i] = 0.5*bw[i];
                }
                s = -s;
            }
            ratint.barycentricbuildxyw(bx, by, bw, m, p);
            ratint.barycentriclintransx(p, 2/(xb-xa), -((xa+xb)/(xb-xa)));
            ratint.barycentriclintransy(p, sb-sa, sa);
            
            //
            // Scale absolute errors obtained from LSFitLinearW.
            // Relative error should be calculated separately
            // (because of shifting/scaling of the task)
            //
            rep.taskrcond = lrep.taskrcond;
            rep.rmserror = lrep.rmserror*(sb-sa);
            rep.avgerror = lrep.avgerror*(sb-sa);
            rep.maxerror = lrep.maxerror*(sb-sa);
            rep.avgrelerror = 0;
            relcnt = 0;
            for(i=0; i<=n-1; i++)
            {
                if( (double)(yoriginal[i])!=(double)(0) )
                {
                    rep.avgrelerror = rep.avgrelerror+Math.Abs(ratint.barycentriccalc(p, xoriginal[i])-yoriginal[i])/Math.Abs(yoriginal[i]);
                    relcnt = relcnt+1;
                }
            }
            if( relcnt!=0 )
            {
                rep.avgrelerror = rep.avgrelerror/relcnt;
            }
        }
Ejemplo n.º 3
0
        /*************************************************************************
        Fitting by polynomials in barycentric form. This function provides  simple
        unterface for unconstrained unweighted fitting. See  PolynomialFitWC()  if
        you need constrained fitting.

        Task is linear, so linear least squares solver is used. Complexity of this
        computational scheme is O(N*M^2), mostly dominated by least squares solver

        SEE ALSO:
            PolynomialFitWC()

        INPUT PARAMETERS:
            X   -   points, array[0..N-1].
            Y   -   function values, array[0..N-1].
            N   -   number of points, N>0
                    * if given, only leading N elements of X/Y are used
                    * if not given, automatically determined from sizes of X/Y
            M   -   number of basis functions (= polynomial_degree + 1), M>=1

        OUTPUT PARAMETERS:
            Info-   same format as in LSFitLinearW() subroutine:
                    * Info>0    task is solved
                    * Info<=0   an error occured:
                                -4 means inconvergence of internal SVD
            P   -   interpolant in barycentric form.
            Rep -   report, same format as in LSFitLinearW() subroutine.
                    Following fields are set:
                    * RMSError      rms error on the (X,Y).
                    * AvgError      average error on the (X,Y).
                    * AvgRelError   average relative error on the non-zero Y
                    * MaxError      maximum error
                                    NON-WEIGHTED ERRORS ARE CALCULATED

        NOTES:
            you can convert P from barycentric form  to  the  power  or  Chebyshev
            basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions  from
            POLINT subpackage.

          -- ALGLIB PROJECT --
             Copyright 10.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfit(double[] x,
            double[] y,
            int n,
            int m,
            ref int info,
            ratint.barycentricinterpolant p,
            polynomialfitreport rep)
        {
            int i = 0;
            double[] w = new double[0];
            double[] xc = new double[0];
            double[] yc = new double[0];
            int[] dc = new int[0];

            info = 0;

            alglib.ap.assert(n>0, "PolynomialFit: N<=0!");
            alglib.ap.assert(m>0, "PolynomialFit: M<=0!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "PolynomialFit: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "PolynomialFit: Length(Y)<N!");
            alglib.ap.assert(apserv.isfinitevector(x, n), "PolynomialFit: X contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "PolynomialFit: Y contains infinite or NaN values!");
            w = new double[n];
            for(i=0; i<=n-1; i++)
            {
                w[i] = 1;
            }
            polynomialfitwc(x, y, w, n, xc, yc, dc, 0, m, ref info, p, rep);
        }
Ejemplo n.º 4
0
 public override alglib.apobject make_copy()
 {
     polynomialfitreport _result = new polynomialfitreport();
     _result.taskrcond = taskrcond;
     _result.rmserror = rmserror;
     _result.avgerror = avgerror;
     _result.avgrelerror = avgrelerror;
     _result.maxerror = maxerror;
     return _result;
 }
Ejemplo n.º 5
0
 /*************************************************************************
 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
 *************************************************************************/
 public static void _pexec_polynomialfitwc(double[] x,
     double[] y,
     double[] w,
     int n,
     double[] xc,
     double[] yc,
     int[] dc,
     int k,
     int m,
     ref int info,
     ratint.barycentricinterpolant p,
     polynomialfitreport rep)
 {
     polynomialfitwc(x,y,w,n,xc,yc,dc,k,m,ref info,p,rep);
 }
Ejemplo n.º 6
0
 /*************************************************************************
 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
 *************************************************************************/
 public static void _pexec_polynomialfit(double[] x,
     double[] y,
     int n,
     int m,
     ref int info,
     ratint.barycentricinterpolant p,
     polynomialfitreport rep)
 {
     polynomialfit(x,y,n,m,ref info,p,rep);
 }
Ejemplo n.º 7
0
    public static void polynomialfitwc(double[] x, double[] y, double[] w, double[] xc, double[] yc, int[] dc, int m, out int info, out barycentricinterpolant p, out polynomialfitreport rep)
    {
        int n;
        int k;
        if( (ap.len(x)!=ap.len(y)) || (ap.len(x)!=ap.len(w)))
            throw new alglibexception("Error while calling 'polynomialfitwc': looks like one of arguments has wrong size");
        if( (ap.len(xc)!=ap.len(yc)) || (ap.len(xc)!=ap.len(dc)))
            throw new alglibexception("Error while calling 'polynomialfitwc': looks like one of arguments has wrong size");
        info = 0;
        p = new barycentricinterpolant();
        rep = new polynomialfitreport();
        n = ap.len(x);
        k = ap.len(xc);
        lsfit.polynomialfitwc(x, y, w, n, xc, yc, dc, k, m, ref info, p.innerobj, rep.innerobj);

        return;
    }
Ejemplo n.º 8
0
    /*************************************************************************
    Weighted  fitting by polynomials in barycentric form, with constraints  on
    function values or first derivatives.

    Small regularizing term is used when solving constrained tasks (to improve
    stability).

    Task is linear, so linear least squares solver is used. Complexity of this
    computational scheme is O(N*M^2), mostly dominated by least squares solver

    SEE ALSO:
        PolynomialFit()

    INPUT PARAMETERS:
        X   -   points, array[0..N-1].
        Y   -   function values, array[0..N-1].
        W   -   weights, array[0..N-1]
                Each summand in square  sum  of  approximation deviations from
                given  values  is  multiplied  by  the square of corresponding
                weight. Fill it by 1's if you don't  want  to  solve  weighted
                task.
        N   -   number of points, N>0.
                * if given, only leading N elements of X/Y/W are used
                * if not given, automatically determined from sizes of X/Y/W
        XC  -   points where polynomial values/derivatives are constrained,
                array[0..K-1].
        YC  -   values of constraints, array[0..K-1]
        DC  -   array[0..K-1], types of constraints:
                * DC[i]=0   means that P(XC[i])=YC[i]
                * DC[i]=1   means that P'(XC[i])=YC[i]
                SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
        K   -   number of constraints, 0<=K<M.
                K=0 means no constraints (XC/YC/DC are not used in such cases)
        M   -   number of basis functions (= polynomial_degree + 1), M>=1

    OUTPUT PARAMETERS:
        Info-   same format as in LSFitLinearW() subroutine:
                * Info>0    task is solved
                * Info<=0   an error occured:
                            -4 means inconvergence of internal SVD
                            -3 means inconsistent constraints
        P   -   interpolant in barycentric form.
        Rep -   report, same format as in LSFitLinearW() subroutine.
                Following fields are set:
                * RMSError      rms error on the (X,Y).
                * AvgError      average error on the (X,Y).
                * AvgRelError   average relative error on the non-zero Y
                * MaxError      maximum error
                                NON-WEIGHTED ERRORS ARE CALCULATED

    IMPORTANT:
        this subroitine doesn't calculate task's condition number for K<>0.

    NOTES:
        you can convert P from barycentric form  to  the  power  or  Chebyshev
        basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions  from
        POLINT subpackage.

    SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:

    Setting constraints can lead  to undesired  results,  like ill-conditioned
    behavior, or inconsistency being detected. From the other side,  it allows
    us to improve quality of the fit. Here we summarize  our  experience  with
    constrained regression splines:
    * even simple constraints can be inconsistent, see  Wikipedia  article  on
      this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
    * the  greater  is  M (given  fixed  constraints),  the  more chances that
      constraints will be consistent
    * in the general case, consistency of constraints is NOT GUARANTEED.
    * in the one special cases, however, we can  guarantee  consistency.  This
      case  is:  M>1  and constraints on the function values (NOT DERIVATIVES)

    Our final recommendation is to use constraints  WHEN  AND  ONLY  when  you
    can't solve your task without them. Anything beyond  special  cases  given
    above is not guaranteed and may result in inconsistency.

      -- ALGLIB PROJECT --
         Copyright 10.12.2009 by Bochkanov Sergey
    *************************************************************************/
    public static void polynomialfitwc(double[] x, double[] y, double[] w, int n, double[] xc, double[] yc, int[] dc, int k, int m, out int info, out barycentricinterpolant p, out polynomialfitreport rep)
    {
        info = 0;
        p = new barycentricinterpolant();
        rep = new polynomialfitreport();
        lsfit.polynomialfitwc(x, y, w, n, xc, yc, dc, k, m, ref info, p.innerobj, rep.innerobj);
        return;
    }
Ejemplo n.º 9
0
    /*************************************************************************
    Fitting by polynomials in barycentric form. This function provides  simple
    unterface for unconstrained unweighted fitting. See  PolynomialFitWC()  if
    you need constrained fitting.

    Task is linear, so linear least squares solver is used. Complexity of this
    computational scheme is O(N*M^2), mostly dominated by least squares solver

    SEE ALSO:
        PolynomialFitWC()

    INPUT PARAMETERS:
        X   -   points, array[0..N-1].
        Y   -   function values, array[0..N-1].
        N   -   number of points, N>0
                * if given, only leading N elements of X/Y are used
                * if not given, automatically determined from sizes of X/Y
        M   -   number of basis functions (= polynomial_degree + 1), M>=1

    OUTPUT PARAMETERS:
        Info-   same format as in LSFitLinearW() subroutine:
                * Info>0    task is solved
                * Info<=0   an error occured:
                            -4 means inconvergence of internal SVD
        P   -   interpolant in barycentric form.
        Rep -   report, same format as in LSFitLinearW() subroutine.
                Following fields are set:
                * RMSError      rms error on the (X,Y).
                * AvgError      average error on the (X,Y).
                * AvgRelError   average relative error on the non-zero Y
                * MaxError      maximum error
                                NON-WEIGHTED ERRORS ARE CALCULATED

    NOTES:
        you can convert P from barycentric form  to  the  power  or  Chebyshev
        basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions  from
        POLINT subpackage.

      -- ALGLIB PROJECT --
         Copyright 10.12.2009 by Bochkanov Sergey
    *************************************************************************/
    public static void polynomialfit(double[] x, double[] y, int n, int m, out int info, out barycentricinterpolant p, out polynomialfitreport rep)
    {
        info = 0;
        p = new barycentricinterpolant();
        rep = new polynomialfitreport();
        lsfit.polynomialfit(x, y, n, m, ref info, p.innerobj, rep.innerobj);
        return;
    }
Ejemplo n.º 10
0
        /*************************************************************************
        Weighted  fitting  by  Chebyshev  polynomial  in  barycentric  form,  with
        constraints on function values or first derivatives.

        Small regularizing term is used when solving constrained tasks (to improve
        stability).

        Task is linear, so linear least squares solver is used. Complexity of this
        computational scheme is O(N*M^2), mostly dominated by least squares solver

        SEE ALSO:
            PolynomialFit()

        INPUT PARAMETERS:
            X   -   points, array[0..N-1].
            Y   -   function values, array[0..N-1].
            W   -   weights, array[0..N-1]
                    Each summand in square  sum  of  approximation deviations from
                    given  values  is  multiplied  by  the square of corresponding
                    weight. Fill it by 1's if you don't  want  to  solve  weighted
                    task.
            N   -   number of points, N>0.
            XC  -   points where polynomial values/derivatives are constrained,
                    array[0..K-1].
            YC  -   values of constraints, array[0..K-1]
            DC  -   array[0..K-1], types of constraints:
                    * DC[i]=0   means that P(XC[i])=YC[i]
                    * DC[i]=1   means that P'(XC[i])=YC[i]
                    SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
            K   -   number of constraints, 0<=K<M.
                    K=0 means no constraints (XC/YC/DC are not used in such cases)
            M   -   number of basis functions (= polynomial_degree + 1), M>=1

        OUTPUT PARAMETERS:
            Info-   same format as in LSFitLinearW() subroutine:
                    * Info>0    task is solved
                    * Info<=0   an error occured:
                                -4 means inconvergence of internal SVD
                                -3 means inconsistent constraints
                                -1 means another errors in parameters passed
                                   (N<=0, for example)
            P   -   interpolant in barycentric form.
            Rep -   report, same format as in LSFitLinearW() subroutine.
                    Following fields are set:
                    * RMSError      rms error on the (X,Y).
                    * AvgError      average error on the (X,Y).
                    * AvgRelError   average relative error on the non-zero Y
                    * MaxError      maximum error
                                    NON-WEIGHTED ERRORS ARE CALCULATED

        IMPORTANT:
            this subroitine doesn't calculate task's condition number for K<>0.

        SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:

        Setting constraints can lead  to undesired  results,  like ill-conditioned
        behavior, or inconsistency being detected. From the other side,  it allows
        us to improve quality of the fit. Here we summarize  our  experience  with
        constrained regression splines:
        * even simple constraints can be inconsistent, see  Wikipedia  article  on
          this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
        * the  greater  is  M (given  fixed  constraints),  the  more chances that
          constraints will be consistent
        * in the general case, consistency of constraints is NOT GUARANTEED.
        * in the one special cases, however, we can  guarantee  consistency.  This
          case  is:  M>1  and constraints on the function values (NOT DERIVATIVES)

        Our final recommendation is to use constraints  WHEN  AND  ONLY  when  you
        can't solve your task without them. Anything beyond  special  cases  given
        above is not guaranteed and may result in inconsistency.

          -- ALGLIB PROJECT --
             Copyright 10.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfitwc(double[] x,
            double[] y,
            ref double[] w,
            int n,
            double[] xc,
            double[] yc,
            ref int[] dc,
            int k,
            int m,
            ref int info,
            ref ratint.barycentricinterpolant p,
            ref polynomialfitreport rep)
        {
            double xa = 0;
            double xb = 0;
            double sa = 0;
            double sb = 0;
            double[] xoriginal = new double[0];
            double[] yoriginal = new double[0];
            double[] y2 = new double[0];
            double[] w2 = new double[0];
            double[] tmp = new double[0];
            double[] tmp2 = new double[0];
            double[] tmpdiff = new double[0];
            double[] bx = new double[0];
            double[] by = new double[0];
            double[] bw = new double[0];
            double[,] fmatrix = new double[0,0];
            double[,] cmatrix = new double[0,0];
            int i = 0;
            int j = 0;
            double mx = 0;
            double decay = 0;
            double u = 0;
            double v = 0;
            double s = 0;
            int relcnt = 0;
            lsfit.lsfitreport lrep = new lsfit.lsfitreport();
            int i_ = 0;

            x = (double[])x.Clone();
            y = (double[])y.Clone();
            xc = (double[])xc.Clone();
            yc = (double[])yc.Clone();

            if( m<1 | n<1 | k<0 | k>=m )
            {
                info = -1;
                return;
            }
            for(i=0; i<=k-1; i++)
            {
                info = 0;
                if( dc[i]<0 )
                {
                    info = -1;
                }
                if( dc[i]>1 )
                {
                    info = -1;
                }
                if( info<0 )
                {
                    return;
                }
            }
            
            //
            // weight decay for correct handling of task which becomes
            // degenerate after constraints are applied
            //
            decay = 10000*AP.Math.MachineEpsilon;
            
            //
            // Scale X, Y, XC, YC
            //
            lsfit.lsfitscalexy(ref x, ref y, n, ref xc, ref yc, ref dc, k, ref xa, ref xb, ref sa, ref sb, ref xoriginal, ref yoriginal);
            
            //
            // allocate space, initialize/fill:
            // * FMatrix-   values of basis functions at X[]
            // * CMatrix-   values (derivatives) of basis functions at XC[]
            // * fill constraints matrix
            // * fill first N rows of design matrix with values
            // * fill next M rows of design matrix with regularizing term
            // * append M zeros to Y
            // * append M elements, mean(abs(W)) each, to W
            //
            y2 = new double[n+m];
            w2 = new double[n+m];
            tmp = new double[m];
            tmpdiff = new double[m];
            fmatrix = new double[n+m, m];
            if( k>0 )
            {
                cmatrix = new double[k, m+1];
            }
            
            //
            // Fill design matrix, Y2, W2:
            // * first N rows with basis functions for original points
            // * next M rows with decay terms
            //
            for(i=0; i<=n-1; i++)
            {
                
                //
                // prepare Ith row
                // use Tmp for calculations to avoid multidimensional arrays overhead
                //
                for(j=0; j<=m-1; j++)
                {
                    if( j==0 )
                    {
                        tmp[j] = 1;
                    }
                    else
                    {
                        if( j==1 )
                        {
                            tmp[j] = x[i];
                        }
                        else
                        {
                            tmp[j] = 2*x[i]*tmp[j-1]-tmp[j-2];
                        }
                    }
                }
                for(i_=0; i_<=m-1;i_++)
                {
                    fmatrix[i,i_] = tmp[i_];
                }
            }
            for(i=0; i<=m-1; i++)
            {
                for(j=0; j<=m-1; j++)
                {
                    if( i==j )
                    {
                        fmatrix[n+i,j] = decay;
                    }
                    else
                    {
                        fmatrix[n+i,j] = 0;
                    }
                }
            }
            for(i_=0; i_<=n-1;i_++)
            {
                y2[i_] = y[i_];
            }
            for(i_=0; i_<=n-1;i_++)
            {
                w2[i_] = w[i_];
            }
            mx = 0;
            for(i=0; i<=n-1; i++)
            {
                mx = mx+Math.Abs(w[i]);
            }
            mx = mx/n;
            for(i=0; i<=m-1; i++)
            {
                y2[n+i] = 0;
                w2[n+i] = mx;
            }
            
            //
            // fill constraints matrix
            //
            for(i=0; i<=k-1; i++)
            {
                
                //
                // prepare Ith row
                // use Tmp for basis function values,
                // TmpDiff for basos function derivatives
                //
                for(j=0; j<=m-1; j++)
                {
                    if( j==0 )
                    {
                        tmp[j] = 1;
                        tmpdiff[j] = 0;
                    }
                    else
                    {
                        if( j==1 )
                        {
                            tmp[j] = xc[i];
                            tmpdiff[j] = 1;
                        }
                        else
                        {
                            tmp[j] = 2*xc[i]*tmp[j-1]-tmp[j-2];
                            tmpdiff[j] = 2*(tmp[j-1]+xc[i]*tmpdiff[j-1])-tmpdiff[j-2];
                        }
                    }
                }
                if( dc[i]==0 )
                {
                    for(i_=0; i_<=m-1;i_++)
                    {
                        cmatrix[i,i_] = tmp[i_];
                    }
                }
                if( dc[i]==1 )
                {
                    for(i_=0; i_<=m-1;i_++)
                    {
                        cmatrix[i,i_] = tmpdiff[i_];
                    }
                }
                cmatrix[i,m] = yc[i];
            }
            
            //
            // Solve constrained task
            //
            if( k>0 )
            {
                
                //
                // solve using regularization
                //
                lsfit.lsfitlinearwc(y2, ref w2, ref fmatrix, cmatrix, n+m, m, k, ref info, ref tmp, ref lrep);
            }
            else
            {
                
                //
                // no constraints, no regularization needed
                //
                lsfit.lsfitlinearwc(y, ref w, ref fmatrix, cmatrix, n, m, 0, ref info, ref tmp, ref lrep);
            }
            if( info<0 )
            {
                return;
            }
            
            //
            // Generate barycentric model and scale it
            // * BX, BY store barycentric model nodes
            // * FMatrix is reused (remember - it is at least MxM, what we need)
            //
            // Model intialization is done in O(M^2). In principle, it can be
            // done in O(M*log(M)), but before it we solved task with O(N*M^2)
            // complexity, so it is only a small amount of total time spent.
            //
            bx = new double[m];
            by = new double[m];
            bw = new double[m];
            tmp2 = new double[m];
            s = 1;
            for(i=0; i<=m-1; i++)
            {
                if( m!=1 )
                {
                    u = Math.Cos(Math.PI*i/(m-1));
                }
                else
                {
                    u = 0;
                }
                v = 0;
                for(j=0; j<=m-1; j++)
                {
                    if( j==0 )
                    {
                        tmp2[j] = 1;
                    }
                    else
                    {
                        if( j==1 )
                        {
                            tmp2[j] = u;
                        }
                        else
                        {
                            tmp2[j] = 2*u*tmp2[j-1]-tmp2[j-2];
                        }
                    }
                    v = v+tmp[j]*tmp2[j];
                }
                bx[i] = u;
                by[i] = v;
                bw[i] = s;
                if( i==0 | i==m-1 )
                {
                    bw[i] = 0.5*bw[i];
                }
                s = -s;
            }
            ratint.barycentricbuildxyw(ref bx, ref by, ref bw, m, ref p);
            ratint.barycentriclintransx(ref p, 2/(xb-xa), -((xa+xb)/(xb-xa)));
            ratint.barycentriclintransy(ref p, sb-sa, sa);
            
            //
            // Scale absolute errors obtained from LSFitLinearW.
            // Relative error should be calculated separately
            // (because of shifting/scaling of the task)
            //
            rep.taskrcond = lrep.taskrcond;
            rep.rmserror = lrep.rmserror*(sb-sa);
            rep.avgerror = lrep.avgerror*(sb-sa);
            rep.maxerror = lrep.maxerror*(sb-sa);
            rep.avgrelerror = 0;
            relcnt = 0;
            for(i=0; i<=n-1; i++)
            {
                if( (double)(yoriginal[i])!=(double)(0) )
                {
                    rep.avgrelerror = rep.avgrelerror+Math.Abs(ratint.barycentriccalc(ref p, xoriginal[i])-yoriginal[i])/Math.Abs(yoriginal[i]);
                    relcnt = relcnt+1;
                }
            }
            if( relcnt!=0 )
            {
                rep.avgrelerror = rep.avgrelerror/relcnt;
            }
        }
Ejemplo n.º 11
0
        /*************************************************************************
        Least squares fitting by polynomial.

        This subroutine is "lightweight" alternative for more complex and feature-
        rich PolynomialFitWC().  See  PolynomialFitWC() for more information about
        subroutine parameters (we don't duplicate it here because of length)

          -- ALGLIB PROJECT --
             Copyright 12.10.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfit(ref double[] x,
            ref double[] y,
            int n,
            int m,
            ref int info,
            ref ratint.barycentricinterpolant p,
            ref polynomialfitreport rep)
        {
            int i = 0;
            double[] w = new double[0];
            double[] xc = new double[0];
            double[] yc = new double[0];
            int[] dc = new int[0];

            if( n>0 )
            {
                w = new double[n];
                for(i=0; i<=n-1; i++)
                {
                    w[i] = 1;
                }
            }
            polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 0, m, ref info, ref p, ref rep);
        }
Ejemplo n.º 12
0
        /*************************************************************************
        *  Weighted  fitting  by  Chebyshev  polynomial  in  barycentric  form,  with
        *  constraints on function values or first derivatives.
        *
        *  Small regularizing term is used when solving constrained tasks (to improve
        *  stability).
        *
        *  Task is linear, so linear least squares solver is used. Complexity of this
        *  computational scheme is O(N*M^2), mostly dominated by least squares solver
        *
        *  SEE ALSO:
        *   PolynomialFit()
        *
        *  INPUT PARAMETERS:
        *   X   -   points, array[0..N-1].
        *   Y   -   function values, array[0..N-1].
        *   W   -   weights, array[0..N-1]
        *           Each summand in square  sum  of  approximation deviations from
        *           given  values  is  multiplied  by  the square of corresponding
        *           weight. Fill it by 1's if you don't  want  to  solve  weighted
        *           task.
        *   N   -   number of points, N>0.
        *   XC  -   points where polynomial values/derivatives are constrained,
        *           array[0..K-1].
        *   YC  -   values of constraints, array[0..K-1]
        *   DC  -   array[0..K-1], types of constraints:
        * DC[i]=0   means that P(XC[i])=YC[i]
        * DC[i]=1   means that P'(XC[i])=YC[i]
        *           SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
        *   K   -   number of constraints, 0<=K<M.
        *           K=0 means no constraints (XC/YC/DC are not used in such cases)
        *   M   -   number of basis functions (= polynomial_degree + 1), M>=1
        *
        *  OUTPUT PARAMETERS:
        *   Info-   same format as in LSFitLinearW() subroutine:
        * Info>0    task is solved
        * Info<=0   an error occured:
        *                       -4 means inconvergence of internal SVD
        *                       -3 means inconsistent constraints
        *                       -1 means another errors in parameters passed
        *                          (N<=0, for example)
        *   P   -   interpolant in barycentric form.
        *   Rep -   report, same format as in LSFitLinearW() subroutine.
        *           Following fields are set:
        * RMSError      rms error on the (X,Y).
        * AvgError      average error on the (X,Y).
        * AvgRelError   average relative error on the non-zero Y
        * MaxError      maximum error
        *                           NON-WEIGHTED ERRORS ARE CALCULATED
        *
        *  IMPORTANT:
        *   this subroitine doesn't calculate task's condition number for K<>0.
        *
        *  SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
        *
        *  Setting constraints can lead  to undesired  results,  like ill-conditioned
        *  behavior, or inconsistency being detected. From the other side,  it allows
        *  us to improve quality of the fit. Here we summarize  our  experience  with
        *  constrained regression splines:
        * even simple constraints can be inconsistent, see  Wikipedia  article  on
        *  this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
        * the  greater  is  M (given  fixed  constraints),  the  more chances that
        *  constraints will be consistent
        * in the general case, consistency of constraints is NOT GUARANTEED.
        * in the one special cases, however, we can  guarantee  consistency.  This
        *  case  is:  M>1  and constraints on the function values (NOT DERIVATIVES)
        *
        *  Our final recommendation is to use constraints  WHEN  AND  ONLY  when  you
        *  can't solve your task without them. Anything beyond  special  cases  given
        *  above is not guaranteed and may result in inconsistency.
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 10.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfitwc(double[] x,
                                           double[] y,
                                           ref double[] w,
                                           int n,
                                           double[] xc,
                                           double[] yc,
                                           ref int[] dc,
                                           int k,
                                           int m,
                                           ref int info,
                                           ref ratint.barycentricinterpolant p,
                                           ref polynomialfitreport rep)
        {
            double xa = 0;
            double xb = 0;
            double sa = 0;
            double sb = 0;

            double[] xoriginal = new double[0];
            double[] yoriginal = new double[0];
            double[] y2        = new double[0];
            double[] w2        = new double[0];
            double[] tmp       = new double[0];
            double[] tmp2      = new double[0];
            double[] tmpdiff   = new double[0];
            double[] bx        = new double[0];
            double[] by        = new double[0];
            double[] bw        = new double[0];
            double[,] fmatrix = new double[0, 0];
            double[,] cmatrix = new double[0, 0];
            int    i      = 0;
            int    j      = 0;
            double mx     = 0;
            double decay  = 0;
            double u      = 0;
            double v      = 0;
            double s      = 0;
            int    relcnt = 0;

            lsfit.lsfitreport lrep = new lsfit.lsfitreport();
            int i_ = 0;

            x  = (double[])x.Clone();
            y  = (double[])y.Clone();
            xc = (double[])xc.Clone();
            yc = (double[])yc.Clone();

            if (m < 1 | n < 1 | k < 0 | k >= m)
            {
                info = -1;
                return;
            }
            for (i = 0; i <= k - 1; i++)
            {
                info = 0;
                if (dc[i] < 0)
                {
                    info = -1;
                }
                if (dc[i] > 1)
                {
                    info = -1;
                }
                if (info < 0)
                {
                    return;
                }
            }

            //
            // weight decay for correct handling of task which becomes
            // degenerate after constraints are applied
            //
            decay = 10000 * AP.Math.MachineEpsilon;

            //
            // Scale X, Y, XC, YC
            //
            lsfit.lsfitscalexy(ref x, ref y, n, ref xc, ref yc, ref dc, k, ref xa, ref xb, ref sa, ref sb, ref xoriginal, ref yoriginal);

            //
            // allocate space, initialize/fill:
            // * FMatrix-   values of basis functions at X[]
            // * CMatrix-   values (derivatives) of basis functions at XC[]
            // * fill constraints matrix
            // * fill first N rows of design matrix with values
            // * fill next M rows of design matrix with regularizing term
            // * append M zeros to Y
            // * append M elements, mean(abs(W)) each, to W
            //
            y2      = new double[n + m];
            w2      = new double[n + m];
            tmp     = new double[m];
            tmpdiff = new double[m];
            fmatrix = new double[n + m, m];
            if (k > 0)
            {
                cmatrix = new double[k, m + 1];
            }

            //
            // Fill design matrix, Y2, W2:
            // * first N rows with basis functions for original points
            // * next M rows with decay terms
            //
            for (i = 0; i <= n - 1; i++)
            {
                //
                // prepare Ith row
                // use Tmp for calculations to avoid multidimensional arrays overhead
                //
                for (j = 0; j <= m - 1; j++)
                {
                    if (j == 0)
                    {
                        tmp[j] = 1;
                    }
                    else
                    {
                        if (j == 1)
                        {
                            tmp[j] = x[i];
                        }
                        else
                        {
                            tmp[j] = 2 * x[i] * tmp[j - 1] - tmp[j - 2];
                        }
                    }
                }
                for (i_ = 0; i_ <= m - 1; i_++)
                {
                    fmatrix[i, i_] = tmp[i_];
                }
            }
            for (i = 0; i <= m - 1; i++)
            {
                for (j = 0; j <= m - 1; j++)
                {
                    if (i == j)
                    {
                        fmatrix[n + i, j] = decay;
                    }
                    else
                    {
                        fmatrix[n + i, j] = 0;
                    }
                }
            }
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                y2[i_] = y[i_];
            }
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                w2[i_] = w[i_];
            }
            mx = 0;
            for (i = 0; i <= n - 1; i++)
            {
                mx = mx + Math.Abs(w[i]);
            }
            mx = mx / n;
            for (i = 0; i <= m - 1; i++)
            {
                y2[n + i] = 0;
                w2[n + i] = mx;
            }

            //
            // fill constraints matrix
            //
            for (i = 0; i <= k - 1; i++)
            {
                //
                // prepare Ith row
                // use Tmp for basis function values,
                // TmpDiff for basos function derivatives
                //
                for (j = 0; j <= m - 1; j++)
                {
                    if (j == 0)
                    {
                        tmp[j]     = 1;
                        tmpdiff[j] = 0;
                    }
                    else
                    {
                        if (j == 1)
                        {
                            tmp[j]     = xc[i];
                            tmpdiff[j] = 1;
                        }
                        else
                        {
                            tmp[j]     = 2 * xc[i] * tmp[j - 1] - tmp[j - 2];
                            tmpdiff[j] = 2 * (tmp[j - 1] + xc[i] * tmpdiff[j - 1]) - tmpdiff[j - 2];
                        }
                    }
                }
                if (dc[i] == 0)
                {
                    for (i_ = 0; i_ <= m - 1; i_++)
                    {
                        cmatrix[i, i_] = tmp[i_];
                    }
                }
                if (dc[i] == 1)
                {
                    for (i_ = 0; i_ <= m - 1; i_++)
                    {
                        cmatrix[i, i_] = tmpdiff[i_];
                    }
                }
                cmatrix[i, m] = yc[i];
            }

            //
            // Solve constrained task
            //
            if (k > 0)
            {
                //
                // solve using regularization
                //
                lsfit.lsfitlinearwc(y2, ref w2, ref fmatrix, cmatrix, n + m, m, k, ref info, ref tmp, ref lrep);
            }
            else
            {
                //
                // no constraints, no regularization needed
                //
                lsfit.lsfitlinearwc(y, ref w, ref fmatrix, cmatrix, n, m, 0, ref info, ref tmp, ref lrep);
            }
            if (info < 0)
            {
                return;
            }

            //
            // Generate barycentric model and scale it
            // * BX, BY store barycentric model nodes
            // * FMatrix is reused (remember - it is at least MxM, what we need)
            //
            // Model intialization is done in O(M^2). In principle, it can be
            // done in O(M*log(M)), but before it we solved task with O(N*M^2)
            // complexity, so it is only a small amount of total time spent.
            //
            bx   = new double[m];
            by   = new double[m];
            bw   = new double[m];
            tmp2 = new double[m];
            s    = 1;
            for (i = 0; i <= m - 1; i++)
            {
                if (m != 1)
                {
                    u = Math.Cos(Math.PI * i / (m - 1));
                }
                else
                {
                    u = 0;
                }
                v = 0;
                for (j = 0; j <= m - 1; j++)
                {
                    if (j == 0)
                    {
                        tmp2[j] = 1;
                    }
                    else
                    {
                        if (j == 1)
                        {
                            tmp2[j] = u;
                        }
                        else
                        {
                            tmp2[j] = 2 * u * tmp2[j - 1] - tmp2[j - 2];
                        }
                    }
                    v = v + tmp[j] * tmp2[j];
                }
                bx[i] = u;
                by[i] = v;
                bw[i] = s;
                if (i == 0 | i == m - 1)
                {
                    bw[i] = 0.5 * bw[i];
                }
                s = -s;
            }
            ratint.barycentricbuildxyw(ref bx, ref by, ref bw, m, ref p);
            ratint.barycentriclintransx(ref p, 2 / (xb - xa), -((xa + xb) / (xb - xa)));
            ratint.barycentriclintransy(ref p, sb - sa, sa);

            //
            // Scale absolute errors obtained from LSFitLinearW.
            // Relative error should be calculated separately
            // (because of shifting/scaling of the task)
            //
            rep.taskrcond   = lrep.taskrcond;
            rep.rmserror    = lrep.rmserror * (sb - sa);
            rep.avgerror    = lrep.avgerror * (sb - sa);
            rep.maxerror    = lrep.maxerror * (sb - sa);
            rep.avgrelerror = 0;
            relcnt          = 0;
            for (i = 0; i <= n - 1; i++)
            {
                if ((double)(yoriginal[i]) != (double)(0))
                {
                    rep.avgrelerror = rep.avgrelerror + Math.Abs(ratint.barycentriccalc(ref p, xoriginal[i]) - yoriginal[i]) / Math.Abs(yoriginal[i]);
                    relcnt          = relcnt + 1;
                }
            }
            if (relcnt != 0)
            {
                rep.avgrelerror = rep.avgrelerror / relcnt;
            }
        }