source: trunk/GDE/PHYML20130708/phyml/src/bionj.c

Last change on this file was 10307, checked in by aboeckma, 11 years ago

added most recent version of phyml

File size: 10.2 KB
Line 
1/*
2
3PHYML :  a program that  computes maximum likelihood  phyLOGenies from
4DNA or AA homoLOGous sequences
5
6Copyright (C) Stephane Guindon. Oct 2003 onward
7
8All parts of  the source except where indicated  are distributed under
9the GNU public licence.  See http://www.opensource.org for details.
10
11*/
12
13/*
14
15The code below is an implementation of the building tree algorithm
16described in "BIONJ: an improved version of the NJ algorithm based
17on a simple model of sequence data." (1997) O. Gascuel. Mol Biol Evol.
1814:685-95. 
19
20*/
21
22#include "bionj.h"
23
24
25void Bionj(matrix *mat)
26{
27  int x,y,i;
28  phydbl vxy,lx,ly,lamda,score;
29
30  Clean_Tree_Connections(mat->tree); 
31  For(i,mat->tree->n_otu) mat->tip_node[i] = mat->tree->a_nodes[i];
32  mat->tree->num_curr_branch_available = 0;
33
34  while(mat->r > 3)
35    {
36      x = y =  0;
37      vxy   = .0;
38      score = .0;
39      Compute_Sx(mat);
40      Best_Pair(mat,&x,&y,&score);
41      vxy=Variance(mat,x,y);
42      lx=Br_Length(mat,x,y);   
43      ly=Br_Length(mat,y,x);
44      lamda=Lamda(mat,x,y,vxy); 
45      Update_Mat(mat,x,y,lx,ly,vxy,lamda);
46      Update_Tree(mat,x,y,lx,ly,score);     
47    }
48  Finish(mat);
49}
50 
51//////////////////////////////////////////////////////////////
52//////////////////////////////////////////////////////////////
53
54
55void Finish(matrix *mat)
56{
57  phydbl dxy,dxz,dyz;
58  int x,y,z;
59  t_node *nx,*ny,*nz,*new;
60  int i;
61
62  dxy = dxz = dyz = -1.;
63  x = y = z = -1;
64
65  For(i,mat->n_otu)
66    {
67      if(mat->on_off[i])
68        {
69          if(x < 0) x=i;
70          else if(y < 0) y = i;
71          else if(z < 0) z = i;
72        }
73    }
74
75  dxy = Dist(mat,x,y);
76  dxz = Dist(mat,x,z);
77  dyz = Dist(mat,y,z);
78
79  nx = mat->tip_node[x];
80  ny = mat->tip_node[y];
81  nz = mat->tip_node[z];
82
83  new = mat->tree->a_nodes[mat->curr_int];
84  new->num = mat->curr_int;
85  new->v[0] = nx;
86  new->v[1] = ny;
87  new->v[2] = nz;
88
89  nx->v[0] = new;
90  ny->v[0] = new;
91  nz->v[0] = new;
92
93 
94  Connect_One_Edge_To_Two_Nodes(new,nx,mat->tree->a_edges[mat->tree->num_curr_branch_available],mat->tree);
95  Connect_One_Edge_To_Two_Nodes(new,ny,mat->tree->a_edges[mat->tree->num_curr_branch_available],mat->tree);
96  Connect_One_Edge_To_Two_Nodes(new,nz,mat->tree->a_edges[mat->tree->num_curr_branch_available],mat->tree);
97 
98 
99  nx->b[0]->l->v = .5*(dxy-dyz+dxz);
100  ny->b[0]->l->v = .5*(dyz-dxz+dxy);
101  nz->b[0]->l->v = .5*(dxz-dxy+dyz);
102   
103  new->b[0]->l->v = nx->b[0]->l->v;
104  new->b[1]->l->v = ny->b[0]->l->v;
105  new->b[2]->l->v = nz->b[0]->l->v;
106}
107
108//////////////////////////////////////////////////////////////
109//////////////////////////////////////////////////////////////
110
111
112void Update_Mat(matrix *mat, int x, int y, phydbl lx, phydbl ly, phydbl vxy, phydbl lamda)
113{
114  int i;
115  int a,b;
116 
117  a = b = -1;
118  For(i,mat->n_otu)
119    {
120      if((mat->on_off[i]) && (i != x) && (i != y))
121        {
122          if(x > i)
123            {
124              a=x;
125              b=i;
126            }
127          else
128            {
129              a=i;
130              b=x;
131            }
132          mat->dist[a][b]=Dist_Red(mat,x,lx,y,ly,i,lamda);
133          mat->dist[b][a]=Var_Red(mat,x,y,i,lamda,vxy);
134        }
135    }
136}
137
138//////////////////////////////////////////////////////////////
139//////////////////////////////////////////////////////////////
140
141
142void Update_Tree(matrix *mat, int x, int y, phydbl lx, phydbl ly, phydbl score)
143{
144  t_node *new, *nx, *ny;
145
146  nx            = mat->tip_node[x];
147  ny            = mat->tip_node[y];
148  new           = mat->tree->a_nodes[mat->curr_int];
149  nx->v[0]      = new;
150  ny->v[0]      = new;
151  new->v[1]     = nx;
152  new->v[2]     = ny;
153  new->num      = mat->curr_int;
154
155  Connect_One_Edge_To_Two_Nodes(new,nx,mat->tree->a_edges[mat->tree->num_curr_branch_available],mat->tree);
156  Connect_One_Edge_To_Two_Nodes(new,ny,mat->tree->a_edges[mat->tree->num_curr_branch_available],mat->tree);
157
158  nx->b[0]->l->v   = lx;
159  ny->b[0]->l->v   = ly;
160 
161  new->b[1]->l->= lx;
162  new->b[2]->l->= ly;
163  new->score[0] = score;
164
165  nx->l[0]      = lx;
166  ny->l[0]      = ly;
167 
168  new->l[1]     = lx;
169  new->l[2]     = ly;
170 
171  mat->tip_node[x] = new;
172  mat->on_off[y] = 0;
173  mat->curr_int++;
174  mat->r--;
175}
176
177//////////////////////////////////////////////////////////////
178//////////////////////////////////////////////////////////////
179
180
181void Best_Pair(matrix *mat, int *x, int *y,phydbl *score)
182{
183  int i,j/* ,n_ties */;
184  phydbl Qmin,Qmin2;
185  phydbl *t_Qij;
186/*   int *ties; */
187
188  t_Qij = (phydbl *)mCalloc(mat->n_otu * mat->n_otu,sizeof(phydbl ));
189/*   ties  = (int *)mCalloc(mat->n_otu * mat->n_otu,sizeof(int )); */
190
191  Qmin = 1.e+10;
192 
193  For(i,mat->n_otu)
194    {
195      if(mat->on_off[i])
196        {
197          for(j=0;j<i;j++)
198            {
199              if(mat->on_off[j])
200                {
201                  t_Qij[mat->n_otu*i+j] = Q_Agglo(mat,i,j);
202
203                  if(t_Qij[mat->n_otu*i+j] < Qmin - 1.E-05)
204                    {
205                      *x = i;
206                      *y = j;
207                      Qmin = t_Qij[mat->n_otu*i+j];
208                    }
209                }
210            }
211        }
212    }
213 
214/*   n_ties = 0; */
215/*   For(i,mat->n_otu) */
216/*     { */
217/*       if(mat->on_off[i]) */
218/*      { */
219/*        for(j=0;j<i;j++) */
220/*          { */
221/*            if(mat->on_off[j]) */
222/*              { */
223/*                if((t_Qij[mat->n_otu*i+j] < Qmin + 1.E-05) && (t_Qij[mat->n_otu*i+j] > Qmin - 1.E-05)) */
224/*                  { */
225/*                    ties[n_ties] = mat->n_otu*i+j; */
226/*                    n_ties++; */
227/*                  } */
228/*              } */
229/*          } */
230/*      } */
231/*     } */
232   
233/*   if(!n_ties) */
234/*     { */
235/*       PhyML_Printf("\n. Err in file %s at line %d\n\n",__FILE__,__LINE__); */
236/*       Warn_And_Exit(""); */
237/*     } */
238
239
240/*   /\* Useful if some pairwise distances are null *\/ */
241/*   if(n_ties > 1) */
242/*     { */
243/*       int cand; */
244/*       *x = *y = -1; */
245/*       cand = (int)RINT(rand()/(phydbl)(RAND_MAX) * (n_ties-1)); */
246/*       *x = (int)(ties[cand] / mat->n_otu); */
247/*       *y = (int)(ties[cand] % mat->n_otu); */
248/*     } */
249
250
251
252  Qmin2 = 1e+10;
253
254  For(i,mat->n_otu)
255    {
256      if((i != *y) && (i != *x) && (t_Qij[mat->n_otu*(*x)+i] < Qmin2)) Qmin2 = t_Qij[mat->n_otu*(*x)+i];
257    }
258
259  For(i,mat->n_otu)
260    {
261      if((i != *y) && (i != *x) && (t_Qij[mat->n_otu*i+(*y)] < Qmin2)) Qmin2 = t_Qij[mat->n_otu*i+(*y)];
262    }
263
264  *score = FABS(Qmin2 - Qmin)/FABS(Qmin);
265
266  Free(t_Qij);
267/*   Free(ties); */
268}
269
270//////////////////////////////////////////////////////////////
271//////////////////////////////////////////////////////////////
272
273
274void Compute_Sx(matrix *mat)
275{
276  int i,j;
277 
278  For(i,mat->n_otu)
279    {
280      mat->dist[i][i] = .0;
281      if(mat->on_off[i])
282        {
283          For(j,mat->n_otu)
284            {
285              if((i != j) && (mat->on_off[j]))
286                {
287                  mat->dist[i][i] += Dist(mat,i,j);
288                }
289            }
290        }
291    }
292}
293             
294//////////////////////////////////////////////////////////////
295//////////////////////////////////////////////////////////////
296
297
298phydbl Sum_S(matrix *mat, int i)
299{
300  return mat->dist[i][i];
301}
302
303//////////////////////////////////////////////////////////////
304//////////////////////////////////////////////////////////////
305
306
307phydbl Dist(matrix *mat, int x, int y)
308{
309    if(x > y)
310      return(mat->dist[x][y]);
311    else
312      return(mat->dist[y][x]);
313}
314
315//////////////////////////////////////////////////////////////
316//////////////////////////////////////////////////////////////
317
318
319phydbl Variance(matrix *mat, int x, int y)
320{
321    if(x > y)
322      {
323        return(mat->dist[y][x]);
324      }
325    else
326      {
327        return(mat->dist[x][y]);
328      }
329}
330
331//////////////////////////////////////////////////////////////
332//////////////////////////////////////////////////////////////
333
334
335phydbl Br_Length(matrix *mat, int x, int y)
336{
337    return .5*(Dist(mat,x,y)+
338              (Sum_S(mat,x)-Sum_S(mat,y))/(phydbl)(mat->r-2.)); 
339}
340
341//////////////////////////////////////////////////////////////
342//////////////////////////////////////////////////////////////
343
344
345phydbl Dist_Red(matrix *mat, int x, phydbl lx, int y, phydbl ly, int i, phydbl lamda)
346{
347  phydbl Dui;
348  Dui=lamda*(Dist(mat,x,i)-lx)
349     +(1.-lamda)*(Dist(mat,y,i)-ly);
350  return(Dui);
351}
352
353//////////////////////////////////////////////////////////////
354//////////////////////////////////////////////////////////////
355
356
357phydbl Var_Red(matrix *mat, int x, int y, int i, phydbl lamda, phydbl vxy)
358{
359  phydbl Vui;
360  Vui=lamda*(Variance(mat,x,i))
361     +(1.-lamda)*(Variance(mat,y,i))
362    -lamda*(1.-lamda)*vxy;
363  return(Vui);
364}
365
366//////////////////////////////////////////////////////////////
367//////////////////////////////////////////////////////////////
368
369
370phydbl Lamda(matrix *mat, int x, int y, phydbl vxy)
371{
372    phydbl lamda=0.0;
373    int i;
374   
375    if(mat->method == 0) /* NJ (Saitou & Nei, 1987) */
376      lamda = 0.5;
377    else /* BioNJ (Gascuel, 1997) */
378      {
379        if(vxy < SMALL && vxy > -SMALL)
380          lamda=0.5;
381        else
382          {
383            For(i,mat->n_otu)
384              {
385                if((x != i) && (y != i) && (mat->on_off[i]))
386                  lamda = lamda + Variance(mat,y,i) - Variance(mat,x,i);
387              }
388            lamda = 0.5 + lamda/(2.*(mat->r-2)*vxy);
389          }
390       
391        if(lamda > 1.0)
392          lamda = 0.5;/*1.0;*/
393        else if(lamda < 0.0)
394          lamda = 0.5;/*0.0;*/
395      }
396
397    return(lamda);
398}
399
400//////////////////////////////////////////////////////////////
401//////////////////////////////////////////////////////////////
402
403
404phydbl Q_Agglo(matrix *mat, int x, int y)
405{
406  phydbl Qxy;
407
408  Qxy = .0;
409  Qxy=(mat->r-2.)*Dist(mat,x,y)-Sum_S(mat,x)-Sum_S(mat,y); 
410  return(Qxy);                       
411}
412
413//////////////////////////////////////////////////////////////
414//////////////////////////////////////////////////////////////
415
416
417void Bionj_Br_Length(matrix *mat)
418{
419  int x;
420
421  x = Bionj_Br_Length_Post(mat->tree->a_nodes[0],
422                           mat->tree->a_nodes[0]->v[0],
423                           mat);
424  mat->tree->a_nodes[0]->b[0]->l->v = Dist(mat,0,x);
425}
426
427//////////////////////////////////////////////////////////////
428//////////////////////////////////////////////////////////////
429
430
431int Bionj_Br_Length_Post(t_node *a, t_node *d, matrix *mat)
432{
433  int i;
434
435  if(d->tax)
436    {
437      return d->num;
438    }
439  else
440    {
441      int d_v1, d_v2;
442      phydbl lx, ly, vxy,lamda;
443      int x,y;
444
445      d_v1 = d_v2 = -1;
446      For(i,3)
447        if(d->v[i] != a) {(d_v1 < 0)?(d_v1 = i):(d_v2 = i);}
448     
449
450      x = Bionj_Br_Length_Post(d,d->v[d_v1],mat);
451      y = Bionj_Br_Length_Post(d,d->v[d_v2],mat);
452
453      vxy = .0;
454      Compute_Sx(mat);
455      vxy=Variance(mat,(x),(y));
456      lx=Br_Length(mat,(x),(y));   
457      ly=Br_Length(mat,(y),(x));
458      lamda=Lamda(mat,(x),(y),vxy); 
459      Update_Mat(mat,(x),(y),lx,ly,vxy,lamda);
460
461      d->b[d_v1]->l->v = lx;
462      d->b[d_v2]->l->v = ly;
463     
464      mat->on_off[y] = 0;
465      mat->r--;
466
467      return x;
468    }
469}
470
471//////////////////////////////////////////////////////////////
472//////////////////////////////////////////////////////////////
473
474
475
476
477
478
479
Note: See TracBrowser for help on using the repository browser.