/**************** Edge EdgeTree2EdgeList Write the edgelist of a network into tail and head arrays. Returns the number of edges in the network. ****************/ Edge EdgeTree2EdgeList(Vertex *tails, Vertex *heads, Network *nwp, Edge nmax){ Edge nextedge=0; /* *** don't forget, tail -> head */ if (nwp->directed_flag) { for (Vertex v=1; v<=nwp->nnodes; v++){ for(Vertex e = EdgetreeMinimum(nwp->outedges, v); nwp->outedges[e].value != 0 && nextedge < nmax; e = EdgetreeSuccessor(nwp->outedges, e)){ tails[nextedge] = v; heads[nextedge] = nwp->outedges[e].value; nextedge++; } } }else{ for (Vertex v=1; v<=nwp->nnodes; v++){ for(Vertex e = EdgetreeMinimum(nwp->outedges, v); nwp->outedges[e].value != 0 && nextedge < nmax; e = EdgetreeSuccessor(nwp->outedges, e)){ Vertex k = nwp->outedges[e].value; if(v < k){ tails[nextedge] = k; heads[nextedge] = v; nextedge++; }else{ tails[nextedge] = v; heads[nextedge] = k; nextedge++; } } } } return nextedge; }
int FindithEdge (Vertex *tail, Vertex *head, Edge i, Network *nwp) { Vertex taili=1; Edge e; /* TODO: This could be speeded up by a factor of 3 or more by starting the search from the tail n rather than tail 1 if i > ndyads/2. */ if (i > nwp->nedges || i<=0) return 0; while (i > nwp->outdegree[taili]) { i -= nwp->outdegree[taili]; taili++; } /* TODO: This could be speeded up by a factor of 3 or more by starting the search from the tree maximum rather than minimum (left over) i > outdegree[taili]. */ e=EdgetreeMinimum(nwp->outedges,taili); while (i-- > 1) { e=EdgetreeSuccessor(nwp->outedges, e); } *tail = taili; *head = nwp->outedges[e].value; return 1; }
int FindithNonedge (Vertex *tail, Vertex *head, Edge i, Network *nwp) { Vertex taili=1; Edge e; Edge ndyads = DYADCOUNT(nwp->nnodes, nwp->bipartite, nwp->directed_flag); // If the index is too high or too low, exit immediately. if (i > ndyads - nwp->nedges || i<=0) return 0; /* TODO: This could be speeded up by a factor of 3 or more by starting the search from the tail n rather than tail 1 if i > ndyads/2. */ Vertex nnt; while (i > (nnt = nwp->nnodes - (nwp->bipartite ? nwp->bipartite : (nwp->directed_flag?1:taili)) - nwp->outdegree[taili])) { // nnt is the number of nonties incident on taili. Note that when network is undirected, tail<head. i -= nnt; taili++; } // Now, our tail is taili. /* TODO: This could be speeded up by a factor of 3 or more by starting the search from the tree maximum rather than minimum (left over) i > outdegree[taili]. */ // If taili 1, then head cannot be 1. If undirected, the smallest it can be is taili+1. If bipartite, the smallest it can be is nwp->bipartite+1. Vertex lhead = ( nwp->bipartite ? nwp->bipartite : (nwp->directed_flag ? taili==1 : taili) ); e = EdgetreeMinimum(nwp->outedges,taili); Vertex rhead = nwp->outedges[e].value; // Note that rhead-lhead-1-(lhead<taili && taili<rhead) is the number of nonties between two successive ties. // the -(lhead<taili && taili<rhead) is because (taili,taili) is not a valid nontie and must be skipped. // Note that if taili is an isolate, rhead will be 0. while (rhead && i > rhead-lhead-1-(lhead<taili && taili<rhead)) { i -= rhead-lhead-1-(lhead<taili && taili<rhead); lhead = rhead; e = EdgetreeSuccessor(nwp->outedges, e); // If rhead was the highest-indexed head, then e is now 0. if(e) rhead = nwp->outedges[e].value; else break; // Note that we don't actually need rhead in the final step. } // Now, the head we are looking for is (left over) i after lhead. *tail = taili; *head = lhead + i + (nwp->directed_flag && lhead+i>=taili); // Skip over the (taili,taili) dyad, if the network is directed. return 1; }
/***************** int DeleteHalfedgeFromTree Delete the TreeNode with value b from the tree rooted at edges[a]. Return 0 if no such TreeNode exists, 1 otherwise. Also update the value of *last_edge appropriately. *****************/ int DeleteHalfedgeFromTree(Vertex a, Vertex b, TreeNode *edges, Edge *last_edge){ Edge x, z, root=(Edge)a; TreeNode *xptr, *zptr, *ptr; if ((z=EdgetreeSearch(a, b, edges))==0) /* z is the current TreeNode. */ return 0; /* This edge doesn't exist, so return 0 */ /* First, determine which node to splice out; this is z. If the current z has two children, then we'll actually splice out its successor. */ if ((zptr=edges+z)->left != 0 && zptr->right != 0) { if(unif_rand()<0.5) z=EdgetreeSuccessor(edges, z); else z=EdgetreePredecessor(edges, z); zptr->value = (ptr=edges+z)->value; zptr=ptr; } /* Set x to the child of z (there is at most one). */ if ((x=zptr->left) == 0) x = zptr->right; /* Splice out node z */ if (z == root) { zptr->value = (xptr=edges+x)->value; if (x != 0) { if ((zptr->left=xptr->left) != 0) (edges+zptr->left)->parent = z; if ((zptr->right=xptr->right) != 0) (edges+zptr->right)->parent = z; zptr=edges+(z=x); } else return 1; } else { if (x != 0) (xptr=edges+x)->parent = zptr->parent; if (z==(ptr=(edges+zptr->parent))->left) ptr->left = x; else ptr->right = x; } /* Clear z node, update *last_edge if necessary. */ zptr->value=0; if(z!=root){ RelocateHalfedge(*last_edge,z,edges); (*last_edge)--; } return 1; }
/********************* void MH_BipartiteCondDegreeDist Pick three nodes -- tail, head, alter -- such that * tail shares an edge with head * tail does not share an edge with A * deg(head) = deg(A) + 1 Then, propose swapping the (tail,head) edge for a (tail,A) edge so that deg(tail) stays the same while deg(head) and deg(A) swap with one another. *********************/ void MH_BipartiteCondDegreeDist (MHproposal *MHp, Network *nwp) { int valid, count; Edge e; Vertex tail, head, A, tailin, tailout, headdeg, Adeg, minA, maxA, i, k; double u; TreeNode *tail_edges; Vertex *headA_degrees; /* *** don't forget, edges are (tail, head) now */ if(MHp->ntoggles == 0) { /* Initialize */ MHp->ntoggles=2; return; } MHp->logratio += 0; /* By symmetry: P(choosing tail,head,A) must equal */ /* P(choosing tail,A,head after head and A swap roles), */ /* which makes the ratio equal to 1. */ for(valid = count = 0; valid == 0 && count<MAX_TRIES/10; count++) { tailin = tailout = 0; /* choose a node at random; ensure it has some edges */ while (tailin + tailout == 0) { u = unif_rand(); if (u < .5) { /* Pick "male" and "female" nodes with equal prob */ tail = 1 + unif_rand() * nwp->bipartite; } else { tail = 1 + nwp->bipartite + unif_rand() * (nwp->nnodes - nwp->bipartite); } tailin = nwp->indegree[tail]; tailout = nwp->outdegree[tail]; } /* select an edge to/from tail at random */ k = (int)(unif_rand() * (tailout + tailin)); if (k < tailout) { /* we chose an outedge */ tail_edges = nwp->outedges; i = k; headA_degrees = nwp->indegree; } else { /* we chose an inedge */ tail_edges = nwp->inedges; i = k - tailout; headA_degrees = nwp->outdegree; } /* Find ith edge in correct edgetree for tail; this will be (tail,head) or (head,tail) */ e=EdgetreeMinimum(tail_edges, tail); while (i-- > 0) { e=EdgetreeSuccessor(tail_edges, e); } head = tail_edges[e].value; headdeg = nwp->directed_flag ? headA_degrees[head] : nwp->indegree[head] + nwp->outdegree[head]; /* Now choose alter at random */ /* Now search for eligible alters */ minA = (u<.5) ? 1 + nwp->bipartite : 1 ; maxA = (u<.5) ? nwp->nnodes : nwp->bipartite; i=0; for (A=minA; A<=maxA; A++) { Adeg = nwp->directed_flag ? headA_degrees[A] : nwp->indegree[A] + nwp->outdegree[A]; /* To be a valid choice, alter (A) must not be tied to tail and it must have */ /* a degree one less than the head */ if (headdeg == Adeg + 1 && EdgetreeSearch(tail, A, tail_edges) == 0) { if (nwp->directed_flag || EdgetreeSearch(A, tail, tail_edges) ==0) { i++; } } } /* After for-loop, i is # of eligible alters. */ if (i>0) { valid = 1; i = 1 + unif_rand()*i; /* Pick an eligible alter at random */ for (A=minA; i>0; A++) { Adeg = nwp->directed_flag ? headA_degrees[A] : nwp->indegree[A] + nwp->outdegree[A]; /* To be a valid choice, alter (A) must not be tied to tail and it must have */ /* a degree one less than the head */ if (headdeg == Adeg + 1 && EdgetreeSearch(tail, A, tail_edges) == 0) { if (nwp->directed_flag || EdgetreeSearch(A, tail, tail_edges) ==0) { i--; /* By counting down, when i==0 we have the selected A. */ } } } } } if ( (!nwp->directed_flag && tail > head) || (nwp->directed_flag && k < tailout) ) { Mtail[0] = head; Mhead[0] = tail; }else{ Mtail[0] = tail; Mhead[0] = head; } if(!valid) { Mtail[1] = Mtail[0]; Mhead[1] = Mtail[0]; } else { if ( (!nwp->directed_flag && tail > A) || (nwp->directed_flag && k < tailout) ) { Mtail[0] = A; Mhead[0] = tail; }else{ Mtail[0] = tail; Mhead[0] = A; } } }