Node* AddExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* arg1 = in(1); Node* arg2 = in(2); const Type* type1 = phase->type(arg1); const Type* type2 = phase->type(arg2); if (type1 != Type::TOP && type1->singleton() && type2 != Type::TOP && type2->singleton()) { jlong val1 = arg1->get_long(); jlong val2 = arg2->get_long(); jlong result = val1 + val2; // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) { Node* con_result = ConLNode::make(phase->C, result); return no_overflow(phase, con_result); } return NULL; } if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { // (Add 0 x) == x Node* add_result = new (phase->C) AddLNode(arg1, arg2); return no_overflow(phase, add_result); } if (type2->singleton()) { return NULL; // no change - keep constant on the right } if (type1->singleton()) { // Make it x + Constant - move constant to the right swap_edges(1, 2); return this; } if (arg2->is_Load()) { return NULL; // no change - keep load on the right } if (arg1->is_Load()) { // Make it x + Load - move load to the right swap_edges(1, 2); return this; } if (arg1->_idx > arg2->_idx) { // Sort the edges swap_edges(1, 2); return this; } return NULL; }
//********************************************************************** //********************************************************************** ///a function that do a rewiring preserving the degree distribution int rewiring_Pk(GRAPH* G,int num_rewires,gsl_rng * randgsl){ printf("Rewiring preserving P(k)...\n");fflush(stdout); int i,pos_r,pos_s,r1,r2,s1,s2; for(i=0;i<num_rewires*G->E;++i){ while(!choose_2_edges_random(G,&pos_r,&pos_s,randgsl)){} ///we try to find two edges avoiding selfedges and multipledges r1 = G->edge[pos_r].s; /// the nodes first link are r2 = G->edge[pos_r].d; s1 = G->edge[pos_s].s; /// the nodes second link are s2 = G->edge[pos_s].d; swap_edges(G,s1,s2,r1,r2); /// we swap the two links G->edge[pos_r].d = s2; /// we modify the edge vector G->edge[pos_s].d = r2; } return 1; }
//_________________________________________________________________________ double graph_molloy_hash::effective_K(int K, int quality) { if(K<3) return 0.0; long sum_K = 0; int *Kbuff = new int[K]; bool *visited = new bool[n]; int i; for(i=0; i<n; i++) visited[i] = false; for(int i=0; i<quality; i++) { // assert(verify()); int f1,f2,t1,t2; int *f1t1, *f2t2; do { // Pick two random vertices do { f1 = pick_random_vertex(); f2 = pick_random_vertex(); } while(f1==f2); // Pick two random neighbours f1t1 = random_neighbour(f1); t1 = *f1t1; f2t2 = random_neighbour(f2); t2 = *f2t2; // test simplicity } while (t1==t2 || f1==t2 || f2==t1 || is_edge(f1,t2) || is_edge(f2,t1)); // swap swap_edges(f1,t2,f2,t1); // assert(verify()); sum_K += effective_isolated(deg[f1]>deg[t2] ? f1 : t2, K, Kbuff, visited); // assert(verify()); sum_K += effective_isolated(deg[f2]>deg[t1] ? f2 : t1, K, Kbuff, visited); // assert(verify()); // undo swap swap_edges(f1,t2,f2,t1); // assert(verify()); } delete[] Kbuff; delete[] visited; return double(sum_K)/double(2*quality); }
//============================================================================= //------------------------------Ideal------------------------------------------ // Check for power-of-2 multiply, then try the regular MulNode::Ideal Node *MulINode::Ideal(PhaseGVN *phase, bool can_reshape) { // Swap constant to right jint con; if( in(1)->get_int( &con ) ) { swap_edges(1, 2); // Finish rest of method to use info in 'con' } else if( !in(2)->get_int( &con ) ) return MulNode::Ideal(phase, can_reshape); // Now we have a constant Node on the right and the constant in con if( con == 0 ) return NULL; // By zero is handled by Value call if( con == 1 ) return NULL; // By one is handled by Identity call // Check for negative constant; if so negate the final result bool sign_flip = false; if( con < 0 ) { con = -con; sign_flip = true; } // Get low bit; check for being the only bit Node *res = NULL; int bit1 = con & -con; // Extract low bit if( bit1 == con ) { // Found a power of 2? res = new (3) LShiftINode( in(1), phase->intcon(log2_intptr(bit1)) ); } else { // Check for constant with 2 bits set int bit2 = con-bit1; bit2 = bit2 & -bit2; // Extract 2nd bit if( bit2 + bit1 == con ) { // Found all bits in con? Node *n1 = phase->transform( new (3) LShiftINode( in(1), phase->intcon(log2_intptr(bit1)) ) ); Node *n2 = phase->transform( new (3) LShiftINode( in(1), phase->intcon(log2_intptr(bit2)) ) ); res = new (3) AddINode( n2, n1 ); // Sleezy: power-of-2 -1. Next time be generic. } else if( is_power_of_2(con+1) ) { int temp = (int) (con + 1); Node *n1 = phase->transform( new (3) LShiftINode( in(1), phase->intcon(log2_intptr(temp)) ) ); res = new (3) SubINode( n1, in(1) ); } else { return MulNode::Ideal(phase, can_reshape); } } if( sign_flip ) { // Need to negate result? res = phase->transform(res);// Transform, before making the zero con res = new (3) SubINode(phase->intcon(0),res); } return res; // Return final result }
//============================================================================= //------------------------------Idealize--------------------------------------- // MINs show up in range-check loop limit calculations. Look for // "MIN2(x+c0,MIN2(y,x+c1))". Pick the smaller constant: "MIN2(x+c0,y)" Node *MinINode::Ideal(PhaseGVN *phase, bool can_reshape) { Node *progress = NULL; // Force a right-spline graph Node *l = in(1); Node *r = in(2); // Transform MinI1( MinI2(a,b), c) into MinI1( a, MinI2(b,c) ) // to force a right-spline graph for the rest of MinINode::Ideal(). if( l->Opcode() == Op_MinI ) { assert( l != l->in(1), "dead loop in MinINode::Ideal" ); r = phase->transform(new (phase->C) MinINode(l->in(2),r)); l = l->in(1); set_req(1, l); set_req(2, r); return this; } // Get left input & constant Node *x = l; int x_off = 0; if( x->Opcode() == Op_AddI && // Check for "x+c0" and collect constant x->in(2)->is_Con() ) { const Type *t = x->in(2)->bottom_type(); if( t == Type::TOP ) return NULL; // No progress x_off = t->is_int()->get_con(); x = x->in(1); } // Scan a right-spline-tree for MINs Node *y = r; int y_off = 0; // Check final part of MIN tree if( y->Opcode() == Op_AddI && // Check for "y+c1" and collect constant y->in(2)->is_Con() ) { const Type *t = y->in(2)->bottom_type(); if( t == Type::TOP ) return NULL; // No progress y_off = t->is_int()->get_con(); y = y->in(1); } if( x->_idx > y->_idx && r->Opcode() != Op_MinI ) { swap_edges(1, 2); return this; } if( r->Opcode() == Op_MinI ) { assert( r != r->in(2), "dead loop in MinINode::Ideal" ); y = r->in(1); // Check final part of MIN tree if( y->Opcode() == Op_AddI &&// Check for "y+c1" and collect constant y->in(2)->is_Con() ) { const Type *t = y->in(2)->bottom_type(); if( t == Type::TOP ) return NULL; // No progress y_off = t->is_int()->get_con(); y = y->in(1); } if( x->_idx > y->_idx ) return new (phase->C) MinINode(r->in(1),phase->transform(new (phase->C) MinINode(l,r->in(2)))); // See if covers: MIN2(x+c0,MIN2(y+c1,z)) if( !phase->eqv(x,y) ) return NULL; // If (y == x) transform MIN2(x+c0, MIN2(x+c1,z)) into // MIN2(x+c0 or x+c1 which less, z). return new (phase->C) MinINode(phase->transform(new (phase->C) AddINode(x,phase->intcon(MIN2(x_off,y_off)))),r->in(2)); } else { // See if covers: MIN2(x+c0,y+c1) if( !phase->eqv(x,y) ) return NULL; // If (y == x) transform MIN2(x+c0,x+c1) into x+c0 or x+c1 which less. return new (phase->C) AddINode(x,phase->intcon(MIN2(x_off,y_off))); } }
//********************************************************************** //********************************************************************** int rewiring_PkkCbar_annealing(GRAPH* G,double B,double increment,double accmin,int rewires,gsl_rng* randgsl){ double Caim = G->Ccoef; /// this is the clustering we want to achieve /*********************************************************************** we calculate the initial clustering of the random network ************************************************************************/ double C = clustering_coeff(G); double Cnew = C; printf("Caim %f Cinitial %f\n",Caim,C); /*********************************************************************** we do the rewiring preserving the P(k,k') ************************************************************************/ int* numEDGESwithK = countEDGESwithK(G); /// we count how many edges with and node of degree k are int **pos_edges_k = createPOSedgesK(G,numEDGESwithK); int s1,s2,r1,r2,kr1,kr2,ks1,ks2,pos_r,pos_s,j=0,l=0; /// rewiring variables that will store the proposed rewiring double p,AH; int accepted=0,rewirestemp=0,pirem=0; /// during the proces we count how many proposals rewirings are with AH>0, AH<o and AH=0 double averAH = 0,averAHneg = 0,averAHpos = 0,oldacc=0; int numAH0 = 0,numAHneg = 0,numAHpos = 0; double H = fabs(C - Caim); /// initial energy /******** we start the rewiring *************/ printf("Fixing the Clustering coefficient by an anneald rewiring preserving P(k,k')...\n");fflush(stdout); time_t start,end; /// we will measure the time double dif; time (&start); FILE *ftemp = fopen("E_vs_T.dat","w"); fprintf(ftemp,"#B\tEnergy\tacceptance\n"); int i; for(i=1; oldacc>accmin || i<rewires*G->E+2 ;++i){ /**** we propose a swap *********/ while(!choose_2_edges_random_pkk(G,&pos_r,&pos_s,numEDGESwithK,pos_edges_k,randgsl)){} /// we try to find two edges avoiding selfedges and multipledges r1 = G->edge[pos_r].s; /// the nodes and its degree are r2 = G->edge[pos_r].d; kr1 = G->node[r1].k; kr2 = G->node[r2].k; s1 = G->edge[pos_s].s; s2 = G->edge[pos_s].d; ks1 = G->node[s1].k; ks2 = G->node[s2].k; /**** we calculate the increment of energy *********/ AH = calc_AH_PkkCbar(G,s1,s2,r1,r2,C,&Cnew,Caim); /// we calculate the increment of energy that would cause the rewiring averAH = averAH + fabs(AH); ///we also counbt the average AH of the proposals if(AH < 0.) { /// we count how many proposals have AH > 0 numAHneg++; averAHneg = averAHneg + AH; } else if (AH > 0.) { /// we count how many proposals have AH < 0 numAHpos++; averAHpos = averAHpos + AH; } else numAH0++; /// we count how many proposals have AH = 0 p = gsl_rng_uniform(randgsl); /// we throw a random number (0,1) /********** IF we acccept **************/ if( p < exp(-B*AH) ){ swap_edges(G,s1,s2,r1,r2); /// we make the proposed rewired G->edge[pos_r].d = s2; /// we modify the edge vector G->edge[pos_s].d = r2; if(kr2!=ks2){ ///we modify the vector pos_edges_k if(kr2!=kr1){ for(j=0;j<numEDGESwithK[kr2];++j){if(pos_edges_k[kr2][j]==pos_r){break;}} } if(ks2!=ks1){ for(l=0;l<numEDGESwithK[ks2];++l){if(pos_edges_k[ks2][l]==pos_s){break;}} } if (kr2!=kr1 && ks2==ks1) pos_edges_k[kr2][j] = pos_s; else if(ks2!=ks1 && kr2==kr1) pos_edges_k[ks2][l] = pos_r; else if(kr2!=kr1 && ks2!=ks1){ /// in case the two other nodes have different degree we just swap the positions of the edges pos_edges_k[kr2][j] = pos_s; pos_edges_k[ks2][l] = pos_r; } j=0; l=0; } C = Cnew; /// we update the clustering vector if(fabs(AH)>0.) accepted++; /// we count how many changes we accept H = H + AH; } /********** IF we reject **************/ else { Cnew = C; /// we recover the old clustering vector } rewirestemp++; /********** we reduce the temperature and we check the acceptance **************/ if(rewirestemp > rewires*G->E ) { ///we try to find the appropiate temperature in order to have the desire acceptation printf("acceptance rate = %f " ,(double)accepted/(numAHneg+numAHpos)); /// the acceptance //printf("AH = %f " ,averAH/(numAHneg+numAHpos)); /// the average energy of the proposed swaps //printf("numAHneg = %f AHneg = %e ",(double)numAHneg/rewirestemp,averAHneg/numAHneg); /// the proportion of negative energy swaps and the average //printf("numAHpos = %f AHpos = %e ",(double)numAHpos/rewirestemp,averAHpos/numAHpos); /// the proportion of positive energy swaps and the average //printf("numAH0=%f " ,(double)numAH0/rewirestemp); /// the proportion of proposals that do not change the energy printf("Beta=%e Energy=%e\n" ,B,H); /// the temperature and the energy fflush(stdout); fprintf(ftemp,"%f\t%f\t%f\n",B,H,(double)accepted/(numAHneg+numAHpos)); if( ((double)accepted/(numAHneg+numAHpos)) > oldacc && i > rewires*G->E + 2 ) pirem++; /// in case we havethe acceptance has increased 10 times the rewiring proces if(pirem>30) break; oldacc = ((double)accepted/(numAHneg+numAHpos)); /// we save the old acceptance in order to compare with the next one accepted = 0; /// we put to zero all the acceptance counters rewirestemp = 0; averAH = 0; numAHneg = 0;averAHneg = 0; numAH0 = 0; numAHpos = 0;averAHpos = 0; B = B*increment; /// we reduce the temperature } } time (&end); ///we count the rewiring time and take conclusions dif = difftime (end,start); printf ("You rewired the entire network %.2f times and it took %.2lf seconds to run.\n",(double)i/G->E, dif ); /*********************************************************************** we print the network and we free the memory ************************************************************************/ printf("Cfinal %f\n",C); fclose(ftemp); free(numEDGESwithK); for(i=1;i<G->max_k+1;++i){free(pos_edges_k[i]);} free(pos_edges_k); return 0; }
//------------------------------Ideal------------------------------------------ // We also canonicalize the Node, moving constants to the right input, // and flatten expressions (so that 1+x+2 becomes x+3). Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) { const Type *t1 = phase->type( in(1) ); const Type *t2 = phase->type( in(2) ); Node *progress = NULL; // Progress flag // We are OK if right is a constant, or right is a load and // left is a non-constant. if( !(t2->singleton() || (in(2)->is_Load() && !(t1->singleton() || in(1)->is_Load())) ) ) { if( t1->singleton() || // Left input is a constant? // Otherwise, sort inputs (commutativity) to help value numbering. (in(1)->_idx > in(2)->_idx) ) { swap_edges(1, 2); const Type *t = t1; t1 = t2; t2 = t; progress = this; // Made progress } } // If the right input is a constant, and the left input is a product of a // constant, flatten the expression tree. uint op = Opcode(); if( t2->singleton() && // Right input is a constant? op != Op_MulF && // Float & double cannot reassociate op != Op_MulD ) { if( t2 == Type::TOP ) return NULL; Node *mul1 = in(1); if( mul1 == this ) { // Check for dead cycle set_req(1, phase->C->top()); return this; // Make it trivially dead } if( mul1->Opcode() == mul_opcode() ) { // Left input is a multiply? // Mul of a constant? const Type *t12 = phase->type( mul1->in(2) ); if( t12->singleton() && t12 != Type::TOP) { // Left input is an add of a constant? // Compute new constant; check for overflow const Type *tcon01 = mul1->is_Mul()->mul_ring(t2,t12); if( tcon01->singleton() ) { // The Mul of the flattened expression set_req(1, mul1->in(1)); set_req(2, phase->makecon( tcon01 )); t2 = tcon01; progress = this; // Made progress } } } // If the right input is a constant, and the left input is an add of a // constant, flatten the tree: (X+con1)*con0 ==> X*con0 + con1*con0 const Node *add1 = in(1); if( add1->Opcode() == add_opcode() ) { // Left input is an add? // Add of a constant? const Type *t12 = phase->type( add1->in(2) ); if( t12->singleton() && t12 != Type::TOP ) { // Left input is an add of a constant? // Check if the add node is dead and self-referencing, // to avoid infinite loop (no progress). if( add1->in(1) == add1 ) return progress; // Compute new constant; check for overflow const Type *tcon01 = mul_ring(t2,t12); if( tcon01->singleton() ) { // Convert (X+con1)*con0 into X*con0 Node *mul = clone(); // mul = ()*con0 mul->set_req(1,add1->in(1)); // mul = X*con0 mul = phase->transform(mul); Node *add2 = add1->clone(); add2->set_req(1, mul); // X*con0 + con0*con1 add2->set_req(2, phase->makecon(tcon01) ); progress = add2; } } } // End of is left input an add } // End of is right input a Mul return progress; }
//********************************************************************** //********************************************************************** ///a function that do a rewiring preserving the joint degree distribution P(k,k') int rewiring_Pkk(GRAPH* G,int num_rewires,gsl_rng * randgsl){ int* numEDGESwithK = countEDGESwithK(G); /// we count how many edges with and node of degree k are int **pos_edges_k = createPOSedgesK(G,numEDGESwithK); int i,s1,s2,r1,r2,kr1,kr2,ks1,ks2,pos_r,pos_s,j=0,l=0; /// rewiring variables that will store the proposed rewiring /******** we start the rewiring *************/ printf("Rewiring preserving P(k,k')...\n");fflush(stdout); for(i=1; i<num_rewires*G->E ;++i){ while(!choose_2_edges_random_pkk(G,&pos_r,&pos_s,numEDGESwithK,pos_edges_k,randgsl)){} /// we try to find two edges avoiding selfedges and multipledges r1 = G->edge[pos_r].s; /// the nodes and its degree are r2 = G->edge[pos_r].d; kr1 = G->node[r1].k; kr2 = G->node[r2].k; s1 = G->edge[pos_s].s; s2 = G->edge[pos_s].d; ks1 = G->node[s1].k; ks2 = G->node[s2].k; swap_edges(G,s1,s2,r1,r2); /// we make the proposed rewired G->edge[pos_r].d = s2; /// we modify the edge vector G->edge[pos_s].d = r2; if(kr2!=ks2){ ///we modify the vector pos_edges_k if(kr2!=kr1){ for(j=0;j<numEDGESwithK[kr2];++j){if(pos_edges_k[kr2][j]==pos_r){break;}} } if(ks2!=ks1){ for(l=0;l<numEDGESwithK[ks2];++l){if(pos_edges_k[ks2][l]==pos_s){break;}} } if (kr2!=kr1 && ks2==ks1) pos_edges_k[kr2][j] = pos_s; else if(ks2!=ks1 && kr2==kr1) pos_edges_k[ks2][l] = pos_r; else if(kr2!=kr1 && ks2!=ks1){ /// in case the two other nodes have different degree we just swap the positions of the edges pos_edges_k[kr2][j] = pos_s; pos_edges_k[ks2][l] = pos_r; } j=0; l=0; } } free(numEDGESwithK); for(i=1;i<G->max_k+1;++i){free(pos_edges_k[i]);} free(pos_edges_k); return 0; }
//********************************************************************** //********************************************************************** int rewiring_Cbar_annealing(GRAPH G,double B,double increment,double accmin,int rewires,gsl_rng* randgsl){ double Caim = G.Ccoef; /*********************************************************************** we create a random network with the same degree sequence ************************************************************************/ rewiring_Pk(G,rewires,randgsl); double C = clustering_coeff(G); double Cnew = C; printf("Caim %f Cinitial %f\n",Caim,C); /*********************************************************************** we do the rewiring preserving the C(k) ************************************************************************/ int s1,s2,r1,r2,pos_r,pos_s; /// rewiring variables that will store the proposed rewiring double p,AH; int accepted=0,rewirestemp=0,pirem=0; /// during the proces we count how many proposals rewirings are with AH>0, AH<o and AH=0 double averAH = 0,averAHneg = 0,averAHpos = 0,oldacc=0; int numAH0 = 0,numAHneg = 0,numAHpos = 0; double H = fabs(C - Caim); /// initial energy /******** we start the rewiring *************/ printf("Annealed rewiring fixing the clustering coefficient...\n");fflush(stdout); time_t start,end; /// we will measure the time double dif; time (&start); int i; for(i=1; oldacc>accmin || i<rewires*G.E+2 ;++i){ while(!choose_2_edges_random(G,&pos_r,&pos_s,randgsl)){} /// we try to find two edges avoiding selfedges and multipledges r1 = G.edge[pos_r].s; /// the nodes are r2 = G.edge[pos_r].d; s1 = G.edge[pos_s].s; s2 = G.edge[pos_s].d; AH = calc_AH_Cbar(G,s1,s2,r1,r2,C,&Cnew,Caim); /// we calculate the increment of energy that would cause the rewiring averAH = averAH + fabs(AH); ///we also counbt the average AH of the proposals if(AH < 0.) { /// we count how many proposals have AH > 0 numAHneg++; averAHneg = averAHneg + AH; } else if (AH > 0.) { /// we count how many proposals have AH < 0 numAHpos++; averAHpos = averAHpos + AH; } else numAH0++; /// we count how many proposals have AH = 0 p = gsl_rng_uniform(randgsl); /// we throw a random number (0,1) /********** IF we acccept **************/ if( p < exp(-B*AH) ){ swap_edges(G,s1,s2,r1,r2); /// we make the proposed rewired G.edge[pos_r].d = s2; /// we modify the edge vector G.edge[pos_s].d = r2; C = Cnew; if(fabs(AH)>0.) accepted++; /// we coubt how many changes we accept H = H + AH; } /********** IF we reject **************/ else { Cnew = C; } rewirestemp++; /********** we reduce the temperature and we check the acceptance **************/ if(rewirestemp > rewires*G.E ) { ///we try to find the appropiate temperature in order to have the desire acceptation printf("acceptance rate = %f " ,(double)accepted/(numAHneg+numAHpos)); /// the acceptance //printf("AH = %f " ,averAH/(numAHneg+numAHpos)); /// the average energy of the proposed swaps //printf("numAHneg = %f AHneg = %e ",(double)numAHneg/rewirestemp,averAHneg/numAHneg); /// the proportion of negative energy swaps and the average //printf("numAHpos = %f AHpos = %e ",(double)numAHpos/rewirestemp,averAHpos/numAHpos); /// the proportion of positive energy swaps and the average //printf("numAH0=%f " ,(double)numAH0/rewirestemp); /// the proportion of proposals that do not change the energy printf("Beta=%e Energy=%e\n" ,B,H); /// the temperature and the energy fflush(stdout); if( ((double)accepted/(numAHneg+numAHpos)) > oldacc && i > rewires*G.E + 2 ) pirem++; /// in case we havethe acceptance has increased 10 times the rewiring proces if(pirem>30) break; oldacc = ((double)accepted/(numAHneg+numAHpos)); /// we save the old acceptance in order to compare with the next one accepted = 0; /// we put to zero all the acceptance counters rewirestemp = 0; averAH = 0; numAHneg = 0;averAHneg = 0; numAH0 = 0; numAHpos = 0;averAHpos = 0; B = B*increment; /// we reduce the temperature } } time (&end); ///we count the rewiring time and take conclusions dif = difftime (end,start); printf ("You rewired the entire network %.2f times with %.2lf seconds.\n",(double)i/G.E, dif ); printf("Cfinal %f\n",C); /*********************************************************************** we free the memory ************************************************************************/ return 0; }