/************************************************************************* 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; }
public override alglib.apobject make_copy() { rbfreport _result = new rbfreport(); _result.arows = arows; _result.acols = acols; _result.annz = annz; _result.iterationscount = iterationscount; _result.nmv = nmv; _result.terminationtype = terminationtype; return _result; }