/* perform metropolis iteration exchanging double edges. Output the temperature */ double dbl_metrop_switches(Network **RN,int nover,int nlimit,double init_t,int real_vec13[14],int rand_vec13[14]) { double t=init_t; register int w,k,num_at_t; int s1,t1,s2,t2; int i,j; int sub13[14]; int add13[14]; double E1,E2,dE; int make_change; int tries; //number of tries to find proper pair of edges to exchange int twin_i=-1,twin_j=-1; w=0; if ((w%1000)==0 && GNRL_ST.out_metrop_mat_flag) fprintf(GNRL_ST.mat_metrop_fp,"\nBeginning double switches\n"); k=0,w=0,num_at_t=0; t=init_t; for (i=1;i<14;i++) { sub13[i]=0; add13[i]=0; } E1=energy(real_vec13,rand_vec13); while ((w<nover)&&(E1>GNRL_ST.e_thresh)) { w++; num_at_t++; if ((k>nlimit)||(num_at_t>nlimit)) { num_at_t=0; k=0; t *= TFACTR; // lower temperature } w++; // random edges to choose : until finding a proper pair of edges which can be candidates // should not choose the same edge or the twin one (of the double) // try this for 100 times if not getting good candidate then probably // there is a only one double edge in the netwprk for(i=get_rand((*RN)->e_dbl_num),j=get_rand((*RN)->e_dbl_num),tries=0; ((j==i) || (j==twin_i)) && (tries<100) ;i=get_rand((*RN)->e_dbl_num),j=get_rand((*RN)->e_dbl_num),tries++); //the way out of deadlock if(tries==100 || (*RN)->e_dbl_num==2) break; //this is needed to know if the twin is i-1 or i+1 if(i & 0x1) twin_i=i+1; else twin_i=i-1; if(j & 0x1) twin_j=j+1; else twin_j=j-1; s1=(*RN)->e_arr_dbl[i].s; t1=(*RN)->e_arr_dbl[i].t; s2=(*RN)->e_arr_dbl[j].s; t2=(*RN)->e_arr_dbl[j].t; //check : 1.that there are no crossing edges in the network, // 2.there are no common vertices of these 2 edges //if hasnt passed the check then have to find other pair to switch if (( !( MatGet((*RN)->mat,s1,t2) || MatGet((*RN)->mat,s2,t1) || MatGet((*RN)->mat,t1,s2)|| MatGet((*RN)->mat,t2,s1)) && (s1!=t2) &&(s2!=t1) && (s1!=s2) && (t1!=t2)) ) { // make fill13_dbl - new function fill_13_dbl((*RN),s1,t1,s2,t2,sub13,add13); update(rand_vec13,sub13,add13,1); E2=energy(real_vec13,rand_vec13); dE=E2-E1; // printf("k=%d E=%lf\n",k,E1); make_change=metrop(dE,t); if (make_change) { if(DEBUG_LEVEL==1 && GNRL_ST.out_log_flag) { fprintf(GNRL_ST.log_fp,"switch #%d: (%d %d) (%d %d)\n", k,s1,t1,s2,t2); fprintf(GNRL_ST.log_fp,"i: %d, twin i %d , j: %d twin j : %d\n", i,twin_i,j,twin_j); } if ((w%1000)==0 && GNRL_ST.out_metrop_mat_flag) { fprintf(GNRL_ST.mat_metrop_fp,"%lf\n",E1); printf("success=%d k=%d E1=%lf T=%lf\n",k,w,E1,t); } E1=E2; if ((w%1000)==0 && GNRL_ST.out_metrop_mat_flag) printf("success=%d k=%d E1=%lf T=%lf\n",k,w,E1,t); //make the switch //update edges array (*RN)->e_arr_dbl[i].t=t2; (*RN)->e_arr_dbl[twin_i].s=t2; (*RN)->e_arr_dbl[j].t=t1; (*RN)->e_arr_dbl[twin_j].s=t1; if(DEBUG_LEVEL==1 && GNRL_ST.out_log_flag) { fprintf(GNRL_ST.log_fp,"(%d %d) (%d %d) (%d %d) (%d %d)\n", (*RN)->e_arr_dbl[i].s,(*RN)->e_arr_dbl[i].t, (*RN)->e_arr_dbl[twin_i].s,(*RN)->e_arr_dbl[twin_i].t, (*RN)->e_arr_dbl[j].s,(*RN)->e_arr_dbl[j].t, (*RN)->e_arr_dbl[twin_j].s,(*RN)->e_arr_dbl[twin_j].t ); } //update matrix MatAsgn((*RN)->mat,s1,t1,0); MatAsgn((*RN)->mat,t1,s1,0); MatAsgn((*RN)->mat,s2,t2,0); MatAsgn((*RN)->mat,t2,s2,0); if(DEBUG_LEVEL==1 && GNRL_ST.out_log_flag) dump_network(GNRL_ST.log_fp,(*RN)); MatAsgn((*RN)->mat,s1,t2,1); MatAsgn((*RN)->mat,t2,s1,1); MatAsgn((*RN)->mat,s2,t1,1); MatAsgn((*RN)->mat,t1,s2,1); if(DEBUG_LEVEL==1 && GNRL_ST.out_log_flag) dump_network(GNRL_ST.log_fp,(*RN)); if (DEBUG_LEVEL>1 && GNRL_ST.out_metrop_mat_flag) { fprintf(GNRL_ST.mat_metrop_fp,"%lf %lf ",E1,t); output13(rand_vec13,GNRL_ST.mat_metrop_fp); } k++; } else /* change rand_vec13 back */ { update(rand_vec13,sub13,add13,0); } } } if(GNRL_ST.out_metrop_mat_flag==TRUE){ fprintf(GNRL_ST.mat_metrop_fp,"%lf\n",E1); printf("success=%d k=%d E1=%lf T=%lf\n",k,w,E1,t); } return(t); }
void anneal(float x[], float y[], int iorder[], int ncity) { int irbit1(unsigned long *iseed); int metrop(float de, float t); float ran3(long *idum); float revcst(float x[], float y[], int iorder[], int ncity, int n[]); void reverse(int iorder[], int ncity, int n[]); float trncst(float x[], float y[], int iorder[], int ncity, int n[]); void trnspt(int iorder[], int ncity, int n[]); int ans,nover,nlimit,i1,i2; int i,j,k,nsucc,nn,idec; static int n[7]; long idum; unsigned long iseed; float path,de,t; nover=100*ncity; nlimit=10*ncity; path=0.0; t=0.5; for (i=1;i<ncity;i++) { i1=iorder[i]; i2=iorder[i+1]; path += ALEN(x[i1],x[i2],y[i1],y[i2]); } i1=iorder[ncity]; i2=iorder[1]; path += ALEN(x[i1],x[i2],y[i1],y[i2]); idum = -1; iseed=111; for (j=1;j<=100;j++) { nsucc=0; for (k=1;k<=nover;k++) { do { n[1]=1+(int) (ncity*ran3(&idum)); n[2]=1+(int) ((ncity-1)*ran3(&idum)); if (n[2] >= n[1]) ++n[2]; nn=1+((n[1]-n[2]+ncity-1) % ncity); } while (nn<3); idec=irbit1(&iseed); if (idec == 0) { n[3]=n[2]+(int) (abs(nn-2)*ran3(&idum))+1; n[3]=1+((n[3]-1) % ncity); de=trncst(x,y,iorder,ncity,n); ans=metrop(de,t); if (ans) { ++nsucc; path += de; trnspt(iorder,ncity,n); } } else { de=revcst(x,y,iorder,ncity,n); ans=metrop(de,t); if (ans) { ++nsucc; path += de; reverse(iorder,ncity,n); } } if (nsucc >= nlimit) break; } printf("\n %s %10.6f %s %12.6f \n","T =",t, " Path Length =",path); printf("Successful Moves: %6d\n",nsucc); t *= TFACTR; if (nsucc == 0) return; } }
/* perform metropolis iteration exchanging single edges. Output the temperature */ double sin_metrop_switches(Network **RN,int nover,int nlimit,double init_t,int real_vec13[14],int rand_vec13[14]) { double t=init_t; register int w,k,num_at_t; int s1,t1,s2,t2; int i,j,l; int sub13[14]; int add13[14]; double E1,E2,dE; int make_change; if(GNRL_ST.out_metrop_mat_flag==TRUE) printf("\nBeginning single switches\n"); k=0,w=0,num_at_t=0; t=init_t; for (i=1;i<14;i++) { sub13[i]=0; add13[i]=0; } E1=energy(real_vec13,rand_vec13); if ((w%1000)==0 && GNRL_ST.out_metrop_mat_flag) fprintf(GNRL_ST.mat_metrop_fp,"\nEsin :\n"); while ((w<nover)&&(E1>GNRL_ST.e_thresh)) { w++; num_at_t++; if ((k>nlimit)||(num_at_t>nlimit)) { num_at_t=0; k=0; t *= TFACTR; // lower temperature } //get random indexes for edges i=get_rand((*RN)->e_sin_num); while ((j=get_rand((*RN)->e_sin_num)) == i); s1=(*RN)->e_arr_sin[i].s; t1=(*RN)->e_arr_sin[i].t; s2=(*RN)->e_arr_sin[j].s; t2=(*RN)->e_arr_sin[j].t; //check : 1.that there are no crossing edges, // 2.there are no common vertices of these 2 edges //if hasnt passed the check then have to find other pair to switch if ( !(MatGet((*RN)->mat,s1,t2) || MatGet((*RN)->mat,s2,t1)|| MatGet((*RN)->mat,t2,s1) || MatGet((*RN)->mat,t1,s2)) &&(s1!=s2) && (s1!=t2) && (t1!=s2) && (t1!=t2) ) { fill_13((*RN),s1,t1,s2,t2,sub13,add13); update(rand_vec13,sub13,add13,1); E2=energy(real_vec13,rand_vec13); dE=E2-E1; // printf("k=%d E=%lf\n",k,E1); make_change=metrop(dE,t); if (make_change) { if ((w%1000)==0 && GNRL_ST.out_metrop_mat_flag) { fprintf(GNRL_ST.mat_metrop_fp,"%lf\n",E1); printf("success=%d k=%d E1=%lf T=%lf\n",k,w,E1,t); } if(DEBUG_LEVEL>1 && GNRL_ST.out_metrop_mat_flag) { fprintf(GNRL_ST.mat_metrop_fp,"The network :\n\n"); for (l=1;l<=(*RN)->e_sin_num;l++) fprintf(GNRL_ST.mat_metrop_fp,"%d %d %d\n",(*RN)->e_arr_sin[l].t,(*RN)->e_arr_sin[l].s,1); } E1=E2; //make the switch //update edges array (*RN)->e_arr_sin[i].t=t2; (*RN)->e_arr_sin[j].t=t1; //update matrix MatAsgn((*RN)->mat,s1,t1,0); MatAsgn((*RN)->mat,s2,t2,0); MatAsgn((*RN)->mat,s1,t2,1); MatAsgn((*RN)->mat,s2,t1,1); //fprintf(GNRL_ST.mat_metrop_fp,"%lf %lf\n ",E1,t); if(DEBUG_LEVEL>1 && GNRL_ST.out_metrop_mat_flag) { fprintf(GNRL_ST.mat_metrop_fp,"Changed to :\n\n"); for (l=1;l<=(*RN)->e_sin_num;l++) fprintf(GNRL_ST.mat_metrop_fp,"%d %d %d\n",(*RN)->e_arr_sin[l].t,(*RN)->e_arr_sin[l].s,1); fprintf(GNRL_ST.mat_metrop_fp,"rand_vec : \n"); output13(rand_vec13,GNRL_ST.mat_metrop_fp); fprintf(GNRL_ST.mat_metrop_fp,"- : \n"); output13(sub13,GNRL_ST.mat_metrop_fp); fprintf(GNRL_ST.mat_metrop_fp,"+ : \n"); output13(add13,GNRL_ST.mat_metrop_fp); fprintf(GNRL_ST.mat_metrop_fp,"The network :\n\n"); for (l=1;l<=(*RN)->e_sin_num;l++) fprintf(GNRL_ST.mat_metrop_fp,"%d %d %d\n",(*RN)->e_arr_sin[l].t,(*RN)->e_arr_sin[l].s,1); fprintf(GNRL_ST.mat_metrop_fp,"\n\n"); } k++; } else /* change rand_vec13 back */ { update(rand_vec13,sub13,add13,0); } } } if(GNRL_ST.out_metrop_mat_flag==TRUE) { fprintf(GNRL_ST.mat_metrop_fp,"%lf\n",E1); printf("success=%d k=%d E1=%lf T=%lf\n",k,w,E1,t); } return(t); }