1 /* #include <stdio.h> */
2 /* #include <stdlib.h> */
3 /* #include <math.h> */
4 /* #include "graph.h" */
5 /* #include <string.h> */
8 /*functions from me_balanced.c*/
9 void makeBMEAveragesTable(tree *T, double **D, double **A);
10 void assignBMEWeights(tree *T, double **A);
13 edge *siblingEdge(edge *e);
14 double **initDoubleMatrix(int d);
15 void freeMatrix(double **D, int size);
16 edge *depthFirstTraverse(tree *T, edge *e);
17 edge *findBottomLeft(edge *e);
20 void weighTree(tree *T);
22 void freeTree(tree *T);
25 void zero3DMatrix(double ***X, int h, int l, int w);
27 void assignTBRDownWeightsUp(edge *etest, node *vtest, node *va, edge *back, node *cprev, double oldD_AB, double coeff, double **A, double ***swapWeights,
28 double *bestWeight, edge **eBestSplit, edge **eBestTop, edge **eBestBottom);
29 void assignTBRDownWeightsSkew(edge *etest, node *vtest, node *va, edge *back, node *cprev, double oldD_AB, double coeff, double **A, double ***swapWeights,
30 double *bestWeight, edge **eBestSplit, edge **eBestTop, edge **eBestBototm);
31 void assignTBRDownWeightsDown(edge *etest, node *vtest, node *va, edge *back, node *cprev, double oldD_AB, double coeff, double **A, double ***swapWeights,
32 double *bestWeight, edge **eBestSplit, edge **eBestTop, edge **eBestBottom);
34 void assignTBRUpWeights(edge *ebottom, node *vtest, node *va, edge *back, node *cprev, double oldD_AB, double coeff, double **A,
35 double **dXTop, double ***swapWeights, edge *etop, double *bestWeight,
36 edge **bestSplit, edge **bestTop, edge **bestBottom)
37 /*function assigns the value for etop if the tree below vtest is moved to be below etop*/
38 /*and SPR for tree bottom tree splits ebottom*/
39 /*recursive function searching over values of ebottom*/
40 /*minor variant of SPR.c's assignUpWeights
41 difference is the index assignment in the array swapWeights, which has a different meaning
42 for the TBR routines*/
43 /*also using dXTop to assign value of average distance to tree above vtest*/
44 { /*SPR performed on tree above vtest...*/
45 edge *sib, *left, *right;
46 /*B is above vtest, A is other tree below vtest unioned with trees in path to vtest*/
47 /*sib is tree C being passed by B*/
48 /*D is tree below etest*/
49 double D_AB, D_CD, D_AC, D_BD;
50 sib = siblingEdge(ebottom);
51 left = ebottom->head->leftEdge;
52 right = ebottom->head->rightEdge;
55 if (NULL == back) /*first recursive call*/
58 return; /*no subtree below for SPR*/
59 else /*NULL == back and NULL == etop*/
61 assignTBRUpWeights(left,vtest,va,ebottom,va,A[va->index][vtest->index],0.5,A,dXTop,swapWeights,NULL,bestWeight,bestSplit,bestTop,bestBottom);
62 assignTBRUpWeights(right,vtest,va,ebottom,va,A[va->index][vtest->index],0.5,A,dXTop,swapWeights,NULL,bestWeight,bestSplit,bestTop,bestBottom);
67 D_BD = A[ebottom->head->index][vtest->index];
68 /*B is tree above vtest, D is tree below ebottom*/
69 D_CD = A[sib->head->index][ebottom->head->index]; /*C is tree below sib*/
70 D_AC = A[back->head->index][sib->head->index] +
71 coeff*(A[va->index][sib->head->index] - A[vtest->index][sib->head->index]);
72 /*va is root of subtree skew back at vtest*/
73 /*A is union of tree below va and all subtrees already passed in path from vtest to ebottom*/
74 D_AB = 0.5*(oldD_AB + A[vtest->index][cprev->index]);
75 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);
76 if (swapWeights[vtest->index][ebottom->head->index][ebottom->head->index] < *bestWeight)
78 *bestSplit = vtest->parentEdge;
80 *bestBottom = ebottom;
81 *bestWeight = swapWeights[vtest->index][ebottom->head->index][ebottom->head->index];
85 assignTBRUpWeights(left,vtest,va,ebottom,sib->head,D_AB,0.5*coeff,A,dXTop,swapWeights,NULL,bestWeight,bestSplit,bestTop,bestBottom);
86 assignTBRUpWeights(right,vtest,va,ebottom,sib->head,D_AB,0.5*coeff,A,dXTop,swapWeights,NULL,bestWeight,bestSplit,bestTop,bestBottom);
92 if (NULL == back) /*first recursive call*/
94 if (swapWeights[vtest->index][etop->head->index][etop->head->index]< *bestWeight)
95 /*this represents value of SPR from esplit to etop, with no SPR in bottom tree*/
97 *bestSplit = vtest->parentEdge;
100 *bestWeight = swapWeights[vtest->index][etop->head->index][etop->head->index];
103 return; /*no subtree below for SPR*/
104 else if (NULL != etop)/*start the process of assigning weights recursively*/
106 assignTBRUpWeights(left,vtest,va,ebottom,va,dXTop[va->index][etop->head->index],0.5,A,dXTop,swapWeights,etop,bestWeight,bestSplit,bestTop,bestBottom);
107 assignTBRUpWeights(right,vtest,va,ebottom,va,dXTop[va->index][etop->head->index],0.5,A,dXTop,swapWeights,etop,bestWeight,bestSplit,bestTop,bestBottom);
110 /*in following bit, any average distance of form A[vtest->index][x->index] is
111 replaced by dXTop[x->index][etop->head->index]*/
112 else /*second or later recursive call, NULL != etop*/
114 D_BD = dXTop[ebottom->head->index][etop->head->index]; /*B is tree above vtest - it is in configuration
116 /*D is tree below ebottom*/
117 D_CD = A[sib->head->index][ebottom->head->index]; /*C is tree below sib*/
118 D_AC = A[back->head->index][sib->head->index] +
119 coeff*(A[va->index][sib->head->index] - A[sib->head->index][vtest->index]);
120 /*it is correct to use A[][] here because the bad average distances involving B from the first term will
121 be cancelled by the bad average distances involving B in the subtracted part*/
122 /*va is root of subtree skew back at vtest*/
123 /*A is union of tree below va and all subtrees already passed in path from vtest to ebottom*/
124 D_AB = 0.5*(oldD_AB + dXTop[cprev->index][etop->head->index]);
125 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);
126 if (swapWeights[vtest->index][ebottom->head->index][etop->head->index] + swapWeights[vtest->index][etop->head->index][etop->head->index]< *bestWeight)
127 /*first term is contribution of second SPR, second term is contribution of first SPR*/
129 *bestSplit = vtest->parentEdge;
131 *bestBottom = ebottom;
132 *bestWeight = swapWeights[vtest->index][ebottom->head->index][etop->head->index] + swapWeights[vtest->index][etop->head->index][etop->head->index];
136 assignTBRUpWeights(left,vtest, va, ebottom, sib->head, D_AB, 0.5*coeff, A, dXTop, swapWeights,etop,bestWeight,bestSplit,bestTop,bestBottom);
137 assignTBRUpWeights(right,vtest, va, ebottom, sib->head, D_AB, 0.5*coeff, A, dXTop, swapWeights,etop,bestWeight,bestSplit,bestTop,bestBottom);
139 } /*else NULL != back, etop*/
143 /*recall NNI formula: change in tree length from AB|CD split to AC|BD split is
144 proportional to D_AC + D_BD - D_AB - D_CD*/
145 /*in our case B is the tree being moved (below vtest), A is the tree backwards below back, but
146 with the vtest subtree removed, C is the sibling tree of back and D is the tree above vtest*/
147 /*use va to denote the root of the sibling tree to B in the original tree*/
148 /*please excuse the multiple uses of the same letters: A,D, etc.*/
149 void assignTBRDownWeightsUp(edge *etest, node *vtest, node *va, edge *back, node *cprev, double oldD_AB, double coeff, double **A, double ***swapWeights,
150 double *bestWeight, edge **bestSplitEdge, edge **bestTop, edge **bestBottom)
152 edge *par, *sib, *skew;
153 double D_AC, D_BD, D_AB, D_CD;
154 par = etest->tail->parentEdge;
155 skew = siblingEdge(etest);
156 if (NULL == back) /*first recursive call*/
160 else /*start the process of assigning weights recursively*/
162 assignTBRDownWeightsUp(par,vtest,va,etest,va,A[va->index][vtest->index],0.5,A,swapWeights,bestWeight,bestSplitEdge,bestTop,bestBottom);
163 assignTBRDownWeightsSkew(skew,vtest,va,etest,va,A[va->index][vtest->index],0.5,A,swapWeights,bestWeight,bestSplitEdge,bestTop,bestBottom);
166 else /*second or later recursive call*/
168 sib = siblingEdge(back);
169 D_BD = A[vtest->index][etest->head->index]; /*straightforward*/
170 D_CD = A[sib->head->index][etest->head->index]; /*this one too*/
171 D_AC = A[sib->head->index][back->head->index] + coeff*(A[sib->head->index][va->index]
172 - A[sib->head->index][vtest->index]);
173 D_AB = 0.5*(oldD_AB + A[vtest->index][cprev->index]);
174 swapWeights[vtest->index][etest->head->index][etest->head->index] = swapWeights[vtest->index][back->head->index][back->head->index] + (D_AC + D_BD - D_AB - D_CD);
175 /*using diagonal to store values for SPR swaps above the split edge*/
176 /*this is value of swapping tree below vtest to break etest*/
177 if (swapWeights[vtest->index][etest->head->index][etest->head->index] < *bestWeight)
179 *bestWeight = swapWeights[vtest->index][etest->head->index][etest->head->index];
180 *bestSplitEdge = vtest->parentEdge;
186 assignTBRDownWeightsUp(par,vtest,va,etest,sib->head,D_AB,0.5*coeff,A,swapWeights,bestWeight,bestSplitEdge,bestTop,bestBottom);
187 assignTBRDownWeightsSkew(skew,vtest,va,etest,sib->head,D_AB,0.5*coeff,A,swapWeights,bestWeight,bestSplitEdge,bestTop,bestBottom);
193 void assignTBRDownWeightsSkew(edge *etest, node *vtest, node *va, edge *back, node *cprev, double oldD_AB, double coeff, double **A, double ***swapWeights,
194 double *bestWeight, edge **bestSplitEdge, edge **bestTop, edge **bestBottom)
196 /*same general idea as assignDownWeights, except needing to keep track of things a bit differently*/
197 edge *par, *left, *right;
198 /*par here = sib before
199 left, right here = par, skew before*/
200 double D_AB, D_CD, D_AC, D_BD;
201 /*B is subtree being moved - below vtest
202 A is subtree remaining fixed - below va, unioned with all trees already passed by B*/
203 /*C is subtree being passed by B, in this case above par
204 D is subtree below etest, fixed on other side*/
205 par = etest->tail->parentEdge;
206 left = etest->head->leftEdge;
207 right = etest->head->rightEdge;
214 assignTBRDownWeightsDown(left,vtest,va,etest,etest->tail,A[vtest->index][etest->tail->index],0.5,A,swapWeights,bestWeight,bestSplitEdge,bestTop,bestBottom);
215 assignTBRDownWeightsDown(right,vtest,va,etest,etest->tail,A[vtest->index][etest->tail->index],0.5,A,swapWeights,bestWeight,bestSplitEdge,bestTop,bestBottom);
220 D_BD = A[vtest->index][etest->head->index];
221 D_CD = A[par->head->index][etest->head->index];
222 D_AC = A[back->head->index][par->head->index] + coeff*(A[va->index][par->head->index] - A[vtest->index][par->head->index]);
223 D_AB = 0.5*(oldD_AB + A[vtest->index][cprev->index]);
224 swapWeights[vtest->index][etest->head->index][etest->head->index] = swapWeights[vtest->index][back->head->index][back->head->index] + (D_AC + D_BD - D_AB - D_CD);
225 if (swapWeights[vtest->index][etest->head->index][etest->head->index] < *bestWeight)
227 *bestWeight = swapWeights[vtest->index][etest->head->index][etest->head->index];
228 *bestSplitEdge = vtest->parentEdge;
234 assignTBRDownWeightsDown(left,vtest, va, etest, etest->tail, D_AB, 0.5*coeff, A, swapWeights,bestWeight,bestSplitEdge,bestTop,bestBottom);
235 assignTBRDownWeightsDown(right,vtest, va, etest, etest->tail, D_AB, 0.5*coeff, A, swapWeights,bestWeight,bestSplitEdge,bestTop,bestBottom);
240 void assignTBRDownWeightsDown(edge *etest, node *vtest, node *va, edge *back, node *cprev, double oldD_AB, double coeff, double **A, double ***swapWeights,
241 double *bestWeight, edge **bestSplitEdge, edge **bestTop, edge **bestBottom)
243 /*again the same general idea*/
244 edge *sib, *left, *right;
245 /*sib here = par in assignDownWeightsSkew
246 rest is the same as assignDownWeightsSkew*/
247 double D_AB, D_CD, D_AC, D_BD;
248 /*B is below vtest, A is below va unioned with all trees already passed by B*/
249 /*C is subtree being passed - below sib*/
250 /*D is tree below etest*/
251 sib = siblingEdge(etest);
252 left = etest->head->leftEdge;
253 right = etest->head->rightEdge;
254 D_BD = A[vtest->index][etest->head->index];
255 D_CD = A[sib->head->index][etest->head->index];
256 D_AC = A[sib->head->index][back->head->index] + coeff*(A[sib->head->index][va->index] - A[sib->head->index][vtest->index]);
257 D_AB = 0.5*(oldD_AB + A[vtest->index][cprev->index]);
258 swapWeights[vtest->index][etest->head->index][etest->head->index] = swapWeights[vtest->index][back->head->index][back->head->index] + ( D_AC + D_BD - D_AB - D_CD);
259 if (swapWeights[vtest->index][etest->head->index][etest->head->index] < *bestWeight)
261 *bestWeight = swapWeights[vtest->index][etest->head->index][etest->head->index];
262 *bestSplitEdge = vtest->parentEdge;
268 assignTBRDownWeightsDown(left,vtest, va, etest, sib->head, D_AB, 0.5*coeff, A, swapWeights,bestWeight,bestSplitEdge,bestTop,bestBottom);
269 assignTBRDownWeightsDown(right,vtest, va, etest, sib->head, D_AB, 0.5*coeff, A, swapWeights,bestWeight,bestSplitEdge,bestTop,bestBottom);
273 /*general idea is to have a double loop for a given edge, testing all SPRs for the subtrees above and below a given edge.
274 Then that function loops over all the edges of a tree*/
276 void TBRswitch(tree *T, edge *e1, edge *e2, edge *e3);
278 /*vbottom is node below esplit for average calculations in matrix dXTop, A is matrix of average
279 distances from original tree, dXout is average distance from vbottom to tree rooted at far edge
280 of eback, if SPR breaking eback, UpOrDown indicates whether etop is in path above split edge
282 void calcTBRTopBottomAverage(node *vbottom, double **A, double **dXTop, double dXOut,
283 edge *esplit, edge *etop, edge *eback, int UpOrDown)
285 edge *enew1, *enew2, *emove;
287 if (esplit == eback) /*top level call - means trivial SPR*/
288 dXTop[vbottom->index][etop->head->index] = A[vbottom->index][esplit->head->index];
290 dXTop[vbottom->index][etop->head->index] = dXTop[vbottom->index][eback->head->index] +
291 0.25*(A[vbottom->index][etop->head->index] - dXOut);
292 /*by moving etop past the vbottom tree, everything in the etop tree is closer by coefficient of
293 0.25, while everything in the old back tree is further by a coefficient of 0.25*/
294 /*everything in the tree that is being moved (emove) keeps the same relative weight in the average
295 distance calculation*/
298 enew1 = etop->tail->parentEdge;
299 if (NULL != enew1) /*need to do recursive calls*/
301 enew2 = siblingEdge(etop);
302 emove = siblingEdge(eback); /*emove is third edge meeting at vertex with eback, etest*/
304 newdXOut = A[vbottom->index][emove->head->index];
306 newdXOut = 0.5*(dXOut + A[vbottom->index][emove->head->index]);
307 calcTBRTopBottomAverage(vbottom,A,dXTop,newdXOut,esplit, enew1,etop,UP); /*old etop is new value for back*/
308 calcTBRTopBottomAverage(vbottom,A,dXTop,newdXOut,esplit, enew2,etop,DOWN);
313 enew1 = etop->head->leftEdge;
316 enew2 = etop->head->rightEdge;
317 if (eback == siblingEdge(etop))
318 emove = etop->tail->parentEdge;
320 emove = siblingEdge(etop);
322 newdXOut = A[vbottom->index][emove->head->index];
324 newdXOut = 0.5*(dXOut + A[vbottom->index][emove->head->index]);
325 calcTBRTopBottomAverage(vbottom,A,dXTop,newdXOut,esplit,enew1,etop,DOWN);
326 calcTBRTopBottomAverage(vbottom,A,dXTop,newdXOut,esplit,enew2,etop,DOWN);
331 void calcTBRaverages(tree *T, edge *esplit, double **A, double **dXTop)
333 edge *ebottom, *par, *sib;
334 for (ebottom = findBottomLeft(esplit); ebottom != esplit; ebottom = depthFirstTraverse(T,ebottom))
336 par = esplit->tail->parentEdge;
337 sib = siblingEdge(esplit);
338 calcTBRTopBottomAverage(ebottom->head,A, dXTop, 0.0, esplit, par,esplit,UP);
339 calcTBRTopBottomAverage(ebottom->head,A, dXTop, 0.0, esplit, sib,esplit,DOWN);
343 void TBR(tree *T, double **D, double **A)
346 edge *esplit, *etop, *eBestTop, *eBestBottom, *eBestSplit;
348 edge *left, *right, *par, *sib;
349 double **dXTop; /*dXTop[i][j] is average distance from subtree rooted at i to tree above split edge, if
350 SPR above split edge cuts edge whose head has index j*/
352 double ***TBRWeights;
353 dXTop = initDoubleMatrix(T->size);
355 TBRWeights = (double ***)calloc(T->size,sizeof(double **));
356 for(i=0;i<T->size;i++)
357 TBRWeights[i] = initDoubleMatrix(T->size);
360 zero3DMatrix(TBRWeights,T->size,T->size,T->size);
362 eBestSplit = eBestTop = eBestBottom = NULL;
363 for(esplit=depthFirstTraverse(T,NULL);NULL!=esplit;esplit=depthFirstTraverse(T,esplit))
365 par = esplit->tail->parentEdge;
368 sib = siblingEdge(esplit);
369 /*next two lines calculate the possible improvements for any SPR above esplit*/
370 assignTBRDownWeightsUp(par,esplit->head,sib->head,NULL,NULL,0.0,1.0,A,TBRWeights,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom);
371 assignTBRDownWeightsSkew(sib,esplit->head,sib->tail,NULL,NULL,0.0,1.0,A,TBRWeights,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom);
372 calcTBRaverages(T,esplit,A,dXTop); /*calculates the average distance from any subtree
373 below esplit to the entire subtree above esplit,
374 after any possible SPR above*/
375 /*for etop above esplit, we loop using information from above to calculate values
376 for all possible SPRs below esplit*/
379 right = esplit->head->rightEdge;
382 left = esplit->head->leftEdge;
383 /*test case: etop = null means only do bottom SPR*/
384 assignTBRUpWeights(left,esplit->head,right->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,NULL,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom);
385 assignTBRUpWeights(right,esplit->head,left->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,NULL,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom);
388 while (NULL != block)
393 assignTBRUpWeights(left,esplit->head,right->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom);
394 assignTBRUpWeights(right,esplit->head,left->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom);
396 eout = siblingEdge(block);
399 etop = findBottomLeft(eout);
400 while (etop->tail != eout->tail)
402 /*for ebottom below esplit*/
404 assignTBRUpWeights(left,esplit->head,right->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom);
405 assignTBRUpWeights(right,esplit->head,left->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom);
406 etop = depthFirstTraverse(T,etop);
411 assignTBRUpWeights(left,esplit->head,right->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom);
412 assignTBRUpWeights(right,esplit->head,left->head,NULL,NULL,0.0,1.0,A,dXTop,TBRWeights,etop,&bestWeight,&eBestSplit,&eBestTop,&eBestBottom);
414 block = block->tail->parentEdge;
416 } /*if NULL != right*/
418 /*find bestWeight, best split edge, etc.*/
419 if (bestWeight < -EPSILON)
423 // printf("TBR #%d: Splitting edge %s: top edge %s, bottom edge %s\n",*count+1,
424 // eBestSplit->label, eBestTop->label,eBestBottom->label);
425 // printf("Old tree weight is %lf, new tree weight should be %lf\n",T->weight, T->weight + 0.25*bestWeight);
427 TBRswitch(T,eBestSplit,eBestTop,eBestBottom);
428 makeBMEAveragesTable(T,D,A);
429 assignBMEWeights(T,A);
432 // printf("TBR: new tree weight is %lf\n\n",T->weight);<
437 } while (bestWeight < -EPSILON);
438 for(i=0;i<T->size;i++)
439 freeMatrix(TBRWeights[i],T->size);
440 freeMatrix(dXTop,T->size);
443 void SPRTopShift(tree *T, node *v, edge *e, int UpOrDown);
445 void TBRswitch(tree *T, edge *es, edge *et, edge *eb)
448 SPRTopShift(T,es->head,et,DOWN); /*DOWN because tree being moved is below split edge*/
450 SPRTopShift(T,es->head,eb,UP); /*UP because tree being moved is above split edge*/