/* * File: cgr7.c * Last Modified : Thu Sep 19 12:14:15 2007 * * Purpose: * Compute the entanglement of a mixed state by optimization * decompose the state with an optimal Unitary matrix * that minimizes entanglement * * Add steep_go,sumM,Etheta, and modified algorithm by ryu * Seunghwa Ryu, shryu@stanford, Wei Cai, caiwei@stanford.edu * * based on Matlab codes: entangleM & cgr7 (hybrid sd & cgr algorithm) * * Sponsored by Lawrence Livermore National Laboratory (LLNL) * */ #include "util.h" double entanglement(int N, complex u[NMAX], int na) { /* entanglement of a pure state u */ complex rhoAB[NMAX][NMAX], rhoA[NMAX][NMAX], lambda[NMAX]; double E, lam[NMAX]; int i, j, k, n,nb; for(i=0;i0) E -= lam[i]*log2(lam[i]); return E; } double unitarydecompose(int N, complex rho[NMAX][NMAX], complex U[NMAX][NMAX], int na, int M) { /* entanglement of a mixed state rho measured by unitary decomposition U */ complex V[NMAX][NMAX], C[NMAX][NMAX], W[NMAX][NMAX]; complex lambda[NMAX], w[NMAX]; double E, p, psqrt, Esub[NMAX], psub[NMAX]; int i, j, nb; complex Vtemp[NMAX][NMAX]; eigvec(N,rho,V,lambda); /* to be consistent with matlab code */ reorder_eigvec(N,V,lambda); clearM(C); for(i=0;i0) { psqrt = sqrt(p); for(j=0;j0) { psqrt = sqrt(p); for(j=0;j0) Esub[i] -= lam[j]*log2(lam[j]); } psub[i] = p; } else { psub[i] = 0; Esub[i] = 0; } E += psub[i] * Esub[i]; } clearM(DS); for(i=0;i0) pre1[j] = -log2(exp(1)*L[i][j]); else pre1[j] = 0; // printf("pre1 ---\n"); /* yes */ // printV(stdout,N,pre1,6); clearM(term2); for(t=0;t1) { sumtmp=sumM(G0,M); sumtmp1=sumM(H,M); if (sumtmp!=0) { // matrixop('N','N',N,1.0,ZERO,ZERO,sumtmp1/sumtmp,H0); //H=H+H0*sumtmp1/sumtmp; matrixop('N','N',M,sumtmp1/sumtmp,EYE,H0,1.0,H); for(j=0;j1e5) { info[1]=info1[1]; info[0]=info1[0]; for (i=0;iE && curstep>1) // { // printf("convergence reached by too small gradient(%e) \n",dtheta); // printf("convergence reached at step = %d\n",curstep); // break; // } dtheta=info[0]; E=info[1]; //update U=U*Ur*diag(exp(I*D*dtheta)) for(i=0;i10) { dE=fabs(E-data[curstep-2]); Hold[(curstep%10)]=dE; } if (curstep>20) { mean=0; for (i=0;i<10;i++) mean=mean+Hold[i]; mean=mean/10.0; // printf("mean %e tol %e\n",mean,tol); if (mean2) break; if(fabs(dtheta)maxstep) E=10; // printf("Echeck = %f curstep = %7d E = %.12e dE = %.5e dtheta = %.5e R = %.5f t = %.6f\n",aa, curstep,E,dE,dtheta,R,t); return E; } int main(int argc, void * argv[]) { unsigned int seed,st1,st2; int M, N, i, N0,maxstep, na, k, Ndm; complex rho[NMAX][NMAX]; /* density matrix */ complex U[NMAX][NMAX]; /* unitary matrix */ complex dEdU[NMAX][NMAX]; complex b[NMAX]; /* complex vector */ double E, delta,tol,tol1; double Emin,R,t; double *Estack; FILE *fp; struct timeval mytime; gettimeofday(&mytime,NULL); /* printf("%ld:%ld\n",mytime.tv_sec, mytime.tv_usec); */ st1=mytime.tv_sec; st2=mytime.tv_usec; /* disclaimer(); */ /* default values: their meaning is explained below */ tol=1e-15; tol1=1e-15; N0=5; N=8; na=2; Ndm=128; M=NMAX; /* M is the dimension of the decomposition unitary matrix, you need to modify NMAX in util.h if you want to change this number */ /* hard coded settings for conjugate gradient relaxation */ delta = 0.5; maxstep = 100000; /* specifies random seed for random number generator */ if(argc==1) { /* if there is no argment in the command line then print out usage information */ printf("Usage: (also see README.txt)\n"); printf("%s [seed=0] [tol=1e-15] [tol1=1e-15] [N0=5] [N=8] [na=2] [Ndm=128]\n",argv[0]); return 0; } else { /* there is at least one argument in the command line then use the first number as random seed -- if it is non-zero */ sscanf(argv[1],"%ud",&seed); if (seed==0) { /* use time as random seed */ st1=st1*1000000+st2; srand48(st1); } else { /* use first value in command line as random seed */ srand48(seed); } } /* specifies tol - convergence criteria (absolute value of entanglement) */ if(argc>2) { sscanf(argv[2],"%lf",&tol); } /* specifies tol1 - convergence criteria (residual gradient) */ if(argc>3) { sscanf(argv[3],"%lf",&tol1); } /* specifies N0 - number of local minimum searches */ if(argc>4) { sscanf(argv[4],"%d",&N0); } /* specifies N = na*nb - dimension of Hilbert space of two partite system */ if(argc>5) { sscanf(argv[5],"%d",&N); } /* specifies na - dimension of Hilbert space qudit a (default = 2) */ if(argc>6) { sscanf(argv[6],"%d",&na); } /* specifies Ndm - number of density matrices to be analyzed in this run */ if(argc>7) { sscanf(argv[7],"%d",&Ndm); } Estack = malloc(N0*sizeof(double)); /* print to matlab input file */ /* randDM(N,rho); randUM_PRA(M,U); fp = fopen("../matlab/entangleM1/rhoU0.m","w"); fprintf(fp,"rho = [\n"); printM(fp,N,rho,16); fprintf(fp,"];\n"); fprintf(fp,"U = [\n"); printM(fp,M,U ,16); fprintf(fp,"];\n"); fclose(fp); */ for (k=0;k