/* gcc eoglassplot.c -o eoglassplot.x -L/usr/X11R6/lib -lplot -lXaw -lXmu -lXt -lSM -lICE -lXext -lX11 -lm */ #include #include #include #include #include #include /*#include*/ #include #include #define min(A,B) ((A) < (B)) ? (A) : (B) #define MAXVERTEX 10000 /* maximal number of vertices in a graph */ #define MAXLINK 20 /* maximal number of links for a vertex */ #define LENGTH 65535 #define C2 32767 #define MAXNEIGHBOR 3 /* maximal number of neighbors in hyperlink */ #define Pspin 2 typedef unsigned short int Natural; struct Vertex { short int spin; /* value of vertex */ Natural links; /* # of connections */ Natural rank; /* position in fitness rank list */ Natural fitness; /* fitness of vertex */ short int *bondcut[MAXLINK]; /* pointer to cutlist, which is +|bond| if bond is satisfied, -|bond| if bond is cut */ struct Vertex *neighbor[MAXLINK][MAXNEIGHBOR]; /* nearest neighbor connectivity vector of i-th edge to j neighbors */ Natural index; /* vertex' own index label, makes only sense for array */ int updatetime; /* time of last update */ }; /* RNG */ double rng1(long int); /* Input and Output */ void initialize(int *,float *,float *,int *,int *,int *); void output(Natural,float,float,int,int,int,int,int,int); /* EO update */ void flip(struct Vertex *, int *); /* making graphs: */ int initrandomgraph(Natural,float,int); int initlattice(int,int,Natural *); int intpow(int, int); int neigh(int, int, int, int , int); /* fixing bonds */ int initbonds(int, float , int); void initspins(Natural, int, int, int *, int *); void initfitness(Natural); /* tau-distribution */ void inittau(double,double); Natural taupick(void); /* rank-ordering */ void initrank(Natural); void rerank(struct Vertex *, Natural); struct Vertex *findvertex(Natural); /************* Plot Stuff *****************************/ void init_keyboard(void); void close_keyboard(void); int kbhit(void); int readch(void); void draw(struct Vertex *,int,int,int,float); void plot(int,float,float,int,int,int,float,int); void initplotwindow(void); void closeplotwindow(void); static struct termios initial_settings, new_settings; static int peek_character = -1; static int pl_handle; const float pl_scale = 100.0; /************* END Plot Stuff *****************************/ struct Vertex V[MAXVERTEX]; short int cutlist[MAXLINK*MAXVERTEX]; struct Vertex *fitlist[MAXLINK][MAXVERTEX]; Natural len[MAXLINK]; Natural minfitness; Natural pdf[LENGTH]; short int bondlist[MAXLINK*MAXVERTEX]; main(void){ int L,d,numlines,timescale; int instance,maxinstance,run,maxrun,maxiter,t,mintime; int seed,seed1,seed2,balance,energy,energy0,minenergy,magnit; struct Vertex *v; Natural nv,rank; float tau,f,dx,p; int plotcounter=0; rng1((unsigned int)getpid()); /* Create a random seed from system if seeds = 0 */ d = 2; initialize(&L,&f,&tau,&maxiter,&seed1,&seed2); numlines = initlattice(L,d,&nv); inittau(tau,nv); balance = initbonds(numlines,f,seed1); initspins(nv,numlines,seed2,&magnit,&energy); energy0 = energy; minenergy = energy; initfitness(nv); initrank(nv); initplotwindow(); dx = pl_scale/(float)L; timescale = 1+LENGTH/maxiter;/*set fade-time for plot*/ for(t=0; tupdatetime = t; /* remember update-time (age) of variable */ flip(v,&energy); if(plotcounter++ > L){ /* plot only every L-th update */ plotcounter = 0; plot(L,f,tau,t,energy,minenergy,dx,timescale); } if(energy < minenergy){ /* remember best-found energy */ minenergy = energy; mintime = t; } } output(nv,f,tau,numlines,energy0,energy,minenergy,maxiter,mintime); closeplotwindow(); } /********** END of MAIN *** *****************************/ /******************************************************************/ /* */ /* Input and output */ /* */ /******************************************************************/ /* */ void initialize(int *L, float *f, float *tau, int *maxiter, int *seed1, int *seed2){ printf("*************************************************************\n"); printf("* *\n"); printf("* Extremal Optimization *\n"); printf("* for a *\n"); printf("* d=2 Ising Spin-Glass *\n"); printf("* (with periodic BC) *\n"); printf("* *\n"); printf("* *\n"); printf("* Stefan Boettcher May 1, 2002 *\n"); printf("* www.physics.emory.edu/faculty/boettcher/ *\n"); printf("*************************************************************\n"); printf("\n"); printf("Color Scheme: Black=0 cut bonds\n"); printf(" Blue =1 cut bonds\n"); printf(" Green=2 cut bonds\n"); printf(" Red >2 cut bonds\n"); printf("Fade-to-white: Indicates time since last update!\n"); printf("\n"); printf("______________BEGIN Input_________________________________\n \n"); printf("Lattice Length: L [<100] = "); scanf("%d",L); printf("Bond Balance (prob. p of +1, 1-p of -1 bonds): p+ = "); scanf("%f",f); printf("EO-parameter: tau = "); scanf("%f",tau); printf("Update Steps per Run: T = "); scanf("%d",maxiter); printf("Random Seeds: Seed(Instance) = "); scanf("%d",seed1); printf("Random Seeds: Seed(Run) = "); scanf("%d",seed2); printf("_____________END Input____________________________________\n"); } void output(Natural nv,float f,float tau, int numlines, int energy0, int energy, int minenergy, int t, int mintime){ printf("\n\nFinal EO result (after %d updates): \n",t); printf("========================================= \n"); printf("Vertices = %d , Edges = %d , p+ = %4.2f, tau = %4.2f \n\n",nv,numlines,f,tau); printf("Initial Cuts = %d , Final Cuts = %d ",energy0,energy); printf("BEST CUTS = %d , obtained at update step %d \n",minenergy,mintime); printf("*************************************************************\n"); } /********** END of Input/Output *****************************/ /******************************************************************/ /* */ /* EO update procedure */ /* */ /******************************************************************/ /* "flip" inverts the state of the submitted vertex v and updates the system energy. Then, it recalculates fitnesses and ranks for the effected vertices, and inverts the state of the effected bonds in cutlist INDIRECTLY via the pointers v.bondcut. */ void flip(struct Vertex *v, int *energy){ struct Vertex *nextV; Natural i,j,sign; v->spin *= -1; *energy += (v->links)-2*(v->fitness); rerank(v,v->links - v->fitness); for(i = 0; i<(v->links); i++){ *v->bondcut[i] *= -1; sign = *v->bondcut[i]; for(j = 0; j<(Pspin-1); j++){ nextV = v->neighbor[i][j]; rerank(nextV,nextV->fitness - sign); } } } /********** END EO updates *****************************/ /******************************************************************/ /* */ /* Various ways of making graphs */ /* */ /******************************************************************/ /* "initrandomgraph" makes an Erdos-Renyi-type Random Graph with n vertices; any pair of vertices is connected with probability p. The rng1 is initiated with "seed". The result is an array of struct Vertex. The procedure returns the number of edges in the graph. */ int initrandomgraph(Natural nv, float p, int seed){ int numlines = 0; Natural i,j; rng1(seed); for(i = 0; i0 !). */ void initfitness(Natural nv){ Natural n,i; for(n = 0; n0 and len[i] = 0 f.a. i>minfitness. */ void initrank(Natural nv){ Natural n,i; minfitness = 0; for(i = 0; i minfitness) minfitness = i; V[n].rank = len[i]; fitlist[i][len[i]++] = &V[n]; } } /* rerank: removes vertex v out of the "entry" position in its current fitlist * "old", moves the last vertex in fitlist[old] from position len[old] to the * "entry" position (to keep fitlist[old] compact!), then makes v the new, * last element in fitlist[new]. * Also, "minfitness" may have to be adjusted, up or down. */ void rerank(struct Vertex *v, Natural new){ Natural entry,old; old = v->fitness; /* no need to change if old=new */ if(old == new) return; entry = v->rank; /* move top-of-list into emptied spot, decrement list */ fitlist[old][entry] = fitlist[old][--len[old]]; /* update location key for moved item */ fitlist[old][entry]->rank = entry; v->fitness = new; /* add new entry on top of new list */ fitlist[new][len[new]] = v; /* update location key for entered item */ v->rank = len[new]++; /* reset minfitness to worst non-zero fitlist */ if(new > minfitness) minfitness = new; else while(len[minfitness] == 0) minfitness--; } /* findvertex: returns the pointer to the k-th ranked vertex. * If the k-th ranked vertex is to be chosen, we look through the fitlist * starting with fitlist[minfitness] in order of increasing fitness until the * fitlist "i" which contains the k-th worst-fit vertex is located. One element * of fitlist[i] is selected at random. This procedure approximates the * distribution well enough. */ struct Vertex *findvertex(Natural rank){ Natural i = minfitness; while(rank > len[i]) rank -= len[i--]; return(fitlist[i][(Natural) (len[i]*rng1(0))]); } /*********************** END fitlist ranking ***********************/ /******************************************************************/ /* */ /* Random Number Generator */ /* */ /* This one does the multiplicative LCG of Lewis, Goodman and */ /* Miller, using the Schrage modulus trick */ /* */ /******************************************************************/ double rng1(long int n){ static const long int ia = 16807; static const long int RMAX = 2147483647; static const double conv1 = .4656612875245797e-9; /* =1/RMAX */ static const long int iq = 127773; static const long int ir = 2836; static long int irandom; long int l; if(n > 0) irandom = n; l = irandom/iq; irandom = (irandom-iq*l)*ia - ir*l; if(irandom < 0) irandom = irandom+RMAX; return(conv1*irandom); } /************ END Random Number Generator ***********************/ /* set up a plotter window */ /* an animation with double buffering */ void initplotwindow(){ pl_parampl ("BITMAPSIZE", "700x700"); pl_parampl ("VANISH_ON_DELETE", "yes"); pl_parampl ("USE_DOUBLE_BUFFERING", "fast"); pl_handle = pl_newpl ("X", stdin, stdout, stderr); pl_selectpl (pl_handle); pl_openpl (); pl_fspace (0.0,-0.2*pl_scale,pl_scale,pl_scale); pl_flinewidth (0.001*pl_scale); /* run over-ridden keyboard ala' DOS */ /*init_keyboard();*/ } void plot(int L,float f,float tau,int t,int energy,int minenergy,float dx,int timescale){ char sbuff[10]; int n,lx,ly,color1,color2,color0; float x,y,x1,y1; pl_erase(); pl_fmove(0.0,-0.15*pl_scale); pl_label("L = "); pl_fmove(0.04*pl_scale,-0.15*pl_scale); pl_label(gcvt(L,3,sbuff)); pl_fmove(0.09*pl_scale,-0.15*pl_scale); pl_label("tau = "); pl_fmove(0.14*pl_scale,-0.15*pl_scale); pl_label(gcvt(tau,3,sbuff)); pl_fmove(0.21*pl_scale,-0.15*pl_scale); pl_label("p+ = "); pl_fmove(0.27*pl_scale,-0.15*pl_scale); pl_label(gcvt(f,3,sbuff)); pl_fmove(0.36*pl_scale,-0.15*pl_scale); pl_label("E = "); pl_fmove(0.4*pl_scale,-0.15*pl_scale); pl_label(gcvt(energy,6,sbuff)); pl_fmove(0.5*pl_scale,-0.15*pl_scale); pl_label("E_0 = "); pl_fmove(0.58*pl_scale,-0.15*pl_scale); pl_label(gcvt(minenergy,6,sbuff)); pl_fmove(0.75*pl_scale,-0.15*pl_scale); pl_label("t = "); pl_fmove(0.8*pl_scale,-0.15*pl_scale); pl_label(gcvt(t,8,sbuff)); /* pl_filltype(0); pl_fbox(0.0,0.0,pl_scale,pl_scale); */ y1 = 0; n = 0; for(ly=0; ly