private static void buildrbfmlayersmodellsqr(double[,] x, ref double[,] y, ref double[,] xc, double rval, ref double[] r, int n, ref int nc, int ny, int nlayers, nearestneighbor.kdtree centerstree, double epsort, double epserr, int maxits, double lambdav, ref int annz, ref double[,] w, ref int info, ref int iterationscount, ref int nmv) { linlsqr.linlsqrstate state = new linlsqr.linlsqrstate(); linlsqr.linlsqrreport lsqrrep = new linlsqr.linlsqrreport(); sparse.sparsematrix spa = new sparse.sparsematrix(); double anorm = 0; double[] omega = new double[0]; double[] xx = new double[0]; double[] tmpy = new double[0]; double[,] cx = new double[0,0]; double yval = 0; int nec = 0; int[] centerstags = new int[0]; int layer = 0; int i = 0; int j = 0; int k = 0; double v = 0; double rmaxbefore = 0; double rmaxafter = 0; xc = new double[0,0]; r = new double[0]; nc = 0; annz = 0; w = new double[0,0]; info = 0; iterationscount = 0; nmv = 0; alglib.ap.assert(nlayers>=0, "BuildRBFMLayersModelLSQR: invalid argument(NLayers<0)"); alglib.ap.assert(n>=0, "BuildRBFMLayersModelLSQR: invalid argument(N<0)"); alglib.ap.assert(mxnx>0 && mxnx<=3, "BuildRBFMLayersModelLSQR: internal error(invalid global const MxNX: either MxNX<=0 or MxNX>3)"); annz = 0; if( n==0 || nlayers==0 ) { info = 1; iterationscount = 0; nmv = 0; return; } nc = n*nlayers; xx = new double[mxnx]; centerstags = new int[n]; xc = new double[nc, mxnx]; r = new double[nc]; for(i=0; i<=nc-1; i++) { for(j=0; j<=mxnx-1; j++) { xc[i,j] = x[i%n,j]; } } for(i=0; i<=nc-1; i++) { r[i] = rval/Math.Pow(2, i/n); } for(i=0; i<=n-1; i++) { centerstags[i] = i; } nearestneighbor.kdtreebuildtagged(xc, centerstags, n, mxnx, 0, 2, centerstree); omega = new double[n]; tmpy = new double[n]; w = new double[nc, ny]; info = -1; iterationscount = 0; nmv = 0; linlsqr.linlsqrcreate(n, n, state); linlsqr.linlsqrsetcond(state, epsort, epserr, maxits); linlsqr.linlsqrsetlambdai(state, 1.0E-6); // // calculate number of non-zero elements for sparse matrix // for(i=0; i<=n-1; i++) { for(j=0; j<=mxnx-1; j++) { xx[j] = x[i,j]; } annz = annz+nearestneighbor.kdtreequeryrnn(centerstree, xx, r[0]*rbfmlradius, true); } for(layer=0; layer<=nlayers-1; layer++) { // // Fill sparse matrix, calculate norm(A) // anorm = 0.0; sparse.sparsecreate(n, n, annz, spa); for(i=0; i<=n-1; i++) { for(j=0; j<=mxnx-1; j++) { xx[j] = x[i,j]; } nec = nearestneighbor.kdtreequeryrnn(centerstree, xx, r[layer*n]*rbfmlradius, true); nearestneighbor.kdtreequeryresultsx(centerstree, ref cx); nearestneighbor.kdtreequeryresultstags(centerstree, ref centerstags); for(j=0; j<=nec-1; j++) { v = Math.Exp(-((math.sqr(xx[0]-cx[j,0])+math.sqr(xx[1]-cx[j,1])+math.sqr(xx[2]-cx[j,2]))/math.sqr(r[layer*n+centerstags[j]]))); sparse.sparseset(spa, i, centerstags[j], v); anorm = anorm+math.sqr(v); } } anorm = Math.Sqrt(anorm); sparse.sparseconverttocrs(spa); // // Calculate maximum residual before adding new layer. // This value is not used by algorithm, the only purpose is to make debugging easier. // rmaxbefore = 0.0; for(j=0; j<=n-1; j++) { for(i=0; i<=ny-1; i++) { rmaxbefore = Math.Max(rmaxbefore, Math.Abs(y[j,i])); } } // // Process NY dimensions of the target function // for(i=0; i<=ny-1; i++) { for(j=0; j<=n-1; j++) { tmpy[j] = y[j,i]; } // // calculate Omega for current layer // linlsqr.linlsqrsetlambdai(state, lambdav*anorm/n); linlsqr.linlsqrsolvesparse(state, spa, tmpy); linlsqr.linlsqrresults(state, ref omega, lsqrrep); if( lsqrrep.terminationtype<=0 ) { info = -4; return; } // // calculate error for current layer // for(j=0; j<=n-1; j++) { yval = 0; for(k=0; k<=mxnx-1; k++) { xx[k] = x[j,k]; } nec = nearestneighbor.kdtreequeryrnn(centerstree, xx, r[layer*n]*rbffarradius, true); nearestneighbor.kdtreequeryresultsx(centerstree, ref cx); nearestneighbor.kdtreequeryresultstags(centerstree, ref centerstags); for(k=0; k<=nec-1; k++) { yval = yval+omega[centerstags[k]]*Math.Exp(-((math.sqr(xx[0]-cx[k,0])+math.sqr(xx[1]-cx[k,1])+math.sqr(xx[2]-cx[k,2]))/math.sqr(r[layer*n+centerstags[k]]))); } y[j,i] = y[j,i]-yval; } // // write Omega in out parameter W // for(j=0; j<=n-1; j++) { w[layer*n+j,i] = omega[j]; } iterationscount = iterationscount+lsqrrep.iterationscount; nmv = nmv+lsqrrep.nmv; } // // Calculate maximum residual before adding new layer. // This value is not used by algorithm, the only purpose is to make debugging easier. // rmaxafter = 0.0; for(j=0; j<=n-1; j++) { for(i=0; i<=ny-1; i++) { rmaxafter = Math.Max(rmaxafter, Math.Abs(y[j,i])); } } } info = 1; }
public kdtree(nearestneighbor.kdtree obj) { _innerobj = obj; }
private static void buildrbfmodellsqr(double[,] x, ref double[,] y, double[,] xc, double[] r, int n, int nc, int ny, nearestneighbor.kdtree pointstree, nearestneighbor.kdtree centerstree, double epsort, double epserr, int maxits, ref int gnnz, ref int snnz, ref double[,] w, ref int info, ref int iterationscount, ref int nmv) { linlsqr.linlsqrstate state = new linlsqr.linlsqrstate(); linlsqr.linlsqrreport lsqrrep = new linlsqr.linlsqrreport(); sparse.sparsematrix spg = new sparse.sparsematrix(); sparse.sparsematrix sps = new sparse.sparsematrix(); int[] nearcenterscnt = new int[0]; int[] nearpointscnt = new int[0]; int[] skipnearpointscnt = new int[0]; int[] farpointscnt = new int[0]; int maxnearcenterscnt = 0; int maxnearpointscnt = 0; int maxfarpointscnt = 0; int sumnearcenterscnt = 0; int sumnearpointscnt = 0; int sumfarpointscnt = 0; double maxrad = 0; int[] pointstags = new int[0]; int[] centerstags = new int[0]; double[,] nearpoints = new double[0,0]; double[,] nearcenters = new double[0,0]; double[,] farpoints = new double[0,0]; int tmpi = 0; int pointscnt = 0; int centerscnt = 0; double[] xcx = new double[0]; double[] tmpy = new double[0]; double[] tc = new double[0]; double[] g = new double[0]; double[] c = new double[0]; int i = 0; int j = 0; int k = 0; int sind = 0; double[,] a = new double[0,0]; double vv = 0; double vx = 0; double vy = 0; double vz = 0; double vr = 0; double gnorm2 = 0; double[] tmp0 = new double[0]; double[] tmp1 = new double[0]; double[] tmp2 = new double[0]; double fx = 0; double[,] xx = new double[0,0]; double[,] cx = new double[0,0]; double mrad = 0; int i_ = 0; gnnz = 0; snnz = 0; w = new double[0,0]; info = 0; iterationscount = 0; nmv = 0; // // Handle special cases: NC=0 // if( nc==0 ) { info = 1; iterationscount = 0; nmv = 0; return; } // // Prepare for general case, NC>0 // xcx = new double[mxnx]; pointstags = new int[n]; centerstags = new int[nc]; info = -1; iterationscount = 0; nmv = 0; // // This block prepares quantities used to compute approximate cardinal basis functions (ACBFs): // * NearCentersCnt[] - array[NC], whose elements store number of near centers used to build ACBF // * NearPointsCnt[] - array[NC], number of near points used to build ACBF // * FarPointsCnt[] - array[NC], number of far points (ones where ACBF is nonzero) // * MaxNearCentersCnt - max(NearCentersCnt) // * MaxNearPointsCnt - max(NearPointsCnt) // * SumNearCentersCnt - sum(NearCentersCnt) // * SumNearPointsCnt - sum(NearPointsCnt) // * SumFarPointsCnt - sum(FarPointsCnt) // nearcenterscnt = new int[nc]; nearpointscnt = new int[nc]; skipnearpointscnt = new int[nc]; farpointscnt = new int[nc]; maxnearcenterscnt = 0; maxnearpointscnt = 0; maxfarpointscnt = 0; sumnearcenterscnt = 0; sumnearpointscnt = 0; sumfarpointscnt = 0; for(i=0; i<=nc-1; i++) { for(j=0; j<=mxnx-1; j++) { xcx[j] = xc[i,j]; } // // Determine number of near centers and maximum radius of near centers // nearcenterscnt[i] = nearestneighbor.kdtreequeryrnn(centerstree, xcx, r[i]*rbfnearradius, true); nearestneighbor.kdtreequeryresultstags(centerstree, ref centerstags); maxrad = 0; for(j=0; j<=nearcenterscnt[i]-1; j++) { maxrad = Math.Max(maxrad, Math.Abs(r[centerstags[j]])); } // // Determine number of near points (ones which used to build ACBF) // and skipped points (the most near points which are NOT used to build ACBF // and are NOT included in the near points count // skipnearpointscnt[i] = nearestneighbor.kdtreequeryrnn(pointstree, xcx, 0.1*r[i], true); nearpointscnt[i] = nearestneighbor.kdtreequeryrnn(pointstree, xcx, (r[i]+maxrad)*rbfnearradius, true)-skipnearpointscnt[i]; alglib.ap.assert(nearpointscnt[i]>=0, "BuildRBFModelLSQR: internal error"); // // Determine number of far points // farpointscnt[i] = nearestneighbor.kdtreequeryrnn(pointstree, xcx, Math.Max(r[i]*rbfnearradius+maxrad*rbffarradius, r[i]*rbffarradius), true); // // calculate sum and max, make some basic checks // alglib.ap.assert(nearcenterscnt[i]>0, "BuildRBFModelLSQR: internal error"); maxnearcenterscnt = Math.Max(maxnearcenterscnt, nearcenterscnt[i]); maxnearpointscnt = Math.Max(maxnearpointscnt, nearpointscnt[i]); maxfarpointscnt = Math.Max(maxfarpointscnt, farpointscnt[i]); sumnearcenterscnt = sumnearcenterscnt+nearcenterscnt[i]; sumnearpointscnt = sumnearpointscnt+nearpointscnt[i]; sumfarpointscnt = sumfarpointscnt+farpointscnt[i]; } snnz = sumnearcenterscnt; gnnz = sumfarpointscnt; alglib.ap.assert(maxnearcenterscnt>0, "BuildRBFModelLSQR: internal error"); // // Allocate temporaries. // // NOTE: we want to avoid allocation of zero-size arrays, so we // use max(desired_size,1) instead of desired_size when performing // memory allocation. // a = new double[maxnearpointscnt+maxnearcenterscnt, maxnearcenterscnt]; tmpy = new double[maxnearpointscnt+maxnearcenterscnt]; g = new double[maxnearcenterscnt]; c = new double[maxnearcenterscnt]; nearcenters = new double[maxnearcenterscnt, mxnx]; nearpoints = new double[Math.Max(maxnearpointscnt, 1), mxnx]; farpoints = new double[Math.Max(maxfarpointscnt, 1), mxnx]; // // fill matrix SpG // sparse.sparsecreate(n, nc, gnnz, spg); sparse.sparsecreate(nc, nc, snnz, sps); for(i=0; i<=nc-1; i++) { centerscnt = nearcenterscnt[i]; // // main center // for(j=0; j<=mxnx-1; j++) { xcx[j] = xc[i,j]; } // // center's tree // tmpi = nearestneighbor.kdtreequeryknn(centerstree, xcx, centerscnt, true); alglib.ap.assert(tmpi==centerscnt, "BuildRBFModelLSQR: internal error"); nearestneighbor.kdtreequeryresultsx(centerstree, ref cx); nearestneighbor.kdtreequeryresultstags(centerstree, ref centerstags); // // point's tree // mrad = 0; for(j=0; j<=centerscnt-1; j++) { mrad = Math.Max(mrad, r[centerstags[j]]); } // // we need to be sure that 'CTree' contains // at least one side center // sparse.sparseset(sps, i, i, 1); c[0] = 1.0; for(j=1; j<=centerscnt-1; j++) { c[j] = 0.0; } if( centerscnt>1 && nearpointscnt[i]>0 ) { // // first KDTree request for points // pointscnt = nearpointscnt[i]; tmpi = nearestneighbor.kdtreequeryknn(pointstree, xcx, skipnearpointscnt[i]+nearpointscnt[i], true); alglib.ap.assert(tmpi==skipnearpointscnt[i]+nearpointscnt[i], "BuildRBFModelLSQR: internal error"); nearestneighbor.kdtreequeryresultsx(pointstree, ref xx); sind = skipnearpointscnt[i]; for(j=0; j<=pointscnt-1; j++) { vx = xx[sind+j,0]; vy = xx[sind+j,1]; vz = xx[sind+j,2]; for(k=0; k<=centerscnt-1; k++) { vr = 0.0; vv = vx-cx[k,0]; vr = vr+vv*vv; vv = vy-cx[k,1]; vr = vr+vv*vv; vv = vz-cx[k,2]; vr = vr+vv*vv; vv = r[centerstags[k]]; a[j,k] = Math.Exp(-(vr/(vv*vv))); } } for(j=0; j<=centerscnt-1; j++) { g[j] = Math.Exp(-((math.sqr(xcx[0]-cx[j,0])+math.sqr(xcx[1]-cx[j,1])+math.sqr(xcx[2]-cx[j,2]))/math.sqr(r[centerstags[j]]))); } // // calculate the problem // gnorm2 = 0.0; for(i_=0; i_<=centerscnt-1;i_++) { gnorm2 += g[i_]*g[i_]; } for(j=0; j<=pointscnt-1; j++) { vv = 0.0; for(i_=0; i_<=centerscnt-1;i_++) { vv += a[j,i_]*g[i_]; } vv = vv/gnorm2; tmpy[j] = -vv; for(i_=0; i_<=centerscnt-1;i_++) { a[j,i_] = a[j,i_] - vv*g[i_]; } } for(j=pointscnt; j<=pointscnt+centerscnt-1; j++) { for(k=0; k<=centerscnt-1; k++) { a[j,k] = 0.0; } a[j,j-pointscnt] = 1.0E-6; tmpy[j] = 0.0; } fbls.fblssolvels(ref a, ref tmpy, pointscnt+centerscnt, centerscnt, ref tmp0, ref tmp1, ref tmp2); for(i_=0; i_<=centerscnt-1;i_++) { c[i_] = tmpy[i_]; } vv = 0.0; for(i_=0; i_<=centerscnt-1;i_++) { vv += g[i_]*c[i_]; } vv = vv/gnorm2; for(i_=0; i_<=centerscnt-1;i_++) { c[i_] = c[i_] - vv*g[i_]; } vv = 1/gnorm2; for(i_=0; i_<=centerscnt-1;i_++) { c[i_] = c[i_] + vv*g[i_]; } for(j=0; j<=centerscnt-1; j++) { sparse.sparseset(sps, i, centerstags[j], c[j]); } } // // second KDTree request for points // pointscnt = farpointscnt[i]; tmpi = nearestneighbor.kdtreequeryknn(pointstree, xcx, pointscnt, true); alglib.ap.assert(tmpi==pointscnt, "BuildRBFModelLSQR: internal error"); nearestneighbor.kdtreequeryresultsx(pointstree, ref xx); nearestneighbor.kdtreequeryresultstags(pointstree, ref pointstags); // //fill SpG matrix // for(j=0; j<=pointscnt-1; j++) { fx = 0; vx = xx[j,0]; vy = xx[j,1]; vz = xx[j,2]; for(k=0; k<=centerscnt-1; k++) { vr = 0.0; vv = vx-cx[k,0]; vr = vr+vv*vv; vv = vy-cx[k,1]; vr = vr+vv*vv; vv = vz-cx[k,2]; vr = vr+vv*vv; vv = r[centerstags[k]]; vv = vv*vv; fx = fx+c[k]*Math.Exp(-(vr/vv)); } sparse.sparseset(spg, pointstags[j], i, fx); } } sparse.sparseconverttocrs(spg); sparse.sparseconverttocrs(sps); // // solve by LSQR method // tmpy = new double[n]; tc = new double[nc]; w = new double[nc, ny]; linlsqr.linlsqrcreate(n, nc, state); linlsqr.linlsqrsetcond(state, epsort, epserr, maxits); for(i=0; i<=ny-1; i++) { for(j=0; j<=n-1; j++) { tmpy[j] = y[j,i]; } linlsqr.linlsqrsolvesparse(state, spg, tmpy); linlsqr.linlsqrresults(state, ref c, lsqrrep); if( lsqrrep.terminationtype<=0 ) { info = -4; return; } sparse.sparsemtv(sps, c, ref tc); for(j=0; j<=nc-1; j++) { w[j,i] = tc[j]; } iterationscount = iterationscount+lsqrrep.iterationscount; nmv = nmv+lsqrrep.nmv; } info = 1; }