/*{{{ minfunc(optimize_struct *ostructp) {*/ LOCAL OPT_DTYPE minfunc(optimize_struct *ostructp) { struct minfunc_struct *mfs=(struct minfunc_struct *)ostructp->fixed_args; int i, N=mfs->nr_of_points; OPT_DTYPE x= *((OPT_DTYPE *)ostructp->opt_args); OPT_DTYPE *points=mfs->points, sumsq=0.0; if (x<=0) return 1e5; for (i=0; i<N; i++) { sumsq+=square(distfun(points[2*i], x)-points[2*i+1]); } return sumsq; }
/* the gateway function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { /* check for proper number of arguments */ if (nrhs<2) { mexErrMsgIdAndTxt("stats:pdistmex:TooFewInputs", "Two input arguments required."); } else if(nlhs>1) { mexErrMsgIdAndTxt("stats:pdistmex:TooManyOutputs", "Too many output arguments."); } /* Check the type of the input array */ /* Currently only works with double or single(float) */ if (mxIsDouble(prhs[0])) { distfun(nlhs, plhs, nrhs, prhs, (double)1.0); } else if (mxIsSingle(prhs[0])) { distfun(nlhs, plhs, nrhs, prhs, (float)1.0); } else { mexErrMsgIdAndTxt("stats:pdistmex:BadInputType", "PDISTMEX only supports real DOUBLE and SINGLE data."); } }
void veg_distance(double *x, int *nr, int *nc, double *d, int *diag, int *method) { int dc, i, j, ij; switch(*method) { case MANHATTAN: distfun = veg_manhattan; break; case EUCLIDEAN: distfun = veg_euclidean; break; case CANBERRA: distfun = veg_canberra; break; case BRAY: case JACCARD: distfun = veg_bray; break; case KULCZYNSKI: distfun = veg_kulczynski; break; case GOWER: distfun = veg_gower; break; case MORISITA: distfun = veg_morisita; break; case HORN: distfun = veg_horn; break; case MOUNTFORD: distfun = veg_mountford; break; case RAUP: distfun = veg_raup; break; case MILLAR: distfun = veg_millar; break; case CHAO: distfun = veg_chao; break; case GOWERDZ: distfun = veg_gowerDZ; break; case CAO: distfun = veg_cao; break; case MATCHING: distfun = veg_matching; break; case NOSHARED: distfun = veg_noshared; break; default: error("Unknown distance in the internal C function"); } dc = (*diag) ? 0 : 1; ij = 0; for (j=0; j <= *nr; j++) for (i=j+dc; i < *nr; i++) { d[ij++] = distfun(x, *nr, *nc, i, j); } }
//=========================================================================== void ClosestPoint::closestPtSurfSurfPlaneFunctional(const std::vector<Point>& epoint, //plane description const std::vector<Point>& epnt1, // start pt. in surf. 1 const std::vector<Point>& epnt2, // start pt. in surf. 2 const Point& epar1, // parameter start pt. in surf. 1 const Point& epar2, // parameter start pt. in surf. 2 const ParamSurface* psurf1, // ptr. to surf. 1 const ParamSurface* psurf2, // ptr. to surf. 2 double aepsge, // absolute tolerance std::vector<Point>& gpnt1, // result of iter. in surf. 1 std::vector<Point>& gpnt2, // result of iter. in surf. 2 Point& gpar1, Point& gpar2, int& jstat) // results of param. //=========================================================================== { // we formulate the problem as minimizing f(x) + c_k P(x), where f(x) is the distance // of the points in surface 1 and surface 2, and P(x) is the distance to the plane. // The criteria that the points must be lying in the plane is approached as the // multiplicative constant c_k increases. By choosing a sufficiently high value // for c_k, we expect to converge within the specified tolerance. gpar1 = gpar2 = Point(2); gpnt1.resize(3); gpnt2.resize(3); const Point plane_normal = epoint[1] / epoint[1].length(); double C = 1; // = compute_constraint_multiplier(plane_normal, epnt1, epnt2, aepsge); double dist_to_plane, old_dist_to_plane; double seed[4]; seed[0] = epar1[0]; seed[1] = epar1[1]; seed[2] = epar2[0]; seed[3] = epar2[1]; dist_to_plane = numeric_limits<double>::max(); while(true) { old_dist_to_plane = dist_to_plane; // make function object here SurfDistFun distfun(psurf1, psurf2, C, epoint[0], plane_normal); // specify function minimizer FunctionMinimizer<SurfDistFun> dfmin(4, distfun, seed, aepsge); // use conjugated gradient algorithm to minimize this function minimise_conjugated_gradient(dfmin);//, 5); // number of iterations in each cycle dist_to_plane = compute_distance_to_plane(psurf1->point(dfmin.getPar(0), dfmin.getPar(1)), psurf2->point(dfmin.getPar(2), dfmin.getPar(3)), epoint[0], plane_normal); if ( (dist_to_plane < aepsge) || (dist_to_plane >= old_dist_to_plane)) { // we will quit the loop at this point gpar1[0] = dfmin.getPar(0); gpar1[1] = dfmin.getPar(1); gpar2[0] = dfmin.getPar(2); gpar2[1] = dfmin.getPar(3); gpnt1.resize(3); gpnt2.resize(3); psurf1->point(gpnt1, gpar1[0], gpar1[1], 1); psurf2->point(gpnt2, gpar2[0], gpar2[1], 1); if (dist_to_plane < aepsge) { jstat = (gpnt1[0].dist(gpnt2[0]) < aepsge) ? 1 : 2; } else { // we are not able to converge properly to plane jstat = 3; } // to fulfill the contract that second derivatives and normal should also // be computed, we will do that here. Note, however, that these values // were used nowhere else in this algorithm. gpnt1.resize(7); gpnt2.resize(7); psurf1->point(gpnt1, gpar1[0], gpar1[1], 2); psurf2->point(gpnt2, gpar2[0], gpar2[1], 2); gpnt1[6] = gpnt1[1].cross(gpnt1[2]); // nb: not normalized here! gpnt2[6] = gpnt2[1].cross(gpnt2[2]); // nb: not normalized here! return; } cout << "multiplying C! New C is : " << C * 10 << endl; C *= 10; // if we redo the loop, we need to augment the value of C copy(dfmin.getPar(), dfmin.getPar() + 4, seed); } }
int main(int argc, char *argv[]) { int i=1, start=0, end=0, freqno; DATATYPE *new_tsdata, hold; array D; OPT_DTYPE ax, bx, cx, fa, fb, fc, xmin, sumsq, weight, sumweight, ave, min_power, optimize_arg, *points; optimize_struct ostruct; struct minfunc_struct mfs; struct transform_info_struct firsttinfo; transform_info_ptr tinfo, tinfo_next; struct transform_methods_struct methods[2]; struct external_methods_struct emethod; tinfo= &firsttinfo; /*{{{ Process command line*/ while (*argv[1]=='-') { switch (argv[1][1]) { } argv++; argc--; } if (argc!=3) { fprintf(stderr, "Usage: %s ascdatafile outfile\n" , argv[0]); return 1; } if (start<0) start=0; if (end<=0) end=start; /*}}} */ clear_external_methods(&emethod); firsttinfo.methods= methods; firsttinfo.emethods= &emethod; /*{{{ Read all data sets*/ select_readasc(tinfo); (*tinfo->methods->transform_defaults)(tinfo); firsttinfo.filename=argv[1]; firsttinfo.epochs= -1; firsttinfo.fromepoch=1; (*tinfo->methods->transform_init)(tinfo); if (start!=0) { while (i<start) { (*tinfo->methods->transform)(tinfo); i++; } } while ((end==0 || i<=end) && (*tinfo->methods->transform)(tinfo)!=NULL) { if ((tinfo_next=malloc(sizeof(struct transform_info_struct)))==NULL) { ERREXIT(&emethod, "similarity: Error malloc'ing tinfo struct\n"); } *(tinfo_next)=firsttinfo; tinfo_next->previous=tinfo; tinfo_next->next=NULL; tinfo->next=tinfo_next; tinfo=tinfo_next; i++; } /* The last tinfo structure was allocated in vein, throw away */ tinfo=tinfo->previous; free(tinfo->next); tinfo->next=NULL; (*firsttinfo.methods->transform_exit)(&firsttinfo); /*}}} */ points=malloc(2*firsttinfo.nr_of_channels*sizeof(OPT_DTYPE)); for (freqno=0; freqno<firsttinfo.nr_of_channels; freqno++) { /*{{{ Construct symmetrical function*/ sumweight=ave=0.0; min_power=1e10; for (i=0, tinfo= &firsttinfo; tinfo!=NULL; tinfo=tinfo->next, i++) { tinfo_array(tinfo, &D); array_transpose(&D); array_reset(&D); D.current_vector=freqno; D.current_element=i; hold=array_readelement(&D); D.current_element=0; do { points[D.current_element*2]=100*channel_distance(tinfo, i, D.current_element); points[D.current_element*2+1]=array_scan(&D)/hold; } while (D.message==ARRAY_CONTINUE); ostruct.function= &minfunc; mfs.nr_of_points=firsttinfo.nr_of_channels; mfs.points=points; ostruct.fixed_args=(void *)&mfs; ostruct.num_opt_args=1; ostruct.opt_args=(void *)&optimize_arg; ax=0.1; bx=12; opt_mnbrak(&ostruct, &ax, &bx, &cx, &fa, &fb, &fc); sumsq=opt_brent(&ostruct, ax, bx, cx, 1e-4, &xmin); # ifdef VERBOSE printf("%d %g %g %g\n", i, xmin, sumsq, hold); # endif weight= 1.0/sumsq; sumweight+=weight; ave+=weight*xmin; if (hold<min_power) min_power=hold; } ave/=sumweight; # ifdef VERBOSE printf("Consensus: %g %g\n", ave, min_power); # endif /*}}} */ /*{{{ Subtract symmetrical function*/ for (i=0, tinfo= &firsttinfo; tinfo!=NULL; tinfo=tinfo->next, i++) { tinfo_array(tinfo, &D); array_transpose(&D); array_reset(&D); D.current_vector=freqno; D.current_element=0; do { hold= min_power*distfun(100*channel_distance(tinfo, i, D.current_element), ave); array_write(&D, array_readelement(&D)-hold); } while (D.message==ARRAY_CONTINUE); } /*}}} */ } free(points); /*{{{ Write all data sets*/ tinfo= &firsttinfo; select_extract_item(tinfo); /* Output real part only */ (*tinfo->methods->transform_defaults)(tinfo); tinfo->methods->local_storage=(void *)0; (*tinfo->methods->transform_init)(tinfo); tinfo->methods++; select_writeasc(tinfo); (*tinfo->methods->transform_defaults)(tinfo); tinfo->outfname=argv[2]; tinfo->methods->local_storage=(void *)1; (*tinfo->methods->transform_init)(tinfo); for (; tinfo!=NULL; tinfo=tinfo->next) { tinfo->outfptr=firsttinfo.outfptr; tinfo->methods=methods; if ((new_tsdata=(*tinfo->methods->transform)(tinfo))==NULL) { ERREXIT(tinfo->emethods, "extract_item failed !\n"); } free(tinfo->tsdata); tinfo->tsdata=new_tsdata; tinfo->methods++; (*tinfo->methods->transform)(tinfo); } tinfo= &firsttinfo; tinfo->methods=methods; (*tinfo->methods->transform_exit)(tinfo); tinfo->methods++; (*tinfo->methods->transform_exit)(tinfo); /*}}} */ return 0; }
void R_distance(double *x, int *nr, int *nc, double *d, int *diag, int *method, double *p) { int dc, i, j; size_t ij; /* can exceed 2^31 - 1 */ double (*distfun)(double*, int, int, int, int) = NULL; #ifdef _OPENMP int nthreads; #endif switch(*method) { case EUCLIDEAN: distfun = R_euclidean; break; case MAXIMUM: distfun = R_maximum; break; case MANHATTAN: distfun = R_manhattan; break; case CANBERRA: distfun = R_canberra; break; case BINARY: distfun = R_dist_binary; break; case MINKOWSKI: if(!R_FINITE(*p) || *p <= 0) error(_("distance(): invalid p")); break; default: error(_("distance(): invalid distance")); } dc = (*diag) ? 0 : 1; /* diag=1: we do the diagonal */ #ifdef _OPENMP if (R_num_math_threads > 0) nthreads = R_num_math_threads; else nthreads = 1; /* for now */ if (nthreads == 1) { /* do the nthreads == 1 case without any OMP overhead to see if it matters on some platforms */ ij = 0; for(j = 0 ; j <= *nr ; j++) for(i = j+dc ; i < *nr ; i++) d[ij++] = (*method != MINKOWSKI) ? distfun(x, *nr, *nc, i, j) : R_minkowski(x, *nr, *nc, i, j, *p); } else /* This produces uneven thread workloads since the outer loop is over the subdiagonal portions of columns. An alternative would be to use a loop on ij and to compute the i and j values from ij. */ #pragma omp parallel for num_threads(nthreads) default(none) \ private(i, j, ij) \ firstprivate(nr, dc, d, method, distfun, nc, x, p) for(j = 0 ; j <= *nr ; j++) { ij = j * (*nr - dc) + j - ((1 + j) * j) / 2; for(i = j+dc ; i < *nr ; i++) d[ij++] = (*method != MINKOWSKI) ? distfun(x, *nr, *nc, i, j) : R_minkowski(x, *nr, *nc, i, j, *p); } #else ij = 0; for(j = 0 ; j <= *nr ; j++) for(i = j+dc ; i < *nr ; i++) d[ij++] = (*method != MINKOWSKI) ? distfun(x, *nr, *nc, i, j) : R_minkowski(x, *nr, *nc, i, j, *p); #endif }