Beispiel #1
0
/******************
 Network NetworkCopy
*****************/
Network *NetworkCopy(Network *dest, Network *src){
  Vertex nnodes = dest->nnodes = src->nnodes;
  dest->last_inedge = src->last_inedge;
  dest->last_outedge = src->last_outedge;

  dest->outdegree = (Vertex *) malloc((nnodes+1)*sizeof(Vertex));
  memcpy(dest->outdegree, src->outdegree, (nnodes+1)*sizeof(Vertex));
  dest->indegree = (Vertex *) malloc((nnodes+1)*sizeof(Vertex));
  memcpy(dest->indegree, src->indegree, (nnodes+1)*sizeof(Vertex));

  Vertex maxedges = dest->maxedges = src->maxedges;

  dest->inedges = (TreeNode *) malloc(maxedges*sizeof(TreeNode));
  memcpy(dest->inedges, src->inedges, maxedges*sizeof(TreeNode));
  dest->outedges = (TreeNode *) malloc(maxedges*sizeof(TreeNode));
  memcpy(dest->outedges, src->outedges, maxedges*sizeof(TreeNode));

  int directed_flag = dest->directed_flag = src->directed_flag;
  Vertex bipartite = dest->bipartite = src->bipartite;

  if(src->duration_info.lasttoggle){
    dest->duration_info.time=src->duration_info.time;
    dest->duration_info.lasttoggle = (int *) calloc(DYADCOUNT(nnodes, bipartite, directed_flag), sizeof(int));
    memcpy(dest->duration_info.lasttoggle, src->duration_info.lasttoggle,DYADCOUNT(nnodes, bipartite, directed_flag) * sizeof(int));
  }
  else dest->duration_info.lasttoggle = NULL;

  dest->nedges = src->nedges;

  return dest;
}
Beispiel #2
0
/********************
   void MH_Formation
   Propose ONLY edges not in the reference graph
***********************/
void MH_Formation (MHProposal *MHp, Network *nwp) 
{  
  static Dyad ndyads;

  if(MHp->ntoggles == 0) { /* Initialize */
    MHp->ntoggles=1;
    ndyads = DYADCOUNT(nwp->nnodes, 0, nwp->directed_flag);
    return;
  }
  
  if(nwp->nedges==ndyads && MHp->discord[0]->nedges==0){ /* Attempting formation on a complete graph. */
    Mtail[0]=MH_FAILED;
    Mhead[0]=MH_IMPOSSIBLE;
    return;
  }
  
  BD_LOOP({
      /* A dyad eligible to be formed is either a nontie in nwp[0] or a tie in MHp->discord-> */
      if(unif_rand() < ((double)MHp->discord[0]->nedges)/(ndyads-nwp->nedges + MHp->discord[0]->nedges)){
	// Tie in MHp->discord[0]:
	GetRandEdge(Mtail, Mhead, MHp->discord[0]);
      }else{
	// Nontie in nwp[0]:
	GetRandNonedge(Mtail, Mhead, nwp);
      }
    });
Beispiel #3
0
void MH_FormationPlusMLE (MHproposal *MHp, Network *nwp)
{
  static Vertex nnodes;
  static Edge nedges0;
  static Dyad ndyads;

  if(MHp->ntoggles == 0) { /* Initialize */
    MHp->ntoggles=1;
    nnodes = nwp[0].nnodes;
    ndyads = DYADCOUNT(nnodes, 0, nwp[0].directed_flag);
    nedges0 = MHp->inputs[0];
    return;
  }

  if(nedges0==ndyads){ /* Attempting formation on a complete graph. */
    Mtail[0]=MH_FAILED;
    Mhead[0]=MH_IMPOSSIBLE;
    return;
  }

  BD_COND_LOOP({
    /* Keep trying dyads until a one that is not an edge in the reference network is found. */
    /* Generate. */
      GetRandDyad(Mtail, Mhead, nwp);
    }, !dEdgeListSearch(Mtail[0],Mhead[0],MHp->inputs), 2);
Beispiel #4
0
int GetRandNonedge(Vertex *tail, Vertex *head, Network *nwp) {
  Edge ndyads = DYADCOUNT(nwp->nnodes, nwp->bipartite, nwp->directed_flag);
  if(ndyads-nwp->nedges==0) return(0);

  /* There are two ways to get a random nonedge: 1) keep trying dyads
     at random until you find one that's not an edge or 2) generate i
     at random and find ith nonedge. Method 1 works better in sparse
     networks, while Method 2, which runs in deterministic time, works
     better in dense networks.

     The expected number of attempts for Method 1 is 1/(1-e/d) =
     d/(d-e), where e is the number of edges and d is the number of
     dyads.
  */

  // FIXME: The constant maxEattempts needs to be tuned.
  const unsigned int maxEattempts=10;
  unsigned int Eattempts = ndyads/(ndyads-nwp->nedges);
  Edge rane;
  
  if(Eattempts>maxEattempts){
    // If the network is too dense, use the deterministic-time method:
    rane=1 + unif_rand() * (ndyads-nwp->nedges);
    FindithNonedge(tail, head, rane, nwp);
  }else{
    do{
      GetRandDyad(tail, head, nwp);
    }while(EdgetreeSearch(*tail, *head, nwp->outedges));
  }
  return 1;
}
Beispiel #5
0
Network NetworkInitialize(Vertex *tails, Vertex *heads, Edge nedges, 
			  Vertex nnodes, int directed_flag, Vertex bipartite,
			  int lasttoggle_flag, int time, int *lasttoggle) {

  Network nw;

  nw.last_inedge = nw.last_outedge = (Edge)nnodes;
  /* Calloc will zero the allocated memory for us, probably a lot
     faster. */
  nw.outdegree = (Vertex *) calloc((nnodes+1),sizeof(Vertex));
  nw.indegree  = (Vertex *) calloc((nnodes+1),sizeof(Vertex));
  nw.maxedges = MAX(nedges,1)+nnodes+2; /* Maybe larger than needed? */
  nw.inedges = (TreeNode *) calloc(nw.maxedges,sizeof(TreeNode));
  nw.outedges = (TreeNode *) calloc(nw.maxedges,sizeof(TreeNode));

  /* GetRNGstate(); R function enabling uniform RNG */

  if(lasttoggle_flag){
    nw.duration_info.time=time;
    nw.duration_info.lasttoggle = (int *) calloc(DYADCOUNT(nnodes, bipartite, directed_flag), sizeof(int));
    if(lasttoggle)
      memcpy(nw.duration_info.lasttoggle, lasttoggle, DYADCOUNT(nnodes, bipartite, directed_flag) * sizeof(int));
  }
  else nw.duration_info.lasttoggle = NULL;

  /*Configure a Network*/
  nw.nnodes = nnodes;
  nw.nedges = 0; /* Edges will be added one by one */
  nw.directed_flag=directed_flag;
  nw.bipartite=bipartite;

  ShuffleEdges(tails,heads,nedges); /* shuffle to avoid worst-case performance */

  for(Edge i = 0; i < nedges; i++) {
    Vertex tail=tails[i], head=heads[i];
    if (!directed_flag && tail > head) 
      AddEdgeToTrees(head,tail,&nw); /* Undir edges always have tail < head */ 
    else 
      AddEdgeToTrees(tail,head,&nw);
  }
  /* PutRNGstate(); */
  return nw;
}
Beispiel #6
0
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;
}
Beispiel #7
0
/********************
   void MH_BipartiteHammingTNT
   Tie/no tie:  Gives at least 50% chance of
   proposing a toggle of an existing edge, as opposed
   to simple random toggles that rarely do so in sparse 
   networks
   MSH: The name Hamming is a hack for the Hamming proposals
        It is no different the MH_BipartiteTNT
***********************/
void MH_BipartiteHammingTNT (MHproposal *MHp, Network *nwp) 
{
  /* *** don't forget, edges are (tail, head) now */  
  Vertex tail, head;
  Edge nddyads=nwp[1].nedges;
  int nd, nc;
  static double comp=0.5;
  static double odds;
  static Dyad ndyads;
  static Edge nnodes;
  static Edge nb1;
  
  if(MHp->ntoggles == 0) { /* Initialize */
    MHp->ntoggles=1;
    odds = comp/(1.0-comp);
    nnodes = nwp[0].nnodes;
    nb1 = nwp[0].bipartite;
    ndyads = DYADCOUNT(nnodes, nb1, 0);
    return;
  }
  
  if (unif_rand() < comp && nddyads > 0) { /* Select a discordant dyad at random */
    GetRandEdge(Mtail, Mhead, &nwp[1]);
    nd = nddyads;
    nc = ndyads-nd;
    /*  Fixme!  Not sure whether the ratio is calculated correctly here.
        Check out the similar ratio calculations for other TNT proposals. */
    MHp->logratio += log((nd*1.0) / (odds*(nc+1)));
/*    MHp->ratio = (1.0*(nce-1)*(ncn-1)) / (nde*ndn*odds); */
/*    MHp->ratio = 1.0; */
/*   Rprintf("disconcord nd %d nc %d nddyads %d MHp->ratio %f\n", */
/*	    nd, nc, nddyads, MHp->ratio); */
  }else{
    /* select a concordant dyad at random */
    do{
      tail = 1 + unif_rand() * nb1;
      head = 1 + nb1 + unif_rand() * (nnodes - nb1);
    }while(EdgetreeSearch(tail,head,nwp[1].outedges)!=0);

    Mtail[0]=tail;
    Mhead[0]=head;
    nd = nddyads;
    nc = ndyads-nd;
    /*  Fixme!  Not sure whether the ratio is calculated correctly here.
        Check out the similar ratio calculations for other TNT proposals. */
    MHp->logratio += log((odds*nc) / ((nd+1)*1.0));
/*   Rprintf("concord nd %d nc %d nddyads %d MHp->ratio %f\n", */
/*	    nd, nc, nddyads, MHp->ratio); */
  }
/*   Rprintf("h0 %d t0 %d h1 %d t1 %d\n", Mtail[0],  Mhead[0],  */
/*                                        Mtail[1],  Mhead[1]);  */
}
Beispiel #8
0
WtNetwork *WtNetworkInitialize(Vertex *tails, Vertex *heads, double *weights,
			       Edge nedges, Vertex nnodes, int directed_flag, Vertex bipartite,
			       int lasttoggle_flag, int time, int *lasttoggle) {
  WtNetwork *nwp = Calloc(1, WtNetwork);

  nwp->last_inedge = nwp->last_outedge = (Edge)nnodes;
  /* Calloc will zero the allocated memory for us, probably a lot
     faster. */
  nwp->outdegree = (Vertex *) Calloc((nnodes+1), Vertex);
  nwp->indegree  = (Vertex *) Calloc((nnodes+1), Vertex);
  nwp->maxedges = MAX(nedges,1)+nnodes+2; /* Maybe larger than needed? */
  nwp->inedges = (WtTreeNode *) Calloc(nwp->maxedges, WtTreeNode);
  nwp->outedges = (WtTreeNode *) Calloc(nwp->maxedges, WtTreeNode);

  if(lasttoggle_flag){
    nwp->duration_info.time=time;
    if(lasttoggle){
      nwp->duration_info.lasttoggle = (int *) Calloc(DYADCOUNT(nnodes, bipartite, directed_flag), int);
      memcpy(nwp->duration_info.lasttoggle, lasttoggle, DYADCOUNT(nnodes, bipartite, directed_flag) * sizeof(int));
    } else nwp->duration_info.lasttoggle = NULL;
  }
Beispiel #9
0
void MCMCDynSArun_wrapper(// Observed network.
			     int *tails, int *heads, int *time, int *lasttoggle, int *n_edges,
			     int *n_nodes, int *dflag, int *bipartite, 
			     // Formation terms and proposals.
			     int *F_nterms, char **F_funnames, char **F_sonames,
			     char **F_MHproposaltype, char **F_MHproposalpackage,
			     double *F_inputs, 
			     // Dissolution terms and proposals.
			     int *D_nterms, char **D_funnames, char **D_sonames, 
			     char **D_MHproposaltype, char **D_MHproposalpackage,
			     double *D_inputs,
			     // Parameter fittig.
			     double *eta0, 
			     int *M_nterms, char **M_funnames, char **M_sonames, double *M_inputs,
			     double *init_dev,
			     int *runlength,
			     double *WinvGradient,
			     double *jitter, double *dejitter,
			     double *dev_guard,
			     double *par_guard,
			     // Degree bounds.
			     int *attribs, int *maxout, int *maxin, int *minout,
			     int *minin, int *condAllDegExact, int *attriblength,
			     // MCMC settings.
			     int *SA_burnin, int *SA_interval, int *min_MH_interval, int *max_MH_interval, double *MH_pval, double *MH_interval_add,
			     // Space for output.
			     int *maxedges, int *maxchanges,
			     int *newnetworktail, int *newnetworkhead, 
			     double *opt_history,
			     // Verbosity.
			     int *fVerbose,
			     int *status){

  Network nw[2];
  Model *F_m, *D_m, *M_m;
  MHproposal F_MH, D_MH;
  
  if(*lasttoggle == 0) lasttoggle = NULL;

  Vertex *difftime, *difftail, *diffhead;
  difftime = (Vertex *) calloc(*maxchanges,sizeof(Vertex));
  difftail = (Vertex *) calloc(*maxchanges,sizeof(Vertex));
  diffhead = (Vertex *) calloc(*maxchanges,sizeof(Vertex));

  memset(newnetworktail,0,*maxedges*sizeof(int));
  memset(newnetworkhead,0,*maxedges*sizeof(int));

  MCMCDyn_init_common(tails, heads, *time, lasttoggle, *n_edges,
		      *n_nodes, *dflag, *bipartite, nw,
		      *F_nterms, *F_funnames, *F_sonames, F_inputs, &F_m,
		      *D_nterms, *D_funnames, *D_sonames, D_inputs, &D_m,
		      *M_nterms, *M_funnames, *M_sonames, M_inputs, &M_m,
		      attribs, maxout, maxin, minout,
		      minin, *condAllDegExact, *attriblength,
		      *F_MHproposaltype, *F_MHproposalpackage, &F_MH,
		      *D_MHproposaltype, *D_MHproposalpackage, &D_MH,
		      *fVerbose);

  *status = MCMCDynSArun(nw,
			    
			 F_m, &F_MH,
			 D_m, &D_MH,
			 
			 eta0, M_m,
			 init_dev, 
			 *runlength,
			 WinvGradient, jitter, dejitter, dev_guard, par_guard,
			 
			 *maxedges, *maxchanges,
			 difftime, difftail, diffhead,
			 opt_history,
			 
			 *SA_burnin, *SA_interval, *min_MH_interval, *max_MH_interval, *MH_pval, *MH_interval_add,
			 *fVerbose);
  
  /* record the final network to pass back to R */

  if(*status==MCMCDyn_OK){
    newnetworktail[0]=newnetworkhead[0]=EdgeTree2EdgeList(newnetworktail+1,newnetworkhead+1,nw,*maxedges);
    *time = nw->duration_info.time;
    if(nw->duration_info.lasttoggle)
    memcpy(lasttoggle, nw->duration_info.lasttoggle, sizeof(int)*DYADCOUNT(*n_nodes, *bipartite, *dflag));
  }

  MCMCDyn_finish_common(nw, F_m, D_m, M_m, &F_MH, &D_MH);
  free(difftime);
  free(difftail);
  free(diffhead);
}
Beispiel #10
0
/********************
   void MH_BipartiteHammingConstantEdges
   Chooses a pair of toggles - one a tie and one not. 
   MSH: The name Hamming is a hack for the Hamming proposals
        It is no different the MH_BipartiteConstantEdges
***********************/
void MH_BipartiteHammingConstantEdges (MHproposal *MHp, Network *nwp) 
{
  /* *** don't forget, edges are (tail, head) now */

  Vertex tail, head;
  Edge nedges=nwp[0].nedges, nddyads=nwp[1].nedges;
  int nde, ndn, nce, ncn;
  static double comp=0.5;
  static double odds;
  static Dyad ndyads;
  static Edge nnodes;
  static Edge nb1;
  
  if(MHp->ntoggles == 0) { /* Initialize */
    MHp->ntoggles=2;
    odds = comp/(1.0-comp);
    nnodes = nwp[0].nnodes;
    nb1 = nwp[0].bipartite;
    ndyads = DYADCOUNT(nnodes, nb1, 0);
    return;
  }
  
  if (unif_rand() < comp && nddyads > 0) { /* Select a discordant pair of tie/nontie at random */
    /* First, select discord edge at random */
    do{
      GetRandEdge(Mtail, Mhead, &nwp[1]);
    }while(EdgetreeSearch(Mtail[0], Mhead[0], nwp[0].outedges) == 0);

    tail=Mtail[0];
    head=Mhead[0];
    /* Next, select discord non-edge at random */
  /* *** don't forget, edges are (tail, head) now */

    do{
      GetRandEdge(Mtail, Mhead, &nwp[1]);
    }while(EdgetreeSearch(Mtail[0], Mhead[0], nwp[0].outedges) != 0);

    Mtail[1]=Mtail[0];
    Mhead[1]=Mhead[0];
    Mtail[0]=tail;
    Mhead[0]=head;
    nde = nddyads / 2;
    ndn = nddyads / 2;
    nce = nedges-nde;
    ncn = ndyads-nedges-ndn;
/*    MHp->ratio = (nddyads*nddyads) / (odds*(nnodes-nddyads-2)*(nnodes-nddyads-2)); */
    MHp->logratio += log((nde*ndn*1.0) / (odds*(nce+1)*(ncn+1)));
/*    MHp->ratio = (1.0*(nce-1)*(ncn-1)) / (nde*ndn*odds); */
/*    MHp->ratio = 1.0; */
/*   Rprintf("disconcord nde %d nce %d ndn %d ncn %d nddyads %d MHp->ratio %f\n", */
/*	    nde, nce, ndn,ncn,nddyads, MHp->ratio); */
  }else{
    /* First, select concordant edge at random */
    do{
      GetRandEdge(Mtail, Mhead, &nwp[0]);
    }while(EdgetreeSearch(Mtail[0], Mhead[0], nwp[1].outedges) == 0);
       
    /* Next, select concord non-edge at random */
    do{
      tail = 1 + unif_rand() * nb1;
      head = 1 + nb1 + unif_rand() * (nnodes - nb1);
    }while((EdgetreeSearch(tail,head,nwp[0].outedges)!=0) ||
	     (EdgetreeSearch(tail,head,nwp[1].outedges)!=0));

    Mtail[1]=tail;
    Mhead[1]=head;
    nde = nddyads / 2;
    ndn = nddyads / 2;
    nce = nedges-nde;
    ncn = ndyads-nedges-ndn;
/*    MHp->ratio = ((nnodes-nddyads)*(nnodes-nddyads)) / (odds*(nddyads+2)*(nddyads+2)); */
    if(nddyads > 4){
      MHp->logratio += log((odds*nce*ncn) / ((nde+1)*(ndn+1)*1.0));
/*    MHp->ratio = ((nde+1)*(ndn+1)*odds) / (1.0*nce*ncn); */
    }else{
      MHp->logratio += 100000000.0;
    }
/*   Rprintf("concord nde %d nce %d ndn %d ncn %d nddyads %d MHp->ratio %f\n", */
/*	    nde, nce, ndn,ncn,nddyads, MHp->ratio); */
  }
/*   Rprintf("h0 %d t0 %d h1 %d t1 %d\n", Mtail[0],  Mhead[0],  */
/*                                        Mtail[1],  Mhead[1]);  */
}