//
        // Public declarations
        //

        public kdtree()
        {
            _innerobj = new nearestneighbor.kdtree();
        }
 public kdtree(nearestneighbor.kdtree obj)
 {
     _innerobj = obj;
 }
        /*************************************************************************
        Testing serialization of KD trees

        This function sets Err to True on errors, but leaves it unchanged on success
        *************************************************************************/
        private static void testkdtreeserialization(ref bool err)
        {
            int n = 0;
            int nx = 0;
            int ny = 0;
            int normtype = 0;
            int i = 0;
            int j = 0;
            int k = 0;
            int q = 0;
            double[,] xy = new double[0,0];
            double[] x = new double[0];
            int[] tags = new int[0];
            int[] qsizes = new int[0];
            double threshold = 0;
            nearestneighbor.kdtree tree0 = new nearestneighbor.kdtree();
            nearestneighbor.kdtree tree1 = new nearestneighbor.kdtree();
            int k0 = 0;
            int k1 = 0;
            double[,] xy0 = new double[0,0];
            double[,] xy1 = new double[0,0];
            int[] tags0 = new int[0];
            int[] tags1 = new int[0];
            int i_ = 0;

            threshold = 100*math.machineepsilon;
            
            //
            // different N, NX, NY, NormType
            //
            n = 1;
            while( n<=51 )
            {
                
                //
                // prepare array with query sizes
                //
                qsizes = new int[4];
                qsizes[0] = 1;
                qsizes[1] = Math.Min(2, n);
                qsizes[2] = Math.Min(4, n);
                qsizes[3] = n;
                
                //
                // different NX/NY/NormType
                //
                for(nx=1; nx<=2; nx++)
                {
                    for(ny=0; ny<=2; ny++)
                    {
                        for(normtype=0; normtype<=2; normtype++)
                        {
                            
                            //
                            // Prepare data
                            //
                            xy = new double[n, nx+ny];
                            tags = new int[n];
                            for(i=0; i<=n-1; i++)
                            {
                                for(j=0; j<=nx+ny-1; j++)
                                {
                                    xy[i,j] = math.randomreal();
                                }
                                tags[i] = math.randominteger(100);
                            }
                            
                            //
                            // Build tree, pass it through serializer
                            //
                            nearestneighbor.kdtreebuildtagged(xy, tags, n, nx, ny, normtype, tree0);
                            {
                                //
                                // This code passes data structure through serializers
                                // (serializes it to string and loads back)
                                //
                                serializer _local_serializer;
                                string _local_str;
                                
                                _local_serializer = new serializer();
                                _local_serializer.alloc_start();
                                nearestneighbor.kdtreealloc(_local_serializer, tree0);
                                _local_serializer.sstart_str();
                                nearestneighbor.kdtreeserialize(_local_serializer, tree0);
                                _local_serializer.stop();
                                _local_str = _local_serializer.get_string();
                                
                                _local_serializer = new serializer();
                                _local_serializer.ustart_str(_local_str);
                                nearestneighbor.kdtreeunserialize(_local_serializer, tree1);
                                _local_serializer.stop();
                            }
                            
                            //
                            // For each point of XY we make queries with different sizes
                            //
                            x = new double[nx];
                            for(k=0; k<=n-1; k++)
                            {
                                for(q=0; q<=ap.len(qsizes)-1; q++)
                                {
                                    for(i_=0; i_<=nx-1;i_++)
                                    {
                                        x[i_] = xy[k,i_];
                                    }
                                    k0 = nearestneighbor.kdtreequeryknn(tree0, x, qsizes[q], true);
                                    k1 = nearestneighbor.kdtreequeryknn(tree1, x, qsizes[q], true);
                                    if( k0!=k1 )
                                    {
                                        err = true;
                                        return;
                                    }
                                    nearestneighbor.kdtreequeryresultsxy(tree0, ref xy0);
                                    nearestneighbor.kdtreequeryresultsxy(tree1, ref xy1);
                                    for(i=0; i<=k0-1; i++)
                                    {
                                        for(j=0; j<=nx+ny-1; j++)
                                        {
                                            if( (double)(Math.Abs(xy0[i,j]-xy1[i,j]))>(double)(threshold) )
                                            {
                                                err = true;
                                                return;
                                            }
                                        }
                                    }
                                    nearestneighbor.kdtreequeryresultstags(tree0, ref tags0);
                                    nearestneighbor.kdtreequeryresultstags(tree1, ref tags1);
                                    for(i=0; i<=k0-1; i++)
                                    {
                                        if( tags0[i]!=tags1[i] )
                                        {
                                            err = true;
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                
                //
                // Next N
                //
                n = n+25;
            }
        }
        /*************************************************************************
        Testing Nearest Neighbor Search on uniformly distributed hypercube

        NormType: 0, 1, 2
        D: space dimension
        N: points count
        *************************************************************************/
        private static void testkdtuniform(double[,] xy,
            int n,
            int nx,
            int ny,
            int normtype,
            ref bool kdterrors)
        {
            double errtol = 0;
            int[] tags = new int[0];
            double[] ptx = new double[0];
            double[] tmpx = new double[0];
            bool[] tmpb = new bool[0];
            nearestneighbor.kdtree treex = new nearestneighbor.kdtree();
            nearestneighbor.kdtree treexy = new nearestneighbor.kdtree();
            nearestneighbor.kdtree treext = new nearestneighbor.kdtree();
            double[,] qx = new double[0,0];
            double[,] qxy = new double[0,0];
            int[] qtags = new int[0];
            double[] qr = new double[0];
            int kx = 0;
            int kxy = 0;
            int kt = 0;
            double eps = 0;
            int i = 0;
            int j = 0;
            int k = 0;
            int task = 0;
            bool isequal = new bool();
            double r = 0;
            int q = 0;
            int qcount = 0;
            int i_ = 0;

            qcount = 10;
            
            //
            // Tol - roundoff error tolerance (for '>=' comparisons)
            //
            errtol = 100000*math.machineepsilon;
            
            //
            // fill tags
            //
            tags = new int[n];
            for(i=0; i<=n-1; i++)
            {
                tags[i] = i;
            }
            
            //
            // build trees
            //
            nearestneighbor.kdtreebuild(xy, n, nx, 0, normtype, treex);
            nearestneighbor.kdtreebuild(xy, n, nx, ny, normtype, treexy);
            nearestneighbor.kdtreebuildtagged(xy, tags, n, nx, 0, normtype, treext);
            
            //
            // allocate arrays
            //
            tmpx = new double[nx];
            tmpb = new bool[n];
            qx = new double[n, nx];
            qxy = new double[n, nx+ny];
            qtags = new int[n];
            qr = new double[n];
            ptx = new double[nx];
            
            //
            // test general K-NN queries (with self-matches):
            // * compare results from different trees (must be equal) and
            //   check that correct (value,tag) pairs are returned
            // * test results from XT tree - let R be radius of query result.
            //   then all points not in result must be not closer than R.
            //
            for(q=1; q<=qcount; q++)
            {
                
                //
                // Select K: 1..N
                //
                if( (double)(math.randomreal())>(double)(0.5) )
                {
                    k = 1+math.randominteger(n);
                }
                else
                {
                    k = 1;
                }
                
                //
                // Select point (either one of the points, or random)
                //
                if( (double)(math.randomreal())>(double)(0.5) )
                {
                    i = math.randominteger(n);
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        ptx[i_] = xy[i,i_];
                    }
                }
                else
                {
                    for(i=0; i<=nx-1; i++)
                    {
                        ptx[i] = 2*math.randomreal()-1;
                    }
                }
                
                //
                // Test:
                // * consistency of results from different queries
                // * points in query are IN the R-sphere (or at the boundary),
                //   and points not in query are outside of the R-sphere (or at the boundary)
                // * distances are correct and are ordered
                //
                kx = nearestneighbor.kdtreequeryknn(treex, ptx, k, true);
                kxy = nearestneighbor.kdtreequeryknn(treexy, ptx, k, true);
                kt = nearestneighbor.kdtreequeryknn(treext, ptx, k, true);
                if( (kx!=k | kxy!=k) | kt!=k )
                {
                    kdterrors = true;
                    return;
                }
                nearestneighbor.kdtreequeryresultsxi(treex, ref qx);
                nearestneighbor.kdtreequeryresultsxyi(treexy, ref qxy);
                nearestneighbor.kdtreequeryresultstagsi(treext, ref qtags);
                nearestneighbor.kdtreequeryresultsdistancesi(treext, ref qr);
                kdterrors = kdterrors | kdtresultsdifferent(xy, n, qx, qxy, qtags, k, nx, ny);
                nearestneighbor.kdtreequeryresultsx(treex, ref qx);
                nearestneighbor.kdtreequeryresultsxy(treexy, ref qxy);
                nearestneighbor.kdtreequeryresultstags(treext, ref qtags);
                nearestneighbor.kdtreequeryresultsdistances(treext, ref qr);
                kdterrors = kdterrors | kdtresultsdifferent(xy, n, qx, qxy, qtags, k, nx, ny);
                for(i=0; i<=n-1; i++)
                {
                    tmpb[i] = true;
                }
                r = 0;
                for(i=0; i<=k-1; i++)
                {
                    tmpb[qtags[i]] = false;
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        tmpx[i_] = ptx[i_];
                    }
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        tmpx[i_] = tmpx[i_] - qx[i,i_];
                    }
                    r = Math.Max(r, vnorm(tmpx, nx, normtype));
                }
                for(i=0; i<=n-1; i++)
                {
                    if( tmpb[i] )
                    {
                        for(i_=0; i_<=nx-1;i_++)
                        {
                            tmpx[i_] = ptx[i_];
                        }
                        for(i_=0; i_<=nx-1;i_++)
                        {
                            tmpx[i_] = tmpx[i_] - xy[i,i_];
                        }
                        kdterrors = kdterrors | (double)(vnorm(tmpx, nx, normtype))<(double)(r*(1-errtol));
                    }
                }
                for(i=0; i<=k-2; i++)
                {
                    kdterrors = kdterrors | (double)(qr[i])>(double)(qr[i+1]);
                }
                for(i=0; i<=k-1; i++)
                {
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        tmpx[i_] = ptx[i_];
                    }
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        tmpx[i_] = tmpx[i_] - xy[qtags[i],i_];
                    }
                    kdterrors = kdterrors | (double)(Math.Abs(vnorm(tmpx, nx, normtype)-qr[i]))>(double)(errtol);
                }
                
                //
                // Test reallocation properties: buffered functions must automatically
                // resize array which is too small, but leave unchanged array which is
                // too large.
                //
                if( n>=2 )
                {
                    
                    //
                    // First step: array is too small, two elements are required
                    //
                    k = 2;
                    kx = nearestneighbor.kdtreequeryknn(treex, ptx, k, true);
                    kxy = nearestneighbor.kdtreequeryknn(treexy, ptx, k, true);
                    kt = nearestneighbor.kdtreequeryknn(treext, ptx, k, true);
                    if( (kx!=k | kxy!=k) | kt!=k )
                    {
                        kdterrors = true;
                        return;
                    }
                    qx = new double[1, 1];
                    qxy = new double[1, 1];
                    qtags = new int[1];
                    qr = new double[1];
                    nearestneighbor.kdtreequeryresultsx(treex, ref qx);
                    nearestneighbor.kdtreequeryresultsxy(treexy, ref qxy);
                    nearestneighbor.kdtreequeryresultstags(treext, ref qtags);
                    nearestneighbor.kdtreequeryresultsdistances(treext, ref qr);
                    kdterrors = kdterrors | kdtresultsdifferent(xy, n, qx, qxy, qtags, k, nx, ny);
                    
                    //
                    // Second step: array is one row larger than needed, so only first
                    // row is overwritten. Test it.
                    //
                    k = 1;
                    kx = nearestneighbor.kdtreequeryknn(treex, ptx, k, true);
                    kxy = nearestneighbor.kdtreequeryknn(treexy, ptx, k, true);
                    kt = nearestneighbor.kdtreequeryknn(treext, ptx, k, true);
                    if( (kx!=k | kxy!=k) | kt!=k )
                    {
                        kdterrors = true;
                        return;
                    }
                    for(i=0; i<=nx-1; i++)
                    {
                        qx[1,i] = Double.NaN;
                    }
                    for(i=0; i<=nx+ny-1; i++)
                    {
                        qxy[1,i] = Double.NaN;
                    }
                    qtags[1] = 999;
                    qr[1] = Double.NaN;
                    nearestneighbor.kdtreequeryresultsx(treex, ref qx);
                    nearestneighbor.kdtreequeryresultsxy(treexy, ref qxy);
                    nearestneighbor.kdtreequeryresultstags(treext, ref qtags);
                    nearestneighbor.kdtreequeryresultsdistances(treext, ref qr);
                    kdterrors = kdterrors | kdtresultsdifferent(xy, n, qx, qxy, qtags, k, nx, ny);
                    for(i=0; i<=nx-1; i++)
                    {
                        kdterrors = kdterrors | !Double.IsNaN(qx[1,i]);
                    }
                    for(i=0; i<=nx+ny-1; i++)
                    {
                        kdterrors = kdterrors | !Double.IsNaN(qxy[1,i]);
                    }
                    kdterrors = kdterrors | !(qtags[1]==999);
                    kdterrors = kdterrors | !Double.IsNaN(qr[1]);
                }
                
                //
                // Test reallocation properties: 'interactive' functions must allocate
                // new array on each call.
                //
                if( n>=2 )
                {
                    
                    //
                    // On input array is either too small or too large
                    //
                    for(k=1; k<=2; k++)
                    {
                        ap.assert(k==1 | k==2, "KNN: internal error (unexpected K)!");
                        kx = nearestneighbor.kdtreequeryknn(treex, ptx, k, true);
                        kxy = nearestneighbor.kdtreequeryknn(treexy, ptx, k, true);
                        kt = nearestneighbor.kdtreequeryknn(treext, ptx, k, true);
                        if( (kx!=k | kxy!=k) | kt!=k )
                        {
                            kdterrors = true;
                            return;
                        }
                        qx = new double[3-k, 3-k];
                        qxy = new double[3-k, 3-k];
                        qtags = new int[3-k];
                        qr = new double[3-k];
                        nearestneighbor.kdtreequeryresultsxi(treex, ref qx);
                        nearestneighbor.kdtreequeryresultsxyi(treexy, ref qxy);
                        nearestneighbor.kdtreequeryresultstagsi(treext, ref qtags);
                        nearestneighbor.kdtreequeryresultsdistancesi(treext, ref qr);
                        kdterrors = kdterrors | kdtresultsdifferent(xy, n, qx, qxy, qtags, k, nx, ny);
                        kdterrors = (kdterrors | ap.rows(qx)!=k) | ap.cols(qx)!=nx;
                        kdterrors = (kdterrors | ap.rows(qxy)!=k) | ap.cols(qxy)!=nx+ny;
                        kdterrors = kdterrors | ap.len(qtags)!=k;
                        kdterrors = kdterrors | ap.len(qr)!=k;
                    }
                }
            }
            
            //
            // test general approximate K-NN queries (with self-matches):
            // * compare results from different trees (must be equal) and
            //   check that correct (value,tag) pairs are returned
            // * test results from XT tree - let R be radius of query result.
            //   then all points not in result must be not closer than R/(1+Eps).
            //
            for(q=1; q<=qcount; q++)
            {
                
                //
                // Select K: 1..N
                //
                if( (double)(math.randomreal())>(double)(0.5) )
                {
                    k = 1+math.randominteger(n);
                }
                else
                {
                    k = 1;
                }
                
                //
                // Select Eps
                //
                eps = 0.5+math.randomreal();
                
                //
                // Select point (either one of the points, or random)
                //
                if( (double)(math.randomreal())>(double)(0.5) )
                {
                    i = math.randominteger(n);
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        ptx[i_] = xy[i,i_];
                    }
                }
                else
                {
                    for(i=0; i<=nx-1; i++)
                    {
                        ptx[i] = 2*math.randomreal()-1;
                    }
                }
                
                //
                // Test:
                // * consistency of results from different queries
                // * points in query are IN the R-sphere (or at the boundary),
                //   and points not in query are outside of the R-sphere (or at the boundary)
                // * distances are correct and are ordered
                //
                kx = nearestneighbor.kdtreequeryaknn(treex, ptx, k, true, eps);
                kxy = nearestneighbor.kdtreequeryaknn(treexy, ptx, k, true, eps);
                kt = nearestneighbor.kdtreequeryaknn(treext, ptx, k, true, eps);
                if( (kx!=k | kxy!=k) | kt!=k )
                {
                    kdterrors = true;
                    return;
                }
                nearestneighbor.kdtreequeryresultsxi(treex, ref qx);
                nearestneighbor.kdtreequeryresultsxyi(treexy, ref qxy);
                nearestneighbor.kdtreequeryresultstagsi(treext, ref qtags);
                nearestneighbor.kdtreequeryresultsdistancesi(treext, ref qr);
                kdterrors = kdterrors | kdtresultsdifferent(xy, n, qx, qxy, qtags, k, nx, ny);
                nearestneighbor.kdtreequeryresultsx(treex, ref qx);
                nearestneighbor.kdtreequeryresultsxy(treexy, ref qxy);
                nearestneighbor.kdtreequeryresultstags(treext, ref qtags);
                nearestneighbor.kdtreequeryresultsdistances(treext, ref qr);
                kdterrors = kdterrors | kdtresultsdifferent(xy, n, qx, qxy, qtags, k, nx, ny);
                for(i=0; i<=n-1; i++)
                {
                    tmpb[i] = true;
                }
                r = 0;
                for(i=0; i<=k-1; i++)
                {
                    tmpb[qtags[i]] = false;
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        tmpx[i_] = ptx[i_];
                    }
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        tmpx[i_] = tmpx[i_] - qx[i,i_];
                    }
                    r = Math.Max(r, vnorm(tmpx, nx, normtype));
                }
                for(i=0; i<=n-1; i++)
                {
                    if( tmpb[i] )
                    {
                        for(i_=0; i_<=nx-1;i_++)
                        {
                            tmpx[i_] = ptx[i_];
                        }
                        for(i_=0; i_<=nx-1;i_++)
                        {
                            tmpx[i_] = tmpx[i_] - xy[i,i_];
                        }
                        kdterrors = kdterrors | (double)(vnorm(tmpx, nx, normtype))<(double)(r*(1-errtol)/(1+eps));
                    }
                }
                for(i=0; i<=k-2; i++)
                {
                    kdterrors = kdterrors | (double)(qr[i])>(double)(qr[i+1]);
                }
                for(i=0; i<=k-1; i++)
                {
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        tmpx[i_] = ptx[i_];
                    }
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        tmpx[i_] = tmpx[i_] - xy[qtags[i],i_];
                    }
                    kdterrors = kdterrors | (double)(Math.Abs(vnorm(tmpx, nx, normtype)-qr[i]))>(double)(errtol);
                }
            }
            
            //
            // test general R-NN queries  (with self-matches):
            // * compare results from different trees (must be equal) and
            //   check that correct (value,tag) pairs are returned
            // * test results from XT tree - let R be radius of query result.
            //   then all points not in result must be not closer than R.
            //
            for(q=1; q<=qcount; q++)
            {
                
                //
                // Select R
                //
                if( (double)(math.randomreal())>(double)(0.3) )
                {
                    r = Math.Max(math.randomreal(), math.machineepsilon);
                }
                else
                {
                    r = math.machineepsilon;
                }
                
                //
                // Select point (either one of the points, or random)
                //
                if( (double)(math.randomreal())>(double)(0.5) )
                {
                    i = math.randominteger(n);
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        ptx[i_] = xy[i,i_];
                    }
                }
                else
                {
                    for(i=0; i<=nx-1; i++)
                    {
                        ptx[i] = 2*math.randomreal()-1;
                    }
                }
                
                //
                // Test:
                // * consistency of results from different queries
                // * points in query are IN the R-sphere (or at the boundary),
                //   and points not in query are outside of the R-sphere (or at the boundary)
                // * distances are correct and are ordered
                //
                kx = nearestneighbor.kdtreequeryrnn(treex, ptx, r, true);
                kxy = nearestneighbor.kdtreequeryrnn(treexy, ptx, r, true);
                kt = nearestneighbor.kdtreequeryrnn(treext, ptx, r, true);
                if( kxy!=kx | kt!=kx )
                {
                    kdterrors = true;
                    return;
                }
                nearestneighbor.kdtreequeryresultsxi(treex, ref qx);
                nearestneighbor.kdtreequeryresultsxyi(treexy, ref qxy);
                nearestneighbor.kdtreequeryresultstagsi(treext, ref qtags);
                nearestneighbor.kdtreequeryresultsdistancesi(treext, ref qr);
                kdterrors = kdterrors | kdtresultsdifferent(xy, n, qx, qxy, qtags, kx, nx, ny);
                nearestneighbor.kdtreequeryresultsx(treex, ref qx);
                nearestneighbor.kdtreequeryresultsxy(treexy, ref qxy);
                nearestneighbor.kdtreequeryresultstags(treext, ref qtags);
                nearestneighbor.kdtreequeryresultsdistances(treext, ref qr);
                kdterrors = kdterrors | kdtresultsdifferent(xy, n, qx, qxy, qtags, kx, nx, ny);
                for(i=0; i<=n-1; i++)
                {
                    tmpb[i] = true;
                }
                for(i=0; i<=kx-1; i++)
                {
                    tmpb[qtags[i]] = false;
                }
                for(i=0; i<=n-1; i++)
                {
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        tmpx[i_] = ptx[i_];
                    }
                    for(i_=0; i_<=nx-1;i_++)
                    {
                        tmpx[i_] = tmpx[i_] - xy[i,i_];
                    }
                    if( tmpb[i] )
                    {
                        kdterrors = kdterrors | (double)(vnorm(tmpx, nx, normtype))<(double)(r*(1-errtol));
                    }
                    else
                    {
                        kdterrors = kdterrors | (double)(vnorm(tmpx, nx, normtype))>(double)(r*(1+errtol));
                    }
                }
                for(i=0; i<=kx-2; i++)
                {
                    kdterrors = kdterrors | (double)(qr[i])>(double)(qr[i+1]);
                }
            }
            
            //
            // Test self-matching:
            // * self-match - nearest neighbor of each point in XY is the point itself
            // * no self-match - nearest neighbor is NOT the point itself
            //
            if( n>1 )
            {
                
                //
                // test for N=1 have non-general form, but it is not really needed
                //
                for(task=0; task<=1; task++)
                {
                    for(i=0; i<=n-1; i++)
                    {
                        for(i_=0; i_<=nx-1;i_++)
                        {
                            ptx[i_] = xy[i,i_];
                        }
                        kx = nearestneighbor.kdtreequeryknn(treex, ptx, 1, task==0);
                        nearestneighbor.kdtreequeryresultsxi(treex, ref qx);
                        if( kx!=1 )
                        {
                            kdterrors = true;
                            return;
                        }
                        isequal = true;
                        for(j=0; j<=nx-1; j++)
                        {
                            isequal = isequal & (double)(qx[0,j])==(double)(ptx[j]);
                        }
                        if( task==0 )
                        {
                            kdterrors = kdterrors | !isequal;
                        }
                        else
                        {
                            kdterrors = kdterrors | isequal;
                        }
                    }
                }
            }
        }
示例#5
0
 public override void init()
 {
     tree = new nearestneighbor.kdtree();
     q = new double[0,0];
     xbuf = new double[0];
     tbuf = new int[0];
     rbuf = new double[0];
     xybuf = new double[0,0];
 }
示例#6
0
        /*************************************************************************
        This   function  builds  RBF  model  and  returns  report  (contains  some 
        information which can be used for evaluation of the algorithm properties).

        Call to this function modifies RBF model by calculating its centers/radii/
        weights  and  saving  them  into  RBFModel  structure.  Initially RBFModel 
        contain zero coefficients, but after call to this function  we  will  have
        coefficients which were calculated in order to fit our dataset.

        After you called this function you can call RBFCalc(),  RBFGridCalc()  and
        other model calculation functions.

        INPUT PARAMETERS:
            S       -   RBF model, initialized by RBFCreate() call
            Rep     -   report:
                        * Rep.TerminationType:
                          * -5 - non-distinct basis function centers were detected,
                                 interpolation aborted
                          * -4 - nonconvergence of the internal SVD solver
                          *  1 - successful termination
                        Fields are used for debugging purposes:
                        * Rep.IterationsCount - iterations count of the LSQR solver
                        * Rep.NMV - number of matrix-vector products
                        * Rep.ARows - rows count for the system matrix
                        * Rep.ACols - columns count for the system matrix
                        * Rep.ANNZ - number of significantly non-zero elements
                          (elements above some algorithm-determined threshold)

        NOTE:  failure  to  build  model will leave current state of the structure
        unchanged.

          -- ALGLIB --
             Copyright 13.12.2011 by Bochkanov Sergey
        *************************************************************************/
        public static void rbfbuildmodel(rbfmodel s,
            rbfreport rep)
        {
            nearestneighbor.kdtree tree = new nearestneighbor.kdtree();
            nearestneighbor.kdtree ctree = new nearestneighbor.kdtree();
            double[] dist = new double[0];
            double[] xcx = new double[0];
            double[,] a = new double[0,0];
            double[,] v = new double[0,0];
            double[,] omega = new double[0,0];
            double[] y = new double[0];
            double[,] residualy = new double[0,0];
            double[] radius = new double[0];
            double[,] xc = new double[0,0];
            double[] mnx = new double[0];
            double[] mxx = new double[0];
            double[] edge = new double[0];
            int[] mxsteps = new int[0];
            int nc = 0;
            double rmax = 0;
            int[] tags = new int[0];
            int[] ctags = new int[0];
            int i = 0;
            int j = 0;
            int k = 0;
            int k2 = 0;
            int snnz = 0;
            double[] tmp0 = new double[0];
            double[] tmp1 = new double[0];
            int layerscnt = 0;

            alglib.ap.assert(s.nx==2 || s.nx==3, "RBFBuildModel: S.NX<>2 or S.NX<>3!");
            
            //
            // Quick exit when we have no points
            //
            if( s.n==0 )
            {
                rep.terminationtype = 1;
                rep.iterationscount = 0;
                rep.nmv = 0;
                rep.arows = 0;
                rep.acols = 0;
                nearestneighbor.kdtreebuildtagged(s.xc, tags, 0, mxnx, 0, 2, s.tree);
                s.xc = new double[0, 0];
                s.wr = new double[0, 0];
                s.nc = 0;
                s.rmax = 0;
                s.v = new double[s.ny, mxnx+1];
                for(i=0; i<=s.ny-1; i++)
                {
                    for(j=0; j<=mxnx; j++)
                    {
                        s.v[i,j] = 0;
                    }
                }
                return;
            }
            
            //
            // General case, N>0
            //
            rep.annz = 0;
            rep.iterationscount = 0;
            rep.nmv = 0;
            xcx = new double[mxnx];
            
            //
            // First model in a sequence - linear model.
            // Residuals from linear regression are stored in the ResidualY variable
            // (used later to build RBF models).
            //
            residualy = new double[s.n, s.ny];
            for(i=0; i<=s.n-1; i++)
            {
                for(j=0; j<=s.ny-1; j++)
                {
                    residualy[i,j] = s.y[i,j];
                }
            }
            if( !buildlinearmodel(s.x, ref residualy, s.n, s.ny, s.aterm, ref v) )
            {
                rep.terminationtype = -5;
                return;
            }
            
            //
            // Handle special case: multilayer model with NLayers=0.
            // Quick exit.
            //
            if( s.algorithmtype==2 && s.nlayers==0 )
            {
                rep.terminationtype = 1;
                rep.iterationscount = 0;
                rep.nmv = 0;
                rep.arows = 0;
                rep.acols = 0;
                nearestneighbor.kdtreebuildtagged(s.xc, tags, 0, mxnx, 0, 2, s.tree);
                s.xc = new double[0, 0];
                s.wr = new double[0, 0];
                s.nc = 0;
                s.rmax = 0;
                s.v = new double[s.ny, mxnx+1];
                for(i=0; i<=s.ny-1; i++)
                {
                    for(j=0; j<=mxnx; j++)
                    {
                        s.v[i,j] = v[i,j];
                    }
                }
                return;
            }
            
            //
            // Second model in a sequence - RBF term.
            //
            // NOTE: assignments below are not necessary, but without them
            //       MSVC complains about unitialized variables.
            //
            nc = 0;
            rmax = 0;
            layerscnt = 0;
            if( s.algorithmtype==1 )
            {
                
                //
                // Add RBF model.
                // This model uses local KD-trees to speed-up nearest neighbor searches.
                //
                if( s.gridtype==1 )
                {
                    mxx = new double[s.nx];
                    mnx = new double[s.nx];
                    mxsteps = new int[s.nx];
                    edge = new double[s.nx];
                    for(i=0; i<=s.nx-1; i++)
                    {
                        mxx[i] = s.x[0,i];
                        mnx[i] = s.x[0,i];
                    }
                    for(i=0; i<=s.n-1; i++)
                    {
                        for(j=0; j<=s.nx-1; j++)
                        {
                            if( (double)(mxx[j])<(double)(s.x[i,j]) )
                            {
                                mxx[j] = s.x[i,j];
                            }
                            if( (double)(mnx[j])>(double)(s.x[i,j]) )
                            {
                                mnx[j] = s.x[i,j];
                            }
                        }
                    }
                    for(i=0; i<=s.nx-1; i++)
                    {
                        mxsteps[i] = (int)((mxx[i]-mnx[i])/(2*s.h))+1;
                        edge[i] = (mxx[i]+mnx[i])/2-s.h*mxsteps[i];
                    }
                    nc = 1;
                    for(i=0; i<=s.nx-1; i++)
                    {
                        mxsteps[i] = 2*mxsteps[i]+1;
                        nc = nc*mxsteps[i];
                    }
                    xc = new double[nc, mxnx];
                    if( s.nx==2 )
                    {
                        for(i=0; i<=mxsteps[0]-1; i++)
                        {
                            for(j=0; j<=mxsteps[1]-1; j++)
                            {
                                for(k2=0; k2<=mxnx-1; k2++)
                                {
                                    xc[i*mxsteps[1]+j,k2] = 0;
                                }
                                xc[i*mxsteps[1]+j,0] = edge[0]+s.h*i;
                                xc[i*mxsteps[1]+j,1] = edge[1]+s.h*j;
                            }
                        }
                    }
                    if( s.nx==3 )
                    {
                        for(i=0; i<=mxsteps[0]-1; i++)
                        {
                            for(j=0; j<=mxsteps[1]-1; j++)
                            {
                                for(k=0; k<=mxsteps[2]-1; k++)
                                {
                                    for(k2=0; k2<=mxnx-1; k2++)
                                    {
                                        xc[i*mxsteps[1]+j,k2] = 0;
                                    }
                                    xc[(i*mxsteps[1]+j)*mxsteps[2]+k,0] = edge[0]+s.h*i;
                                    xc[(i*mxsteps[1]+j)*mxsteps[2]+k,1] = edge[1]+s.h*j;
                                    xc[(i*mxsteps[1]+j)*mxsteps[2]+k,2] = edge[2]+s.h*k;
                                }
                            }
                        }
                    }
                }
                else
                {
                    if( s.gridtype==2 )
                    {
                        nc = s.n;
                        xc = new double[nc, mxnx];
                        for(i=0; i<=nc-1; i++)
                        {
                            for(j=0; j<=mxnx-1; j++)
                            {
                                xc[i,j] = s.x[i,j];
                            }
                        }
                    }
                    else
                    {
                        if( s.gridtype==3 )
                        {
                            nc = s.nc;
                            xc = new double[nc, mxnx];
                            for(i=0; i<=nc-1; i++)
                            {
                                for(j=0; j<=mxnx-1; j++)
                                {
                                    xc[i,j] = s.xc[i,j];
                                }
                            }
                        }
                        else
                        {
                            alglib.ap.assert(false, "RBFBuildModel: either S.GridType<1 or S.GridType>3!");
                        }
                    }
                }
                rmax = 0;
                radius = new double[nc];
                ctags = new int[nc];
                for(i=0; i<=nc-1; i++)
                {
                    ctags[i] = i;
                }
                nearestneighbor.kdtreebuildtagged(xc, ctags, nc, mxnx, 0, 2, ctree);
                if( s.fixrad )
                {
                    
                    //
                    // Fixed radius
                    //
                    for(i=0; i<=nc-1; i++)
                    {
                        radius[i] = s.radvalue;
                    }
                    rmax = radius[0];
                }
                else
                {
                    
                    //
                    // Dynamic radius
                    //
                    if( nc==0 )
                    {
                        rmax = 1;
                    }
                    else
                    {
                        if( nc==1 )
                        {
                            radius[0] = s.radvalue;
                            rmax = radius[0];
                        }
                        else
                        {
                            
                            //
                            // NC>1, calculate radii using distances to nearest neigbors
                            //
                            for(i=0; i<=nc-1; i++)
                            {
                                for(j=0; j<=mxnx-1; j++)
                                {
                                    xcx[j] = xc[i,j];
                                }
                                if( nearestneighbor.kdtreequeryknn(ctree, xcx, 1, false)>0 )
                                {
                                    nearestneighbor.kdtreequeryresultsdistances(ctree, ref dist);
                                    radius[i] = s.radvalue*dist[0];
                                }
                                else
                                {
                                    
                                    //
                                    // No neighbors found (it will happen when we have only one center).
                                    // Initialize radius with default value.
                                    //
                                    radius[i] = 1.0;
                                }
                            }
                            
                            //
                            // Apply filtering
                            //
                            apserv.rvectorsetlengthatleast(ref tmp0, nc);
                            for(i=0; i<=nc-1; i++)
                            {
                                tmp0[i] = radius[i];
                            }
                            tsort.tagsortfast(ref tmp0, ref tmp1, nc);
                            for(i=0; i<=nc-1; i++)
                            {
                                radius[i] = Math.Min(radius[i], s.radzvalue*tmp0[nc/2]);
                            }
                            
                            //
                            // Calculate RMax, check that all radii are non-zero
                            //
                            for(i=0; i<=nc-1; i++)
                            {
                                rmax = Math.Max(rmax, radius[i]);
                            }
                            for(i=0; i<=nc-1; i++)
                            {
                                if( (double)(radius[i])==(double)(0) )
                                {
                                    rep.terminationtype = -5;
                                    return;
                                }
                            }
                        }
                    }
                }
                apserv.ivectorsetlengthatleast(ref tags, s.n);
                for(i=0; i<=s.n-1; i++)
                {
                    tags[i] = i;
                }
                nearestneighbor.kdtreebuildtagged(s.x, tags, s.n, mxnx, 0, 2, tree);
                buildrbfmodellsqr(s.x, ref residualy, xc, radius, s.n, nc, s.ny, tree, ctree, s.epsort, s.epserr, s.maxits, ref rep.annz, ref snnz, ref omega, ref rep.terminationtype, ref rep.iterationscount, ref rep.nmv);
                layerscnt = 1;
            }
            else
            {
                if( s.algorithmtype==2 )
                {
                    rmax = s.radvalue;
                    buildrbfmlayersmodellsqr(s.x, ref residualy, ref xc, s.radvalue, ref radius, s.n, ref nc, s.ny, s.nlayers, ctree, 1.0E-6, 1.0E-6, 50, s.lambdav, ref rep.annz, ref omega, ref rep.terminationtype, ref rep.iterationscount, ref rep.nmv);
                    layerscnt = s.nlayers;
                }
                else
                {
                    alglib.ap.assert(false, "RBFBuildModel: internal error(AlgorithmType neither 1 nor 2)");
                }
            }
            if( rep.terminationtype<=0 )
            {
                return;
            }
            
            //
            // Model is built
            //
            s.nc = nc/layerscnt;
            s.rmax = rmax;
            s.nl = layerscnt;
            s.xc = new double[s.nc, mxnx];
            s.wr = new double[s.nc, 1+s.nl*s.ny];
            s.v = new double[s.ny, mxnx+1];
            for(i=0; i<=s.nc-1; i++)
            {
                for(j=0; j<=mxnx-1; j++)
                {
                    s.xc[i,j] = xc[i,j];
                }
            }
            apserv.ivectorsetlengthatleast(ref tags, s.nc);
            for(i=0; i<=s.nc-1; i++)
            {
                tags[i] = i;
            }
            nearestneighbor.kdtreebuildtagged(s.xc, tags, s.nc, mxnx, 0, 2, s.tree);
            for(i=0; i<=s.nc-1; i++)
            {
                s.wr[i,0] = radius[i];
                for(k=0; k<=layerscnt-1; k++)
                {
                    for(j=0; j<=s.ny-1; j++)
                    {
                        s.wr[i,1+k*s.ny+j] = omega[k*s.nc+i,j];
                    }
                }
            }
            for(i=0; i<=s.ny-1; i++)
            {
                for(j=0; j<=mxnx; j++)
                {
                    s.v[i,j] = v[i,j];
                }
            }
            rep.terminationtype = 1;
            rep.arows = s.n;
            rep.acols = s.nc;
        }
示例#7
0
 public override void init()
 {
     tree = new nearestneighbor.kdtree();
     xc = new double[0,0];
     wr = new double[0,0];
     v = new double[0,0];
     x = new double[0,0];
     y = new double[0,0];
     calcbufxcx = new double[0];
     calcbufx = new double[0,0];
     calcbuftags = new int[0];
 }
 public idwinterpolant()
 {
     tree = new nearestneighbor.kdtree();
     q = new double[0,0];
     xbuf = new double[0];
     tbuf = new int[0];
     rbuf = new double[0];
     xybuf = new double[0,0];
 }
 public rbfmodel()
 {
     tree = new nearestneighbor.kdtree();
     xc = new double[0,0];
     wr = new double[0,0];
     v = new double[0,0];
     x = new double[0,0];
     y = new double[0,0];
     calcbufxcx = new double[0];
     calcbufx = new double[0,0];
     calcbuftags = new int[0];
 }