Exemple #1
0
 public spline1dfitreport(lsfit.spline1dfitreport obj)
 {
     _innerobj = obj;
 }
        private static void testsplinefitting(ref bool fiterrors)
        {
            double threshold = 0;
            double nonstrictthreshold = 0;
            int passcount = 0;
            int n = 0;
            int m = 0;
            int i = 0;
            int k = 0;
            int pass = 0;
            double[] x = new double[0];
            double[] y = new double[0];
            double[] w = new double[0];
            double[] w2 = new double[0];
            double[] xc = new double[0];
            double[] yc = new double[0];
            double[] d = new double[0];
            int[] dc = new int[0];
            double sa = 0;
            double sb = 0;
            int info = 0;
            int info1 = 0;
            int info2 = 0;
            spline1d.spline1dinterpolant c = new spline1d.spline1dinterpolant();
            spline1d.spline1dinterpolant c2 = new spline1d.spline1dinterpolant();
            lsfit.spline1dfitreport rep = new lsfit.spline1dfitreport();
            lsfit.spline1dfitreport rep2 = new lsfit.spline1dfitreport();
            double s = 0;
            double ds = 0;
            double d2s = 0;
            int stype = 0;
            double t = 0;
            double v = 0;
            double v1 = 0;
            double v2 = 0;
            double refrms = 0;
            double refavg = 0;
            double refavgrel = 0;
            double refmax = 0;
            double rho = 0;

            
            //
            // Valyes:
            // * pass count
            // * threshold - for tests which must be satisfied exactly
            // * nonstrictthreshold - for approximate tests
            //
            passcount = 20;
            threshold = 10000*math.machineepsilon;
            nonstrictthreshold = 1.0E-4;
            fiterrors = false;
            
            //
            // Test fitting by Cubic and Hermite splines (obsolete, but still supported)
            //
            for(pass=1; pass<=passcount; pass++)
            {
                
                //
                // Cubic splines
                // Ability to handle boundary constraints (1-4 constraints on F, dF/dx).
                //
                for(m=4; m<=8; m++)
                {
                    for(k=1; k<=4; k++)
                    {
                        if( k>=m )
                        {
                            continue;
                        }
                        n = 100;
                        x = new double[n];
                        y = new double[n];
                        w = new double[n];
                        xc = new double[4];
                        yc = new double[4];
                        dc = new int[4];
                        sa = 1+math.randomreal();
                        sb = 2*math.randomreal()-1;
                        for(i=0; i<=n-1; i++)
                        {
                            x[i] = sa*math.randomreal()+sb;
                            y[i] = 2*math.randomreal()-1;
                            w[i] = 1+math.randomreal();
                        }
                        xc[0] = sb;
                        yc[0] = 2*math.randomreal()-1;
                        dc[0] = 0;
                        xc[1] = sb;
                        yc[1] = 2*math.randomreal()-1;
                        dc[1] = 1;
                        xc[2] = sa+sb;
                        yc[2] = 2*math.randomreal()-1;
                        dc[2] = 0;
                        xc[3] = sa+sb;
                        yc[3] = 2*math.randomreal()-1;
                        dc[3] = 1;
                        lsfit.spline1dfitcubicwc(x, y, w, n, xc, yc, dc, k, m, ref info, c, rep);
                        if( info<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            
                            //
                            // Check that constraints are satisfied
                            //
                            for(i=0; i<=k-1; i++)
                            {
                                spline1d.spline1ddiff(c, xc[i], ref s, ref ds, ref d2s);
                                if( dc[i]==0 )
                                {
                                    fiterrors = fiterrors | (double)(Math.Abs(s-yc[i]))>(double)(threshold);
                                }
                                if( dc[i]==1 )
                                {
                                    fiterrors = fiterrors | (double)(Math.Abs(ds-yc[i]))>(double)(threshold);
                                }
                                if( dc[i]==2 )
                                {
                                    fiterrors = fiterrors | (double)(Math.Abs(d2s-yc[i]))>(double)(threshold);
                                }
                            }
                        }
                    }
                }
                
                //
                // Cubic splines
                // Ability to handle one internal constraint
                //
                for(m=4; m<=8; m++)
                {
                    n = 100;
                    x = new double[n];
                    y = new double[n];
                    w = new double[n];
                    xc = new double[1];
                    yc = new double[1];
                    dc = new int[1];
                    sa = 1+math.randomreal();
                    sb = 2*math.randomreal()-1;
                    for(i=0; i<=n-1; i++)
                    {
                        x[i] = sa*math.randomreal()+sb;
                        y[i] = 2*math.randomreal()-1;
                        w[i] = 1+math.randomreal();
                    }
                    xc[0] = sa*math.randomreal()+sb;
                    yc[0] = 2*math.randomreal()-1;
                    dc[0] = math.randominteger(2);
                    lsfit.spline1dfitcubicwc(x, y, w, n, xc, yc, dc, 1, m, ref info, c, rep);
                    if( info<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        
                        //
                        // Check that constraints are satisfied
                        //
                        spline1d.spline1ddiff(c, xc[0], ref s, ref ds, ref d2s);
                        if( dc[0]==0 )
                        {
                            fiterrors = fiterrors | (double)(Math.Abs(s-yc[0]))>(double)(threshold);
                        }
                        if( dc[0]==1 )
                        {
                            fiterrors = fiterrors | (double)(Math.Abs(ds-yc[0]))>(double)(threshold);
                        }
                        if( dc[0]==2 )
                        {
                            fiterrors = fiterrors | (double)(Math.Abs(d2s-yc[0]))>(double)(threshold);
                        }
                    }
                }
                
                //
                // Hermite splines
                // Ability to handle boundary constraints (1-4 constraints on F, dF/dx).
                //
                for(m=4; m<=8; m++)
                {
                    for(k=1; k<=4; k++)
                    {
                        if( k>=m )
                        {
                            continue;
                        }
                        if( m%2!=0 )
                        {
                            continue;
                        }
                        n = 100;
                        x = new double[n];
                        y = new double[n];
                        w = new double[n];
                        xc = new double[4];
                        yc = new double[4];
                        dc = new int[4];
                        sa = 1+math.randomreal();
                        sb = 2*math.randomreal()-1;
                        for(i=0; i<=n-1; i++)
                        {
                            x[i] = sa*math.randomreal()+sb;
                            y[i] = 2*math.randomreal()-1;
                            w[i] = 1+math.randomreal();
                        }
                        xc[0] = sb;
                        yc[0] = 2*math.randomreal()-1;
                        dc[0] = 0;
                        xc[1] = sb;
                        yc[1] = 2*math.randomreal()-1;
                        dc[1] = 1;
                        xc[2] = sa+sb;
                        yc[2] = 2*math.randomreal()-1;
                        dc[2] = 0;
                        xc[3] = sa+sb;
                        yc[3] = 2*math.randomreal()-1;
                        dc[3] = 1;
                        lsfit.spline1dfithermitewc(x, y, w, n, xc, yc, dc, k, m, ref info, c, rep);
                        if( info<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            
                            //
                            // Check that constraints are satisfied
                            //
                            for(i=0; i<=k-1; i++)
                            {
                                spline1d.spline1ddiff(c, xc[i], ref s, ref ds, ref d2s);
                                if( dc[i]==0 )
                                {
                                    fiterrors = fiterrors | (double)(Math.Abs(s-yc[i]))>(double)(threshold);
                                }
                                if( dc[i]==1 )
                                {
                                    fiterrors = fiterrors | (double)(Math.Abs(ds-yc[i]))>(double)(threshold);
                                }
                                if( dc[i]==2 )
                                {
                                    fiterrors = fiterrors | (double)(Math.Abs(d2s-yc[i]))>(double)(threshold);
                                }
                            }
                        }
                    }
                }
                
                //
                // Hermite splines
                // Ability to handle one internal constraint
                //
                for(m=4; m<=8; m++)
                {
                    if( m%2!=0 )
                    {
                        continue;
                    }
                    n = 100;
                    x = new double[n];
                    y = new double[n];
                    w = new double[n];
                    xc = new double[1];
                    yc = new double[1];
                    dc = new int[1];
                    sa = 1+math.randomreal();
                    sb = 2*math.randomreal()-1;
                    for(i=0; i<=n-1; i++)
                    {
                        x[i] = sa*math.randomreal()+sb;
                        y[i] = 2*math.randomreal()-1;
                        w[i] = 1+math.randomreal();
                    }
                    xc[0] = sa*math.randomreal()+sb;
                    yc[0] = 2*math.randomreal()-1;
                    dc[0] = math.randominteger(2);
                    lsfit.spline1dfithermitewc(x, y, w, n, xc, yc, dc, 1, m, ref info, c, rep);
                    if( info<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        
                        //
                        // Check that constraints are satisfied
                        //
                        spline1d.spline1ddiff(c, xc[0], ref s, ref ds, ref d2s);
                        if( dc[0]==0 )
                        {
                            fiterrors = fiterrors | (double)(Math.Abs(s-yc[0]))>(double)(threshold);
                        }
                        if( dc[0]==1 )
                        {
                            fiterrors = fiterrors | (double)(Math.Abs(ds-yc[0]))>(double)(threshold);
                        }
                        if( dc[0]==2 )
                        {
                            fiterrors = fiterrors | (double)(Math.Abs(d2s-yc[0]))>(double)(threshold);
                        }
                    }
                }
            }
            for(m=4; m<=8; m++)
            {
                for(stype=0; stype<=1; stype++)
                {
                    for(pass=1; pass<=passcount; pass++)
                    {
                        if( stype==1 & m%2!=0 )
                        {
                            continue;
                        }
                        
                        //
                        // cubic/Hermite spline fitting:
                        // * generate "template spline" C2
                        // * generate 2*N points from C2, such that result of
                        //   ideal fit should be equal to C2
                        // * fit, store in C
                        // * compare C and C2
                        //
                        sa = 1+math.randomreal();
                        sb = 2*math.randomreal()-1;
                        if( stype==0 )
                        {
                            x = new double[m-2];
                            y = new double[m-2];
                            for(i=0; i<=m-2-1; i++)
                            {
                                x[i] = sa*i/(m-2-1)+sb;
                                y[i] = 2*math.randomreal()-1;
                            }
                            spline1d.spline1dbuildcubic(x, y, m-2, 1, 2*math.randomreal()-1, 1, 2*math.randomreal()-1, c2);
                        }
                        if( stype==1 )
                        {
                            x = new double[m/2];
                            y = new double[m/2];
                            d = new double[m/2];
                            for(i=0; i<=m/2-1; i++)
                            {
                                x[i] = sa*i/(m/2-1)+sb;
                                y[i] = 2*math.randomreal()-1;
                                d[i] = 2*math.randomreal()-1;
                            }
                            spline1d.spline1dbuildhermite(x, y, d, m/2, c2);
                        }
                        n = 50;
                        x = new double[2*n];
                        y = new double[2*n];
                        w = new double[2*n];
                        for(i=0; i<=n-1; i++)
                        {
                            
                            //
                            // "if i=0" and "if i=1" are needed to
                            // synchronize interval size for C2 and
                            // spline being fitted (i.e. C).
                            //
                            t = math.randomreal();
                            x[i] = sa*math.randomreal()+sb;
                            if( i==0 )
                            {
                                x[i] = sb;
                            }
                            if( i==1 )
                            {
                                x[i] = sa+sb;
                            }
                            v = spline1d.spline1dcalc(c2, x[i]);
                            y[i] = v+t;
                            w[i] = 1+math.randomreal();
                            x[n+i] = x[i];
                            y[n+i] = v-t;
                            w[n+i] = w[i];
                        }
                        if( stype==0 )
                        {
                            lsfit.spline1dfitcubicwc(x, y, w, 2*n, xc, yc, dc, 0, m, ref info, c, rep);
                        }
                        if( stype==1 )
                        {
                            lsfit.spline1dfithermitewc(x, y, w, 2*n, xc, yc, dc, 0, m, ref info, c, rep);
                        }
                        if( info<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for(i=0; i<=n-1; i++)
                            {
                                v = sa*math.randomreal()+sb;
                                fiterrors = fiterrors | (double)(Math.Abs(spline1d.spline1dcalc(c, v)-spline1d.spline1dcalc(c2, v)))>(double)(threshold);
                            }
                        }
                    }
                }
            }
            for(m=4; m<=8; m++)
            {
                for(pass=1; pass<=passcount; pass++)
                {
                    
                    //
                    // prepare points/weights
                    //
                    sa = 1+math.randomreal();
                    sb = 2*math.randomreal()-1;
                    n = 10+math.randominteger(10);
                    x = new double[n];
                    y = new double[n];
                    w = new double[n];
                    for(i=0; i<=n-1; i++)
                    {
                        x[i] = sa*math.randomreal()+sb;
                        y[i] = 2*math.randomreal()-1;
                        w[i] = 1;
                    }
                    
                    //
                    // Fit cubic with unity weights, without weights, then compare
                    //
                    if( m>=4 )
                    {
                        lsfit.spline1dfitcubicwc(x, y, w, n, xc, yc, dc, 0, m, ref info1, c, rep);
                        lsfit.spline1dfitcubic(x, y, n, m, ref info2, c2, rep2);
                        if( info1<=0 | info2<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for(i=0; i<=n-1; i++)
                            {
                                v = sa*math.randomreal()+sb;
                                fiterrors = fiterrors | (double)(spline1d.spline1dcalc(c, v))!=(double)(spline1d.spline1dcalc(c2, v));
                                fiterrors = fiterrors | (double)(rep.taskrcond)!=(double)(rep2.taskrcond);
                                fiterrors = fiterrors | (double)(rep.rmserror)!=(double)(rep2.rmserror);
                                fiterrors = fiterrors | (double)(rep.avgerror)!=(double)(rep2.avgerror);
                                fiterrors = fiterrors | (double)(rep.avgrelerror)!=(double)(rep2.avgrelerror);
                                fiterrors = fiterrors | (double)(rep.maxerror)!=(double)(rep2.maxerror);
                            }
                        }
                    }
                    
                    //
                    // Fit Hermite with unity weights, without weights, then compare
                    //
                    if( m>=4 & m%2==0 )
                    {
                        lsfit.spline1dfithermitewc(x, y, w, n, xc, yc, dc, 0, m, ref info1, c, rep);
                        lsfit.spline1dfithermite(x, y, n, m, ref info2, c2, rep2);
                        if( info1<=0 | info2<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for(i=0; i<=n-1; i++)
                            {
                                v = sa*math.randomreal()+sb;
                                fiterrors = fiterrors | (double)(spline1d.spline1dcalc(c, v))!=(double)(spline1d.spline1dcalc(c2, v));
                                fiterrors = fiterrors | (double)(rep.taskrcond)!=(double)(rep2.taskrcond);
                                fiterrors = fiterrors | (double)(rep.rmserror)!=(double)(rep2.rmserror);
                                fiterrors = fiterrors | (double)(rep.avgerror)!=(double)(rep2.avgerror);
                                fiterrors = fiterrors | (double)(rep.avgrelerror)!=(double)(rep2.avgrelerror);
                                fiterrors = fiterrors | (double)(rep.maxerror)!=(double)(rep2.maxerror);
                            }
                        }
                    }
                }
            }
            
            //
            // check basic properties of penalized splines which are
            // preserved independently of Rho parameter.
            //
            for(m=4; m<=10; m++)
            {
                for(k=-5; k<=5; k++)
                {
                    rho = k;
                    
                    //
                    // when we have two points (even with different weights),
                    // resulting spline must be equal to the straight line
                    //
                    x = new double[2];
                    y = new double[2];
                    w = new double[2];
                    x[0] = -0.5-math.randomreal();
                    y[0] = 0.5+math.randomreal();
                    w[0] = 1+math.randomreal();
                    x[1] = 0.5+math.randomreal();
                    y[1] = 0.5+math.randomreal();
                    w[1] = 1+math.randomreal();
                    lsfit.spline1dfitpenalized(x, y, 2, m, rho, ref info, c, rep);
                    if( info>0 )
                    {
                        v = 2*math.randomreal()-1;
                        v1 = (v-x[0])/(x[1]-x[0])*y[1]+(v-x[1])/(x[0]-x[1])*y[0];
                        fiterrors = fiterrors | (double)(Math.Abs(v1-spline1d.spline1dcalc(c, v)))>(double)(nonstrictthreshold);
                    }
                    else
                    {
                        fiterrors = true;
                    }
                    lsfit.spline1dfitpenalizedw(x, y, w, 2, m, rho, ref info, c, rep);
                    if( info>0 )
                    {
                        v = 2*math.randomreal()-1;
                        v1 = (v-x[0])/(x[1]-x[0])*y[1]+(v-x[1])/(x[0]-x[1])*y[0];
                        fiterrors = fiterrors | (double)(Math.Abs(v1-spline1d.spline1dcalc(c, v)))>(double)(nonstrictthreshold);
                    }
                    else
                    {
                        fiterrors = true;
                    }
                    
                    //
                    // spline fitting is invariant with respect to
                    // scaling of weights (of course, ANY fitting algorithm
                    // must be invariant, but we want to test this property
                    // just to be sure that it is correctly implemented)
                    //
                    for(n=2; n<=2*m; n++)
                    {
                        x = new double[n];
                        y = new double[n];
                        w = new double[n];
                        w2 = new double[n];
                        s = 1+Math.Exp(10*math.randomreal());
                        for(i=0; i<=n-1; i++)
                        {
                            x[i] = (double)i/(double)(n-1);
                            y[i] = math.randomreal();
                            w[i] = 0.1+math.randomreal();
                            w2[i] = w[i]*s;
                        }
                        lsfit.spline1dfitpenalizedw(x, y, w, n, m, rho, ref info, c, rep);
                        lsfit.spline1dfitpenalizedw(x, y, w2, n, m, rho, ref info2, c2, rep2);
                        if( info>0 & info2>0 )
                        {
                            v = math.randomreal();
                            v1 = spline1d.spline1dcalc(c, v);
                            v2 = spline1d.spline1dcalc(c2, v);
                            fiterrors = fiterrors | (double)(Math.Abs(v1-v2))>(double)(nonstrictthreshold);
                        }
                        else
                        {
                            fiterrors = true;
                        }
                    }
                }
            }
            
            //
            // Advanced proprties:
            // * penalized spline with M about 5*N and sufficiently small Rho
            //   must pass through all points on equidistant grid
            //
            for(n=2; n<=10; n++)
            {
                m = 5*n;
                rho = -5;
                x = new double[n];
                y = new double[n];
                w = new double[n];
                for(i=0; i<=n-1; i++)
                {
                    x[i] = (double)i/(double)(n-1);
                    y[i] = math.randomreal();
                    w[i] = 0.1+math.randomreal();
                }
                lsfit.spline1dfitpenalized(x, y, n, m, rho, ref info, c, rep);
                if( info>0 )
                {
                    for(i=0; i<=n-1; i++)
                    {
                        fiterrors = fiterrors | (double)(Math.Abs(y[i]-spline1d.spline1dcalc(c, x[i])))>(double)(nonstrictthreshold);
                    }
                }
                else
                {
                    fiterrors = true;
                }
                lsfit.spline1dfitpenalizedw(x, y, w, n, m, rho, ref info, c, rep);
                if( info>0 )
                {
                    for(i=0; i<=n-1; i++)
                    {
                        fiterrors = fiterrors | (double)(Math.Abs(y[i]-spline1d.spline1dcalc(c, x[i])))>(double)(nonstrictthreshold);
                    }
                }
                else
                {
                    fiterrors = true;
                }
            }
            
            //
            // Check correctness of error reports
            //
            for(pass=1; pass<=passcount; pass++)
            {
                ap.assert(passcount>=2, "PassCount should be 2 or greater!");
                
                //
                // solve simple task (all X[] are the same, Y[] are specially
                // calculated to ensure simple form of all types of errors)
                // and check correctness of the errors calculated by subroutines
                //
                // First pass is done with zero Y[], other passes - with random Y[].
                // It should test both ability to correctly calculate errors and
                // ability to not fail while working with zeros :)
                //
                n = 4;
                if( pass==1 )
                {
                    v1 = 0;
                    v2 = 0;
                    v = 0;
                }
                else
                {
                    v1 = math.randomreal();
                    v2 = math.randomreal();
                    v = 1+math.randomreal();
                }
                x = new double[4];
                y = new double[4];
                w = new double[4];
                x[0] = 0;
                y[0] = v-v2;
                w[0] = 1;
                x[1] = 0;
                y[1] = v-v1;
                w[1] = 1;
                x[2] = 0;
                y[2] = v+v1;
                w[2] = 1;
                x[3] = 0;
                y[3] = v+v2;
                w[3] = 1;
                refrms = Math.Sqrt((math.sqr(v1)+math.sqr(v2))/2);
                refavg = (Math.Abs(v1)+Math.Abs(v2))/2;
                if( pass==1 )
                {
                    refavgrel = 0;
                }
                else
                {
                    refavgrel = 0.25*(Math.Abs(v2)/Math.Abs(v-v2)+Math.Abs(v1)/Math.Abs(v-v1)+Math.Abs(v1)/Math.Abs(v+v1)+Math.Abs(v2)/Math.Abs(v+v2));
                }
                refmax = Math.Max(v1, v2);
                
                //
                // Test penalized spline
                //
                lsfit.spline1dfitpenalizedw(x, y, w, 4, 4, 0.0, ref info, c, rep);
                if( info<=0 )
                {
                    fiterrors = true;
                }
                else
                {
                    s = spline1d.spline1dcalc(c, 0);
                    fiterrors = fiterrors | (double)(Math.Abs(s-v))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.rmserror-refrms))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.avgerror-refavg))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.avgrelerror-refavgrel))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.maxerror-refmax))>(double)(threshold);
                }
                
                //
                // Test cubic fitting
                //
                lsfit.spline1dfitcubic(x, y, 4, 4, ref info, c, rep);
                if( info<=0 )
                {
                    fiterrors = true;
                }
                else
                {
                    s = spline1d.spline1dcalc(c, 0);
                    fiterrors = fiterrors | (double)(Math.Abs(s-v))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.rmserror-refrms))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.avgerror-refavg))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.avgrelerror-refavgrel))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.maxerror-refmax))>(double)(threshold);
                }
                
                //
                // Test Hermite fitting
                //
                lsfit.spline1dfithermite(x, y, 4, 4, ref info, c, rep);
                if( info<=0 )
                {
                    fiterrors = true;
                }
                else
                {
                    s = spline1d.spline1dcalc(c, 0);
                    fiterrors = fiterrors | (double)(Math.Abs(s-v))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.rmserror-refrms))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.avgerror-refavg))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.avgrelerror-refavgrel))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.maxerror-refmax))>(double)(threshold);
                }
            }
        }
Exemple #3
0
 public spline1dfitreport()
 {
     _innerobj = new lsfit.spline1dfitreport();
 }