void compute(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[], const int atria_preprocessing_given, METRIC dummy) { long bins = 32; double start_dist = 0; double maximal_search_radius = 0; double scale_factor = 1; long opt_flag = 0; // 0 => eucl.norm, 1 => max.norm, utm, 2 => eucl, silent 3 => max., silent /* handle matrix I/O */ const long N = mxGetM(prhs[0]); const long dim = mxGetN(prhs[0]); const double* p = (double *)mxGetPr(prhs[0]); const long R = mxGetM(prhs[1]); const double* ref = (double *)mxGetPr(prhs[1]); const double relative_range = (double) *((double *)mxGetPr(prhs[2])); if (nrhs > 3) bins = (long) *((double *)mxGetPr(prhs[3])); if (nrhs > 4) opt_flag = (long) *((double *)mxGetPr(prhs[4])); if (N < 1) { mexErrMsgTxt("Data set must consist of at least two points (row vectors)"); return; } if (dim < 1) { mexErrMsgTxt("Data points must be at least of dimension one"); return; } if (relative_range <= 0) { mexErrMsgTxt("Relative range must be greater zero"); return; } if ((mxGetN(prhs[1]) == 0) || (mxGetM(prhs[1]) == 0)) { mexErrMsgTxt("Wrong reference indices given"); return; } if (bins < 2) { mexErrMsgTxt("Number of bins should be two"); return; } if (R < 1) { mexErrMsgTxt("At least one reference point must be given"); return; } if (mxGetN(prhs[1]) != dim) { mexErrMsgTxt("Dimension of reference points and data set points is not the same"); return; } if ((opt_flag < 0) || (opt_flag > 3)) { mexErrMsgTxt("Flag must be out of 0...3"); return; } point_set<METRIC> points(N,dim, p); point_set<METRIC> ref_points(R, dim, ref); ATRIA< point_set<METRIC> >* searcher = 0; #ifdef MATLAB_MEX_FILE if (atria_preprocessing_given) { searcher = new ATRIA< point_set<METRIC> >(points, prhs[-1]); // this constructor used the data from the preprocessing if (searcher->geterr()) { delete searcher; searcher = 0; } } #endif if (searcher == 0) { searcher = new ATRIA< point_set<METRIC> >(points); } if (searcher->geterr()) { mexErrMsgTxt("Error preparing searcher"); return; } if (mxGetM(prhs[2])*mxGetN(prhs[2]) == 2) { start_dist = (double) ((double *)mxGetPr(prhs[2]))[0]; maximal_search_radius = (double) ((double *)mxGetPr(prhs[2]))[1]; if (start_dist <= 0) { mexErrMsgTxt("Starting radius is zero or negativ"); return; } if (maximal_search_radius <= start_dist) { mexErrMsgTxt("Maximal search radius must be greater than starting radius"); return; } } else { maximal_search_radius = relative_range * searcher->data_set_radius(); // compute the maximal search radius using information about attractor size // try to determine an estimate for the minimum inter-point distance in the data set, but greater zero double* const coord = new double[dim]; for (long n=0; n < 128; n++) { const long actual = (long) (((double)rand() * (double) (N-2))/(double)RAND_MAX); vector<neighbor> v; for (long k=0; k < dim; k++) coord[k] = points.coordinate(actual,k); searcher->search_k_neighbors(v, 1, coord, actual, actual); // search the nearest neighbor if (v.size() > 0) { if (start_dist == 0) start_dist = v[0].dist(); if (v[0].dist() > 0) { if (v[0].dist() < start_dist) start_dist = v[0].dist(); } } } if (start_dist <= 0) { // first try to search again for a minimum inter-point distance greater zero for (long n=0; n < 512; n++) { const long actual = (long) (((double)rand() * (double) (N-2))/(double)RAND_MAX); vector<neighbor> v; for (long k=0; k < dim; k++) coord[k] = points.coordinate(actual,k); searcher->search_k_neighbors(v, 1, coord, actual, actual); // search the nearest neighbor if (v.size() > 0) { if (start_dist == 0) start_dist = v[0].dist(); if (v[0].dist() > 0) { if (v[0].dist() < start_dist) start_dist = v[0].dist(); } } } } delete[] coord; if (start_dist <= 0) { // give up if we cannot find an interpoint distance greater zero mexErrMsgTxt("Cannot find an interpoint distance greater zero, maybe ill-conditioned data set given"); return; } if (maximal_search_radius <= start_dist) { mexErrMsgTxt("Maximal search radius must be greater than starting radius"); return; } } scale_factor = pow(maximal_search_radius/start_dist, 1.0/(bins-1)); if (be_verbose) { mexPrintf("Number of reference points : %d\n", R); mexPrintf("Upper bound for attractor size : %f\n", 2 * searcher->data_set_radius()); mexPrintf("Starting distance : %f\n", start_dist); mexPrintf("Maximal search radius : %f\n", maximal_search_radius); mexPrintf("Number of partitions used : %d\n\n", bins); } plhs[0] = mxCreateDoubleMatrix(bins, 1, mxREAL); double* corrsums = (double *) mxGetPr(plhs[0]); double* dists; if (nlhs > 1) { plhs[1] = mxCreateDoubleMatrix(bins, 1, mxREAL); dists = (double *) mxGetPr(plhs[1]); } else dists = new double[bins]; double x = start_dist; // initialize vectors // corrsum[i] counts the number of points/distances (real) smaller than dists[i] for (long bin=0; bin < bins; bin++) { corrsums[bin] = 0; dists[bin] = x; x *= scale_factor; } long total_pairs = 0; // count the total number of points pairs that were at least theoretically tested for (long n=0; n < R; n++) { /* iterate over all reference points */ vector<neighbor> v; const long pairs = N; if (pairs <= 0) continue; total_pairs += pairs; searcher->search_range(v, maximal_search_radius, ref_points.point_begin(n), -1, -1); if (v.size() > 0) { for (vector<neighbor>::iterator i = v.begin(); i < v.end(); i++) { // v is unsorted (!!!) const double dist = (*i).dist(); int mi, ni; // index of first and last (inclusive) element of array dists if (dist >= dists[ni = bins-1]) // => we know that dist <= dists[ni] continue; if (dist < dists[mi = 0]) { // => we know that dists[mi] < dist corrsums[0]++; continue; } do { const int ki = (mi + ni) / 2; // "mi < ki < ni" if "mi + 1 < ni" if (dist < dists[ki]) ni = ki; // "dists[mi] < dist <= dists[ni]" is still valid else mi = ki; // "dists[mi] < dist <= dists[ni]" is still valid } while (ni > mi+1); // now, "ni == mi+1" and "dists[mi] < dist <= dists[ni]" is true, // so "dists[mi] < dist <= dists[mi+1]", so mi+1 is the desired bin where // to count this distance corrsums[ni]++; } } } if (total_pairs > 0) { unsigned long sum = 0; for (long bin=0; bin < bins; bin++) { sum += (long) corrsums[bin]; corrsums[bin] = ((double) sum) / (double) total_pairs; } } if (nlhs > 2) { plhs[2] = mxCreateDoubleMatrix(1, 1, mxREAL); *((double *) mxGetPr(plhs[2])) = (double) total_pairs; } if (!(nlhs > 1)) delete[] dists; delete searcher; }
void compute(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[], const int atria_preprocessing_given, METRIC dummy) { long i,j,n,k; /* loop variables */ /* handle matrix I/O */ const long N = mxGetM(prhs[0]); const long dim = mxGetN(prhs[0]); const double* p = (double *)mxGetPr(prhs[0]); const long R = max(mxGetM(prhs[1]), mxGetN(prhs[1])); const double* ref = (double *)mxGetPr(prhs[1]); const double relative_range = (double) *((double *)mxGetPr(prhs[2])); const long past = (long) *((double *)mxGetPr(prhs[3])); if (N < 1) { mexErrMsgTxt("Data set must consist of at least two points (row vectors)"); return; } if (dim < 2) { mexErrMsgTxt("Data points must be at least of dimension two"); return; } if ((mxGetN(prhs[1]) == 0) || (mxGetM(prhs[1]) == 0)) { mexErrMsgTxt("Wrong reference indices given"); return; } if (R < 1) { mexErrMsgTxt("At least one reference index or point must be given"); return; } for (i=0; i < R; i++) { if ((ref[i] < 1) || (ref[i]>N)) { mexErrMsgTxt("Reference indices out of range"); return; } } point_set<METRIC> points(N,dim, p); ATRIA< point_set<METRIC> >* searcher = 0; #ifdef MATLAB_MEX_FILE if (atria_preprocessing_given) { searcher = new ATRIA< point_set<METRIC> >(points, prhs[-1]); // this constructor used the data from the preprocessing if (searcher->geterr()) { delete searcher; searcher = 0; } } #endif if (searcher == 0) { searcher = new ATRIA< point_set<METRIC> >(points); } if (searcher->geterr()) { mexErrMsgTxt("Error preparing searcher"); return; } double range; if (relative_range > 0) range = relative_range * searcher->data_set_radius(); // compute the maximal search radius using information about attractor size else range = fabs(relative_range); // if relative_range is negativ, use it's value (without sign) as maximal search radius mexPrintf("Number of reference points : %d\n", R); mexPrintf("Upper bound for attractor size : %f\n", 2 * searcher->data_set_radius()); mexPrintf("Maximal search radius : %f\n", range); plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); double* out = (double *) mxGetPr(plhs[0]); unsigned long counter = 0; double sum = 0; for (n=0; n < R; n++) { /* iterate over all reference points */ const long actual = (long) ref[n]-1; /* Matlab to C means indices change from 1 to 0, 2 to 1, 3 to 2 ...*/ if (actual > past) { vector<neighbor> v; searcher->search_range(v, range, points.point_begin(actual), actual-past, N); // don't search points from [actual-past .. N-1] //overall_points += (actual-past); // count the total number of points pairs that were at least theoretically tested if (v.size() > 0) { vector<neighbor>::iterator i; for (i = v.begin(); i < v.end(); i++) { // v is unsorted const double dist = (*i).dist(); if (dist > 0) { sum += log(dist/range); counter++; } } } } } if (counter > 0) *out = -((double)counter)/sum; else *out = 0; delete searcher; }
void compute(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[], const int atria_preprocessing_given, METRIC dummy) { long bins = 32; double start_dist = 0; double maximal_search_radius = 0; double scale_factor = 1; long opt_flag = 0; // 0 => eucl.norm, upper triangle matrix, 1 => max.norm, utm, 2 => eucl,full matrix, 3 => max.,full matrix long Nref_min; long Nref_max; /* handle matrix I/O */ #ifdef C_STYLE_POINT_SET const long N = mxGetN(prhs[0]); const long dim = mxGetM(prhs[0]); #else // this is the default const long N = mxGetM(prhs[0]); const long dim = mxGetN(prhs[0]); #endif const double* p = (double *)mxGetPr(prhs[0]); const long Npairs = (long) *((double *)mxGetPr(prhs[1])); // number of pairs if (mxGetM(prhs[1])*mxGetN(prhs[1]) == 3) { Nref_min = (long) ((double *)mxGetPr(prhs[1]))[1]; Nref_max = (long) ((double *)mxGetPr(prhs[1]))[2]; } else { Nref_min = 1; Nref_max = N; } const double relative_range = (double) *((double *)mxGetPr(prhs[2])); const long past = (long) *((double *)mxGetPr(prhs[3])); if (nrhs > 4) bins = (long) *((double *)mxGetPr(prhs[4])); if (nrhs > 5) opt_flag = (long) *((double *)mxGetPr(prhs[5])); if (N < 1) { mexErrMsgTxt("Data set must consist of at least two points (row vectors)"); return; } if (dim < 1) { mexErrMsgTxt("Data points must be at least of dimension one"); return; } if (relative_range <= 0) { mexErrMsgTxt("Relative range must be greater zero"); return; } if (bins < 2) { mexErrMsgTxt("Number of bins should be two"); return; } if (Npairs < 1) { mexErrMsgTxt("Number of pairs must be positive"); return; } if ((opt_flag < 0) || (opt_flag > 7)) { mexErrMsgTxt("Flag must be out of 0..7"); return; } if (Nref_min < 1) Nref_min = 1; if (Nref_max > N) Nref_max = N; point_set<METRIC> points(N,dim, p); ATRIA< point_set<METRIC> >* searcher = 0; #ifdef MATLAB_MEX_FILE if (atria_preprocessing_given) { searcher = new ATRIA< point_set<METRIC> >(points, prhs[-1]); // this constructor used the data from the preprocessing if (searcher->geterr()) { delete searcher; searcher = 0; } } #endif if (searcher == 0) { searcher = new ATRIA< point_set<METRIC> >(points); } if (searcher->geterr()) { mexErrMsgTxt("Error preparing searcher"); return; } if (mxGetM(prhs[2])*mxGetN(prhs[2]) == 2) { start_dist = (double) ((double *)mxGetPr(prhs[2]))[0]; maximal_search_radius = (double) ((double *)mxGetPr(prhs[2]))[1]; if (start_dist <= 0) { mexErrMsgTxt("Starting radius is zero or negativ"); return; } if (maximal_search_radius <= start_dist) { mexErrMsgTxt("Maximal search radius must be greater than starting radius"); return; } } else { maximal_search_radius = relative_range * searcher->data_set_radius(); // compute the maximal search radius using information about attractor size // try to determine an estimate for the minimum inter-point distance in the data set, but greater zero for (long n=0; n < 128; n++) { const long actual = (long) (((double)rand() * (double) (N-2))/(double)RAND_MAX); vector<neighbor> v; searcher->search_k_neighbors(v, 1, points.point_begin(actual), actual, actual); // search the nearest neighbor if (v.size() > 0) { if (start_dist == 0) start_dist = v[0].dist(); if (v[0].dist() > 0) { if (v[0].dist() < start_dist) start_dist = v[0].dist(); } } } if (start_dist <= 0) { // first try to search again for a minimum inter-point distance greater zero for (long n=0; n < 512; n++) { const long actual = (long) (((double)rand() * (double) (N-2))/(double)RAND_MAX); vector<neighbor> v; searcher->search_k_neighbors(v, 1, points.point_begin(actual), actual, actual); // search the nearest neighbor if (v.size() > 0) { if (start_dist == 0) start_dist = v[0].dist(); if (v[0].dist() > 0) { if (v[0].dist() < start_dist) start_dist = v[0].dist(); } } } } if (start_dist <= 0) { // give up if we cannot find an interpoint distance greater zero mexErrMsgTxt("Cannot find an interpoint distance greater zero, maybe ill-conditioned data set given"); return; } if (maximal_search_radius <= start_dist) { mexErrMsgTxt("Maximal search radius must be greater than starting radius"); return; } } scale_factor = pow(maximal_search_radius/start_dist, 1.0/(bins-1)); if (be_verbose) { //mexPrintf("Number of reference points : %d\n", R); mexPrintf("Number of data set points : %d\n", N); mexPrintf("Number of pairs to find : %d\n", Npairs); mexPrintf("Miniumum number of reference points : %d\n", Nref_min); mexPrintf("Maximum number of reference points : %d\n", Nref_max); mexPrintf("Upper bound for attractor size : %f\n", 2 * searcher->data_set_radius()); mexPrintf("Number of partitions used : %d\n", bins); mexPrintf("Time window to exclude from search : %d\n", past); mexPrintf("Minimal length scale : %f\n", start_dist); mexPrintf("Starting at maximal length scale : %f\n", maximal_search_radius); } plhs[0] = mxCreateDoubleMatrix(bins, 1, mxREAL); double* corrsums = (double *) mxGetPr(plhs[0]); long* const ref = new long[N]; // needed to create random reference indices long* const total_pairs = new long[bins]; // number of total pairs is not equal for all bins long* const pairs_found = new long[bins]; // number of pairs found within distance dist double* dists; if (nlhs > 1) { plhs[1] = mxCreateDoubleMatrix(bins, 1, mxREAL); dists = (double *) mxGetPr(plhs[1]); } else dists = new double[bins]; double x = start_dist; // initialize vectors // pairs_found[i] counts the number of points/distances (real) smaller than dists[i] for (long bin=0; bin < bins; bin++) { pairs_found[bin] = 0; total_pairs[bin] = 0; dists[bin] = x; x *= scale_factor; } for (long r=0; r < N; r++) ref[r] = r; long R = 0; // number of reference points actually used long bin = bins-1; // the current highest bin (and length scale) that needs to be filled over Npairs while(((R < Nref_min) || (pairs_found[bin] < Npairs)) && (R < Nref_max)) { vector<neighbor> v; long first, last; // all points with indices i so that first <= i <= last are excluded(!) from search long pairs = 0; const long actual = random_permutation(ref, N, R++); // choose random index from 0...N-1, without reoccurences if (opt_flag & (long)2) { first = actual-past; last = actual+past; if (past >= 0) pairs = lmax(0,first) + lmax(N-1-last,0); else pairs = N; } else { if (past >= 0) first = actual-past; else first = actual; last = N; pairs = lmin(first,last); // don't search points from [actual-past .. N-1] } if (pairs <= 0) { continue; } searcher->search_range(v, dists[bin], points.point_begin(actual), first, last); if (v.size() > 0) { for (vector<neighbor>::iterator i = v.begin(); i < v.end(); i++) { // v is unsorted (!!!) const double d = (*i).dist(); for (long n = bin; n >= 0; n--) { if (d > dists[n]) break; pairs_found[n]++; } } } for (long n = 0; n <= bin; n++) { total_pairs[n] += pairs; } // see if we can reduce length scale int bins_changed = 0; while((pairs_found[bin] >= Npairs) && (bin > 0) && (R >= Nref_min)) { bin--; bins_changed = 1; } if (be_verbose) { if (bins_changed) { mexPrintf("Reference points used so far : %d\n", R); mexPrintf("Switching to length scale : %f\n", dists[bin]); } } } if (be_verbose) { mexPrintf("Number of reference points used : %d\n", R); } for (long bin=0; bin < bins; bin++) { corrsums[bin] = ((double) pairs_found[bin]) / ((double) total_pairs[bin]); } if (nlhs > 2) { plhs[2] = mxCreateDoubleMatrix(bins, 1, mxREAL); double* const y = mxGetPr(plhs[2]); for (long b=0; b < bins; b++) y[b] = (double) pairs_found[b]; } if (nlhs > 3) { plhs[3] = mxCreateDoubleMatrix(bins, 1, mxREAL); double* const y = mxGetPr(plhs[3]); for (long b=0; b < bins; b++) y[b] = (double) total_pairs[b]; } if (nlhs > 4) { plhs[4] = mxCreateDoubleMatrix(R, 1, mxREAL); double* const y = mxGetPr(plhs[4]); for (long r=0; r < R; r++) y[r] = (double) ref[r]+1; // C to Matlab means } delete[] total_pairs; delete[] pairs_found; delete[] ref; if (!(nlhs > 1)) delete[] dists; delete searcher; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int atria_preprocessing_given = 0; // flag wheter preprocessing is already given on command line ATRIA< point_set<euclidian_distance> >* searcher = 0; // try to see if the first parameter given is an atria structure // If this is true, the order of input parameters is shifted by one // try to see if the first parameter given is an atria structure // If this is true, the order of input parameters is shifted by one if ((nrhs) && (mxIsStruct(prhs[0]))) { atria_preprocessing_given = 1; prhs++; // these two lines enable us to use the old argument parsing block without changing it nrhs--; } /* check input args */ if (nrhs < 5) { mexErrMsgTxt("Largest lyapunov exponent : Data set of points (row vectors), reference indices, length of prediction, maximal number of neighbours and past must be given"); return; } /* handle matrix I/O */ const long N = mxGetM(prhs[0]); const long dim = mxGetN(prhs[0]); const double* p = (double *)mxGetPr(prhs[0]); const long R = mxGetM(prhs[1]) * mxGetN(prhs[1]); // number of reference points const double* ref = (double *)mxGetPr(prhs[1]); const long length = (long) *((double *)mxGetPr(prhs[2])); // length of prediction const long NNR = (long) *((double *)mxGetPr(prhs[3])); // number of nearest neighbors const long past = (long) *((double *)mxGetPr(prhs[4])); // number of points to be excluded from search if (fabs((double) N) - fabs((double)length) < 1) { mexErrMsgTxt("Data set must consist of at least two points (row vectors)"); return; } if (dim < 1) { mexErrMsgTxt("Data points must be at least of dimension one"); return; } if (length <= 0) { mexErrMsgTxt("Prediction length must be greater zero"); return; } if ((mxGetN(prhs[1]) == 0) || (mxGetM(prhs[1]) == 0)) { mexErrMsgTxt("Wrong reference indices given"); return; } if ((NNR < 1) || (NNR > N)) { mexErrMsgTxt("Number of nearest neighbours must be within 1 and number of points in the data set"); return; } mexPrintf("Number of reference points : %d\n", R); if (R < 1) { mexErrMsgTxt("At least one reference index or point must be given"); return; } for (long i=0; i < R; i++) { // check reference indices if ((ref[i] < 1) || (ref[i]>N-length)) { mexErrMsgTxt("Reference indices out of range"); return; } } #include "create_searcher.cpp" plhs[0] = mxCreateDoubleMatrix(length+1, 1, mxREAL); double* x = (double *) mxGetPr(plhs[0]); const double logarithm_of_2 = log(2.0); int issue_warning = 1; long count = 0; // count the number of pairs with distance > 0 for (long step = 0; step <= length; step++) x[step] = 0; for (long n=0; n < R; n++) { /* main loop, iterate over all reference points */ vector<neighbor>::iterator i; vector<neighbor> v; const long actual = (long) ref[n]-1; /* Matlab to C means indices change from 1 to 0, 2 to 1, 3 to 2 ...*/ // try to find at least NNR valid pairs (reference point - neighbor) // a valid pair must fullfil several criteria : // 1) both must have a known future of at least lenght steps, so that we // don't run out of the data set size when computing the divergence // 2) initial distance must be greater zero // 3) inital indices must differ by at least "past" steps for (long nnr=NNR; nnr < 4 * NNR; nnr++) { vector<neighbor> v_test; v.erase(v.begin(), v.end()); searcher->search_k_neighbors(v_test, nnr, points.point_begin(actual), actual-past, actual+past); for (i = v_test.begin(); i < v_test.end(); i++) { if (((*i).dist() > 0) && ((*i).index() < N-length)) { v.push_back(*i); } } if (v.size() >= NNR) break; } for (i = v.begin(); i < v.end(); i++) { // v is the sorted vector of neighbors const long nnindex = (*i).index(); const double nndist = (*i).dist(); const double log_nndist = log(nndist); count++; for (long step = 0; step <= length; step++) { const double dist = points.distance(actual+step, nnindex+step); if (dist > 0) { x[step] += log(dist) - log_nndist; } else { if (issue_warning) { issue_warning = 0; // don't issue this warning again mexPrintf("Largelyap warning : cannot take logarithm of distance zero \n"); } } } } } if (count > 0) { for (long step = 0; step <= length; step++) x[step] /= (count*logarithm_of_2); } delete searcher; }