Example #1
0
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);
}
Example #2
0
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;
}
Example #3
0
//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;
}
Example #5
0
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;
}
Example #6
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);
}
Example #7
0
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);
}
Example #8
0
/* 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);
} 
Example #9
0
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;
}
Example #10
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);
}