bNNI.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:14k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: bNNI.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 18:09:47  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.2
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: bNNI.cpp,v 1000.1 2004/06/01 18:09:47 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author:  Richard Desper
  35. *
  36. * File Description:  bNNI.cpp
  37. *
  38. *    A part of the Miminum Evolution algorithm
  39. *
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <math.h>
  45. #include "graph.h"
  46. #include "fastme.h"
  47. BEGIN_NCBI_SCOPE
  48. BEGIN_SCOPE(fastme)
  49. boolean leaf(meNode *v);
  50. meEdge *siblingEdge(meEdge *e);
  51. meEdge *depthFirstTraverse(meTree *T, meEdge *e);
  52. meEdge *findBottomLeft(meEdge *e);
  53. meEdge *topFirstTraverse(meTree *T, meEdge *e);
  54. meEdge *moveUpRight(meEdge *e);
  55. void WFext(meEdge *e, double **A);
  56. void WFint(meEdge *e, double **A);
  57. void limitedFillTableUp(meEdge *e, meEdge *f, double **A, meEdge *trigger);
  58. void assignBalWeights(meTree *T, double **A);
  59. void updateAveragesMatrix(meTree *T, double **A, meNode *v,int direction);
  60. void bNNItopSwitch(meTree *T, meEdge *e, int direction, double **A);
  61. int bNNIEdgeTest(meEdge *e, meTree *T, double **A, double *weight);
  62. void updatePair(double **A, meEdge *nearEdge, meEdge *farEdge, meNode *closer, meNode *further, double dcoeff, int direction);
  63. int *initPerm(int size);
  64. void reHeapElement(int *p, int *q, double *v, int length, int i);
  65. void pushHeap(int *p, int *q, double *v, int length, int i);
  66. void popHeap(int *p, int *q, double *v, int length, int i);
  67. void bNNIRetestEdge(int *p, int *q, meEdge *e,meTree *T, double **avgDistArray,
  68. double *weights, int *location, int *possibleSwaps)
  69. {
  70.   int tloc;
  71.   tloc = location[e->head->index+1];
  72.   location[e->head->index+1] =
  73.     bNNIEdgeTest(e,T,avgDistArray,weights + e->head->index+1);
  74.   if (NONE == location[e->head->index+1])
  75.     {
  76.       if (NONE != tloc)
  77. popHeap(p,q,weights,(*possibleSwaps)--,q[e->head->index+1]);
  78.     }
  79.   else
  80.     {
  81.       if (NONE == tloc)
  82. pushHeap(p,q,weights,(*possibleSwaps)++,q[e->head->index+1]);
  83.       else
  84. reHeapElement(p,q,weights,*possibleSwaps,q[e->head->index+1]);
  85.     }
  86. }
  87. int makeThreshHeap(int *p, int *q, double *v, int arraySize, double thresh);
  88. void permInverse(int *p, int *q, int length);
  89. void printMatrix(double **M, int dim, FILE *ofile,meTree *T)
  90. {
  91.   meEdge *e,*f;
  92.   fprintf(ofile,"%dn",dim-1);
  93.   for(e=depthFirstTraverse(T,NULL);NULL!=e;e=depthFirstTraverse(T,e))
  94.     {
  95.       fprintf(ofile,"%s ",e->head->label);
  96.       for(f=depthFirstTraverse(T,NULL);NULL!=f;f=depthFirstTraverse(T,f))
  97. fprintf(ofile,"%lf ",M[e->head->index][f->head->index]);
  98.       fprintf(ofile,"n");
  99.     }
  100. }
  101. void weighTree(meTree *T)
  102. {
  103.   meEdge *e;
  104.   T->weight = 0;
  105.   for(e = depthFirstTraverse(T,NULL);NULL!=e;e=depthFirstTraverse(T,e))
  106.     T->weight += e->distance;
  107. }
  108. void bNNI(meTree *T, double **avgDistArray, int *count)
  109. {
  110.   meEdge *e, *centerEdge;
  111.   meEdge **edgeArray;
  112.   int *p, *location, *q;
  113.   int i;
  114.   int possibleSwaps;
  115.   double *weights;
  116.   p = initPerm(T->size+1);
  117.   q = initPerm(T->size+1);
  118.   edgeArray = (meEdge **) malloc((T->size+1)*sizeof(double));
  119.   weights = (double *) malloc((T->size+1)*sizeof(double));
  120.   location = (int *) malloc((T->size+1)*sizeof(int));
  121.   for (i=0;i<T->size+1;i++)
  122.     {
  123.       weights[i] = 0.0;
  124.       location[i] = NONE;
  125.     }
  126.   if (verbose)
  127.     {
  128.       assignBalWeights(T,avgDistArray);
  129.       weighTree(T);
  130.     }
  131.   e = findBottomLeft(T->root->leftEdge);
  132.   while (NULL != e)
  133.     {
  134.       edgeArray[e->head->index+1] = e;
  135.       location[e->head->index+1] =
  136. bNNIEdgeTest(e,T,avgDistArray,weights + e->head->index + 1);
  137.       e = depthFirstTraverse(T,e);
  138.     }
  139.   possibleSwaps = makeThreshHeap(p,q,weights,T->size+1,0.0);
  140.   permInverse(p,q,T->size+1);
  141.   /*we put the negative values of weights into a heap, indexed by p
  142.     with the minimum value pointed to by p[1]*/
  143.   /*p[i] is index (in edgeArray) of edge with i-th position
  144.     in the heap, q[j] is the position of edge j in the heap */
  145.   while (weights[p[1]] < 0)
  146.     {
  147.       centerEdge = edgeArray[p[1]];
  148.       (*count)++;
  149.       if (verbose)
  150. {
  151.   T->weight = T->weight + weights[p[1]];
  152.   printf("New tree weight is %lf.n",T->weight);
  153. }
  154.       bNNItopSwitch(T,edgeArray[p[1]],location[p[1]],avgDistArray);
  155.       location[p[1]] = NONE;
  156.       weights[p[1]] = 0.0;  /*after the bNNI, this edge is in optimal
  157.       configuration*/
  158.       popHeap(p,q,weights,possibleSwaps--,1);
  159.       /*but we must retest the other edges of T*/
  160.       /*CHANGE 2/28/2003 expanding retesting to _all_ edges of T*/
  161.       e = depthFirstTraverse(T,NULL);
  162.       while (NULL != e)
  163. {
  164.   bNNIRetestEdge(p,q,e,T,avgDistArray,weights,location,&possibleSwaps);
  165.   e = depthFirstTraverse(T,e);
  166. }
  167.     }
  168.   free(p);
  169.   free(q);
  170.   free(location);
  171.   free(edgeArray);
  172.   assignBalWeights(T,avgDistArray);
  173. }
  174. /*This function is the meat of the average distance matrix recalculation*/
  175. /*Idea is: we are looking at the subtree rooted at rootEdge.  The subtree
  176. rooted at closer is closer to rootEdge after the NNI, while the subtree
  177. rooted at further is further to rootEdge after the NNI.  direction tells
  178. the direction of the NNI with respect to rootEdge*/
  179. void updateSubTreeAfterNNI(double **A, meNode *v, meEdge *rootEdge, meNode *closer, meNode *further,
  180.    double dcoeff, int direction)
  181. {
  182.   meEdge *sib;
  183.   switch(direction)
  184.     {
  185.     case UP: /*rootEdge is below the center edge of the NNI*/
  186.       /*recursive calls to subtrees, if necessary*/
  187.       if (NULL != rootEdge->head->leftEdge)
  188. updateSubTreeAfterNNI(A, v, rootEdge->head->leftEdge, closer, further, 0.5*dcoeff,UP);
  189.       if (NULL != rootEdge->head->rightEdge)
  190. updateSubTreeAfterNNI(A, v, rootEdge->head->rightEdge, closer, further, 0.5*dcoeff,UP);
  191.       updatePair(A, rootEdge, rootEdge, closer, further, dcoeff, UP);
  192.       sib = siblingEdge(v->parentEdge);
  193.       A[rootEdge->head->index][v->index] =
  194. A[v->index][rootEdge->head->index] =
  195. 0.5*A[rootEdge->head->index][sib->head->index] +
  196. 0.5*A[rootEdge->head->index][v->parentEdge->tail->index];
  197.       break;
  198.     case DOWN: /*rootEdge is above the center edge of the NNI*/
  199.       sib = siblingEdge(rootEdge);
  200.       if (NULL != sib)
  201. updateSubTreeAfterNNI(A, v, sib, closer, further, 0.5*dcoeff, SKEW);
  202.       if (NULL != rootEdge->tail->parentEdge)
  203. updateSubTreeAfterNNI(A, v, rootEdge->tail->parentEdge, closer, further, 0.5*dcoeff, DOWN);
  204.       updatePair(A, rootEdge, rootEdge, closer, further, dcoeff, DOWN);
  205.       A[rootEdge->head->index][v->index] =
  206. A[v->index][rootEdge->head->index] =
  207. 0.5*A[rootEdge->head->index][v->leftEdge->head->index] +
  208. 0.5*A[rootEdge->head->index][v->rightEdge->head->index];
  209.       break;
  210.     case SKEW: /*rootEdge is in subtree skew to v*/
  211.       if (NULL != rootEdge->head->leftEdge)
  212. updateSubTreeAfterNNI(A, v, rootEdge->head->leftEdge, closer, further, 0.5*dcoeff,SKEW);
  213.       if (NULL != rootEdge->head->rightEdge)
  214. updateSubTreeAfterNNI(A, v, rootEdge->head->rightEdge, closer, further, 0.5*dcoeff,SKEW);
  215.       updatePair(A, rootEdge, rootEdge, closer, further, dcoeff, UP);
  216.       A[rootEdge->head->index][v->index] =
  217. A[v->index][rootEdge->head->index] =
  218. 0.5*A[rootEdge->head->index][v->leftEdge->head->index] +
  219. 0.5*A[rootEdge->head->index][v->rightEdge->head->index];
  220.       break;
  221.     }
  222. }
  223. /*swapping across edge whose head is v*/
  224. void bNNIupdateAverages(double **A, meNode *v, meEdge *par, meEdge *skew,
  225. meEdge *swap, meEdge *fixed)
  226. {
  227.   A[v->index][v->index] = 0.25*(A[fixed->head->index][par->head->index] +
  228. A[fixed->head->index][swap->head->index] +
  229. A[skew->head->index][par->head->index] +
  230. A[skew->head->index][swap->head->index]);
  231.   updateSubTreeAfterNNI(A, v, fixed, skew->head, swap->head, 0.25, UP);
  232.   updateSubTreeAfterNNI(A, v, par, swap->head, skew->head, 0.25, DOWN);
  233.   updateSubTreeAfterNNI(A, v, skew, fixed->head, par->head, 0.25, UP);
  234.   updateSubTreeAfterNNI(A, v, swap, par->head, fixed->head, 0.25, SKEW);
  235. }
  236. void bNNItopSwitch(meTree *T, meEdge *e, int direction, double **A)
  237. {
  238.   meEdge *down, *swap, *fixed;
  239.   meNode *u, *v;
  240.   if (verbose)
  241.     {
  242.       printf("Performing branch swap across edge %s ",e->label);
  243.       printf("with ");
  244.       if (LEFT == direction)
  245. printf("left ");
  246.       else printf("right ");
  247.       printf("subtree.n");
  248.     }
  249.   down = siblingEdge(e);
  250.   u = e->tail;
  251.   v = e->head;
  252.   if (LEFT == direction)
  253.     {
  254.       swap = e->head->leftEdge;
  255.       fixed = e->head->rightEdge;
  256.       v->leftEdge = down;
  257.     }
  258.   else
  259.     {
  260.       swap = e->head->rightEdge;
  261.       fixed = e->head->leftEdge;
  262.       v->rightEdge = down;
  263.     }
  264.   swap->tail = u;
  265.   down->tail = v;
  266.   if(e->tail->leftEdge == e)
  267.     u->rightEdge = swap;
  268.   else
  269.     u->leftEdge = swap;
  270.   bNNIupdateAverages(A, v, e->tail->parentEdge, down, swap, fixed);
  271. }
  272. double wf5(double D_AD, double D_BC, double D_AC, double D_BD,
  273.    double D_AB, double D_CD)
  274. {
  275.   double weight;
  276.   weight = 0.25*(D_AC + D_BD + D_AD + D_BC) + 0.5*(D_AB + D_CD);
  277.   return(weight);
  278. }
  279. int bNNIEdgeTest(meEdge *e, meTree *T, double **A, double *weight)
  280. {
  281.   meEdge *f;
  282.   double D_LR, D_LU, D_LD, D_RD, D_RU, D_DU;
  283.   double w1,w2,w0;
  284.   /*if (verbose)
  285.     printf("Branch swap: testing edge %s.n",e->label);*/
  286.   if ((leaf(e->tail)) || (leaf(e->head)))
  287.     return(NONE);
  288.   f = siblingEdge(e);
  289.   D_LR = A[e->head->leftEdge->head->index][e->head->rightEdge->head->index];
  290.   D_LU = A[e->head->leftEdge->head->index][e->tail->index];
  291.   D_LD = A[e->head->leftEdge->head->index][f->head->index];
  292.   D_RU = A[e->head->rightEdge->head->index][e->tail->index];
  293.   D_RD = A[e->head->rightEdge->head->index][f->head->index];
  294.   D_DU = A[e->tail->index][f->head->index];
  295.   w0 = wf5(D_RU,D_LD,D_LU,D_RD,D_DU,D_LR); /*weight of current config*/
  296.   w1 = wf5(D_RU,D_LD,D_DU,D_LR,D_LU,D_RD); /*weight with L<->D switch*/
  297.   w2 = wf5(D_DU,D_LR,D_LU,D_RD,D_RU,D_LD); /*weight with R<->D switch*/
  298.   if (w0 <= w1)
  299.     {
  300.       if (w0 <= w2) /*w0 <= w1,w2*/
  301. {
  302.   *weight = 0.0;
  303.   return(NONE);
  304. }
  305.       else /*w2 < w0 <= w1 */
  306. {
  307.   *weight = w2 - w0;
  308.   if (verbose)
  309.     {
  310.       printf("Possible swap across %s. ",e->label);
  311.       printf("Weight dropping by %lf.n",w0 - w2);
  312.       printf("New weight would be %lf.n",T->weight + w2 - w0);
  313.     }
  314.   return(RIGHT);
  315. }
  316.     }
  317.   else if (w2 <= w1) /*w2 <= w1 < w0*/
  318.     {
  319.       *weight = w2 - w0;
  320.       if (verbose)
  321. {
  322.   printf("Possible swap across %s. ",e->label);
  323.   printf("Weight dropping by %lf.n",w0 - w2);
  324.   printf("New weight should be %lf.n",T->weight + w2 - w0);
  325. }
  326.       return(RIGHT);
  327.     }
  328.   else /*w1 < w2, w0*/
  329.     {
  330.       *weight = w1 - w0;
  331.       if (verbose)
  332. {
  333.   printf("Possible swap across %s. ",e->label);
  334.   printf("Weight dropping by %lf.n",w0 - w1);
  335.   printf("New weight should be %lf.n",T->weight + w1 - w0);
  336. }
  337.       return(LEFT);
  338.     }
  339. }
  340. /*limitedFillTableUp fills all the entries in D associated with
  341.   e->head,f->head and those edges g->head above e->head, working
  342.   recursively and stopping when trigger is reached*/
  343. void limitedFillTableUp(meEdge *e, meEdge *f, double **A, meEdge *trigger)
  344. {
  345.   meEdge *g,*h;
  346.   g = f->tail->parentEdge;
  347.   if (f != trigger)
  348.     limitedFillTableUp(e,g,A,trigger);
  349.   h = siblingEdge(f);
  350.   A[e->head->index][f->head->index] =
  351.     A[f->head->index][e->head->index] =
  352.     0.5*(A[e->head->index][g->head->index] + A[e->head->index][h->head->index]);
  353. }
  354. void WFext(meEdge *e, double **A) /*works except when e is the one edge
  355.   inserted to new vertex v by firstInsert*/
  356. {
  357.   meEdge *f, *g;
  358.   if ((leaf(e->head)) && (leaf(e->tail)))
  359.     e->distance = A[e->head->index][e->head->index];
  360.   else if (leaf(e->head))
  361.     {
  362.       f = e->tail->parentEdge;
  363.       g = siblingEdge(e);
  364.       e->distance = 0.5*(A[e->head->index][g->head->index]
  365.  + A[e->head->index][f->head->index]
  366.  - A[g->head->index][f->head->index]);
  367.     }
  368.   else
  369.     {
  370.       f = e->head->leftEdge;
  371.       g = e->head->rightEdge;
  372.       e->distance = 0.5*(A[g->head->index][e->head->index]
  373.  + A[f->head->index][e->head->index]
  374.  - A[f->head->index][g->head->index]);
  375.     }
  376. }
  377. void WFint(meEdge *e, double **A)
  378. {
  379.   int up, down, left, right;
  380.   up = e->tail->index;
  381.   down = (siblingEdge(e))->head->index;
  382.   left = e->head->leftEdge->head->index;
  383.   right = e->head->rightEdge->head->index;
  384.   e->distance = 0.25*(A[up][left] + A[up][right] + A[left][down] + A[right][down]) - 0.5*(A[down][up] + A[left][right]);
  385. }
  386. void assignBalWeights(meTree *T, double **A)
  387. {
  388.   meEdge *e;
  389.   e = depthFirstTraverse(T,NULL);
  390.   while (NULL != e) {
  391.     if ((leaf(e->head)) || (leaf(e->tail)))
  392.       WFext(e,A);
  393.     else
  394.       WFint(e,A);
  395.     e = depthFirstTraverse(T,e);
  396.   }
  397. }
  398. END_SCOPE(fastme)
  399. END_NCBI_SCOPE
  400. /*
  401.  * ===========================================================================
  402.  * $Log: bNNI.cpp,v $
  403.  * Revision 1000.1  2004/06/01 18:09:47  gouriano
  404.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.2
  405.  *
  406.  * Revision 1.2  2004/05/21 21:41:03  gorelenk
  407.  * Added PCH ncbi_pch.hpp
  408.  *
  409.  * Revision 1.1  2004/02/10 15:16:00  jcherry
  410.  * Initial version
  411.  *
  412.  * ===========================================================================
  413.  */