double EMD(Ap_FeatureVector1D *ap_fv1, FeatureVector1D *w1, Ap_FeatureVector1D *ap_fv2, FeatureVector1D *w2, Metric m) { signature_t *Signature1, *Signature2; double distance; Signature1 = (signature_t *)malloc(sizeof(signature_t)); if (Signature1 == NULL) { Error(MSG1,"CreateSignature"); } Signature2 = (signature_t *)malloc(sizeof(signature_t)); if (Signature2 == NULL) { Error(MSG1,"CreateSignature"); } Signature1->n = w1->n; Signature1->Features = (feature_t *)ap_fv1; Signature1->Weights = w1->X; Signature2->n = w2->n; Signature2->Features = (feature_t *)ap_fv2; Signature2->Weights = w2->X; distance = emd(Signature1, Signature2, m, NULL, NULL); free(Signature1); free(Signature2); return(distance); }
float pnm_labelmap_emd(pnm_labelmap_t *pgml1, pnm_labelmap_t *pgml2, int num) { int i,nb1,nb2,nb_min,size1,size2; float fl,nb,scale1,scale2; emd_signature_t s1,s2; nb1 = pnm_labelmap_numOfPix(pgml1); nb2 = pnm_labelmap_numOfPix(pgml2); nb_min = (nb1<nb2) ? ((nb1<num) ? nb1 : num) : ((nb2<num) ? nb2 : num); pnm_labelmap_signature(&s1,pgml1,nb_min); /*fprintf(stderr, "Signature: n=%d, nb_min=%d, num=%d.\n",s1.n,nb_min,num); */ pnm_labelmap_signature(&s2,pgml2,nb_min); /*fprintf(stderr, "Signature: n=%d, nb_min=%d, num=%d.\n",s2.n,nb_min,num); */ fl = emd(&s1, &s2, pnm_dist, 0, 0); /*fl = emd_normalized(&s1, &s2, pnm_dist, 0, 0);*/ emd_signature_free(&s1); emd_signature_free(&s2); return fl; }
//earth move distance float PaletteIndex::histMatchDist(vector<int>& a, vector<int>& b) { //convert vector to signature feature_t fa[512],fb[512]; float wa[512],wb[512]; int i = 0; for (vector<int>::iterator it = a.begin(); it != a.end(); ++it) { fa[i].X=colors[i][0]; fa[i].Y=colors[i][1]; fa[i].Z=colors[i][2]; wa[i]=*it; i++; } i = 0; for (vector<int>::iterator it = b.begin(); it != b.end(); ++it) { fb[i].X=colors[i][0]; fb[i].Y=colors[i][1]; fb[i].Z=colors[i][2]; wb[i]=*it; i++; } signature_t sa={512,fa,wa},sb={512,fb,wb}; float e = emd(&sa, &sb, dist, 0, 0); return e; }
float EmdSimilarity(GARG *garg1, GARG *garg2) { signature_t g1,g2; int i; float dist; // load g1 g1.n = garg1->node_num; g1.Features = (feature_t *)malloc(sizeof(feature_t)*g1.n); g1.Weights = (float *)malloc(sizeof(float)*g1.n); for(i=0;i<g1.n;i++) { garg1->GetNodeFeature(g1.Features[i],i); g1.Features[i][0]/=320; g1.Features[i][1]/=240; g1.Features[i][2]/=256; g1.Features[i][3]/=256; g1.Features[i][4]/=256; g1.Weights[i] = 1.0f/g1.n; } // load g2 g2.n = garg2->node_num; g2.Features = (feature_t *)malloc(sizeof(feature_t)*g2.n); g2.Weights = (float *)malloc(sizeof(float)*g2.n); for(i=0;i<g2.n;i++) { garg2->GetNodeFeature(g2.Features[i],i); g2.Features[i][0]/=320; g2.Features[i][1]/=240; g2.Features[i][2]/=256; g2.Features[i][3]/=256; g2.Features[i][4]/=256; g2.Weights[i] = 1.0f/g2.n; } // Earth Mover's Distance // download emd.c from http://ai.stanford.edu/~rubner/emd/default.htm // then change emd.c to emd.cpp #ifdef EMD_CODE_INCLUDED dist = emd(&g1,&g2,_fdistance,NULL,NULL); #else dist = 0; #endif free(g1.Features); free(g2.Features); return 1-dist; }
int compute_distance_matrix(EmdDB &db, double** mat) { // init diagonal to 0 for (int i=0; i<db.numEntries; i++) { mat[i][i] = 0; } cout << "Computing distance matrix. " << db.numEntries << " entries." << endl; for (int i=0; i<db.numEntries; i++) { for (int j=i+1; j<db.numEntries; j++) { entry_t e1 = db.getEntry(i); entry_t e2 = db.getEntry(j); normalize_by_centroid(e1.signature); normalize_by_centroid(e2.signature); int64 emd_start = cvGetTickCount(); float e = emd(&e1.signature, &e2.signature, euclid_dist2, NULL, NULL); int64 emd_end = cvGetTickCount(); double emd_time = ((double)emd_end - (double)emd_start) / cvGetTickFrequency(); mat[i][j] = e; mat[j][i] = e; //cout << i << ", " << j << " : " << e << endl; *log_stream << db.getPath() << "," << e1.filename << "," << e2.filename << "," << e1.signature.n << "," << e2.signature.n << "," << signature_weight_sum(e1.signature) << "," << signature_weight_sum(e2.signature) << "," << emd_time << endl; } } return 0; }
double EarthMoversDistance(signatures *sample1, signatures *sample2, TrainingSet *ts) { double distance = 0.0, avg_weight = 0.0; signature_t s1, s2; long feature_index = 0, in_histogram = 0; float *values1 = new float[ts->signature_count]; float *values2 = new float[ts->signature_count]; float *weights1 = new float[ts->signature_count]; flow_t *flow = new flow_t[ts->signature_count * 2 - 1]; /* the maximum possible size of the flow */ for (long sig_index = 0; sig_index < sample1->count; sig_index++) { // if (is_histogram_bin(ts->SignatureNames[sig_index])) // { if (feature_index>0 && is_same_hist(ts->SignatureNames[sig_index], ts->SignatureNames[sig_index - 1])==0) /* new histogram starts here */ { if (avg_weight > 0) /* if the total weight is zero - no point computing the distance */ { int flowsize; s1.n = feature_index; s2.n = feature_index; s1.Features = values1; s2.Features = values2; s1.Weights = weights1; s2.Weights = weights1; /* compute the distance */ emd(&s1, &s2, dist, flow, &flowsize); avg_weight /= feature_index; for (long i = 0; i < flowsize; i++) distance += avg_weight*flow[i].amount*fabs((float)(flow[i].to - flow[i].from)); } feature_index = 0; avg_weight = 0.0; } // else /* another histogram bin */ if (is_histogram_bin(ts->SignatureNames[sig_index])) { values1[feature_index] = (float)sample1->data[sig_index].value; values2[feature_index] = (float)sample2->data[sig_index].value; weights1[feature_index] = (float)ts->SignatureWeights[sig_index]; feature_index++; avg_weight += ts->SignatureWeights[sig_index]; } else distance += ts->SignatureWeights[sig_index] * fabs(sample1->data[sig_index].value - sample2->data[sig_index].value); /* independent value - no histogram */ } /* for (long sig_index = 0; sig_index < sample1->count; sig_index++) if (ts->SignatureWeights[sig_index]>0) { values1[feature_index] = (float)sample1->data[sig_index].value; values2[feature_index] = (float)sample2->data[sig_index].value; weights1[feature_index] = (float)ts->SignatureWeights[sig_index]; feature_index++; } //feature_index = 300; s1.n = feature_index; s2.n = feature_index; s1.Features = values1; s2.Features = values2; s1.Weights = weights1; s2.Weights = weights1; flow_t *flow = new flow_t[feature_index * 2 - 1]; int flowsize; // distance = emd(&s1, &s2, dist, 0, 0); distance=emd(&s1, &s2, dist, flow, &flowsize); distance = 0; for (long i = 0; i < flowsize; i++) distance += flow[i].amount*fabs((float)(flow[i].to - flow[i].from)); */ delete values1; delete values2; delete weights1; delete flow; return(distance); }
static PyObject *compute_emd(PyObject *self, PyObject *args, PyObject *keywds) { static char *kwlist[] = {"feature1", "feature2", "weight1", "weight2", NULL}; PyObject *feature1, *feature2, *weight1, *weight2; double *f1, *f2; float *w1, *w2; int length1, length2; signature_t signature1, signature2; float distance; PyObject *item; int i; if(!PyArg_ParseTupleAndKeywords(args, keywds, "OOOO", kwlist, &feature1, &feature2, &weight1, &weight2)) return NULL; if(!PySequence_Check(feature1)) { PyErr_SetString(PyExc_TypeError, "feature1 must be a sequence"); return NULL; } if(!PySequence_Check(feature2)) { PyErr_SetString(PyExc_TypeError, "feature2 must be a sequence"); return NULL; } if(!PySequence_Check(weight1)) { PyErr_SetString(PyExc_TypeError, "weight1 must be a sequence"); return NULL; } if(!PySequence_Check(weight2)) { PyErr_SetString(PyExc_TypeError, "weight2 must be a sequence"); return NULL; } length1 = PySequence_Size(feature1); length2 = PySequence_Size(feature2); if(PySequence_Size(weight1) != length1) { PyErr_SetString(PyExc_TypeError, "feature1 and weight1 must be the same"); return NULL; } if(PySequence_Size(weight2) != length2) { PyErr_SetString(PyExc_TypeError, "feature2 and weight2 must be the same"); return NULL; } f1 = alloca(length1 * sizeof(double)); f2 = alloca(length2 * sizeof(double)); w1 = alloca(length1 * sizeof(double)); w2 = alloca(length2 * sizeof(double)); for(i = 0; i < length1; i ++) { item = PySequence_GetItem(feature1, i); if(!PyFloat_Check(item) && !PyInt_Check(item)) { Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "f1 should be a sequence of numbers"); return NULL; } f1[i] = PyFloat_AsDouble(item); Py_DECREF(item); item = PySequence_GetItem(weight1, i); if(!PyFloat_Check(item) && !PyInt_Check(item)) { Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "w1 should be a sequence of numbers"); return NULL; } w1[i] = PyFloat_AsDouble(item); Py_DECREF(item); } for(i = 0; i < length2; i ++) { item = PySequence_GetItem(feature2, i); if(!PyFloat_Check(item) && !PyInt_Check(item)) { Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "f2 should be a sequence of numbers"); return NULL; } f2[i] = PyFloat_AsDouble(item); Py_DECREF(item); item = PySequence_GetItem(weight2, i); if(!PyFloat_Check(item) && !PyInt_Check(item)) { Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "w2 should be a sequence of numbers"); return NULL; } w2[i] = PyFloat_AsDouble(item); Py_DECREF(item); } signature1.n = length1; signature1.Features = f1; signature1.Weights = w1; signature2.n = length2; signature2.Features = f2; signature2.Weights = w2; distance = emd(&signature1, &signature2, double_dist, 0, 0); return Py_BuildValue("d", distance); }
/* The gateway routine */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *c1, *w1, *c2, *w2, d, *pr; int n1, n2, ndims, nflow; feature_t *f1, *f2; flow_t *pf; if (nrhs < 4) mexErrMsgTxt("Usage: [dist,flow] = emd(Centroid1, Weight1, Centroid2, weight2, <domain_size>, <distance_type>)\n Non-zero domain size in any dimension means that dimension is periodic.\n"); c1 = mxGetPr(prhs[0]); w1 = mxGetPr(prhs[1]); c2 = mxGetPr(prhs[2]); w2 = mxGetPr(prhs[3]); if (nrhs > 5) { DISTANCE_TYPE_p = mxGetScalar(prhs[5]); } else DISTANCE_TYPE_p = 2; /* Default distance = L_2 (Euclidean) */ ndims = mxGetM(prhs[0]); /* Number of rows */ if (ndims != mxGetM(prhs[2])) mexErrMsgTxt("Both signatures should have the same dimension\n"); if (nrhs > 4) { if (ndims != mxGetM(prhs[4])) mexErrMsgTxt("Signature max size vector has wrong dimension\n"); Fmax.x = mxGetPr(prhs[4]); Fmax.size = ndims; } else { Fmax.allocate(ndims); /* Default non-periodic*/ for(int i=0; i<ndims; ++i) Fmax.x[i] = 0; } /* Signature lengths */ n1 = mxGetN(prhs[0]); n2 = mxGetN(prhs[2]); if (mxGetNumberOfElements(prhs[1]) != n1 || mxGetNumberOfElements(prhs[3]) != n2) mexErrMsgTxt("Length of weight vector != Length of signature vector"); if( n1 > MAX_SIG_SIZE || n2 > MAX_SIG_SIZE ) { char err[100] = "Signature size should be less than "; mexErrMsgTxt(strcat(err, mxArrayToString(mxCreateDoubleScalar( MAX_SIG_SIZE)))); } f1 = new feature_t[n1]; f2 = new feature_t[n2]; for (int i=0; i<n1; ++i) { f1[i].size = ndims; f1[i].x = c1 + ndims*i; // for (int j=0; j<ndims; ++j) // std::cout << f1[i].x[j] << ' '; // std::cout << std::endl << std::fflush; } for (int i=0; i<n2; ++i) { f2[i].size = ndims; f2[i].x = c2 + ndims*i; // for (int j=0; j<ndims; ++j) // std::cout << f1[i].x[j] << ' '; // std::cout << std::endl << std::fflush; } // Make sure all points are inside the domain for periodic distances for (int i=0; i<ndims; ++i) { if (Fmax.x[i]==0) continue; for (int j=0; j<n1; ++j) if(f1[j].x[i] < 0 || f1[j].x[i] > Fmax.x[i]) mexErrMsgTxt("Point outside domain in signature 1"); for (int j=0; j<n2; ++j) if(f2[j].x[i] < 0 || f2[j].x[i] > Fmax.x[i]) mexErrMsgTxt("Point outside domain in signature 2"); } signature_t s1 = {n1, f1, w1}, s2 = {n2, f2, w2}; if (nlhs>1) { pf = new flow_t[n1+n2-1]; d = emd(&s1, &s2, dist_p, pf, &nflow); plhs[1] = mxCreateDoubleMatrix(n1,n2,mxREAL); pr = mxGetPr(plhs[1]); for (int i=0; i<nflow; ++i) pr[ pf[i].from + pf[i].to * n1 ] = pf[i].amount; delete []pf; } else { d = emd(&s1, &s2, dist_p, NULL, NULL); } plhs[0] = mxCreateDoubleScalar(d); }
int main(int argc, char **argv) { #ifdef _OPENMP printf("ERKALE - EMD from Hel, OpenMP version, running on %i cores.\n",omp_get_max_threads()); #else printf("ERKALE - EMD from Hel, serial version.\n"); #endif print_copyright(); print_license(); #ifdef SVNRELEASE printf("At svn revision %s.\n\n",SVNREVISION); #endif print_hostname(); if(argc!=1 && argc!=2) { printf("Usage: $ %s (runfile)\n",argv[0]); return 0; } Timer t; // Parse settings Settings set; set.add_string("LoadChk","Checkpoint file to load density from","erkale.chk"); set.add_bool("DoEMD", "Perform calculation of isotropic EMD (moments of EMD, Compton profile)", true); set.add_double("EMDTol", "Tolerance for the numerical integration of the radial EMD",1e-8); set.add_string("EMDlm", "Which projection of the radial EMD to compute",""); set.add_bool("EMDAdapt", "Use adaptive grid to compute EMD?", true); set.add_string("EMDCube", "Calculate EMD on a cube? e.g. -10:.3:10 -5:.2:4 -2:.1:3", ""); set.add_string("EMDOrbitals", "Compute EMD of given orbitals, e.g. 1,2,4:6",""); set.add_string("Similarity", "Compute similarity measure to checkpoint",""); set.add_string("SimilarityGrid", "Grid to use for computing similarity integrals","500 77"); set.add_bool("SimilarityLM", "Seminumerical computation of similarity integrals?", false); set.add_int("SimilarityLmax", "Maximum angular momentum for seminumerical computation", 6); if(argc==2) set.parse(argv[1]); else printf("Using default settings.\n"); set.print(); // Get the tolerance double tol=set.get_double("EMDTol"); // Load checkpoint Checkpoint chkpt(set.get_string("LoadChk"),false); // Load basis set BasisSet basis; chkpt.read(basis); // Load density matrix arma::cx_mat P; arma::mat Pr, Pi; chkpt.read("P",Pr); if(chkpt.exist("P_im")) { chkpt.read("P_im",Pi); P=Pr*COMPLEX1 + Pi*COMPLEXI; } else P=Pr*COMPLEX1; // The projection to calculate int l=0, m=0; std::string lmstr=set.get_string("EMDlm"); if(lmstr.size()) { // Get l and m values std::vector<std::string> lmval=splitline(lmstr); if(lmval.size()!=2) throw std::runtime_error("Invalid specification of l and m values.\n"); l=readint(lmval[0]); m=readint(lmval[1]); } bool adaptive=set.get_bool("EMDAdapt"); // Compute orbital EMDs? if(set.get_string("EMDOrbitals")!="") { // Get orbitals std::vector<std::string> orbs=splitline(set.get_string("EMDOrbitals")); // Polarized calculation? bool restr; chkpt.read("Restricted",restr); if(restr!= (orbs.size()==1)) throw std::runtime_error("Invalid occupancies for spin alpha and beta!\n"); if(l!=0) printf("\nComputing the (%i %+i) projection of the orbital EMD.\n",l,m); for(size_t ispin=0;ispin<orbs.size();ispin++) { // Indices of orbitals to include. std::vector<size_t> idx=parse_range(orbs[ispin]); // Change into C++ indexing for(size_t i=0;i<idx.size();i++) idx[i]--; // Read orbitals arma::mat C; if(restr) chkpt.read("C",C); else { if(ispin==0) chkpt.read("Ca",C); else chkpt.read("Cb",C); } for(size_t i=0;i<idx.size();i++) { // Names of output files char emdname[80]; char momname[80]; char Jname[80]; char Jintname[80]; char suffix[80]; if(l==0) sprintf(suffix,".txt"); else sprintf(suffix,"_%i_%i.txt",l,m); if(restr) { sprintf(emdname,"emd-%i%s",(int) idx[i]+1,suffix); sprintf(momname,"moments-%i%s",(int) idx[i]+1,suffix); sprintf(Jname,"compton-%i%s",(int) idx[i]+1,suffix); sprintf(Jintname,"compton-interp-%i%s",(int) idx[i]+1,suffix); } else { if(ispin==0) { sprintf(emdname,"emd-a-%i%s",(int) idx[i]+1,suffix); sprintf(momname,"moments-a-%i%s",(int) idx[i]+1,suffix); sprintf(Jname,"compton-a-%i%s",(int) idx[i]+1,suffix); sprintf(Jintname,"compton-interp-a-%i%s",(int) idx[i]+1,suffix); } else { sprintf(emdname,"emd-b-%i%s",(int) idx[i]+1,suffix); sprintf(momname,"moments-b-%i%s",(int) idx[i]+1,suffix); sprintf(Jname,"compton-b-%i%s",(int) idx[i]+1,suffix); sprintf(Jintname,"compton-interp-b-%i%s",(int) idx[i]+1,suffix); } } // Generate dummy density matrix arma::cx_mat Pdum=C.col(idx[i])*arma::trans(C.col(idx[i]))*COMPLEX1; Timer temd; GaussianEMDEvaluator *poseval=new GaussianEMDEvaluator(basis,Pdum,l,std::abs(m)); GaussianEMDEvaluator *negeval; if(m!=0) negeval=new GaussianEMDEvaluator(basis,Pdum,l,-std::abs(m)); else negeval=NULL; EMD emd(poseval, negeval, 1, l, m); if(adaptive) { emd.initial_fill(); if(l==0 && m==0) emd.find_electrons(); emd.optimize_moments(true,tol); } else emd.fixed_fill(); emd.save(emdname); emd.moments(momname); if(l==0 && m==0) { emd.compton_profile(Jname); emd.compton_profile_interp(Jintname); } delete poseval; if(m!=0) delete negeval; } } } if(set.get_bool("DoEMD")) { t.print_time(); printf("\nCalculating EMD properties.\n"); printf("Please read and cite the reference:\n%s\n%s\n%s\n", \ "J. Lehtola, M. Hakala, J. Vaara and K. Hämäläinen", \ "Calculation of isotropic Compton profiles with Gaussian basis sets", \ "Phys. Chem. Chem. Phys. 13 (2011), pp. 5630 - 5641."); if(l!=0) printf("\nComputing the (%i %+i) projection of the EMD.\n",l,m); else printf("\nComputing the isotropic projection of the EMD.\n"); // Amount of electrons is int Nel; chkpt.read("Nel",Nel); // Construct EMD evaluators Timer temd; GaussianEMDEvaluator *poseval=new GaussianEMDEvaluator(basis,P,l,std::abs(m)); GaussianEMDEvaluator *negeval; if(m!=0) negeval=new GaussianEMDEvaluator(basis,P,l,-std::abs(m)); else negeval=NULL; temd.set(); EMD emd(poseval, negeval, Nel, l, m); if(adaptive) { emd.initial_fill(); if(l==0 && m==0) emd.find_electrons(); emd.optimize_moments(true,tol); } else emd.fixed_fill(); if(l==0 && m==0) { emd.save("emd.txt"); emd.moments("moments.txt"); emd.compton_profile("compton.txt"); emd.compton_profile_interp("compton-interp.txt"); } else { char fname[80]; sprintf(fname,"emd_%i_%i.txt",l,m); emd.save(fname); sprintf(fname,"moments_%i_%i.txt",l,m); emd.moments(fname); } if(l==0 && m==0) printf("Calculating isotropic EMD properties took %s.\n",temd.elapsed().c_str()); else printf("Calculating projected EMD properties took %s.\n",temd.elapsed().c_str()); delete poseval; if(m!=0) delete negeval; } // Do EMD on a cube? if(stricmp(set.get_string("EMDCube"),"")!=0) { t.print_time(); Timer temd; // Form grid in p space. std::vector<double> px, py, pz; parse_cube(set.get_string("EMDCube"),px,py,pz); // Calculate EMD on cube emd_cube(basis,P,px,py,pz); printf("Calculating EMD on a cube took %s.\n",temd.elapsed().c_str()); } // Compute similarity? if(stricmp(set.get_string("Similarity"),"")!=0) { // Load checkpoint Checkpoint simchk(set.get_string("Similarity"),false); // Get grid size std::vector<std::string> gridsize=splitline(set.get_string("SimilarityGrid")); if(gridsize.size()!=2) { throw std::runtime_error("Invalid grid size!\n"); } int nrad=readint(gridsize[0]); int lmax=readint(gridsize[1]); int radlmax=set.get_int("SimilarityLmax"); // Load basis set BasisSet simbas; simchk.read(simbas); // Load density matrix arma::mat simPr, simPi; arma::cx_mat simP; simchk.read("P",simPr); if(simchk.exist("P_im")) { simchk.read("P_im",simPi); simP=simPr*COMPLEX1 + simPi*COMPLEXI; } else simP=simPr*COMPLEX1; // Compute momentum density overlap arma::cube ovl; if(set.get_bool("SimilarityLM")) ovl=emd_overlap_semi(basis,P,simbas,simP,nrad,radlmax); else ovl=emd_overlap(basis,P,simbas,simP,nrad,lmax); // Amount of electrons int Nela, Nelb; chkpt.read("Nel", Nela); simchk.read("Nel", Nelb); // Shape function overlap arma::cube sh=emd_similarity(ovl,Nela,Nelb); sh.slice(0).save("similarity.dat",arma::raw_ascii); sh.slice(1).save("similarity_avg.dat",arma::raw_ascii); for(int s=0;s<2;s++) { if(s) { printf("%2s\t%9s\t%9s\t%9s\t%9s\t%9s\t%9s\t%9s\n","k","S0(AA)","S0(BB)","S0(AB)","I0(AA)","I0(BB)","I0(AB)","D0(AB)"); for(int k=-1;k<3;k++) // Vandenbussche don't include p^2 in the spherical average printf("%2i\t%e\t%e\t%e\t%e\t%e\t%e\t%e\n", k+1, sh(k+1,0,s), sh(k+1,1,s), sh(k+1,2,s), sh(k+1,3,s), sh(k+1,4,s), sh(k+1,5,s), sh(k+1,6,s)); } else { printf("%2s\t%9s\t%9s\t%9s\t%9s\t%9s\t%9s\t%9s\n","k","S(AA)","S(BB)","S(AB)","I(AA)","I(BB)","I(AB)","D(AB)"); for(int k=-1;k<3;k++) printf("%2i\t%e\t%e\t%e\t%e\t%e\t%e\t%e\n", k, sh(k+1,0,s), sh(k+1,1,s), sh(k+1,2,s), sh(k+1,3,s), sh(k+1,4,s), sh(k+1,5,s), sh(k+1,6,s)); } printf("\n"); } } return 0; }
int main(void) { gslpp::complex zi = gslpp::complex::i(); std::vector<double> sd = {10., 5., 1.}; std::vector<gslpp::complex> sc = {30. + zi, 2. + 3. * zi, 1. + 4. * zi}; gslpp::matrix<double> md1(2, 2); md1(0, 0) = 10.; md1(1, 0) = 20.; md1(0, 1) = 5.; md1(1, 1) = 1.; gslpp::matrix<double> md2(2, 2); md2(0, 0) = -3.; md2(1, 0) = 30.; md2(0, 1) = -5.; md2(1, 1) = 4.; gslpp::matrix<gslpp::complex> mc1(2, 2); mc1.assign(0, 0, 9. + 2 * zi); mc1.assign(1, 0, 19. - 4 * zi); mc1.assign(0, 1, 4. - 6 * zi); mc1.assign(1, 1, 3. + 2 * zi); gslpp::matrix<gslpp::complex> mc2(2, 2); mc2.assign(0, 0, -8. + 3 * zi); mc2.assign(1, 0, 11. - 5 * zi); mc2.assign(0, 1, 2. + 5 * zi); mc2.assign(1, 1, -3. + 4 * zi); gslpp::vector<double> vd1(2); gslpp::vector<double> vd2(2); vd1(0) = 14.; vd1(1) = -5; vd2(0) = -9.; vd2(1) = 3; gslpp::vector<gslpp::complex> vc1(2); gslpp::vector<gslpp::complex> vc2(2); vc1.assign(0, 4. - 2. * zi); vc1.assign(1, 6. - 8. * zi); vc2.assign(0, 5. + 3. * zi); vc2.assign(1, 4. - 12. * zi); Expanded<double> esd(sd); Expanded<gslpp::complex> esc(sc); std::vector<gslpp::matrix<double> > mdv = {md1, md2}; Expanded<gslpp::matrix<double> > emd(mdv); std::vector<gslpp::matrix<gslpp::complex> > mcv = {mc1, mc2}; Expanded<gslpp::matrix<gslpp::complex> > emc(mcv); std::vector<gslpp::vector<double> > vdv = {vd1, vd2}; Expanded<gslpp::vector<double> > evd(vdv); std::vector<gslpp::vector<gslpp::complex> > vcv = {vc1, vc2}; Expanded<gslpp::vector<gslpp::complex> > evc(vcv); // Print Input std::cout << std::endl; std::cout << "esd " << esd << std::endl; std::cout << "esc " << esc << std::endl; std::cout << "evd " << evd << std::endl; std::cout << "evc " << evc << std::endl; std::cout << "emd " << emd << std::endl; std::cout << "emc " << emc << std::endl; std::cout << "-------------" << std::endl; std::cout << "-sd " << -esd << std::endl; std::cout << "-sc " << -esc << std::endl; std::cout << "-vd " << -evd << std::endl; std::cout << "-vc " << -evc << std::endl; std::cout << "-md " << -emd << std::endl; std::cout << "-mc " << -emc << std::endl; std::cout << "-------------" << std::endl; // Expanded * Expanded std::cout << "sd*sd " << esd * esd << std::endl; std::cout << "sd*sc " << esd * esc << std::endl; std::cout << "sd*vd " << esd * evd << std::endl; std::cout << "sd*vc " << esd * evc << std::endl; std::cout << "sd*md " << esd * emd << std::endl; std::cout << "sd*mc " << esd * emc << std::endl; std::cout << "sc*sd " << esc * esd << std::endl; std::cout << "sc*sc " << esc * esc << std::endl; std::cout << "sc*vd " << esc * evd << std::endl; std::cout << "sc*vc " << esc * evc << std::endl; std::cout << "sc*md " << esc * emd << std::endl; std::cout << "sc*mc " << esc * emc << std::endl; std::cout << "vd*sd " << evd * esd << std::endl; std::cout << "vd*sc " << evd * esc << std::endl; std::cout << "vd*vd " << evd * evd << std::endl; std::cout << "vd*vc " << evd * evc << std::endl; std::cout << "vd*md " << evd * emd << std::endl; std::cout << "vd*mc " << evd * emc << std::endl; std::cout << "vc*sd " << evc * esd << std::endl; std::cout << "vc*sc " << evc * esc << std::endl; std::cout << "vc*vd " << evc * evd << std::endl; std::cout << "vc*vc " << evc * evc << std::endl; std::cout << "vc*md " << evc * emd << std::endl; std::cout << "vc*mc " << evc * emc << std::endl; std::cout << "md*sd " << emd * esd << std::endl; std::cout << "md*sc " << emd * esc << std::endl; std::cout << "md*vd " << emd * evd << std::endl; std::cout << "md*vc " << emd * evc << std::endl; std::cout << "md*md " << emd * emd << std::endl; std::cout << "md*mc " << emd * emc << std::endl; std::cout << "mc*sd " << emc * esd << std::endl; std::cout << "mc*sc " << emc * esc << std::endl; std::cout << "mc*vd " << emc * evd << std::endl; std::cout << "mc*vc " << emc * evc << std::endl; std::cout << "mc*md " << emc * emd << std::endl; std::cout << "mc*mc " << emc * emc << std::endl; std::cout << "-------------" << std::endl; // Expanded + Expanded std::cout << "sd + sd " << esd + esd << std::endl; std::cout << "sd + sc " << esd + esc << std::endl; std::cout << "sc + sd " << esc + esd << std::endl; std::cout << "sc + sc " << esc + esc << std::endl; std::cout << "vd + vd " << evd + evd << std::endl; std::cout << "vd + vc " << evd + evc << std::endl; std::cout << "vc + vd " << evc + evd << std::endl; std::cout << "vc + vc " << evc + evc << std::endl; std::cout << "md + md " << emd + emd << std::endl; std::cout << "md + mc " << emd + emc << std::endl; std::cout << "mc + md " << emc + emd << std::endl; std::cout << "mc + mc " << emc + emc << std::endl; // std::cout << "-------------" << std::endl; // Expanded - Expanded std::cout << "sd - sd " << esd - esd << std::endl; std::cout << "sd - sc " << esd - esc << std::endl; std::cout << "sc - sd " << esc - esd << std::endl; std::cout << "sc - sc " << esc - esc << std::endl; std::cout << "vd - vd " << evd - evd << std::endl; std::cout << "vd - vc " << evd - evc << std::endl; std::cout << "vc - vd " << evc - evd << std::endl; std::cout << "vc - vc " << evc - evc << std::endl; std::cout << "md - md " << emd - emd << std::endl; std::cout << "md - mc " << emd - emc << std::endl; std::cout << "mc - md " << emc - emd << std::endl; std::cout << "mc - mc " << emc - emc << std::endl; std::cout << "-------------" << std::endl; // Expanded * UnExpanded std::cout << "esd*5 = " << esd * 5. << std::endl; std::cout << "esd*(4-2I) = " << esd * (4. - 2. * zi) << std::endl; std::cout << "esd*vd1 = " << esd * vd1 << std::endl; std::cout << "esd*vc1 = " << esd * vc1 << std::endl; std::cout << "esd*md1 = " << esd * md1 << std::endl; std::cout << "esd*mc1 = " << esd * mc1 << std::endl; // std::cout << "esc*5 = " << esc * 5. << std::endl; std::cout << "esc*(4-2I) = " << esc * (4. - 2. * zi) << std::endl; std::cout << "esc*vd1 = " << esc * vd1 << std::endl; std::cout << "esc*vc1 = " << esc * vc1 << std::endl; std::cout << "esc*md1 = " << esc * md1 << std::endl; std::cout << "esc*mc1 = " << esc * mc1 << std::endl; // std::cout << "evd*5 = " << evd * 5. << std::endl; std::cout << "evd*(4-2I) = " << evd * (4. - 2. * zi) << std::endl; std::cout << "evd*vd1 = " << evd * vd1 << std::endl; std::cout << "evd*vc1 = " << evd * vc1 << std::endl; std::cout << "evd*md1 = " << evd * md1 << std::endl; std::cout << "evd*mc1 = " << evd * mc1 << std::endl; // std::cout << "evc*5 = " << evc * 5. << std::endl; std::cout << "evc*(4-2I) = " << evc * (4. - 2. * zi) << std::endl; std::cout << "evc*vd1 = " << evc * vd1 << std::endl; std::cout << "evc*vc1 = " << evc * vc1 << std::endl; std::cout << "evc*md1 = " << evc * md1 << std::endl; std::cout << "evc*mc1 = " << evc * mc1 << std::endl; // std::cout << "emd*5 = " << emd * 5. << std::endl; std::cout << "emd*(4-2I) = " << emd * (4. - 2. * zi) << std::endl; std::cout << "emd*vd1 = " << emd * vd1 << std::endl; std::cout << "emd*vc1 = " << emd * vc1 << std::endl; std::cout << "emd*md1 = " << emd * md1 << std::endl; std::cout << "emd*mc1 = " << emd * mc1 << std::endl; // std::cout << "emc*5 = " << emc * 5. << std::endl; std::cout << "emc*(4-2I) = " << emc * (4. - 2. * zi) << std::endl; std::cout << "emc*vd1 = " << emc * vd1 << std::endl; std::cout << "emc*vc1 = " << emc * vc1 << std::endl; std::cout << "emc*md1 = " << emc * md1 << std::endl; std::cout << "emc*mc1 = " << emc * mc1 << std::endl; std::cout << "-------------" << std::endl; // // Expanded / UnExpanded-Scalar std::cout << "esd/5 = " << esd / 5. << std::endl; std::cout << "esd/(4-2I) = " << esd / (4. - 2. * zi) << std::endl; std::cout << "esc/5 = " << esc / 5. << std::endl; std::cout << "esc/(4-2I) = " << esc / (4. - 2. * zi) << std::endl; std::cout << "evd/5 = " << evd / 5. << std::endl; std::cout << "evd/(4-2I) = " << evd / (4. - 2. * zi) << std::endl; std::cout << "evc/5 = " << evc / 5. << std::endl; std::cout << "evc/(4-2I) = " << evc / (4. - 2. * zi) << std::endl; std::cout << "emd/5 = " << emd / 5. << std::endl; std::cout << "emd/(4-2I) = " << emd / (4. - 2. * zi) << std::endl; std::cout << "emc/5 = " << emc / 5. << std::endl; std::cout << "emc/(4-2I) = " << emc / (4. - 2. * zi) << std::endl; std::cout << "-------------" << std::endl; // UnExpanded * Expanded easy-check (must be 0) std::cout << "zero1 = " << 5. * esd - esd * 5. << std::endl; std::cout << "zero1 = " << 5. * esc - esc * 5. << std::endl; std::cout << "zero1 = " << 5. * evd - evd * 5. << std::endl; std::cout << "zero1 = " << 5. * evc - evc * 5. << std::endl; std::cout << "zero1 = " << 5. * emd - emd * 5. << std::endl; std::cout << "zero1 =" << 5. * emc - emc * 5. << std::endl; // std::cout << "zero2 = " << (4 - 2 * zi) * esd - esd * (4 - 2 * zi) << std::endl; std::cout << "zero2 = " << (4 - 2 * zi) * esc - esc * (4 - 2 * zi) << std::endl; std::cout << "zero2 = " << (4 - 2 * zi) * evd - evd * (4 - 2 * zi) << std::endl; std::cout << "zero2 = " << (4 - 2 * zi) * evc - evc * (4 - 2 * zi) << std::endl; std::cout << "zero2 = " << (4 - 2 * zi) * emd - emd * (4 - 2 * zi) << std::endl; std::cout << "zero2 = " << (4 - 2 * zi) * emc - emc * (4 - 2 * zi) << std::endl; std::cout << "zero3 = " << vd1 * esd - esd * vd1 << std::endl; std::cout << "zero3 = " << vd1 * esc - esc * vd1 << std::endl; std::cout << "zero3 = " << vd1 * evd - evd * vd1 << std::endl; std::cout << "zero3 = " << vd1 * evc - evc * vd1 << std::endl; std::cout << "zero3 = " << vd1 * emd - emd.transpose() * vd1 << std::endl; std::cout << "zero3 = " << vd1 * emc - emc.transpose() * vd1 << std::endl; // std::cout << "zero4 = " << vc1 * esd - esd * vc1 << std::endl; std::cout << "zero4 = " << vc1 * esc - esc * vc1 << std::endl; std::cout << "zero4 = " << vc1 * evd - evd * vc1 << std::endl; std::cout << "zero4 = " << vc1 * evc - evc * vc1 << std::endl; std::cout << "zero4 = " << vc1 * emd - emd.transpose() * vc1 << std::endl; std::cout << "zero4 = " << vc1 * emc - emc.transpose() * vc1 << std::endl; // std::cout << "zero5 = " << md1 * esd - esd * md1 << std::endl; std::cout << "zero5 = " << md1 * esc - esc * md1 << std::endl; std::cout << "zero5 = " << md1 * evd - evd * md1.transpose() << std::endl; std::cout << "zero5 = " << md1 * evc - evc * md1.transpose() << std::endl; std::cout << "zero5 = " << md1 * emd - (emd.transpose() * md1.transpose()).transpose() << std::endl; std::cout << "zero5 = " << md1 * emc - (emc.transpose() * md1.transpose()).transpose() << std::endl; // std::cout << "zero6 = " << mc1 * esd - esd * mc1 << std::endl; std::cout << "zero6 = " << mc1 * esc - esc * mc1 << std::endl; std::cout << "zero6 = " << mc1 * evd - evd * mc1.transpose() << std::endl; std::cout << "zero6 = " << mc1 * evc - evc * mc1.transpose() << std::endl; std::cout << "zero6 = " << mc1 * emd - (emd.transpose() * mc1.transpose()).transpose() << std::endl; std::cout << "zero6 = " << mc1 * emc - (emc.transpose() * mc1.transpose()).transpose() << std::endl; std::cout << "true = " << (esd == esd) << std::endl; std::cout << "true = " << (esc == esc) << std::endl; std::cout << "true = " << (evd == evd) << std::endl; std::cout << "true = " << (evc == evc) << std::endl; std::cout << "true = " << (emd == emd) << std::endl; std::cout << "true = " << (emc == emc) << std::endl; std::cout << "false = " << (esd == esd * esd) << std::endl; std::cout << "false = " << (esc == esc * esc) << std::endl; std::cout << "false = " << (evd == 5 * evd) << std::endl; std::cout << "false = " << (evc == 7 * evc) << std::endl; std::cout << "false = " << (emd == emd * emd) << std::endl; std::cout << "false = " << (emc == emc * emc) << std::endl; Expanded<double> esd1(sd, 2); std::vector<double> sdx = {10., 5., 1.,-7}; Expanded<double> esd2(sdx, 1); std::cout << "esd1 * esd2 = " << esd1*esd2 << std::endl; std::cout << "esd1 + esd2 = " << esd1+esd2 << std::endl; std::cout << "esd1 - esd2 = " << esd1-esd2 << std::endl; std::vector<double> q1={1.,0.}; std::vector<double> q2={5.,7.}; std::vector<std::vector<double> > v1 = {q1,q2}; std::vector<double> w1={3.,4.}; std::vector<double> w2={8.}; std::vector<std::vector<double> > v2 = {w1,w2}; Expanded<double> ev1(v1, 1, 0); Expanded<double> ev2(v2); std::cout << "ev1 = " << ev1 << std::endl; std::cout << "ev2 = " << ev2 << std::endl; std::cout << "ev1 * ev2 = " << ev1*ev2 << std::endl; std::cout << "ev1 + ev2 = " << ev1+ev2 << std::endl; std::cout << "1/ev1 = " << ev1.inverse() << std::endl; std::cout << "1/ev2 = " << ev2.inverse() << std::endl; complex ii(0, 1); std::vector<complex> r1={1.+2.*ii, 3.+4.*ii}; std::vector<complex> r2={5. + 6.*ii, 7.+8.*ii, 9.+10.*ii}; std::vector<std::vector<complex> > vv1 = {r1,r2}; Expanded<complex> evv1(vv1, 1, 1); std::cout << "evv1 = " << evv1 << std::endl; std::cout << "1/evv1 = " << evv1.inverse() << std::endl; std::cout << "ev1/evv1 = " << ev1/evv1 << std::endl; std::cout << "evv1/ev1 = " << evv1/ev1 << std::endl; Expanded<complex> tmp(evv1.truncate(std::vector<int>(2,2),2)); std::cout << "evv1 trunc at (std::vector<int>(2,2),2)" << tmp << std::endl; std::cout << "evv1 series = " << evv1.Series(std::vector<int>(2,2),2) << std::endl; Expanded<double> pp; return (0); }