Example #1
0
/* 
void MH_CondDegreeTetradMixMore

   Select two edges with no nodes in common, A1-A2 and B1-B2, s.t. A1-B2 and B1-A2 are not edges, and propose to replace the former two by the latter two.
 */
void MH_CondDegreeTetradMixMore(MHproposal *MHp, Network *nwp)  {  
  Vertex A1, A2, B1, B2;
  
  if(MHp->ntoggles == 0) { /* Initialize */
    MHp->ntoggles=4;    
    return;
  }
//  Rprintf("0 %f 1 %f 2 %f 3 %f\n",MHp->inputs[0],MHp->inputs[1],MHp->inputs[2],MHp->inputs[3]); 
//  Rprintf("0 %f 1 %f 2 %f 3 %f\n",MHp->inputs[4],MHp->inputs[5],MHp->inputs[6],MHp->inputs[7]); 
//  Rprintf("0 %f 1 %f 2 %f 3 %f\n",MHp->inputs[8],MHp->inputs[9],MHp->inputs[10],MHp->inputs[11]); 

  do{
    GetRandEdge(&A1, &A2, nwp);
    GetRandEdge(&B1, &B2, nwp);
//Rprintf("A1 %d A2 %d B1 %d B2 %d\n",A1,A2,B1,B2); 
//Rprintf("g: A1 %f A2 %f B1 %f B2 %f\n",MHp->inputs[A1-1],MHp->inputs[A2-1],MHp->inputs[B1-1],MHp->inputs[B2-1]); 
  }while(
  	 ((fabs(MHp->inputs[A1-1]-MHp->inputs[A2-1])>0.001)||(fabs(MHp->inputs[B2-1]-MHp->inputs[B1-1])>0.001)||(fabs(MHp->inputs[A1-1]-MHp->inputs[B1-1])<0.001))|| 
	  A1==B1 || A1==B2 || A2==B1 || A2==B2 || 
	 (nwp->directed_flag ? 
	  IS_OUTEDGE(A1, B2) || IS_OUTEDGE(B1, A2) : // Directed
	  IS_UNDIRECTED_EDGE(A1,B2) || IS_UNDIRECTED_EDGE(B1,A2) // Undirected
	  ));
//Rprintf("in A1 %d A2 %d B1 %d B2 %d\n",A1,A2,B1,B2); 
Rprintf("M: A1 %f A2 %f B1 %f B2 %f\n",MHp->inputs[A1-1],MHp->inputs[A2-1],MHp->inputs[B1-1],MHp->inputs[B2-1]); 
  Mtail[0]=A1; Mhead[0]=A2;
  Mtail[1]=A1; Mhead[1]=B2;
  Mtail[2]=B1; Mhead[2]=B2;
  Mtail[3]=B1; Mhead[3]=A2;
}
Example #2
0
/* 
void MH_CondDegreeHexad

   Select three edges A1->A2, B1->B2, C1->C2 at random and rotate them to 
   A1->B2, B1->C2, and C1->A2.

   Note that while all the *1s need to be distinct and all the *2s
   need to be distinct and all dyads to be created must be empty and
   meaningful (i.e. not loops), it's OK if A1=C2, B1=A2, and/or
   C1=B2. Indeed, "reversing" the cyclical triangle is the one
   operation that tetradic toggles can't accomplish.

   Note that this must *never* be called for undirected networks.

 */
void MH_CondDegreeHexad(MHproposal *MHp, Network *nwp)  {  
  Vertex A1, A2, B1, B2, C1, C2;
  
  if(MHp->ntoggles == 0) { /* Initialize */
    MHp->ntoggles=6;
    return;
  }

  GetRandEdge(&A1, &A2, nwp);

  do{
    GetRandEdge(&B1, &B2, nwp);
  }while(B1==A1 || B2==A1 || B2==A2 || EdgetreeSearch(A1, B2, nwp->outedges));

  do{
    GetRandEdge(&C1, &C2, nwp);
  }while(C1==A1 || C1==B1 || C1==A2 || C2==A2 || C2==B2 || C2==B1 || EdgetreeSearch(B1, C2, nwp->outedges) || EdgetreeSearch(C1, A2, nwp->outedges));

  Mtail[0]=A1; Mhead[0]=A2;
  Mtail[1]=A1; Mhead[1]=B2;
  Mtail[2]=B1; Mhead[2]=B2;
  Mtail[3]=B1; Mhead[3]=C2;
  Mtail[4]=C1; Mhead[4]=C2;
  Mtail[5]=C1; Mhead[5]=A2;
}
Example #3
0
/* 
void MH_CondDegreeTetrad

   Select two edges with no nodes in common, A1-A2 and B1-B2, s.t. A1-B2 and B1-A2 are not edges, and propose to replace the former two by the latter two.
 */
void MH_CondDegreeTetrad(MHproposal *MHp, Network *nwp)  {  
  Vertex A1, A2, B1, B2;
  
  if(MHp->ntoggles == 0) { /* Initialize */
    MHp->ntoggles=4;    
    return;
  }

//nstats = N_CHANGE_STATS;
//matchvaltail = INPUT_PARAM[tail-1+2*nstats];
//matchvalhead = INPUT_PARAM[head-1+2*nstats];
  do{
    /*
      The reason the following randomization is needed is that, given
      the a tetrad with (only) A1-A2 and B1-B2 having edges, there are
      two degree-preserving proposals that can be made: to replace the
      edges with A1-B2 and B1-A2 or to replace with A1-B1 and A2-B2.
      
      GetRandEdge always returns tail<head for undirected networks, so
      a sampler that only uses GetRandEdge(&A1, &A2, nwp) misses out
      on potential proposals. This causes it to become trapped in
      bipartite or near-bipartite configurations. Bipartite networks
      are already bipartite, so they are not affected.

      Swapping A1 and A2 half the time allows either of the above
      proposals to be considered.
    */
    if(!nwp->directed_flag && !nwp->bipartite && unif_rand()<0.5) GetRandEdge(&A2, &A1, nwp);
    else GetRandEdge(&A1, &A2, nwp);

    GetRandEdge(&B1, &B2, nwp);
    //Rprintf("A1 %d A2 %d B1 %d B2 %d\n",A1,A2,B1,B2); 
  }while(A1==B1 || A1==B2 || A2==B1 || A2==B2 || 
	 (nwp->directed_flag ? 
	  (IS_OUTEDGE(A1, B2) || IS_OUTEDGE(B1, A2)) : // Directed
	  (IS_UNDIRECTED_EDGE(A1,B2) || IS_UNDIRECTED_EDGE(B1,A2)) // Undirected
	  ));
  //Rprintf("in A1 %d A2 %d B1 %d B2 %d\n",A1,A2,B1,B2); 
  if(nwp->directed_flag){
    Mtail[0]=A1; Mhead[0]=A2;
    Mtail[1]=A1; Mhead[1]=B2;
    Mtail[2]=B1; Mhead[2]=B2;
    Mtail[3]=B1; Mhead[3]=A2;
  }else{
    Mtail[0]=MIN(A1,A2); Mhead[0]=MAX(A1,A2);
    Mtail[1]=MIN(A1,B2); Mhead[1]=MAX(A1,B2);
    Mtail[2]=MIN(B1,B2); Mhead[2]=MAX(B1,B2);
    Mtail[3]=MIN(B1,A2); Mhead[3]=MAX(B1,A2);
  }
}
Example #4
0
void MH_CondDegreeMixChangeOrig(MHproposal *MHp, Network *nwp)  {  
  Vertex A1, A2, B1, B2;
  int b;
  int bb, bbb=0;
  
  if(MHp->ntoggles == 0) { /* Initialize */
    MHp->ntoggles=4;    
    return;
  }
//  Rprintf("0 %f 1 %f 2 %f 3 %f\n",MHp->inputs[0],MHp->inputs[1],MHp->inputs[2],MHp->inputs[3]); 
//  Rprintf("0 %f 1 %f 2 %f 3 %f\n",MHp->inputs[4],MHp->inputs[5],MHp->inputs[6],MHp->inputs[7]); 
//  Rprintf("0 %f 1 %f 2 %f 3 %f\n",MHp->inputs[8],MHp->inputs[9],MHp->inputs[10],MHp->inputs[11]); 

  do{
    GetRandEdge(&A1, &A2, nwp);
    GetRandEdge(&B1, &B2, nwp);
    bb=(unif_rand() > 0.05);
    bbb++;
    if(bb){
//  if(unif_rand() > 0.5){
//  Less
  	 b=((fabs(MHp->inputs[A1-1]-MHp->inputs[A2-1])<0.001)||(fabs(MHp->inputs[B2-1]-MHp->inputs[B1-1])<0.001)||(fabs(MHp->inputs[A1-1]-MHp->inputs[B1-1])<0.001));
    }else{
//  More
  	 b=((fabs(MHp->inputs[A1-1]-MHp->inputs[A2-1])>0.001)||(fabs(MHp->inputs[B2-1]-MHp->inputs[B1-1])>0.001)||(fabs(MHp->inputs[A1-1]-MHp->inputs[B1-1])<0.001));
    }
//    if(unif_rand() > 0.999){
//Rprintf("A1 %d A2 %d B1 %d B2 %d\n",A1,A2,B1,B2); 
//Rprintf("g: A1 %f A2 %f B1 %f B2 %f\n",MHp->inputs[A1-1],MHp->inputs[A2-1],MHp->inputs[B1-1],MHp->inputs[B2-1]); 
//}
  }while(
  	 (bbb<20) || b || A1==B1 || A1==B2 || A2==B1 || A2==B2 || 
	 (nwp->directed_flag ? 
	  IS_OUTEDGE(A1, B2) || IS_OUTEDGE(B1, A2) : // Directed
	  IS_UNDIRECTED_EDGE(A1,B2) || IS_UNDIRECTED_EDGE(B1,A2) // Undirected
	  ));
//Rprintf("in A1 %d A2 %d B1 %d B2 %d\n",A1,A2,B1,B2); 
//Rprintf("%d: A1 %f A2 %f B1 %f B2 %f\n",bb,MHp->inputs[A1-1],MHp->inputs[A2-1],MHp->inputs[B1-1],MHp->inputs[B2-1]); 
 if(bbb==20){
   Mtail[0]=A1; Mhead[0]=A2;
   Mtail[1]=A1; Mhead[1]=A2;
   Mtail[2]=B1; Mhead[2]=B2;
   Mtail[3]=B1; Mhead[3]=B2;
  }else{
   Mtail[0]=A1; Mhead[0]=A2;
   Mtail[1]=A1; Mhead[1]=B2;
   Mtail[2]=B1; Mhead[2]=B2;
   Mtail[3]=B1; Mhead[3]=A2;
  }
}
Example #5
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);
      }
    });
Example #6
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]);  */
}
Example #7
0
void MH_CondB2Degree(MHproposal *MHp, Network *nwp)  {  
  Vertex A1, A2, B1;
  
  if(MHp->ntoggles == 0) { /* Initialize */
    MHp->ntoggles=2;
    return;
  }

  do{
    GetRandEdge(&A1, &A2, nwp);
    B1 = 1 + unif_rand() * nwp->bipartite;
  }while(A1==B1 || A2==B1 || EdgetreeSearch(B1, A2, nwp->outedges));

//Rprintf("A1 %d A2 %d B1 %d B2 %d\n",A1,A2,B1,B2); 
//Rprintf("in A1 %d A2 %d B1 %d B2 %d\n",A1,A2,B1,B2); 
  Mtail[0]=A1; Mhead[0]=A2;
  Mtail[1]=B1; Mhead[1]=A2;
}
Example #8
0
void MH_CondDegreeMix(MHproposal *MHp, Network *nwp)  {  
  Vertex A11, A12, B11, B12;
  Vertex A21, A22, B21, B22;
  int bad;
  /* int goodtype; */
  int pm, numtrys;
  
  if(MHp->ntoggles == 0) { /* Initialize */
    MHp->ntoggles=8;    
    return;
  }

  numtrys=0;
  pm=(unif_rand() > 0.5);
  if(pm){
  do{
    GetRandEdge(&A11, &A12, nwp);
    GetRandEdge(&B11, &B12, nwp);
    numtrys++;
  	bad=((fabs(MHp->inputs[A11-1]-MHp->inputs[A12-1])<0.001)&(fabs(MHp->inputs[B12-1]-MHp->inputs[B11-1])<0.001)&(fabs(MHp->inputs[A11-1]-MHp->inputs[B11-1])>0.001));
    /* goodtype = 2; */
  }while(
  	 (numtrys<1000) && ((!bad) || A11==B11 || A11==B12 || A12==B11 || A12==B12 || 
	 (nwp->directed_flag ? 
	  IS_OUTEDGE(A11, B12) || IS_OUTEDGE(B11, A12) : // Directed
	  IS_UNDIRECTED_EDGE(A11,B12) || IS_UNDIRECTED_EDGE(B11,A12) // Undirected
	  )));
  do{
    GetRandEdge(&A21, &A22, nwp);
    GetRandEdge(&B21, &B22, nwp);
    numtrys++;
  	bad=((fabs(MHp->inputs[A21-1]-MHp->inputs[A22-1])>0.001)&(fabs(MHp->inputs[B22-1]-MHp->inputs[B21-1])>0.001)&(fabs(MHp->inputs[A21-1]-MHp->inputs[B22-1])<0.001));
    /* goodtype = 0; */
  }while(
  	 (numtrys<1000) && ((!bad) || A21==B21 || A21==B22 || A22==B21 || A22==B22 || 
	 (nwp->directed_flag ? 
	  IS_OUTEDGE(A21, B22) || IS_OUTEDGE(B21, A22) : // Directed
	  IS_UNDIRECTED_EDGE(A21,B22) || IS_UNDIRECTED_EDGE(B21,A22) // Undirected
	  )));
 }else{
  do{
    GetRandEdge(&A11, &A12, nwp);
    GetRandEdge(&B11, &B12, nwp);
    numtrys++;
  	bad=((fabs(MHp->inputs[A11-1]-MHp->inputs[A12-1])<0.001)&(fabs(MHp->inputs[B12-1]-MHp->inputs[B11-1])<0.001)&(fabs(MHp->inputs[A11-1]-MHp->inputs[B11-1])<0.001));
    /* goodtype = 3; */
  }while(
  	 (numtrys<1000) && ((!bad) || A11==B11 || A11==B12 || A12==B11 || A12==B12 || 
	 (nwp->directed_flag ? 
	  IS_OUTEDGE(A11, B12) || IS_OUTEDGE(B11, A12) : // Directed
	  IS_UNDIRECTED_EDGE(A11,B12) || IS_UNDIRECTED_EDGE(B11,A12) // Undirected
	  )));
  do{
    GetRandEdge(&A21, &A22, nwp);
    GetRandEdge(&B21, &B22, nwp);
    numtrys++;
  	bad=((fabs(MHp->inputs[A21-1]-MHp->inputs[A22-1])>0.001)&(fabs(MHp->inputs[B22-1]-MHp->inputs[B21-1])>0.001)&(fabs(MHp->inputs[A21-1]-MHp->inputs[B22-1])>0.001));
    /* goodtype = 4;*/
  }while(
  	 (numtrys<1000) && ((!bad) || A21==B21 || A21==B22 || A22==B21 || A22==B22 || 
	 (nwp->directed_flag ? 
	  IS_OUTEDGE(A21, B22) || IS_OUTEDGE(B21, A22) : // Directed
	  IS_UNDIRECTED_EDGE(A21,B22) || IS_UNDIRECTED_EDGE(B21,A22) // Undirected
	  )));
 }
//Rprintf("try %d bad %d (A1==B1 || A1==B2 || A2==B1 || A2==B2) %d edge %d\n",numtrys,bad,(A1==B1 || A1==B2 || A2==B1 || A2==B2), (IS_UNDIRECTED_EDGE(A1,B2) || IS_UNDIRECTED_EDGE(B1,A2))); 

//if(numtrys < 1000){
//Rprintf("A11 %d A12 %d B11 %d B12 %d numtrys %d type %d\n",A11,A12,B11,B12,numtrys,goodtype); 
//}
 if(numtrys==1000){
   Mtail[0]=A11; Mhead[0]=A12;
   Mtail[1]=A11; Mhead[1]=A12;
   Mtail[2]=B11; Mhead[2]=B12;
   Mtail[3]=B11; Mhead[3]=B12;
   Mtail[4]=A21; Mhead[4]=A22;
   Mtail[5]=A21; Mhead[5]=A22;
   Mtail[6]=B21; Mhead[6]=B22;
   Mtail[7]=B21; Mhead[7]=B22;
// MHp->toggletail[0]=MH_FAILED;
// MHp->togglehead[0]=MH_UNSUCCESSFUL;
  }else{
   Mtail[0]=A11; Mhead[0]=A12;
   Mtail[1]=A11; Mhead[1]=B12;
   Mtail[2]=B11; Mhead[2]=B12;
   Mtail[3]=B11; Mhead[3]=A12;
   Mtail[4]=A21; Mhead[4]=A22;
   Mtail[5]=A21; Mhead[5]=B22;
   Mtail[6]=B21; Mhead[6]=B22;
   Mtail[7]=B21; Mhead[7]=A22;
  }
}
Example #9
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]);  */
}