void assignUpWeights(edge *etest, node *vtest, node *va, edge *back, node *cprev, double oldD_AB, double coeff, double **A, double ***swapWeights) { /*SPR performed on tree above vtest...*/ /*same idea as above, with appropriate selections of edges and nodes*/ edge *sib, *left, *right; /*B is above vtest, A is other tree below vtest unioned with trees in path to vtest*/ /*sib is tree C being passed by B*/ /*D is tree below etest*/ double D_AB, D_CD, D_AC, D_BD; // double thisWeight; deleted by EP, 2013-09-16, also below sib = siblingEdge(etest); left = etest->head->leftEdge; right = etest->head->rightEdge; if (NULL == back) /*first recursive call*/ { if (NULL == left) return; else /*start the process of assigning weights recursively*/ { assignUpWeights(left,vtest,va,etest,va,A[va->index][vtest->index],0.5,A,swapWeights); assignUpWeights(right,vtest,va,etest,va,A[va->index][vtest->index],0.5,A,swapWeights); } } else /*second or later recursive call*/ { D_BD = A[vtest->index][etest->head->index]; D_CD = A[sib->head->index][etest->head->index]; D_AC = A[back->head->index][sib->head->index] + coeff*(A[va->index][sib->head->index] - A[vtest->index][sib->head->index]); D_AB = 0.5*(oldD_AB + A[vtest->index][cprev->index]); // thisWeight = deleted by EP, 2013-09-16 swapWeights[1][vtest->index][etest->head->index] = swapWeights[1][vtest->index][back->head->index] + (D_AC + D_BD - D_AB - D_CD); if (NULL != left) { assignUpWeights(left,vtest, va, etest, sib->head, D_AB, 0.5*coeff, A, swapWeights); assignUpWeights(right,vtest, va, etest, sib->head, D_AB, 0.5*coeff, A, swapWeights); } } }
void BalWFext(meEdge *e, double **A) /*works except when e is the one edge inserted to new vertex v by firstInsert*/ { meEdge *f, *g; if ((leaf(e->head)) && (leaf(e->tail))) e->distance = A[e->head->index][e->head->index]; else if (leaf(e->head)) { f = e->tail->parentEdge; g = siblingEdge(e); e->distance = 0.5*(A[e->head->index][g->head->index] + A[e->head->index][f->head->index] - A[g->head->index][f->head->index]); } else { f = e->head->leftEdge; g = e->head->rightEdge; e->distance = 0.5*(A[g->head->index][e->head->index] + A[f->head->index][e->head->index] - A[f->head->index][g->head->index]); } }
void assignDownWeightsDown (edge *etest, node *vtest, node *va, edge *back, node *cprev, double oldD_AB, double coeff, double **A, double ***swapWeights) { /* again the same general idea */ edge *sib, *left, *right; /* sib here = par in assignDownWeightsSkew * rest is the same as assignDownWeightsSkew */ double D_AB, D_CD, D_AC, D_BD; /* B is below vtest, A is below va unioned with all trees already passed by B * C is subtree being passed - below sib * D is tree below etest */ sib = siblingEdge (etest); left = etest->head->leftEdge; right = etest->head->rightEdge; D_BD = A[vtest->index][etest->head->index]; D_CD = A[sib->head->index][etest->head->index]; D_AC = A[sib->head->index][back->head->index] + coeff * (A[sib->head->index][va->index] - A[sib->head->index][vtest->index]); D_AB = 0.5 * (oldD_AB + A[vtest->index][cprev->index]); swapWeights[0][vtest->index][etest->head->index] = swapWeights[0][vtest->index][back->head->index] + ( D_AC + D_BD - D_AB - D_CD); if (NULL != left) { assignDownWeightsDown (left, vtest, va, etest, sib->head, D_AB, 0.5 * coeff, A, swapWeights); assignDownWeightsDown (right, vtest, va, etest, sib->head, D_AB, 0.5 * coeff, A, swapWeights); } return; }
void bNNItopSwitch(meTree *T, meEdge *e, int direction, double **A) { meEdge *down, *swap, *fixed; meNode *u, *v; if (verbose) { printf("Performing branch swap across edge %s ",e->label); printf("with "); if (LEFT == direction) printf("left "); else printf("right "); printf("subtree.\n"); } down = siblingEdge(e); u = e->tail; v = e->head; if (LEFT == direction) { swap = e->head->leftEdge; fixed = e->head->rightEdge; v->leftEdge = down; } else { swap = e->head->rightEdge; fixed = e->head->leftEdge; v->rightEdge = down; } swap->tail = u; down->tail = v; if(e->tail->leftEdge == e) u->rightEdge = swap; else u->leftEdge = swap; bNNIupdateAverages(A, v, e->tail->parentEdge, down, swap, fixed); }
void TBR(tree *T, double **D, double **A) { int i; edge *esplit, *etop, *eBestTop, *eBestBottom, *eBestSplit; edge *eout, *block; edge *left, *right, *par, *sib; double **dXTop; /*dXTop[i][j] is average distance from subtree rooted at i to tree above split edge, if SPR above split edge cuts edge whose head has index j*/ double bestWeight; double ***TBRWeights; dXTop = initDoubleMatrix(T->size); weighTree(T); TBRWeights = (double ***)calloc(T->size,sizeof(double **)); for(i=0;i<T->size;i++) TBRWeights[i] = initDoubleMatrix(T->size); do { zero3DMatrix(TBRWeights,T->size,T->size,T->size); bestWeight = 0.0; eBestSplit = eBestTop = eBestBottom = NULL; for(esplit=depthFirstTraverse(T,NULL);NULL!=esplit;esplit=depthFirstTraverse(T,esplit)) { par = esplit->tail->parentEdge; if (NULL != par) { sib = siblingEdge(esplit); /*next two lines calculate the possible improvements for any SPR above esplit*/ assignTBRDownWeightsUp(par,esplit->head,sib->head,NULL,NULL,0.0,1.0,A,TBRWeights,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom); assignTBRDownWeightsSkew(sib,esplit->head,sib->tail,NULL,NULL,0.0,1.0,A,TBRWeights,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom); calcTBRaverages(T,esplit,A,dXTop); /*calculates the average distance from any subtree below esplit to the entire subtree above esplit, after any possible SPR above*/ /*for etop above esplit, we loop using information from above to calculate values for all possible SPRs below esplit*/ } right = esplit->head->rightEdge; if (NULL != right) { left = esplit->head->leftEdge; /*test case: etop = null means only do bottom SPR*/ assignTBRUpWeights(left,esplit->head,right->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,NULL,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom); assignTBRUpWeights(right,esplit->head,left->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,NULL,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom); block = esplit; while (NULL != block) { if (block != esplit) { etop = block; assignTBRUpWeights(left,esplit->head,right->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom); assignTBRUpWeights(right,esplit->head,left->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom); } eout = siblingEdge(block); if (NULL != eout) { etop = findBottomLeft(eout); while (etop->tail != eout->tail) { /*for ebottom below esplit*/ assignTBRUpWeights(left,esplit->head,right->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom); assignTBRUpWeights(right,esplit->head,left->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom); etop = depthFirstTraverse(T,etop); } /*etop == eout*/ assignTBRUpWeights(left,esplit->head,right->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom); assignTBRUpWeights(right,esplit->head,left->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom); } block = block->tail->parentEdge; } } /*if NULL != right*/ } /*for esplit*/ /*find bestWeight, best split edge, etc.*/ if (bestWeight < -EPSILON) { // if (verbose) // { // printf("TBR #%d: Splitting edge %s: top edge %s, bottom edge %s\n",*count+1, // eBestSplit->label, eBestTop->label,eBestBottom->label); // printf("Old tree weight is %lf, new tree weight should be %lf\n",T->weight, T->weight + 0.25*bestWeight); // } TBRswitch(T,eBestSplit,eBestTop,eBestBottom); makeBMEAveragesTable(T,D,A); assignBMEWeights(T,A); weighTree(T); // if (verbose) // printf("TBR: new tree weight is %lf\n\n",T->weight);< // (*count)++; } else bestWeight = 1.0; } while (bestWeight < -EPSILON); for(i=0;i<T->size;i++) freeMatrix(TBRWeights[i],T->size); freeMatrix(dXTop,T->size); }
void assignTBRUpWeights(edge *ebottom, node *vtest, node *va, edge *back, node *cprev, double oldD_AB, double coeff, double **A, double **dXTop, double ***swapWeights, edge *etop, double *bestWeight, edge **bestSplit, edge **bestTop, edge **bestBottom) /*function assigns the value for etop if the tree below vtest is moved to be below etop*/ /*and SPR for tree bottom tree splits ebottom*/ /*recursive function searching over values of ebottom*/ /*minor variant of SPR.c's assignUpWeights difference is the index assignment in the array swapWeights, which has a different meaning for the TBR routines*/ /*also using dXTop to assign value of average distance to tree above vtest*/ { /*SPR performed on tree above vtest...*/ edge *sib, *left, *right; /*B is above vtest, A is other tree below vtest unioned with trees in path to vtest*/ /*sib is tree C being passed by B*/ /*D is tree below etest*/ double D_AB, D_CD, D_AC, D_BD; sib = siblingEdge(ebottom); left = ebottom->head->leftEdge; right = ebottom->head->rightEdge; if (NULL == etop) { if (NULL == back) /*first recursive call*/ { if (NULL == left) return; /*no subtree below for SPR*/ else /*NULL == back and NULL == etop*/ { assignTBRUpWeights(left,vtest,va,ebottom,va,A[va->index][vtest->index],0.5,A,dXTop,swapWeights,NULL,bestWeight,bestSplit,bestTop,bestBottom); assignTBRUpWeights(right,vtest,va,ebottom,va,A[va->index][vtest->index],0.5,A,dXTop,swapWeights,NULL,bestWeight,bestSplit,bestTop,bestBottom); } } else /*NULL != back*/ { D_BD = A[ebottom->head->index][vtest->index]; /*B is tree above vtest, D is tree below ebottom*/ D_CD = A[sib->head->index][ebottom->head->index]; /*C is tree below sib*/ D_AC = A[back->head->index][sib->head->index] + coeff*(A[va->index][sib->head->index] - A[vtest->index][sib->head->index]); /*va is root of subtree skew back at vtest*/ /*A is union of tree below va and all subtrees already passed in path from vtest to ebottom*/ D_AB = 0.5*(oldD_AB + A[vtest->index][cprev->index]); swapWeights[vtest->index][ebottom->head->index][ebottom->head->index] = swapWeights[vtest->index][back->head->index][back->head->index] + (D_AC + D_BD - D_AB - D_CD); if (swapWeights[vtest->index][ebottom->head->index][ebottom->head->index] < *bestWeight) { *bestSplit = vtest->parentEdge; *bestTop = NULL; *bestBottom = ebottom; *bestWeight = swapWeights[vtest->index][ebottom->head->index][ebottom->head->index]; } if (NULL != left) { assignTBRUpWeights(left,vtest,va,ebottom,sib->head,D_AB,0.5*coeff,A,dXTop,swapWeights,NULL,bestWeight,bestSplit,bestTop,bestBottom); assignTBRUpWeights(right,vtest,va,ebottom,sib->head,D_AB,0.5*coeff,A,dXTop,swapWeights,NULL,bestWeight,bestSplit,bestTop,bestBottom); } } } else /*NULL != etop*/ { if (NULL == back) /*first recursive call*/ { if (swapWeights[vtest->index][etop->head->index][etop->head->index]< *bestWeight) /*this represents value of SPR from esplit to etop, with no SPR in bottom tree*/ { *bestSplit = vtest->parentEdge; *bestTop = etop; *bestBottom = NULL; *bestWeight = swapWeights[vtest->index][etop->head->index][etop->head->index]; } if (NULL == left) return; /*no subtree below for SPR*/ else if (NULL != etop)/*start the process of assigning weights recursively*/ { assignTBRUpWeights(left,vtest,va,ebottom,va,dXTop[va->index][etop->head->index],0.5,A,dXTop,swapWeights,etop,bestWeight,bestSplit,bestTop,bestBottom); assignTBRUpWeights(right,vtest,va,ebottom,va,dXTop[va->index][etop->head->index],0.5,A,dXTop,swapWeights,etop,bestWeight,bestSplit,bestTop,bestBottom); } } /*NULL == back*/ /*in following bit, any average distance of form A[vtest->index][x->index] is replaced by dXTop[x->index][etop->head->index]*/ else /*second or later recursive call, NULL != etop*/ { D_BD = dXTop[ebottom->head->index][etop->head->index]; /*B is tree above vtest - it is in configuration indexed by etop*/ /*D is tree below ebottom*/ D_CD = A[sib->head->index][ebottom->head->index]; /*C is tree below sib*/ D_AC = A[back->head->index][sib->head->index] + coeff*(A[va->index][sib->head->index] - A[sib->head->index][vtest->index]); /*it is correct to use A[][] here because the bad average distances involving B from the first term will be cancelled by the bad average distances involving B in the subtracted part*/ /*va is root of subtree skew back at vtest*/ /*A is union of tree below va and all subtrees already passed in path from vtest to ebottom*/ D_AB = 0.5*(oldD_AB + dXTop[cprev->index][etop->head->index]); swapWeights[vtest->index][ebottom->head->index][etop->head->index] = swapWeights[vtest->index][back->head->index][etop->head->index] + (D_AC + D_BD - D_AB - D_CD); if (swapWeights[vtest->index][ebottom->head->index][etop->head->index] + swapWeights[vtest->index][etop->head->index][etop->head->index]< *bestWeight) /*first term is contribution of second SPR, second term is contribution of first SPR*/ { *bestSplit = vtest->parentEdge; *bestTop = etop; *bestBottom = ebottom; *bestWeight = swapWeights[vtest->index][ebottom->head->index][etop->head->index] + swapWeights[vtest->index][etop->head->index][etop->head->index]; } if (NULL != left) { assignTBRUpWeights(left,vtest, va, ebottom, sib->head, D_AB, 0.5*coeff, A, dXTop, swapWeights,etop,bestWeight,bestSplit,bestTop,bestBottom); assignTBRUpWeights(right,vtest, va, ebottom, sib->head, D_AB, 0.5*coeff, A, dXTop, swapWeights,etop,bestWeight,bestSplit,bestTop,bestBottom); } } /*else NULL != back, etop*/ } }
/* An inelegant iterative version */ void SPRUpShift (node *vmove, edge *esplit) { edge *f; edge **EPath; edge **sib; node **v; int i; int pathLength; for (f=esplit->tail->parentEdge,pathLength=1; f->tail != vmove; f=f->tail->parentEdge) pathLength++; /* count number of edges to vmove * note that pathLength > 0 will hold */ EPath = (edge **) mCalloc (pathLength, sizeof(edge *)); v = (node **) mCalloc (pathLength, sizeof(edge *)); sib = (edge **) mCalloc ((pathLength+1), sizeof(edge *)); /* there are pathLength + 1 side trees, one at the head and tail of each edge in the path */ sib[pathLength] = siblingEdge (esplit); i = pathLength; f = esplit->tail->parentEdge; while (i > 0) { i--; EPath[i] = f; sib[i] = siblingEdge (f); v[i] = f->head; f = f->tail->parentEdge; } /* indexed so head of Epath is v[i], tail is v[i-1] and sibling edge is sib[i] * need to assign head, tail of each edge in path * as well as have proper values for the left and right fields */ if (esplit == esplit->tail->leftEdge) { vmove->leftEdge = esplit; vmove->rightEdge = EPath[pathLength-1]; } else { vmove->rightEdge = esplit; vmove->leftEdge = EPath[pathLength-1]; } esplit->tail = vmove; /* espilt->head remains unchanged * vmove has the proper fields for left, right, and parentEdge */ for(i=0; i<(pathLength-1); i++) EPath[i]->tail = v[i+1]; /* this bit flips the orientation along the path * the tail of Epath[i] is now v[i+1] instead of v[i-1] */ EPath[pathLength-1]->tail = vmove; for (i=1; i<pathLength; i++) { if (sib[i+1] == v[i]->leftEdge) v[i]->rightEdge = EPath[i-1]; else v[i]->leftEdge = EPath[i-1]; } if (sib[1] == v[0]->leftEdge) v[0]->rightEdge = sib[0]; else v[0]->leftEdge = sib[0]; sib[0]->tail = v[0]; free(EPath); free(v); free(sib); return; }
int NNIEdgeTest(edge *e, tree *T, double **A, double *weight) { int a,b,c,d; edge *f; double *lambda; double D_LR, D_LU, D_LD, D_RD, D_RU, D_DU; double w1,w2,w0; if ((leaf(e->tail)) || (leaf(e->head))) return(NONE); lambda = (double *)malloc(3*sizeof(double)); a = e->tail->parentEdge->topsize; f = siblingEdge(e); b = f->bottomsize; c = e->head->leftEdge->bottomsize; d = e->head->rightEdge->bottomsize; lambda[0] = ((double) b*c + a*d)/((a + b)*(c+d)); lambda[1] = ((double) b*c + a*d)/((a + c)*(b+d)); lambda[2] = ((double) c*d + a*b)/((a + d)*(b+c)); D_LR = A[e->head->leftEdge->head->index][e->head->rightEdge->head->index]; D_LU = A[e->head->leftEdge->head->index][e->tail->index]; D_LD = A[e->head->leftEdge->head->index][f->head->index]; D_RU = A[e->head->rightEdge->head->index][e->tail->index]; D_RD = A[e->head->rightEdge->head->index][f->head->index]; D_DU = A[e->tail->index][f->head->index]; w0 = wf2(lambda[0],D_RU,D_LD,D_LU,D_RD,D_DU,D_LR); w1 = wf2(lambda[1],D_RU,D_LD,D_DU,D_LR,D_LU,D_RD); w2 = wf2(lambda[2],D_DU,D_LR,D_LU,D_RD,D_RU,D_LD); free(lambda); if (w0 <= w1) { if (w0 <= w2) /*w0 <= w1,w2*/ { *weight = 0.0; return(NONE); } else /*w2 < w0 <= w1 */ { *weight = w2 - w0; /* if (verbose) { printf("Swap across %s. ",e->label); printf("Weight dropping by %lf.\n",w0 - w2); printf("New weight should be %lf.\n",T->weight + w2 - w0); }*/ return(RIGHT); } } else if (w2 <= w1) /*w2 <= w1 < w0*/ { *weight = w2 - w0; /* if (verbose) { printf("Swap across %s. ",e->label); printf("Weight dropping by %lf.\n",w0 - w2); printf("New weight should be %lf.\n",T->weight + w2 - w0); }*/ return(RIGHT); } else /*w1 < w2, w0*/ { *weight = w1 - w0; /* if (verbose) { printf("Swap across %s. ",e->label); printf("Weight dropping by %lf.\n",w0 - w1); printf("New weight should be %lf.\n",T->weight + w1 - w0); }*/ return(LEFT); } }
//void NNI(tree *T, double **avgDistArray, int *count) void NNI(tree *T, double **avgDistArray, int *count, double **D, int numSpecies) { edge *e, *centerEdge; edge **edgeArray; int *location; int *p,*q; int i,j; int possibleSwaps; double *weights; p = initPerm(T->size+1); q = initPerm(T->size+1); edgeArray = (edge **) malloc((T->size+1)*sizeof(double)); weights = (double *) malloc((T->size+1)*sizeof(double)); location = (int *) malloc((T->size+1)*sizeof(int)); double epsilon = 0.0; for (i=0; i<numSpecies; i++) for (j=0; j<numSpecies; j++) epsilon += D[i][j]; epsilon = (epsilon / (numSpecies * numSpecies)) * EPSILON; for (i=0;i<T->size+1;i++) { weights[i] = 0.0; location[i] = NONE; } e = findBottomLeft(T->root->leftEdge); /* *count = 0; */ while (NULL != e) { edgeArray[e->head->index+1] = e; location[e->head->index+1] = NNIEdgeTest(e,T,avgDistArray,weights + e->head->index + 1); e = depthFirstTraverse(T,e); } possibleSwaps = makeThreshHeap(p,q,weights,T->size+1,0.0); permInverse(p,q,T->size+1); /*we put the negative values of weights into a heap, indexed by p with the minimum value pointed to by p[1]*/ /*p[i] is index (in edgeArray) of edge with i-th position in the heap, q[j] is the position of edge j in the heap */ while (weights[p[1]] + epsilon < 0) { centerEdge = edgeArray[p[1]]; (*count)++; T->weight = T->weight + weights[p[1]]; NNItopSwitch(T,edgeArray[p[1]],location[p[1]],avgDistArray); location[p[1]] = NONE; weights[p[1]] = 0.0; /*after the NNI, this edge is in optimal configuration*/ popHeap(p,q,weights,possibleSwaps--,1); /*but we must retest the other four edges*/ e = centerEdge->head->leftEdge; NNIRetestEdge(p,q,e,T,avgDistArray,weights,location,&possibleSwaps); e = centerEdge->head->rightEdge; NNIRetestEdge(p,q,e,T,avgDistArray,weights,location,&possibleSwaps); e = siblingEdge(centerEdge); NNIRetestEdge(p,q,e,T,avgDistArray,weights,location,&possibleSwaps); e = centerEdge->tail->parentEdge; NNIRetestEdge(p,q,e,T,avgDistArray,weights,location,&possibleSwaps); } free(p); free(q); free(location); free(edgeArray); }
int bNNIEdgeTest(meEdge *e, meTree *T, double **A, double *weight) { meEdge *f; double D_LR, D_LU, D_LD, D_RD, D_RU, D_DU; double w1,w2,w0; /*if (verbose) printf("Branch swap: testing edge %s.\n",e->label);*/ if ((leaf(e->tail)) || (leaf(e->head))) return(NONE); f = siblingEdge(e); D_LR = A[e->head->leftEdge->head->index][e->head->rightEdge->head->index]; D_LU = A[e->head->leftEdge->head->index][e->tail->index]; D_LD = A[e->head->leftEdge->head->index][f->head->index]; D_RU = A[e->head->rightEdge->head->index][e->tail->index]; D_RD = A[e->head->rightEdge->head->index][f->head->index]; D_DU = A[e->tail->index][f->head->index]; w0 = wf5(D_RU,D_LD,D_LU,D_RD,D_DU,D_LR); /*weight of current config*/ w1 = wf5(D_RU,D_LD,D_DU,D_LR,D_LU,D_RD); /*weight with L<->D switch*/ w2 = wf5(D_DU,D_LR,D_LU,D_RD,D_RU,D_LD); /*weight with R<->D switch*/ if (w0 <= w1) { if (w0 <= w2) /*w0 <= w1,w2*/ { *weight = 0.0; return(NONE); } else /*w2 < w0 <= w1 */ { *weight = w2 - w0; if (verbose) { printf("Possible swap across %s. ",e->label); printf("Weight dropping by %lf.\n",w0 - w2); printf("New weight would be %lf.\n",T->weight + w2 - w0); } return(RIGHT); } } else if (w2 <= w1) /*w2 <= w1 < w0*/ { *weight = w2 - w0; if (verbose) { printf("Possible swap across %s. ",e->label); printf("Weight dropping by %lf.\n",w0 - w2); printf("New weight should be %lf.\n",T->weight + w2 - w0); } return(RIGHT); } else /*w1 < w2, w0*/ { *weight = w1 - w0; if (verbose) { printf("Possible swap across %s. ",e->label); printf("Weight dropping by %lf.\n",w0 - w1); printf("New weight should be %lf.\n",T->weight + w1 - w0); } return(LEFT); } }
int bNNIEdgeTest (edge *e, tree *T, double **A, double *weight) { edge *f; double D_LR, D_LU, D_LD, D_RD, D_RU, D_DU; double w1, w2, w0; if ((leaf(e->tail)) || (leaf(e->head))) return (NONE); f = siblingEdge (e); D_LR = A[e->head->leftEdge->head->index][e->head->rightEdge->head->index]; D_LU = A[e->head->leftEdge->head->index][e->tail->index]; D_LD = A[e->head->leftEdge->head->index][f->head->index]; D_RU = A[e->head->rightEdge->head->index][e->tail->index]; D_RD = A[e->head->rightEdge->head->index][f->head->index]; D_DU = A[e->tail->index][f->head->index]; w0 = wf5 (D_RU, D_LD, D_LU, D_RD, D_DU, D_LR); // weight of current config w1 = wf5 (D_RU, D_LD, D_DU, D_LR, D_LU, D_RD); // weight with L<->D switch w2 = wf5 (D_DU, D_LR, D_LU, D_RD, D_RU, D_LD); // weight with R<->D switch if (w0 <= w1) { if (w0 <= w2) // w0 <= w1,w2 { *weight = 0.0; return (NONE); } else // w2 < w0 <= w1 { *weight = w2 - w0; if (verbose > 2 && !isBoostrap) { Debug ( (char*)"Possible swap across '%s'. Weight dropping by %f.", e->label, w0 - w2); Debug ( (char*)"New tree length should be %f.", T->weight + w2 - w0); } return (RIGHT); } } else if (w2 <= w1) // w2 <= w1 < w0 { *weight = w2 - w0; if (verbose > 2 && !isBoostrap) { Debug ( (char*)"Possible swap across '%s'. Weight dropping by %f.", e->label, w0 - w2); Debug ( (char*)"New tree length should be %f.", T->weight + w2 - w0); } return(RIGHT); } else // w1 < w2, w0 { *weight = w1 - w0; if (verbose > 2 && !isBoostrap) { Debug ( (char*)"Possible swap across '%s'. Weight dropping by %f.", e->label, w0 - w1); Debug ( (char*)"New tree length should be %f.", T->weight + w1 - w0); } return(LEFT); } }
void updateSubTreeAfterNNI (double **A, node *v, edge *rootEdge, node *closer, node *further, double dcoeff, int direction) { edge *sib; switch (direction) { case UP : /* rootEdge is below the center edge of the NNI * recursive calls to subtrees, if necessary */ if (NULL != rootEdge->head->leftEdge) updateSubTreeAfterNNI (A, v, rootEdge->head->leftEdge, closer, further, 0.5 * dcoeff, UP); if (NULL != rootEdge->head->rightEdge) updateSubTreeAfterNNI (A, v, rootEdge->head->rightEdge, closer, further, 0.5 * dcoeff, UP); updatePair (A, rootEdge, rootEdge, closer, further, dcoeff, UP); sib = siblingEdge (v->parentEdge); A[rootEdge->head->index][v->index] = A[v->index][rootEdge->head->index] = 0.5 * A[rootEdge->head->index][sib->head->index] + 0.5 * A[rootEdge->head->index][v->parentEdge->tail->index]; break; case DOWN : /* rootEdge is above the center edge of the NNI */ sib = siblingEdge (rootEdge); if (NULL != sib) updateSubTreeAfterNNI (A, v, sib, closer, further, 0.5 * dcoeff, SKEW); if (NULL != rootEdge->tail->parentEdge) updateSubTreeAfterNNI (A, v, rootEdge->tail->parentEdge, closer, further, 0.5 * dcoeff, DOWN); updatePair (A, rootEdge, rootEdge, closer, further, dcoeff, DOWN); A[rootEdge->head->index][v->index] = A[v->index][rootEdge->head->index] = 0.5 * A[rootEdge->head->index][v->leftEdge->head->index] + 0.5 * A[rootEdge->head->index][v->rightEdge->head->index]; break; case SKEW : /* rootEdge is in subtree skew to v */ if (NULL != rootEdge->head->leftEdge) updateSubTreeAfterNNI (A, v, rootEdge->head->leftEdge, closer, further, 0.5 * dcoeff, SKEW); if (NULL != rootEdge->head->rightEdge) updateSubTreeAfterNNI (A, v, rootEdge->head->rightEdge, closer, further, 0.5 * dcoeff, SKEW); updatePair (A, rootEdge, rootEdge, closer, further, dcoeff, UP); A[rootEdge->head->index][v->index] = A[v->index][rootEdge->head->index] = 0.5 * A[rootEdge->head->index][v->leftEdge->head->index] + 0.5 * A[rootEdge->head->index][v->rightEdge->head->index]; break; } return; }