source: branches/profile/GDE/PHYLIP/wagner.c

Last change on this file was 2175, checked in by westram, 20 years ago

upgrade to PHYLIP 3.6

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.6 KB
Line 
1
2#include "phylip.h"
3#include "disc.h"
4#include "wagner.h"
5
6/* version 3.6. (c) Copyright 1993-2000 by the University of Washington.
7   Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
8   Permission is granted to copy and use this program provided no fee is
9   charged for it and provided that this copyright notice is not removed. */
10
11void inputmixture(bitptr wagner0)
12{
13  /* input mixture of methods */
14  /* used in mix, move, & penny */
15  long i, j, k;
16  Char ch;
17  boolean wag;
18
19  for (i = 1; i < nmlngth; i++) {
20    ch = gettc(infile);
21    if (ch == '\n')
22      ch = ' ';
23  }
24  for (i = 0; i < (words); i++)
25    wagner0[i] = 0;
26  j = 0;
27  k = 1;
28  for (i = 1; i <= (chars); i++) {
29    do {
30      if (eoln(infile))
31        scan_eoln(infile);
32      ch = gettc(infile);
33      if (ch == '\n')
34        ch = ' ';
35    } while (ch == ' ');
36    uppercase(&ch);
37    wag = false;
38    if (ch == 'W' || ch == '?')
39      wag = true;
40    else if (ch == 'S' || ch == 'C')
41      wag = false;
42    else {
43      printf("BAD METHOD: %c\n", ch);
44      exxit(-1);
45    }
46    j++;
47    if (j > bits) {
48      j = 1;
49      k++;
50    }
51    if (wag)
52      wagner0[k - 1] = (long)wagner0[k - 1] | (1L << j);
53  }
54  scan_eoln(infile);
55}  /* inputmixture */
56
57void inputmixturenew(bitptr wagner0)
58{
59  /* input mixture of methods */
60  /* used in mix, move, & penny */
61  long i, j, k;
62  Char ch;
63  boolean wag;
64
65  for (i = 0; i < (words); i++)
66    wagner0[i] = 0;
67  j = 0;
68  k = 1;
69  for (i = 1; i <= (chars); i++) {
70    do {
71      if (eoln(mixfile))
72        scan_eoln(mixfile);
73      ch = gettc(mixfile);
74      if (ch == '\n')
75        ch = ' ';
76    } while (ch == ' ');
77    uppercase(&ch);
78    wag = false;
79    if (ch == 'W' || ch == '?')
80      wag = true;
81    else if (ch == 'S' || ch == 'C')
82      wag = false;
83    else {
84      printf("BAD METHOD: %c\n", ch);
85      exxit(-1);
86    }
87    j++;
88    if (j > bits) {
89      j = 1;
90      k++;
91    }
92    if (wag)
93      wagner0[k - 1] = (long)wagner0[k - 1] | (1L << j);
94  }
95  scan_eoln(mixfile);
96}  /* inputmixture */
97
98
99void printmixture(FILE *filename, bitptr wagner)
100{
101  /* print out list of parsimony methods */
102  /* used in mix, move, & penny */
103  long i, k, l;
104
105  fprintf(filename, "Parsimony methods:\n");
106  l = 0;
107  k = 1;
108  for (i = 1; i <= nmlngth + 3; i++)
109    putc(' ', filename);
110  for (i = 1; i <= (chars); i++) {
111    newline(filename, i, 55, nmlngth + 3);
112    l++;
113    if (l > bits) {
114      l = 1;
115      k++;
116    }
117    if (((1L << l) & wagner[k - 1]) != 0)
118      putc('W', filename);
119    else
120      putc('S', filename);
121    if (i % 5 == 0)
122      putc(' ', filename);
123  }
124  fprintf(filename, "\n\n");
125}  /* printmixture */
126
127
128void fillin(node2 *p,long fullset,boolean full,bitptr wagner,bitptr zeroanc)
129{
130  /* Sets up for each node in the tree two statesets.
131     stateone and statezero are the sets of character
132     states that must be 1 or must be 0, respectively,
133     in a most parsimonious reconstruction, based on the
134     information at or above this node.  Note that this
135     state assignment may change based on information further
136     down the tree.  If a character is in both sets it is in
137     state "P".  If in neither, it is "?". */
138  long i;
139  long l0, l1, r0, r1, st, wa, za;
140
141  for (i = 0; i < (words); i++) {
142    if (full) {
143      l0 = p->next->back->fulstte0[i];
144      l1 = p->next->back->fulstte1[i];
145      r0 = p->next->next->back->fulstte0[i];
146      r1 = p->next->next->back->fulstte1[i];
147    }
148    else {
149      l0 = p->next->back->empstte0[i];
150      l1 = p->next->back->empstte1[i];
151      r0 = p->next->next->back->empstte0[i];
152      r1 = p->next->next->back->empstte1[i];
153    }
154    st = (l1 & r0) | (l0 & r1);
155    wa = wagner[i];
156    za = zeroanc[i];
157    if (full) {
158      p->fulstte1[i] = (l1 | r1) & (~(st & (wa | za)));
159      p->fulstte0[i] = (l0 | r0) & (~(st & (wa | (fullset & (~za)))));
160      p->fulsteps[i] = st;
161    }
162    else {
163      p->empstte1[i] = (l1 | r1) & (~(st & (wa | za)));
164      p->empstte0[i] = (l0 | r0) & (~(st & (wa | (fullset & (~za)))));
165      p->empsteps[i] = st;
166    }
167  }
168}  /* fillin */
169
170
171void count(long *stps, bitptr zeroanc, steptr numszero, steptr numsone)
172{
173  /* counts the number of steps in a fork of the tree.
174     The program spends much of its time in this PROCEDURE */
175  /* used in mix & penny */
176  long i, j, l;
177
178  j = 1;
179  l = 0;
180  for (i = 0; i < (chars); i++) {
181    l++;
182    if (l > bits) {
183      l = 1;
184      j++;
185    }
186    if (((1L << l) & stps[j - 1]) != 0) {
187      if (((1L << l) & zeroanc[j - 1]) != 0)
188        numszero[i] += weight[i];
189      else
190        numsone[i] += weight[i];
191    }
192  }
193}  /* count */
194
195
196void postorder(node2 *p, long fullset, boolean full, bitptr wagner,
197                        bitptr zeroanc)
198{
199  /* traverses a binary tree, calling PROCEDURE fillin at a
200     node's descendants before calling fillin at the node2 */
201  /* used in mix & penny */
202  if (p->tip)
203    return;
204  postorder(p->next->back, fullset, full, wagner, zeroanc);
205  postorder(p->next->next->back, fullset, full, wagner, zeroanc);
206  if (!p->visited) {
207    fillin(p, fullset, full, wagner, zeroanc);
208    if (!full) p->visited = true;
209  }
210}  /* postorder */
211
212void cpostorder(node2 *p, boolean full, bitptr zeroanc, steptr numszero,
213                        steptr numsone)
214{
215  /* traverses a binary tree, calling PROCEDURE count at a
216     node's descendants before calling count at the node2 */
217  /* used in mix & penny */
218  if (p->tip)
219    return;
220  cpostorder(p->next->back, full, zeroanc, numszero, numsone);
221  cpostorder(p->next->next->back, full, zeroanc, numszero, numsone);
222  if (full)
223    count(p->fulsteps, zeroanc, numszero, numsone);
224  else
225    count(p->empsteps, zeroanc, numszero, numsone);
226}  /* cpostorder */
227
228
229void filltrav(node2 *r, long fullset, boolean full, bitptr wagner,
230                        bitptr zeroanc)
231{
232  /* traverse to fill in interior node states */
233  if (r->tip)
234    return;
235  filltrav(r->next->back, fullset, full, wagner, zeroanc);
236  filltrav(r->next->next->back, fullset, full, wagner, zeroanc);
237  fillin(r, fullset, full, wagner, zeroanc);
238}  /* filltrav */
239
240
241void hyprint(struct htrav_vars2 *htrav, boolean unknown, boolean noroot,
242                        boolean didreroot, bitptr wagner, Char *guess)
243{
244  /* print out states at node2 */
245  long i, j, k;
246  char l;
247  boolean dot, a0, a1, s0, s1;
248
249  if (htrav->bottom) {
250    if (noroot && !didreroot)
251      fprintf(outfile, "       ");
252    else
253      fprintf(outfile, "root   ");
254  } else
255    fprintf(outfile, "%3ld    ", htrav->r->back->index - spp);
256  if (htrav->r->tip) {
257    for (i = 0; i < nmlngth; i++)
258      putc(nayme[htrav->r->index - 1][i], outfile);
259  } else
260    fprintf(outfile, "%4ld      ", htrav->r->index - spp);
261  if (htrav->bottom && noroot && !didreroot)
262    fprintf(outfile, "          ");
263  else if (htrav->nonzero)
264    fprintf(outfile, "   yes    ");
265  else if (unknown)
266    fprintf(outfile, "    ?     ");
267  else if (htrav->maybe)
268    fprintf(outfile, "  maybe   ");
269  else
270    fprintf(outfile, "   no     ");
271  for (j = 1; j <= (chars); j++) {
272    newline(outfile, j, 40, nmlngth + 17);
273    k = (j - 1) / bits + 1;
274    l = (j - 1) % bits + 1;
275    dot = (((1L << l) & wagner[k - 1]) == 0 && guess[j - 1] == '?');
276    s0 = (((1L << l) & htrav->r->empstte0[k - 1]) != 0);
277    s1 = (((1L << l) & htrav->r->empstte1[k - 1]) != 0);
278    a0 = (((1L << l) & htrav->zerobelow->bits_[k - 1]) != 0);
279    a1 = (((1L << l) & htrav->onebelow->bits_[k - 1]) != 0);
280    dot = (dot || ((!htrav->bottom || !noroot || didreroot) && a1 == s1 &&
281                   a0 == s0 && s0 != s1));
282    if (dot)
283      putc('.', outfile);
284    else {
285      if (s0)
286        putc('0', outfile);
287      else if (s1)
288        putc('1', outfile);
289      else
290        putc('?', outfile);
291    }
292    if (j % 5 == 0)
293      putc(' ', outfile);
294  }
295  putc('\n', outfile);
296}  /* hyprint */
297
298
299void hyptrav(node2 *r_, boolean unknown, bitptr dohyp, long fullset,
300        boolean noroot, boolean didreroot, bitptr wagner,
301        bitptr zeroanc, bitptr oneanc, pointptr2 treenode, Char *guess,
302        gbit *garbage)
303{
304  /* compute, print out states at one interior node2 */
305  /* used in mix & penny */
306  struct htrav_vars2 vars;
307  long i;
308  long l0, l1, r0, r1, s0, s1, a0, a1, temp, dh, wa;
309
310  vars.r = r_;
311  disc_gnu(&vars.zerobelow, &garbage);
312  disc_gnu(&vars.onebelow, &garbage);
313  vars.bottom = (vars.r->back == NULL);
314  vars.maybe = false;
315  vars.nonzero = false;
316  if (vars.bottom) {
317    memcpy(vars.zerobelow->bits_, zeroanc, words*sizeof(long));
318    memcpy(vars.onebelow->bits_, oneanc, words*sizeof(long));
319  } else {
320    memcpy(vars.zerobelow->bits_, treenode[vars.r->back->index - 1]->empstte0,
321           words*sizeof(long));
322    memcpy(vars.onebelow->bits_, treenode[vars.r->back->index - 1]->empstte1,
323           words*sizeof(long));
324  }
325  for (i = 0; i < (words); i++) {
326    dh = dohyp[i];
327    s0 = vars.r->empstte0[i];
328    s1 = vars.r->empstte1[i];
329    a0 = vars.zerobelow->bits_[i];
330    a1 = vars.onebelow->bits_[i];
331    if (!vars.r->tip) {
332      wa = wagner[i];
333      l0 = vars.r->next->back->empstte0[i];
334      l1 = vars.r->next->back->empstte1[i];
335      r0 = vars.r->next->next->back->empstte0[i];
336      r1 = vars.r->next->next->back->empstte1[i];
337      s0 = (wa & ((a0 & l0) | (a0 & r0) | (l0 & r0))) |
338           (dh & fullset & (~wa) & s0);
339      s1 = (wa & ((a1 & l1) | (a1 & r1) | (l1 & r1))) |
340           (dh & fullset & (~wa) & s1);
341      temp = fullset & (~(s0 | s1 | l1 | l0 | r1 | r0));
342      s0 |= temp & a0;
343      s1 |= temp & a1;
344      vars.r->empstte0[i] = s0;
345      vars.r->empstte1[i] = s1;
346    }
347    vars.maybe = (vars.maybe || (dh & (s0 | s1)) != (a0 | a1));
348    vars.nonzero = (vars.nonzero || ((s1 & a0) | (s0 & a1)) != 0);
349  }
350  hyprint(&vars,unknown, noroot, didreroot, wagner, guess);
351  if (!vars.r->tip) {               
352    hyptrav(vars.r->next->back,unknown,dohyp, fullset, noroot,didreroot,
353               wagner, zeroanc, oneanc, treenode, guess, garbage);
354    hyptrav(vars.r->next->next->back, unknown,dohyp, fullset, noroot,
355               didreroot, wagner, zeroanc, oneanc, treenode, guess, garbage);
356  }
357  disc_chuck(vars.zerobelow, &garbage);
358  disc_chuck(vars.onebelow, &garbage);
359}  /* hyptrav */
360
361
362void hypstates(long fullset, boolean full, boolean noroot, boolean didreroot,
363                        node2 *root, bitptr wagner, bitptr zeroanc, bitptr oneanc,
364                        pointptr2 treenode, Char *guess, gbit *garbage)
365{
366  /* fill in and describe states at interior nodes */
367  /* used in mix & penny */
368  boolean unknown;
369  bitptr dohyp;
370  long i, j, k;
371
372  for (i = 0; i < (words); i++) {
373    zeroanc[i] = 0;
374    oneanc[i] = 0;
375  }
376  unknown = false;
377  for (i = 0; i < (chars); i++) {
378    j = i / bits + 1;
379    k = i % bits + 1;
380    if (guess[i] == '0')
381      zeroanc[j - 1] = ((long)zeroanc[j - 1]) | (1L << k);
382    if (guess[i] == '1')
383      oneanc[j - 1] = ((long)oneanc[j - 1]) | (1L << k);
384    unknown = (unknown || ((((1L << k) & wagner[j - 1]) == 0) &&
385                  guess[i] == '?'));
386  }
387  dohyp = (bitptr)Malloc(words*sizeof(long));
388  for (i = 0; i < (words); i++)
389    dohyp[i] = wagner[i] | zeroanc[i] | oneanc[i];
390  filltrav(root, fullset, full, wagner, zeroanc);
391  fprintf(outfile, "From    To     Any Steps?    ");
392  fprintf(outfile, "State at upper node\n");
393  fprintf(outfile, "                             ");
394  fprintf(outfile, "( . means same as in the node below it on tree)\n\n");
395  hyptrav(root,unknown,dohyp, fullset, noroot, didreroot, wagner,
396                zeroanc, oneanc, treenode, guess, garbage);
397  free(dohyp);
398}  /* hypstates */
399
400
401void drawline(long i, double scale, node2 *root)
402{
403  /* draws one row of the tree diagram by moving up tree */
404  node2 *p, *q, *r, *first =NULL, *last =NULL;
405  long n, j;
406  boolean extra, done;
407
408  p = root;
409  q = root;
410  extra = false;
411  if (i == p->ycoord && p == root) {
412    if (p->index - spp >= 10)
413      fprintf(outfile, "-%2ld", p->index - spp);
414    else
415      fprintf(outfile, "--%ld", p->index - spp);
416    extra = true;
417  } else
418    fprintf(outfile, "  ");
419  do {
420    if (!p->tip) {
421      r = p->next;
422      done = false;
423      do {
424        if (i >= r->back->ymin && i <= r->back->ymax) {
425          q = r->back;
426          done = true;
427        }
428        r = r->next;
429      } while (!(done || r == p));
430      first = p->next->back;
431      r = p->next;
432      while (r->next != p)
433        r = r->next;
434      last = r->back;
435    }
436    done = (p == q);
437    n = (long)(scale * (p->xcoord - q->xcoord) + 0.5);
438    if (n < 3 && !q->tip)
439      n = 3;
440    if (extra) {
441      n--;
442      extra = false;
443    }
444    if (q->ycoord == i && !done) {
445      putc('+', outfile);
446      if (!q->tip) {
447        for (j = 1; j <= n - 2; j++)
448          putc('-', outfile);
449        if (q->index - spp >= 10)
450          fprintf(outfile, "%2ld", q->index - spp);
451        else
452          fprintf(outfile, "-%ld", q->index - spp);
453        extra = true;
454      } else {
455        for (j = 1; j < n; j++)
456          putc('-', outfile);
457      }
458    } else if (!p->tip) {
459      if (last->ycoord > i && first->ycoord < i && i != p->ycoord) {
460        putc('!', outfile);
461        for (j = 1; j < n; j++)
462          putc(' ', outfile);
463      } else {
464        for (j = 1; j <= n; j++)
465          putc(' ', outfile);
466      }
467    } else {
468      for (j = 1; j <= n; j++)
469        putc(' ', outfile);
470    }
471    if (p != q)
472      p = q;
473  } while (!done);
474  if (p->ycoord == i && p->tip) {
475    for (j = 0; j < nmlngth; j++)
476      putc(nayme[p->index - 1][j], outfile);
477  }
478  putc('\n', outfile);
479}  /* drawline */
480
481
482void printree(boolean treeprint,boolean noroot,boolean didreroot,node2 *root)
483{
484  /* prints out diagram of the tree */
485  /* used in mix & penny */
486  long tipy, i;
487  double scale;
488
489  putc('\n', outfile);
490  if (!treeprint)
491    return;
492  putc('\n', outfile);
493  tipy = 1;
494  coordinates2(root, &tipy);
495  scale = 1.5;
496  putc('\n', outfile);
497  for (i = 1; i <= (tipy - down); i++)
498    drawline(i, scale, root);
499  if (noroot) {
500    fprintf(outfile, "\n  remember:");
501    if (didreroot)
502      fprintf(outfile, " (although rooted by outgroup)");
503    fprintf(outfile, " this is an unrooted tree!\n");
504  }
505  putc('\n', outfile);
506}  /* printree */
507
508
509void writesteps(boolean weights, steptr numsteps)
510{ /* write number of steps */
511  /* used in mix & penny */
512  long i, j, k;
513
514  if (weights)
515    fprintf(outfile, "weighted ");
516  fprintf(outfile, "steps in each character:\n");
517  fprintf(outfile, "      ");
518  for (i = 0; i <= 9; i++)
519    fprintf(outfile, "%4ld", i);
520  fprintf(outfile, "\n     *-----------------------------------------\n");
521  for (i = 0; i <= (chars / 10); i++) {
522    fprintf(outfile, "%5ld", i * 10);
523    putc('!', outfile);
524    for (j = 0; j <= 9; j++) {
525      k = i * 10 + j;
526    if (k == 0 || k > chars)
527      fprintf(outfile, "    ");
528    else
529      fprintf(outfile, "%4ld", numsteps[k - 1] + extras[k - 1]);
530    }
531    putc('\n', outfile);
532  }
533  putc('\n', outfile);
534}  /* writesteps */
535
Note: See TracBrowser for help on using the repository browser.