source: tags/initial/GDE/PHYLIP/dnapenny.c

Last change on this file was 2, checked in by oldcode, 24 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 45.8 KB
Line 
1#include "phylip.h"
2
3/* version 3.56c. (c) Copyright 1993 by Joseph Felsenstein.
4   Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
5   Permission is granted to copy and use this program provided no fee is
6   charged for it and provided that this copyright notice is not removed. */
7
8#define nmlngth         10    /* number of characters in species name        */
9#define maxtrees        100   /* maximum number of trees to be printed out   */
10#define often           100   /* how often to notify how many trees examined */
11#define many            1000  /* how many multiples of howoften before stop  */
12
13#define ibmpc0          false
14#define ansi0           true
15#define vt520           false
16#define down            2
17
18typedef short *steptr;
19typedef short *stepshortptr;
20typedef Char **sequence;
21
22typedef enum {
23  A, C, G, U, O
24} bases;
25typedef char *baseptr;
26
27typedef struct gbases {
28  baseptr base;
29  struct gbases *next;
30} gbases;
31
32/* nodes will form a binary tree */
33
34typedef struct node {         /* describes a tip species or an ancestor */
35  struct node *next, *back;
36  short index;
37  boolean tip;                /* present species are tips of tree       */
38  baseptr base;             /* the sequence                           */
39  stepshortptr numsteps;    /* bookkeeps steps                        */
40  short xcoord, ycoord, ymin;  /* used by printree                       */
41  short ymax;
42} node;
43
44typedef node **pointptr;
45
46/* Local variables for hyptrav: */
47struct LOC_hyptrav {
48  node *r;
49  char *hypset;
50  boolean maybe, nonzero;
51  short tempset, anc;
52} ;
53
54Static node *root, *p;
55Static FILE *infile, *outfile, *treefile;
56Static short spp, nonodes, chars, endsite, outgrno, howmany, howoften, col,
57            datasets, ith, i, j;
58/* spp = number of species
59   nonodes = number of nodes in tree
60   chars = number of sites in actual sequences
61   outgrno indicates outgroup */
62Static boolean weights, thresh, simple, trout, outgropt,  printdata,
63               progress, treeprint, stepbox, ancseq, mulsets, firstset,
64               interleaved, ibmpc, vt52, ansi;
65Static short *weight, *oldweight;
66Static steptr alias, ally, location;
67Static pointptr treenode;   /* pointers to all nodes in tree */
68Static Char **name;   /* names of species */
69Static sequence y;
70Static double threshold, fracdone, fracinc;
71Static boolean *added;
72Static gbases *garbage;
73Static Char basechar[]="ACMGRSVTWYHKDBNO???????????????";
74
75typedef short *treenumbers;
76typedef double *valptr;
77typedef short *placeptr;
78
79/* Variables for maketree, propagated globally for C version: */
80short nextree, examined, mults;
81boolean firsttime, done, recompute;
82double like, bestyet;
83treenumbers *bestorders, *bestrees;
84treenumbers current, order;
85long *threshwt;
86baseptr nothing;
87node *temp, *temp1;
88static short suppno[] =
89  { 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,4};
90
91static char suppset[] =          /* this was previously a function. */
92{                                  /* in C, it doesn't need to be.    */
93   1 << ((Char)A),
94   1 << ((Char)C),
95   1 << ((Char)G),
96   1 << ((Char)U),
97   1 << ((Char)O),
98   (1 << ((Char)A)) | (1 << ((Char)C)),
99   (1 << ((Char)A))|(1 << ((Char)G)),
100   (1 << ((Char)A))|(1 << ((Char)U)),
101   (1 << ((Char)A)) | (1 << ((Char)O)),
102   (1 << ((Char)C)) | (1 << ((Char)G)),
103   (1 << ((Char)C)) | (1 << ((Char)U)),
104   (1 << ((Char)C)) | (1 << ((Char)O)),
105   (1 << ((Char)G)) | (1 << ((Char)U)),
106   (1 << ((Char)G)) | (1 << ((Char)O)),
107   (1 << ((Char)U)) | (1 << ((Char)O)),
108   (1 << ((Char)A)) | (1 << ((Char)C)) | (1 << ((Char)G)),
109   (1 << ((Char)A)) | (1 << ((Char)C)) | (1 << ((Char)U)),
110   (1 << ((Char)A)) | (1 << ((Char)C)) | (1 << ((Char)O)),
111   (1 << ((Char)A)) | (1 << ((Char)G)) | (1 << ((Char)U)),
112   (1 << ((Char)A)) | (1 << ((Char)G)) | (1 << ((Char)O)),
113   (1 << ((Char)A)) | (1 << ((Char)U)) | (1 << ((Char)O)),
114   (1 << ((Char)C)) | (1 << ((Char)G)) | (1 << ((Char)U)),
115   (1 << ((Char)C)) | (1 << ((Char)G)) | (1 << ((Char)O)),
116   (1 << ((Char)C)) | (1 << ((Char)U)) | (1 << ((Char)O)),
117   (1 << ((Char)G)) | (1 << ((Char)U)) | (1 << ((Char)O)),
118   (1 << ((Char)A))|(1 << ((Char)C))|(1 << ((Char)G))|(1 << ((Char)U)),
119   (1 << ((Char)A))|(1 << ((Char)C))|(1 << ((Char)G))|(1 << ((Char)O)),
120   (1 << ((Char)A))|(1 << ((Char)C))|(1 << ((Char)U))|(1 << ((Char)O)),
121   (1 << ((Char)A))|(1 << ((Char)G))|(1 << ((Char)U))|(1 << ((Char)O)),
122   (1 << ((Char)C))|(1 << ((Char)G))|(1 << ((Char)U)) | (1 << ((Char)O)),
123   (1 << ((Char)A))|(1 << ((Char)C))|(1 << ((Char)G)) | (1 << ((Char)U)) | (1 << ((Char)O))};
124
125
126openfile(fp,filename,mode,application,perm)
127FILE **fp;
128char *filename;
129char *mode;
130char *application;
131char *perm;
132{
133  FILE *of;
134  char file[100];
135  strcpy(file,filename);
136  while (1){
137    of = fopen(file,mode);
138    if (of)
139      break;
140    else {
141      switch (*mode){
142      case 'r':
143        printf("%s:  can't read %s\n",application,file);
144        file[0] = '\0';
145        while (file[0] =='\0'){
146          printf("Please enter a new filename>");
147          gets(file);}
148        break;
149      case 'w':
150      case 'a':
151        printf("%s: can't write %s\n",application,file);
152        file[0] = '\0';
153        while (file[0] =='\0'){
154          printf("Please enter a new filename>");
155          gets(file);}
156        break;
157      }
158    }
159  }
160  *fp=of;
161
162  if (perm != NULL)
163    strcpy(perm,file);
164}
165
166
167
168Static Void gnu(p)
169gbases **p;
170{
171  /* this and the following are do-it-yourself garbage collectors.
172     Make a new node or pull one off the garbage list */
173  if (garbage != NULL) {
174    *p = garbage;
175    garbage = garbage->next;
176  } else {
177    *p = (gbases *)Malloc(sizeof(gbases));
178    (*p)->base = (baseptr)Malloc(endsite*sizeof(char));
179  }
180  (*p)->next = NULL;
181}  /* gnu */
182
183
184Static Void chuck(p)
185gbases *p;
186{
187  /* collect garbage on p -- put it on front of garbage list */
188  p->next = garbage;
189  garbage = p;
190}  /* chuck */
191
192
193Static Void uppercase(ch)
194Char *ch;
195{
196    *ch = (islower (*ch) ? toupper(*ch) : (*ch));
197}  /* uppercase */
198
199
200
201Local Void inputnumbers()
202{
203  /* input the numbers of species and of characters */
204  fscanf(infile, "%hd%hd", &spp, &chars);
205  if (printdata)
206    fprintf(outfile, "%2hd species, %3hd  sites\n", spp, chars);
207  if (printdata)
208    putc('\n', outfile);
209  if (progress)
210    putchar('\n');
211  nonodes = spp * 2 - 1;
212}  /* inputnumbers */
213
214Local Void getoptions()
215{
216  /* interactively set options */
217  Char ch;
218  boolean  done1;
219
220  fprintf(outfile, "\nPenny algorithm for DNA, version %s\n",VERSION);
221  fprintf(outfile, " branch-and-bound to find all");
222  fprintf(outfile, " most parsimonious trees\n\n");
223  howoften = often;
224  howmany = many;
225  outgrno = 1;
226  outgropt = false;
227  simple = true;
228  thresh = false;
229  threshold = spp;
230  trout = true;
231  weights = false;
232  printdata = false;
233  progress = true;
234  treeprint = true;
235  stepbox = false;
236  ancseq = false;
237  interleaved = true;
238  for (;;) {
239    printf(ansi ? "\033[2J\033[H" : vt52 ? "\033E\033H" : "\n");
240    printf("\nPenny algorithm for DNA, version %s\n",VERSION);
241    printf(" branch-and-bound to find all most parsimonious trees\n\n");
242    printf("Settings for this run:\n");
243    printf("  H        How many groups of %4hd trees:%6hd\n", howoften, howmany);
244    printf("  F        How often to report, in trees:  %4hd\n", howoften);
245    printf("  S           Branch and bound is simple?  %s\n",
246           (simple ?  "Yes" : "No. reconsiders order of species"));
247    printf("  O                        Outgroup root?  %s%3hd\n",
248           (outgropt ? "Yes, at sequence number" :
249                       "No, use as outgroup species"),outgrno);
250    printf("  T              Use Threshold parsimony?");
251    if (thresh)
252      printf("  Yes, count steps up to%4.1f per site\n", threshold);
253    else
254      printf("  No, use ordinary parsimony\n");
255    printf("  M           Analyze multiple data sets?");
256    if (mulsets)
257      printf("  Yes, %2hd sets\n", datasets);
258    else
259      printf("  No\n");
260    printf("  I          Input sequences interleaved?  %s\n",
261           (interleaved ? "Yes" : "No, sequential"));
262    printf("  0   Terminal type (IBM PC, VT52, ANSI)?  %s\n",
263           (ibmpc ? "IBM PC" : ansi ? "ANSI" : vt52 ? "VT52" : "(none)"));
264    printf("  1    Print out the data at start of run  %s\n",
265           (printdata ? "Yes" : "No"));
266    printf("  2  Print indications of progress of run  %s\n",
267           (progress ? "Yes" : "No"));
268    printf("  3                        Print out tree  %s\n",
269           (treeprint ? "Yes" : "No"));
270    printf("  4          Print out steps in each site  %s\n",
271           (stepbox ? "Yes" : "No" ));
272    printf("  5  Print sequences at all nodes of tree  %s\n",
273           (ancseq ? "Yes" : "No"));
274    printf("  6       Write out trees onto tree file?  %s\n",
275           (trout ? "Yes" : "No"));
276    printf("\nAre these settings correct? (type Y or the letter for one to change)\n");
277    scanf("%c%*[^\n]", &ch);
278    getchar();
279    if (ch == '\n')
280      ch = ' ';
281    uppercase(&ch);
282    if (ch == 'Y')
283      break;
284    uppercase(&ch);
285    if ((strchr("HMSOFTI1234560",ch)) != NULL){
286      switch (ch) {
287       
288      case 'H':
289        do {
290          printf("How many cycles of %4hd trees?\n", howoften);
291          scanf("%hd%*[^\n]", &howmany);
292          getchar();
293        } while (howmany <= 0);
294        break;
295       
296      case 'M':
297        mulsets = !mulsets;
298        if (mulsets) {
299          done1 = false;
300          do {
301            printf("How many data sets?\n");
302            scanf("%hd%*[^\n]", &datasets);
303            getchar();
304            done1 = (datasets >= 1);
305            if (!done1)
306              printf("BAD DATA SETS NUMBER:  it must be greater than 1\n");
307          } while (done1 != true);
308        }
309        break;
310       
311      case 'F':
312        do {
313          printf("How many trees per cycle?\n");
314          scanf("%hd%*[^\n]", &howoften);
315          getchar();
316        } while (howoften <= 0);
317        break;
318       
319      case 'S':
320        simple = !simple;
321        break;
322       
323      case 'O':
324        outgropt = !outgropt;
325        if (outgropt) {
326          done1 = true;
327          do {
328            printf("Type number of the outgroup:\n");
329            scanf("%hd%*[^\n]", &outgrno);
330            getchar();
331            done1 = (outgrno >= 1 && outgrno <= spp);
332            if (!done1) {
333              printf("BAD OUTGROUP NUMBER: %4hd\n", outgrno);
334              printf("  Must be in range 1 -%2hd\n", spp);
335            }
336          } while (done1 != true);
337        }
338        else
339           outgrno = 1;
340        break;
341       
342        case 'T':
343        thresh = !thresh;
344        if (thresh) {
345          done1 = false;
346          do {
347            printf("What will be the threshold value?\n");
348            scanf("%lf%*[^\n]", &threshold);
349            getchar();
350            done1 = (threshold >= 1.0);
351            if (!done1)
352              printf("BAD THRESHOLD VALUE:  it must be greater than 1\n");
353            else
354              threshold = (short)(threshold * 10.0 + 0.5) / 10.0;
355          } while (done1 != true);
356        }
357        break;
358       
359      case 'I':
360        interleaved = !interleaved;
361        break;
362       
363      case '0':
364        if (ibmpc) {
365          ibmpc = false;
366          vt52 = true;
367        } else {
368          if (vt52) {
369            vt52 = false;
370            ansi = true;
371          } else if (ansi)
372            ansi = false;
373          else
374            ibmpc = true;
375        }
376        break;
377       
378      case '1':
379        printdata = !printdata;
380        break;
381       
382      case '2':
383        progress = !progress;
384        break;
385       
386      case '3':
387        treeprint = !treeprint;
388        break;
389       
390      case '4':
391        stepbox = !stepbox;
392        break;
393       
394      case '5':
395        ancseq = !ancseq;
396        break;
397       
398      case '6':
399        trout = !trout;
400        break;
401      }
402    } else
403      printf("Not a possible option!\n");
404  }
405}  /* getoptions */
406
407
408Static Void doinit()
409{
410  /* initializes variables */
411  short i, j;
412  node *p, *q;
413
414  inputnumbers();
415  getoptions();
416  y = (Char **)Malloc(spp*sizeof(Char *));
417  for (i = 0; i < spp; i++)
418    y[i] = (Char *)Malloc(chars*sizeof(Char));
419  treenode = (pointptr)Malloc(nonodes*sizeof(node *));
420  for (i = 0; i < spp; i++)
421    treenode[i] = (node *)Malloc(sizeof(node));
422  for (i = spp; i < nonodes; i++) {
423    q = NULL;
424    for (j = 1; j <= 3; j++) {
425      p = (node *)Malloc(sizeof(node));
426      p->next = q;
427      q = p;
428    }
429    p->next->next->next = p;
430    treenode[i] = p;
431  }
432}  /* doinit*/
433
434
435
436Local Void inputweights()
437{
438  /* input the character weights, 0-9 and A-Z for weights
439     0 - 35 */
440  Char ch;
441  short i;
442
443  for (i = 1; i < nmlngth; i++) {
444    ch = getc(infile);
445    if (ch == '\n')
446      ch = ' ';
447  }
448  for (i = 0; i < chars; i++) {
449    do {
450      if (eoln(infile)) {
451        fscanf(infile, "%*[^\n]");
452        getc(infile);
453      }
454      ch = getc(infile);
455      if (ch == '\n')
456        ch = ' ';
457    } while (ch == ' ');
458    weight[i] = 1;
459    if (isdigit(ch))
460      weight[i] = ch - '0';
461    else if (isalpha(ch)) {
462      uppercase(&ch);
463      if (ch >= 'A' && ch <= 'I')
464        weight[i] = ch - 55;
465      else if (ch >= 'J' && ch <= 'R')
466        weight[i] = ch - 55;
467      else
468        weight[i] = ch - 55;
469    } else {
470      printf("BAD WEIGHT CHARACTER: %c\n", ch);
471      exit(-1);
472    }
473  }
474  fscanf(infile, "%*[^\n]");
475  getc(infile);
476  weights = true;
477}  /* inputweights */
478
479Local Void printweights()
480{
481  /* print out the weights of sites */
482  short i, j, k;
483
484  fprintf(outfile, "    Sites are weighted as follows:\n");
485  fprintf(outfile, "        ");
486  for (i = 0; i <= 9; i++)
487    fprintf(outfile, "%3hd", i);
488  fprintf(outfile, "\n     *---------------------------------\n");
489  for (j = 0; j <= (chars / 10); j++) {
490    fprintf(outfile, "%5hd!  ", j * 10);
491    for (i = 0; i <= 9; i++) {
492      k = j * 10 + i;
493      if (k > 0 && k <= chars)
494        fprintf(outfile, "%3hd", weight[k - 1]);
495      else
496        fprintf(outfile, "   ");
497    }
498    putc('\n', outfile);
499  }
500  putc('\n', outfile);
501}  /* printweights */
502
503Local Void inputoptions()
504{
505  /* input the information on the options */
506  Char ch;
507  short extranum, i, cursp, curchs;
508
509  if (!firstset) {
510    if (eoln(infile)) {
511      fscanf(infile, "%*[^\n]");
512      getc(infile);
513    }
514    fscanf(infile, "%hd%hd", &cursp, &curchs);
515    if (cursp != spp) {
516      printf("\nERROR: INCONSISTENT NUMBER OF SPECIES IN DATA SET %4hd\n",ith);
517      exit(-1);
518    }
519    chars = curchs;
520  }
521  weights = false;
522  extranum = 0;
523  while (!(eoln(infile))) {
524    ch = getc(infile);
525    if (ch == '\n')
526      ch = ' ';
527    uppercase(&ch);
528    if (ch == 'W')
529      extranum++;
530    else if (ch != ' ') {
531      printf("BAD OPTION CHARACTER: %c\n", ch);
532      exit(-1);
533    }
534  }
535  fscanf(infile, "%*[^\n]");
536  getc(infile);
537  for (i = 0; i < chars; i++)
538    weight[i] = 1;
539  for (i = 1; i <= extranum; i++) {
540    ch = getc(infile);
541    if (ch == '\n')
542      ch = ' ';
543    uppercase(&ch);
544    if (ch == 'W')
545      inputweights();
546    else {
547      printf("ERROR: INCORRECT AUXILIARY OPTIONS LINE WHICH STARTS WITH %c\n",
548             ch);
549      exit(-1);}
550  }
551  if (weights)
552    printweights();
553}  /* inputoptions */
554
555Local Void inputdata()
556{
557  /* input the names and sequences for each species */
558  short i, j, k, l, basesread, basesnew;
559  Char charstate;
560  boolean allread, done;
561
562  putc('\n', outfile);
563  j = nmlngth + (chars + (chars - 1) / 10) / 2 - 5;
564  if (j < nmlngth - 1)
565    j = nmlngth - 1;
566  if (j > 37)
567    j = 37;
568  if (printdata) {
569    fprintf(outfile, "Name");
570    for (i = 1; i <= j; i++)
571      putc(' ', outfile);
572    fprintf(outfile, "Sequences\n");
573    fprintf(outfile, "----");
574    for (i = 1; i <= j; i++)
575      putc(' ', outfile);
576    fprintf(outfile, "---------\n\n");
577  }
578  basesread = 0;
579  allread = false;
580  while (!(allread)) {
581    allread = true;
582    if (eoln(infile)) {
583      fscanf(infile, "%*[^\n]");
584      getc(infile);
585    }
586    i = 1;
587    while (i <= spp ) {
588      if ((interleaved && basesread == 0) || !interleaved) {
589        for (j = 0; j < nmlngth; j++) {
590          name[i - 1][j] = getc(infile);
591          if (eof(infile) | eoln(infile)){
592            printf("ERROR: END-OF-LINE OR END-OF-FILE");
593            printf(" IN THE MIDDLE OF A SPECIES NAME\n");
594            exit(-1);}
595        }
596      }
597      j = interleaved ? basesread : 0;
598      done = false;
599      while (!done && !eof(infile)) {
600        if (interleaved)
601          done = true;
602        while (j < chars && !(eoln(infile) || eof(infile))) {
603          charstate = getc(infile);
604          if (charstate == ' ' || (charstate >= '0' && charstate <= '9'))
605            continue;
606          uppercase(&charstate);
607          if ((strchr("ABCDGHKMNRSTUVWXY?O-.",charstate)) == NULL){
608            printf("ERROR: BAD BASE:%c AT POSITION%5hd OF SPECIES %3hd\n",
609                   charstate, j, i);
610            exit(-1);
611          }
612          j++;
613          if (charstate == '.')
614            charstate = y[0][j - 1];
615          y[i - 1][j - 1] = charstate;
616        }
617        if (interleaved)
618          continue;
619        if (j < chars) {
620          fscanf(infile, "%*[^\n]");
621          getc(infile);
622        } else if (j == chars)
623          done = true;
624      }
625      if (interleaved && i == 1)
626        basesnew = j;
627      fscanf(infile, "%*[^\n]");
628      getc(infile);
629      if ((interleaved && j != basesnew) || ((!interleaved) && j != chars)){
630        printf("ERROR: SEQUENCES OUT OF ALIGNMENT\n");
631        exit(-1);}
632      i++;
633    }
634    if (interleaved) {
635      basesread = basesnew;
636      allread = (basesread == chars);
637    } else
638      allread = (i > spp);
639  }
640  if (!printdata)
641    return;
642   for (i = 1; i <= ((chars - 1) / 60 + 1); i++) {
643     for (j = 1; j <= spp; j++) {
644      for (k = 0; k < nmlngth; k++)
645        putc(name[j - 1][k], outfile);
646      fprintf(outfile, "   ");
647      l = i * 60;
648      if (l > chars)
649        l = chars;
650      for (k = (i - 1) * 60 + 1; k <= l; k++) {
651        if (j > 1 && y[j - 1][k - 1] == y[0][k - 1])
652          charstate = '.';
653        else
654          charstate = y[j - 1][k - 1];
655        putc(charstate, outfile);
656        if (k % 10 == 0 && k % 60 != 0)
657          putc(' ', outfile);
658      }
659      putc('\n', outfile);
660    }
661     putc('\n', outfile);
662   }
663  putc('\n', outfile);
664}  /* inputdata */
665
666Local Void sitesort()
667{
668  /* Shell sort keeping sites, weights in same order */
669  short gap, i, j, jj, jg, k, itemp;
670  boolean flip, tied;
671
672  gap = chars / 2;
673  while (gap > 0) {
674    for (i = gap + 1; i <= chars; i++) {
675      j = i - gap;
676      flip = true;
677      while (j > 0 && flip) {
678        jj = alias[j - 1];
679        jg = alias[j + gap - 1];
680        tied = true;
681        k = 1;
682        while (k <= spp && tied) {
683          flip = (y[k - 1][jj - 1] > y[k - 1][jg - 1]);
684          tied = (tied && y[k - 1][jj - 1] == y[k - 1][jg - 1]);
685          k++;
686        }
687        if (!flip)
688          break;
689        itemp = alias[j - 1];
690        alias[j - 1] = alias[j + gap - 1];
691        alias[j + gap - 1] = itemp;
692        itemp = weight[j - 1];
693        weight[j - 1] = weight[j + gap - 1];
694        weight[j + gap - 1] = itemp;
695        j -= gap;
696      }
697    }
698    gap /= 2;
699  }
700}  /* sitesort */
701
702Local Void sitecombine()
703{
704  /* combine sites that have identical patterns */
705  short i, j, k;
706  boolean tied;
707
708  i = 1;
709  while (i < chars) {
710    j = i + 1;
711    tied = true;
712    while (j <= chars && tied) {
713      k = 1;
714      while (k <= spp && tied) {
715        tied = (tied &&
716            y[k - 1][alias[i - 1] - 1] == y[k - 1][alias[j - 1] - 1]);
717        k++;
718      }
719      if (tied) {
720        weight[i - 1] += weight[j - 1];
721        weight[j - 1] = 0;
722        ally[alias[j - 1] - 1] = alias[i - 1];
723      }
724      j++;
725    }
726    i = j - 1;
727  }
728}  /* sitecombine */
729
730Local Void sitescrunch()
731{
732  /* move so positively weighted sites come first */
733  short i, j, itemp;
734  boolean done, found;
735
736  done = false;
737  i = 1;
738  j = 2;
739  while (!done) {
740    if (ally[alias[i - 1] - 1] != alias[i - 1]) {
741      if (j <= i)
742        j = i + 1;
743      if (j <= chars) {
744        found = false;
745        do {
746          found = (ally[alias[j - 1] - 1] == alias[j - 1]);
747          j++;
748        } while (!(found || j > chars));
749        if (found) {
750          j--;
751          itemp = alias[i - 1];
752          alias[i - 1] = alias[j - 1];
753          alias[j - 1] = itemp;
754          itemp = weight[i - 1];
755          weight[i - 1] = weight[j - 1];
756          weight[j - 1] = itemp;
757        } else
758          done = true;
759      } else
760        done = true;
761    }
762    i++;
763    done = (done || i >= chars);
764  }
765}  /* sitescrunch */
766
767Local Void makeweights()
768{
769  /* make up weights vector to avoid duplicate computations */
770  short i;
771
772  for (i = 1; i <= chars; i++) {
773    alias[i - 1] = i;
774    oldweight[i - 1] = weight[i - 1];
775    ally[i - 1] = i;
776  }
777  sitesort();
778  sitecombine();
779  sitescrunch();
780  endsite = 0;
781  for (i = 1; i <= chars; i++) {
782    if (ally[i - 1] == i)
783      endsite++;
784  }
785  for (i = 1; i <= endsite; i++)
786    location[alias[i - 1] - 1] = i;
787  if (!thresh)
788    threshold = spp;
789  threshwt = (long *)Malloc(endsite*sizeof(long));
790  for (i = 0; i < endsite; i++) {
791    weight[i] *= 10;
792    threshwt[i] = (long)(threshold * weight[i] + 0.5);
793  }
794}  /* makeweights */
795
796Local Void makevalues()
797{
798  /* set up fractional likelihoods at tips */
799  short i, j;
800  char ns;
801  node *p;
802  for (i = 1; i <= nonodes; i++) {
803    treenode[i - 1]->back = NULL;
804    treenode[i - 1]->tip = (i <= spp);
805    treenode[i - 1]->index = i;
806    if (i > spp) {
807      p = treenode[i - 1]->next;
808      while (p != treenode[i - 1]) {
809        p->back = NULL;
810        p->tip = false;
811        p->index = i;
812        p = p->next;
813      }
814    }
815  }
816  for (i = 0; i < spp; i++) {
817    treenode[i]->numsteps = (stepshortptr)Malloc(endsite*sizeof(short));
818    treenode[i]->base = (baseptr)Malloc(endsite*sizeof(char));
819  }
820  for (i = spp; i < nonodes; i++) {
821    p = treenode[i];
822    for (j = 1; j <= 3; j++) {
823      p->numsteps = (stepshortptr)Malloc(endsite*sizeof(short));
824      p->base = (baseptr)Malloc(endsite*sizeof(char));
825      p = p->next;
826    }
827  }
828  for (j = 0; j < endsite; j++) {
829    for (i = 0; i < spp; i++) {
830      switch (y[i][alias[j] - 1]) {
831
832      case 'A':
833        ns = 1 << ((char)A);
834        break;
835
836      case 'C':
837        ns = 1 << ((char)C);
838        break;
839
840      case 'G':
841        ns = 1 << ((char)G);
842        break;
843
844      case 'U':
845        ns = 1 << ((char)U);
846        break;
847
848      case 'T':
849        ns = 1 << ((char)U);
850        break;
851
852      case 'M':
853        ns = (1 << ((char)A)) | (1 << ((char)C));
854        break;
855
856      case 'R':
857        ns = (1 << ((char)A)) | (1 << ((char)G));
858        break;
859
860      case 'W':
861        ns = (1 << ((char)A)) | (1 << ((char)U));
862        break;
863
864      case 'S':
865        ns = (1 << ((char)C)) | (1 << ((char)G));
866        break;
867
868      case 'Y':
869        ns = (1 << ((char)C)) | (1 << ((char)U));
870        break;
871
872      case 'K':
873        ns = (1 << ((char)G)) | (1 << ((char)U));
874        break;
875
876      case 'B':
877        ns = (1 << ((char)C)) | (1 << ((char)G)) | (1 << ((char)U));
878        break;
879
880      case 'D':
881        ns = (1 << ((char)A)) | (1 << ((char)G)) | (1 << ((char)U));
882        break;
883
884      case 'H':
885        ns = (1 << ((char)A)) | (1 << ((char)C)) | (1 << ((char)U));
886        break;
887
888      case 'V':
889        ns = (1 << ((char)A)) | (1 << ((char)C)) | (1 << ((char)G));
890        break;
891
892      case 'N':
893        ns = (1 << ((char)A)) | (1 << ((char)C)) | (1 << ((char)G)) |
894             (1 << ((char)U));
895        break;
896
897      case 'X':
898        ns = (1 << ((char)A)) | (1 << ((char)C)) | (1 << ((char)G)) |
899             (1 << ((char)U));
900        break;
901
902      case '?':
903        ns = (1 << ((char)A)) | (1 << ((char)C)) | (1 << ((char)G)) |
904             (1 << ((char)U)) | (1 << ((char)O));
905        break;
906
907      case 'O':
908        ns = 1 << ((char)O);
909        break;
910
911      case '-':
912        ns = 1 << ((char)O);
913        break;
914      }
915      treenode[i]->base[j] = ns;
916      treenode[i]->numsteps[j] = 0;
917    }
918  }
919}  /* makevalues */
920
921
922Static Void doinput()
923{
924  /* reads the input data */
925  inputoptions();
926  inputdata();
927  makeweights();
928  makevalues();
929}  /* doinput */
930
931
932
933
934Local Void fillin(p, left, rt)
935node *p, *left, *rt;
936{
937  /* sets up for each node in the tree the base sequence
938     at that point and counts the changes.  The program
939     spends much of its time in this PROCEDURE */
940  short i;
941  short ns, rs, ls;
942
943  for (i = 0; i < endsite; i++) {
944    if (left != NULL)
945      ls = left->base[i];
946    if (rt != NULL)
947      rs = rt->base[i];
948    if (left == NULL) {
949      ns = rs;
950      p->numsteps[i] = rt->numsteps[i];
951    } else if (rt == NULL) {
952      ns = ls;
953      p->numsteps[i] = left->numsteps[i];
954    } else {
955      ns = ls & rs;
956      p->numsteps[i] = left->numsteps[i] + rt->numsteps[i];
957    }
958    if (ns == 0) {
959      if (left != NULL && rt != NULL)
960        ns = ls | rs;
961      p->numsteps[i] += weight[i];
962    }
963    p->base[i] = ns;
964  }
965}  /* fillin */
966
967Local Void preorder(p)
968node *p;
969{
970  /* recompute number of steps in preorder taking both ancestoral and
971     descendent steps into account */
972  if (p == NULL || p->tip)
973    return;
974  fillin(p->next, p->next->next->back, p->back);
975  fillin(p->next->next, p->back, p->next->back);
976  preorder(p->next->back);
977  preorder(p->next->next->back);
978}  /* preorder */
979
980Local Void add(below, newtip, newfork)
981node **below, **newtip, **newfork;
982
983{
984  /* inserts the nodes newfork and its left descendant, newtip,
985     to the tree.  below becomes newfork's right descendant.
986     The global variable root is also updated */
987  if (*below != treenode[(*below)->index - 1])
988    *below = treenode[(*below)->index - 1];
989  if ((*below)->back != NULL)
990    (*below)->back->back = *newfork;
991  (*newfork)->back = (*below)->back;
992  (*below)->back = (*newfork)->next->next;
993  (*newfork)->next->next->back = *below;
994  (*newfork)->next->back = *newtip;
995  (*newtip)->back = (*newfork)->next;
996  if (root == *below)
997    root = *newfork;
998  if (!recompute)
999    return;
1000  fillin(*newfork, (*newfork)->next->back, (*newfork)->next->next->back);
1001  preorder(*newfork);
1002  if (*newfork != root)
1003    preorder((*newfork)->back);
1004}  /* add */
1005
1006Local Void re_move(item, fork)
1007node **item, **fork;
1008{
1009  /* removes nodes item and its ancestor, fork, from the tree.
1010     the new descendant of fork's ancestor is made to be
1011     fork's second descendant (other than item).  Also
1012     returns pointers to the deleted nodes, item and fork.
1013     The global variable root is also updated */
1014  node *p, *q, *other;
1015
1016  if ((*item)->back == NULL) {
1017    *fork = NULL;
1018    return;
1019  }
1020  *fork = treenode[(*item)->back->index - 1];
1021  if (*item == (*fork)->next->back)
1022    other = (*fork)->next->next->back;
1023  else
1024    other = (*fork)->next->back;
1025  if (root == *fork)
1026    root = other;
1027  p = (*item)->back->next->back;
1028  q = (*item)->back->next->next->back;
1029  if (p != NULL)
1030    p->back = q;
1031  if (q != NULL)
1032    q->back = p;
1033  (*fork)->back = NULL;
1034  p = (*fork)->next;
1035  while (p != *fork) {
1036    p->back = NULL;
1037    p = p->next;
1038  }
1039  (*item)->back = NULL;
1040  if (!recompute)
1041    return;
1042  preorder(other);
1043  if (other != root)
1044    preorder(other->back);
1045}  /* re_move */
1046
1047
1048Local Void supplement(r)
1049node *r;
1050{
1051  /* determine minimum number of steps more which will
1052     be added when rest of species are put in tree */
1053  short i, j, k, sum, sumall, sumadded;
1054  boolean doneadded, allhave, addedhave, has;
1055  char supps;
1056
1057  for (i = 0; i < endsite; i++) {
1058    sum = 3;
1059    j = 1;
1060    doneadded = false;
1061    do {
1062      allhave = true;
1063      addedhave = true;
1064      supps = suppset[j-1];
1065      for (k = 0; k < spp; k++) {
1066        has = ((treenode[k]->base[i] & supps) != 0);
1067        if (added[k] && !doneadded)
1068          addedhave = (addedhave && has);
1069        allhave = (allhave && has);
1070      }
1071      if (allhave)
1072        sumall = suppno[j - 1];
1073      if (addedhave)
1074        sumadded = suppno[j - 1];
1075      doneadded = (doneadded || addedhave);
1076      j++;
1077    } while (!(j > 31 || (allhave && doneadded)));
1078    if (addedhave && allhave)
1079      sum = sumall - sumadded;
1080    r->numsteps[i] += sum * weight[i];
1081  }
1082}  /* supplement */
1083
1084Local Void evaluate(r)
1085node *r;
1086{
1087  /* determines the number of steps needed for a tree. this is
1088     the minimum number of steps needed to evolve sequences on
1089     this tree */
1090  short i, steps;
1091  double sum;
1092
1093  sum = 0.0;
1094  supplement(r);
1095  for (i = 0; i < endsite; i++) {
1096    steps = r->numsteps[i];
1097    if ((long)steps <= threshwt[i])
1098      sum += steps;
1099    else
1100      sum += threshwt[i];
1101  }
1102  if (examined == 0 && mults == 0)
1103    bestyet = -1.0;
1104  like = sum;
1105}  /* evaluate */
1106
1107Local Void postorder(p)
1108node *p;
1109{
1110  /* traverses a binary tree, calling PROCEDURE fillin at a
1111     node's descendants before calling fillin at the node */
1112  if (p->tip)
1113    return;
1114  postorder(p->next->back);
1115  postorder(p->next->next->back);
1116  fillin(p, p->next->back, p->next->next->back);
1117}  /* postorder */
1118
1119
1120
1121Local Void addtraverse(p, item, fork, m,n,valyew,place)
1122node *p, *item, *fork;
1123short *m,*n;
1124valptr valyew;
1125placeptr place;
1126{
1127  /* traverse all places to add item */
1128  if (done)
1129    return;
1130  if (*m <= 2 || (p != root && p != root->next->back)) {
1131    if (p == root)
1132      fillin(temp, item, p);
1133    else {
1134      fillin(temp1, item, p);
1135      fillin(temp, temp1, p->back);
1136    }
1137    (*n)++;
1138    evaluate(temp);
1139    examined++;
1140    if (examined == howoften) {
1141      examined = 0;
1142      mults++;
1143      if (mults == howmany)
1144        done = true;
1145      if (progress) {
1146        printf("%7hd", mults);
1147        if (bestyet >= 0)
1148          printf("%16.1f", bestyet / 10.0);
1149        else
1150          printf("            -   ");
1151        printf("%17hd%20.2f\n", nextree - 1, fracdone * 100);
1152      }
1153    }
1154    valyew[(*n) - 1] = like;
1155    place[(*n) - 1] = p->index;
1156  }
1157  if (!p->tip) {
1158    addtraverse(p->next->back, item, fork, m,n,valyew,place);
1159    addtraverse(p->next->next->back, item, fork,m,n,valyew,place);
1160  }
1161}  /* addtraverse */
1162
1163Local Void shellsort(a, b, n)
1164double *a;
1165short *b;
1166short n;
1167{
1168  /* Shell sort keeping a, b in same order */
1169  short gap, i, j, itemp;
1170  double rtemp;
1171
1172  gap = n / 2;
1173  while (gap > 0) {
1174    for (i = gap + 1; i <= n; i++) {
1175      j = i - gap;
1176      while (j > 0) {
1177        if (a[j - 1] > a[j + gap - 1]) {
1178          rtemp = a[j - 1];
1179          a[j - 1] = a[j + gap - 1];
1180          a[j + gap - 1] = rtemp;
1181          itemp = b[j - 1];
1182          b[j - 1] = b[j + gap - 1];
1183          b[j + gap - 1] = itemp;
1184        }
1185        j -= gap;
1186      }
1187    }
1188    gap /= 2;
1189  }
1190}  /* shellsort */
1191
1192Local Void addit(m)
1193short m;
1194{
1195  /* adds the species one by one, recursively */
1196  short n;
1197  valptr valyew;
1198  placeptr place;
1199  short i, j, n1, besttoadd;
1200  valptr bestval;
1201  placeptr bestplace;
1202  double oldfrac, oldfdone, sum, bestsum;
1203
1204  valyew = (valptr)Malloc(nonodes*sizeof(double));
1205  bestval = (valptr)Malloc(nonodes*sizeof(double));
1206  place = (placeptr)Malloc(nonodes*sizeof(short));
1207  bestplace = (placeptr)Malloc(nonodes*sizeof(short));
1208  if (simple && !firsttime) {
1209    n = 0;
1210    added[order[m - 1] - 1] = true;
1211    addtraverse(root, treenode[order[m - 1] - 1],
1212                treenode[spp + m - 2], &m,&n,valyew,place);
1213    besttoadd = order[m - 1];
1214    memcpy(bestplace, place, nonodes*sizeof(short));
1215    memcpy(bestval, valyew, nonodes*sizeof(double));
1216  } else {
1217    bestsum = -1.0;
1218    for (i = 1; i <= spp; i++) {
1219      if (!added[i - 1]) {
1220        n = 0;
1221        added[i - 1] = true;
1222        addtraverse(root, treenode[i - 1], treenode[spp + m - 2],
1223                    &m,&n,valyew,place);
1224        added[i - 1] = false;
1225        sum = 0.0;
1226        for (j = 0; j < n; j++)
1227          sum += valyew[j];
1228        if (sum > bestsum) {
1229          bestsum = sum;
1230          besttoadd = i;
1231          memcpy(bestplace, place, nonodes*sizeof(short));
1232          memcpy(bestval, valyew, nonodes*sizeof(double));
1233        }
1234      }
1235    }
1236  }
1237  order[m - 1] = besttoadd;
1238  memcpy(place, bestplace, nonodes*sizeof(short));
1239  memcpy(valyew, bestval, nonodes*sizeof(double));
1240  shellsort(valyew, place, n);
1241  oldfrac = fracinc;
1242  oldfdone = fracdone;
1243  n1 = 0;
1244  for (i = 0; i < n; i++) {
1245    if (valyew[i] <= bestyet || bestyet < 0.0)
1246      n1++;
1247  }
1248  if (n1 > 0)
1249    fracinc /= n1;
1250  for (i = 0; i < n; i++) {
1251    if (valyew[i] <= bestyet || bestyet < 0.0) {
1252      current[m - 1] = place[i];
1253      recompute = (m < spp);
1254      add(&treenode[place[i] - 1], &treenode[besttoadd - 1],
1255          &treenode[spp + m - 2]);
1256      added[besttoadd - 1] = true;
1257      if (m < spp)
1258        addit(m + 1);
1259      else {
1260        if (valyew[i] < bestyet || bestyet < 0.0) {
1261          nextree = 1;
1262          bestyet = valyew[i];
1263        }
1264        if (nextree <= maxtrees) {
1265          memcpy(bestorders[nextree - 1], order,
1266                 spp*sizeof(short));
1267          memcpy(bestrees[nextree - 1], current,
1268                 spp*sizeof(short));
1269        }
1270        nextree++;
1271        firsttime = false;
1272      }
1273      recompute = (m < spp);
1274      re_move(&treenode[besttoadd - 1], &treenode[spp + m - 2]);
1275      added[besttoadd - 1] = false;
1276    }
1277    fracdone += fracinc;
1278  }
1279  fracinc = oldfrac;
1280  fracdone = oldfdone;
1281  free(valyew);
1282  free(bestval);
1283  free(place);
1284  free(bestplace);
1285}  /* addit */
1286
1287Local Void reroot(outgroup)
1288node *outgroup;
1289{
1290  /* reorients tree, putting outgroup in desired position. */
1291  node *p, *q, *newbottom, *oldbottom;
1292
1293  if (outgroup->back->index == root->index)
1294    return;
1295  newbottom = outgroup->back;
1296  p = treenode[newbottom->index - 1]->back;
1297  while (p->index != root->index) {
1298    oldbottom = treenode[p->index - 1];
1299    treenode[p->index - 1] = p;
1300    p = oldbottom->back;
1301  }
1302  p = root->next;
1303  q = root->next->next;
1304  p->back->back = q->back;
1305  q->back->back = p->back;
1306  p->back = outgroup;
1307  q->back = outgroup->back;
1308  outgroup->back->back = root->next->next;
1309  outgroup->back = root->next;
1310  treenode[newbottom->index - 1] = newbottom;
1311}  /* reroot */
1312
1313
1314Local Void coordinates(p, tipy)
1315node *p;
1316short *tipy;
1317{
1318  /* establishes coordinates of nodes */
1319  node *q, *first, *last;
1320
1321  if (p->tip) {
1322    p->xcoord = 0;
1323    p->ycoord = (*tipy);
1324    p->ymin = (*tipy);
1325    p->ymax = (*tipy);
1326    (*tipy) += down;
1327    return;
1328  }
1329  q = p->next;
1330  do {
1331    coordinates(q->back, tipy);
1332    q = q->next;
1333  } while (p != q);
1334  first = p->next->back;
1335  q = p->next;
1336  while (q->next != p)
1337    q = q->next;
1338  last = q->back;
1339  p->xcoord = last->ymax - first->ymin;
1340  p->ycoord = (first->ycoord + last->ycoord) / 2;
1341  p->ymin = first->ymin;
1342  p->ymax = last->ymax;
1343}  /* coordinates */
1344
1345Local Void drawline(i, scale)
1346short i;
1347double scale;
1348{
1349  /* draws one row of the tree diagram by moving up tree */
1350  node *p, *q, *r, *first, *last;
1351  short n, j;
1352  boolean extra, done;
1353
1354  p = root;
1355  q = root;
1356  extra = false;
1357  if (i == p->ycoord && p == root) {
1358    if (p->index - spp >= 10)
1359      fprintf(outfile, "-%2hd", p->index - spp);
1360    else
1361      fprintf(outfile, "--%hd", p->index - spp);
1362    extra = true;
1363  } else
1364    fprintf(outfile, "  ");
1365  do {
1366    if (!p->tip) {
1367      r = p->next;
1368      done = false;
1369      do {
1370        if (i >= r->back->ymin && i <= r->back->ymax) {
1371          q = r->back;
1372          done = true;
1373        }
1374        r = r->next;
1375      } while (!(done || r == p));
1376      first = p->next->back;
1377      r = p->next;
1378      while (r->next != p)
1379        r = r->next;
1380      last = r->back;
1381    }
1382    done = (p == q);
1383    n = (short)(scale * (p->xcoord - q->xcoord) + 0.5);
1384    if (n < 3 && !q->tip)
1385      n = 3;
1386    if (extra) {
1387      n--;
1388      extra = false;
1389    }
1390    if (q->ycoord == i && !done) {
1391      putc('+', outfile);
1392      if (!q->tip) {
1393        for (j = 1; j <= n - 2; j++)
1394          putc('-', outfile);
1395        if (q->index - spp >= 10)
1396          fprintf(outfile, "%2hd", q->index - spp);
1397        else
1398          fprintf(outfile, "-%hd", q->index - spp);
1399        extra = true;
1400      } else {
1401        for (j = 1; j < n; j++)
1402          putc('-', outfile);
1403      }
1404    } else if (!p->tip) {
1405      if (last->ycoord > i && first->ycoord < i && i != p->ycoord) {
1406        putc('!', outfile);
1407        for (j = 1; j < n; j++)
1408          putc(' ', outfile);
1409      } else {
1410        for (j = 1; j <= n; j++)
1411          putc(' ', outfile);
1412      }
1413    } else {
1414      for (j = 1; j <= n; j++)
1415        putc(' ', outfile);
1416    }
1417    if (p != q)
1418      p = q;
1419  } while (!done);
1420  if (p->ycoord == i && p->tip) {
1421    for (j = 0; j < nmlngth; j++)
1422      putc(name[p->index - 1][j], outfile);
1423  }
1424  putc('\n', outfile);
1425}  /* drawline */
1426
1427Local Void printree()
1428{
1429  /* prints out diagram of the tree */
1430/* Local variables for printree: */
1431  short tipy;
1432  double scale;
1433  short i;
1434
1435  putc('\n', outfile);
1436  if (!treeprint)
1437    return;
1438  putc('\n', outfile);
1439  tipy = 1;
1440  coordinates(root, &tipy);
1441  scale = 1.5;
1442  putc('\n', outfile);
1443  for (i = 1; i <= (tipy - down); i++)
1444    drawline(i, scale);
1445  fprintf(outfile, "\n  remember:");
1446  if (outgropt)
1447    fprintf(outfile, " (although rooted by outgroup)");
1448  fprintf(outfile, " this is an unrooted tree!\n\n");
1449}  /* printree */
1450
1451
1452
1453Local Void ancestset(a, b, c)
1454char *a, *b, *c;
1455{
1456  /* make the set of ancestral states below nodes
1457     whose base sets are a and b */
1458  *c = (*a) & (*b);
1459  if (*c == 0)
1460    *c = (*a) | (*b);
1461}  /* ancestset */
1462
1463
1464Local Void hyprint(b1, b2, bottom,HyptravVars)
1465short b1, b2;
1466boolean *bottom;
1467struct LOC_hyptrav *HyptravVars;
1468{
1469  /* print out states in sites b1 through b2 at node */
1470  short i, j, k, n;
1471  boolean dot;
1472  bases b;
1473
1474  if (*bottom) {
1475    if (!outgropt)
1476      fprintf(outfile, "       ");
1477    else
1478      fprintf(outfile, "root   ");
1479  } else
1480    fprintf(outfile, "%4hd   ", HyptravVars->r->back->index - spp);
1481  if (HyptravVars->r->tip) {
1482    for (i = 0; i < nmlngth; i++)
1483      putc(name[HyptravVars->r->index - 1][i], outfile);
1484  } else
1485    fprintf(outfile, "%4hd      ", HyptravVars->r->index - spp);
1486  if (*bottom)
1487    fprintf(outfile, "          ");
1488  else if (HyptravVars->nonzero)
1489    fprintf(outfile, "   yes    ");
1490  else if (HyptravVars->maybe)
1491    fprintf(outfile, "  maybe   ");
1492  else
1493    fprintf(outfile, "   no     ");
1494  for (i = b1; i <= b2; i++) {
1495    j = location[ally[i - 1] - 1];
1496    HyptravVars->tempset = HyptravVars->r->base[j - 1];
1497    HyptravVars->anc = HyptravVars->hypset[j - 1];
1498    if (!(*bottom))
1499      HyptravVars->anc = treenode[HyptravVars->r->back->index - 1]->base[j - 1];
1500    dot = (HyptravVars->tempset == HyptravVars->anc && !(*bottom));
1501    if (dot)
1502      putc('.', outfile);
1503    else if (HyptravVars->tempset == 1 << ((char)A))
1504      putc('A', outfile);
1505    else if (HyptravVars->tempset == 1 << ((char)C))
1506      putc('C', outfile);
1507    else if (HyptravVars->tempset == 1 << ((char)G))
1508      putc('G', outfile);
1509    else if (HyptravVars->tempset == 1 << ((char)U))
1510      putc('T', outfile);
1511    else if (HyptravVars->tempset == 1 << ((char)O))
1512      putc('-', outfile);
1513    else {
1514      k = 1;
1515      n = 0;
1516      for (b = A; (char)b <= (char)O; b = (bases)((char)b + 1)) {
1517        if (((1 << ((char)b)) & HyptravVars->tempset) != 0)
1518
1519          n += k;
1520        k += k;
1521      }
1522      putc(basechar[n - 1], outfile);
1523    }
1524    if (i % 10 == 0)
1525      putc(' ', outfile);
1526  }
1527  putc('\n', outfile);
1528}  /* hyprint */
1529
1530
1531Local Void hyptrav(r_, hypset_, b1, b2, bottom)
1532node *r_;
1533char *hypset_;
1534short b1, b2;
1535boolean *bottom;
1536{
1537  /*  compute, print out states at one interior node */
1538  struct LOC_hyptrav Vars;
1539  short i, j;
1540  char left, rt;
1541  gbases *temparray, *ancset;
1542
1543  Vars.r = r_;
1544  Vars.hypset = hypset_;
1545  gnu(&ancset);
1546  gnu(&temparray);
1547  Vars.maybe = false;
1548  Vars.nonzero = false;
1549  for (i = b1 - 1; i < b2; i++) {
1550    j = location[ally[i] - 1];
1551    Vars.anc = Vars.hypset[j - 1];
1552    if (!Vars.r->tip) {
1553      left = Vars.r->next->back->base[j - 1];
1554      rt = Vars.r->next->next->back->base[j - 1];
1555      Vars.tempset = left & rt & Vars.anc;
1556      if (Vars.tempset == 0) {
1557        Vars.tempset = (left & rt) | (left & Vars.anc) | (rt & Vars.anc);
1558        if (Vars.tempset == 0)
1559          Vars.tempset = left | rt | Vars.anc;
1560      }
1561      Vars.r->base[j - 1] = Vars.tempset;
1562    }
1563    if (!(*bottom))
1564      Vars.anc = treenode[Vars.r->back->index - 1]->base[j - 1];
1565    Vars.nonzero = (Vars.nonzero || (Vars.r->base[j - 1] & Vars.anc) == 0);
1566    Vars.maybe = (Vars.maybe || Vars.r->base[j - 1] != Vars.anc);
1567  }
1568  hyprint(b1, b2, bottom,&Vars);
1569  (*bottom) = false;
1570  if (!Vars.r->tip) {
1571    memcpy(temparray->base, Vars.r->next->back->base, endsite*sizeof(char));
1572    for (i = b1 - 1; i < b2; i++) {
1573      j = location[ally[i] - 1];
1574      ancestset(&Vars.hypset[j - 1], &Vars.r->next->next->back->base[j - 1],
1575                &ancset->base[j - 1]);
1576    }
1577    hyptrav(Vars.r->next->back, ancset->base, b1, b2,bottom);
1578    for (i = b1 - 1; i < b2; i++) {
1579      j = location[ally[i] - 1];
1580      ancestset(&Vars.hypset[j - 1], &temparray->base[j - 1],
1581                &ancset->base[j - 1]);
1582    }
1583    hyptrav(Vars.r->next->next->back, ancset->base, b1, b2,bottom);
1584  }
1585  chuck(temparray);
1586  chuck(ancset);
1587}  /* hyptraVars */
1588
1589Local Void hypstates()
1590{
1591  /* fill in and describe states at interior nodes */
1592  boolean bottom;
1593  short i, n;
1594
1595  fprintf(outfile, "\nFrom    To     Any Steps?    State at upper node\n");
1596  fprintf(outfile, "                            ");
1597  fprintf(outfile, " ( . means same as in the node below it on tree)\n\n");
1598  nothing = (baseptr)Malloc(endsite*sizeof(char));
1599  for (i = 0; i < endsite; i++)
1600    nothing[i] = 0;
1601  for (i = 1; i <= ((chars - 1 ) / 40 + 1); i++) {
1602    putc('\n', outfile);
1603    bottom = true;
1604    n = i * 40;
1605    if (n > chars)
1606      n = chars;
1607    hyptrav(root, nothing, i * 40 - 39, n, &bottom);
1608  }
1609  free(nothing);
1610}  /* hypstates */
1611
1612Local Void treeout(p)
1613node *p;
1614{
1615  /* write out file with representation of final tree */
1616  short i, n;
1617  Char c;
1618
1619  if (p->tip) {
1620    n = 0;
1621    for (i = 1; i <= nmlngth; i++) {
1622      if (name[p->index - 1][i - 1] != ' ')
1623        n = i;
1624    }
1625    for (i = 0; i < n; i++) {
1626      c = name[p->index - 1][i];
1627      if (c == ' ')
1628        c = '_';
1629      putc(c, treefile);
1630    }
1631    col += n;
1632  } else {
1633    putc('(', treefile);
1634    col++;
1635    treeout(p->next->back);
1636    putc(',', treefile);
1637    col++;
1638    if (col > 65) {
1639      putc('\n', treefile);
1640      col = 0;
1641    }
1642    treeout(p->next->next->back);
1643    putc(')', treefile);
1644    col++;
1645  }
1646  if (p != root)
1647    return;
1648  if (nextree > 2)
1649    fprintf(treefile, "[%6.4f];\n", 1.0 / (nextree - 1));
1650  else
1651    fprintf(treefile, ";\n");
1652}  /* treeout */
1653
1654Local Void describe()
1655{
1656  /* prints ancestors, steps and table of numbers of steps in
1657     each site */
1658  short i, j, k, l;
1659
1660  if (stepbox) {
1661    putc('\n', outfile);
1662    if (weights)
1663      fprintf(outfile, " weighted");
1664    fprintf(outfile, " steps in each site:\n");
1665    fprintf(outfile, "      ");
1666    for (i = 0; i <= 9; i++)
1667      fprintf(outfile, "%4hd", i);
1668    fprintf(outfile, "\n     *------------------------------------");
1669    fprintf(outfile, "-----\n");
1670    for (i = 0; i <= (chars / 10); i++) {
1671      fprintf(outfile, "%5hd", i * 10);
1672      putc('!', outfile);
1673      for (j = 0; j <= 9; j++) {
1674        k = i * 10 + j;
1675        if (k == 0 || k > chars)
1676          fprintf(outfile, "    ");
1677        else {
1678          l = location[ally[k - 1] - 1];
1679          if (oldweight[k - 1] > 0)
1680            fprintf(outfile, "%4hd",
1681                    oldweight[k - 1] *
1682                    (root->numsteps[l - 1] / weight[l - 1]));
1683          else
1684            fprintf(outfile, "   0");
1685        }
1686      }
1687      putc('\n', outfile);
1688    }
1689  }
1690  if (ancseq) {
1691    hypstates();
1692    putc('\n', outfile);
1693  }
1694  putc('\n', outfile);
1695  if (trout) {
1696    col = 0;
1697    treeout(root);
1698  }
1699}  /* describe */
1700
1701
1702Static Void maketree()
1703{
1704  /* tree construction recursively by branch and bound */
1705  short i, j, k;
1706  node *dummy;
1707
1708  if (progress) {
1709    printf("\nHow many\n");
1710    printf("trees looked                                       Approximate\n");
1711    printf("at so far      Length of        How many           percentage\n");
1712    printf("(multiples     shortest tree    trees this long    searched\n");
1713    printf("of %4hd):       found so far     found so far       so far\n",
1714           howoften);
1715    printf("----------     ------------     ------------       ------------\n");
1716  }
1717  done = false;
1718  mults = 0;
1719  examined = 0;
1720  nextree = 1;
1721  root = treenode[0];
1722  firsttime = true;
1723  for (i = 0; i < spp; i++)
1724    added[i] = false;
1725  added[0] = true;
1726  order[0] = 1;
1727  k = 2;
1728  fracdone = 0.0;
1729  fracinc = 1.0;
1730  bestyet = -1.0;
1731  recompute = true;
1732  temp = (node *)Malloc(sizeof(node));
1733  temp->numsteps = (stepshortptr)Malloc(endsite*sizeof(short));
1734  temp->base = (baseptr)Malloc(endsite*sizeof(char));
1735  temp1 = (node *)Malloc(sizeof(node));
1736  temp1->numsteps = (stepshortptr)Malloc(endsite*sizeof(short));
1737  temp1->base = (baseptr)Malloc(endsite*sizeof(char));
1738  addit(k);
1739  if (done) {
1740    if (progress) {
1741      printf("Search broken off!  Not guaranteed to\n");
1742      printf(" have found the most parsimonious trees.\n");
1743    }
1744    if (treeprint) {
1745      fprintf(outfile, "Search broken off!  Not guaranteed to\n");
1746      fprintf(outfile, " have found the most parsimonious\n");
1747      fprintf(outfile, " trees, but here is what we found:\n");
1748    }
1749  }
1750  if (treeprint) {
1751    fprintf(outfile, "\nrequires a total of %18.3f\n\n", bestyet / 10.0);
1752    if (nextree == 2)
1753      fprintf(outfile, "One most parsimonious tree found:\n");
1754    else
1755      fprintf(outfile, "%6hd trees in all found\n", nextree - 1);
1756  }
1757  if (nextree > maxtrees + 1) {
1758    if (treeprint)
1759      fprintf(outfile, "here are the first%4hd of them\n", (short)maxtrees);
1760    nextree = maxtrees + 1;
1761  }
1762  if (treeprint)
1763    putc('\n', outfile);
1764  for (i = 0; i < spp; i++)
1765    added[i] = true;
1766  for (i = 0; i <= nextree - 2; i++) {
1767    root = treenode[0];
1768    for (j = k; j <= spp; j++)
1769      add(&treenode[bestrees[i][j - 1] - 1],
1770          &treenode[bestorders[i][j - 1] - 1], &treenode[spp + j - 2]);
1771    reroot(treenode[outgrno - 1]);
1772    postorder(root);
1773    evaluate(root);
1774    printree();
1775    describe();
1776    for (j = k - 1; j < spp; j++)
1777      re_move(&treenode[bestorders[i][j] - 1], &dummy);
1778  }
1779  if (progress) {
1780    printf("\nOutput written to output file\n\n");
1781    if (trout)
1782      printf("Trees also written onto treefile\n\n");
1783  }
1784  free(temp->numsteps);
1785  free(temp->base);
1786  free(temp);
1787  free(temp1->numsteps);
1788  free(temp1->base);
1789  free(temp1);
1790}  /* maketree */
1791
1792
1793main(argc, argv)
1794int argc;
1795Char *argv[];
1796{  /* Penny's branch-and-bound method for DNA sequences */
1797char infilename[100],outfilename[100],trfilename[100];
1798#ifdef MAC
1799   macsetup("Dnapenny","");
1800#endif
1801
1802  /* Reads in the number of species, number of characters,
1803     options and data.  Then finds all most parsimonious trees */
1804  openfile(&infile,INFILE,"r",argv[0],infilename);
1805  openfile(&outfile,OUTFILE,"w",argv[0],outfilename);
1806
1807  ibmpc = ibmpc0;
1808  ansi = ansi0;
1809  vt52 = vt520;
1810  mulsets = false;
1811  garbage = NULL;
1812  datasets = 1;
1813  firstset = true;
1814  doinit();
1815  if (trout)
1816    openfile(&treefile,TREEFILE,"w",argv[0],trfilename);
1817  weight = (short *)Malloc(chars*sizeof(short));
1818  oldweight = (short *)Malloc(chars*sizeof(short));
1819  alias = (steptr)Malloc(chars*sizeof(short));
1820  ally = (steptr)Malloc(chars*sizeof(short));
1821  location = (steptr)Malloc(chars*sizeof(short));
1822  name = (Char **)Malloc(spp*sizeof(Char *));
1823  for (j = 1; j <= spp; j++)
1824    name[j - 1] = (Char *)Malloc(nmlngth*sizeof(char));
1825  bestorders = (treenumbers *)Malloc(maxtrees*sizeof(treenumbers));
1826  for (j = 1; j <= maxtrees; j++)
1827    bestorders[j - 1] = (treenumbers)Malloc(spp*sizeof(short));
1828  bestrees = (treenumbers *)Malloc(maxtrees*sizeof(treenumbers));
1829  for (j = 1; j <= maxtrees; j++)
1830    bestrees[j - 1] = (treenumbers)Malloc(spp*sizeof(short));
1831  current = (treenumbers)Malloc(spp*sizeof(short));
1832  order = (treenumbers)Malloc(spp*sizeof(short));
1833  added = (boolean *)Malloc(nonodes*sizeof(boolean));
1834  for (ith = 1; ith <= datasets; ith++) {
1835    doinput();
1836    if (ith == 1)
1837      firstset = false;
1838    if (datasets > 1) {
1839      fprintf(outfile, "\nData set # %hd:\n",ith);
1840      if (progress)
1841        printf("\nData set # %hd:\n",ith);
1842    }
1843    maketree();
1844    free(threshwt);
1845    for (i = 0; i < spp; i++) {
1846      free(treenode[i]->numsteps);
1847      free(treenode[i]->base);
1848    }
1849    for (i = spp; i < nonodes; i++) {
1850      p = treenode[i];
1851      for (j = 1; j <= 3; j++) {
1852        free(p->numsteps);
1853        free(p->base);
1854        p = p->next;
1855      }
1856    }
1857  }
1858  FClose(infile);
1859  FClose(outfile);
1860  FClose(treefile);
1861#ifdef MAC
1862  fixmacfile(outfilename);
1863  fixmacfile(trfilename);
1864#endif
1865  exit(0);
1866}  /* Penny's branch-and-bound method for DNA sequences */
1867
1868int eof(f)
1869FILE *f;
1870{
1871    register int ch;
1872
1873    if (feof(f))
1874        return 1;
1875    if (f == stdin)
1876        return 0;
1877    ch = getc(f);
1878    if (ch == EOF)
1879        return 1;
1880    ungetc(ch, f);
1881    return 0;
1882}
1883
1884
1885int eoln(f)
1886FILE *f;
1887{
1888    register int ch;
1889
1890    ch = getc(f);
1891    if (ch == EOF)
1892        return 1;
1893    ungetc(ch, f);
1894    return (ch == '\n');
1895}
1896
1897void memerror()
1898{
1899printf("Error allocating memory\n");
1900exit(-1);
1901}
1902
1903MALLOCRETURN *mymalloc(x)
1904long x;
1905{
1906MALLOCRETURN *mem;
1907mem = (MALLOCRETURN *)malloc((size_t)x);
1908if (!mem)
1909  memerror();
1910else
1911  return (MALLOCRETURN *)mem;
1912}
Note: See TracBrowser for help on using the repository browser.