source: tags/initial/GDE/PHYLIP/kitsch.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: 37.1 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 namelength      10   /* number of characters in species name    */
9#define epsilon         0.000001   /* a very small but not too small number */
10
11#define ibmpc0          false
12#define ansi0           true
13#define vt520           false
14#define down            2
15#define over            60
16
17typedef double *vector;       /* nodes will form binary tree           */
18typedef Char naym[namelength];
19
20typedef struct node {         /* describes a tip species or an ancestor */
21  struct node *next, *back;
22  long index;
23  boolean tip;                /* present species are tips of tree       */
24  vector d, w;                /* distances and weights                  */
25  double t;                   /* time                                   */
26  boolean sametime;           /* bookkeeps scrunched nodes              */
27  double weight;              /* weight of node used by scrunch         */
28  boolean processed;          /* used by evaluate                       */
29  long xcoord, ycoord, ymin;  /* used by printree                       */
30  long ymax;
31} node;
32
33typedef node **pointptr;
34typedef long longer[6];
35
36Static node *root, *best;
37Static FILE *infile, *outfile, *treefile;
38Static long numsp, numsp2, inseed, numtrees, col, datasets, ith,
39            i, j, l, jumb, njumble;
40/* numsp = number of species
41   numtrees is used by usertree option part of maketree */
42Static pointptr treenode, bestree;   /* pointers to all nodes in tree */
43Static naym *nayms;
44Static boolean jumble, usertree, lower, upper, negallowed, replicates, trout,
45               printdata, progress, treeprint, mulsets, ibmpc, vt52,
46               ansi, firstset;
47Static double power;
48Static longer seed;
49Static long *enterorder;
50Char ch;
51/* Local variables for maketree, propagated globally for C version: */
52  long examined;
53  double like, bestyet;
54  node *there;
55
56
57openfile(fp,filename,mode,application,perm)
58FILE **fp;
59char *filename;
60char *mode;
61char *application;
62char *perm;
63{
64  FILE *of;
65  char file[100];
66  strcpy(file,filename);
67  while (1){
68    of = fopen(file,mode);
69    if (of)
70      break;
71    else {
72      switch (*mode){
73      case 'r':
74        printf("%s:  can't read %s\n",application,file);
75        file[0] = '\0';
76        while (file[0] =='\0'){
77          printf("Please enter a new filename>");
78          gets(file);}
79        break;
80      case 'w':
81        printf("%s: can't write %s\n",application,file);
82        file[0] = '\0';
83        while (file[0] =='\0'){
84          printf("Please enter a new filename>");
85          gets(file);}
86        break;
87      }
88    }
89  }
90  *fp=of;
91  if (perm != NULL)
92    strcpy(perm,file);
93}
94
95
96double randum(seed)
97long *seed;
98{
99  /* random number generator -- slow but machine independent */
100  long i, j, k, sum;
101  longer mult, newseed;
102  double x;
103
104  mult[0] = 13;
105  mult[1] = 24;
106  mult[2] = 22;
107  mult[3] = 6;
108  for (i = 0; i <= 5; i++)
109    newseed[i] = 0;
110  for (i = 0; i <= 5; i++) {
111    sum = newseed[i];
112    k = i;
113    if (i > 3)
114      k = 3;
115    for (j = 0; j <= k; j++)
116      sum += mult[j] * seed[i - j];
117    newseed[i] = sum;
118    for (j = i; j <= 4; j++) {
119      newseed[j + 1] += newseed[j] / 64;
120      newseed[j] &= 63;
121    }
122  }
123  memcpy(seed, newseed, sizeof(longer));
124  seed[5] &= 3;
125  x = 0.0;
126  for (i = 0; i <= 5; i++)
127    x = x / 64.0 + seed[i];
128  x /= 4.0;
129  return x;
130}  /* randum */
131
132void uppercase(ch)
133Char *ch;
134{/* convert a character to upper case -- either ASCII or EBCDIC */
135    *ch = islower(*ch) ? toupper(*ch) :(*ch);
136}  /* uppercase */
137
138
139void getnums()
140{
141  /* read species number */
142  fscanf(infile, "%ld", &numsp);
143  fprintf(outfile, "\n%4ld Populations\n", numsp);
144  numsp2 = numsp * 2 - 1;
145}  /* getnums */
146
147void getoptions()
148{
149  /* interactively set options */
150  long i, inseed0;
151  Char ch;
152  boolean done, done1;
153
154  fprintf(outfile, "\nFitch-Margoliash method ");
155  fprintf(outfile, "with contemporary tips, version %s\n\n",VERSION);
156  jumble = false;
157  njumble = 1;
158  lower = false;
159  negallowed = false;
160  power = 2.0;
161  replicates = false;
162  upper = false;
163  usertree = false;
164  trout = true;
165  printdata = false;
166  progress = true;
167  treeprint = true;
168  for(;;) {
169   printf( ansi ? "\033[2J\033[H" :
170           vt52 ? "\033E\033H"    :
171                  "\n");
172    printf("\nFitch-Margoliash method ");
173    printf("with contemporary tips, version %s\n\n",VERSION);
174    printf("Settings for this run:\n");
175    printf("  U                 Search for best tree?  %s\n",
176           usertree ? "No, use user trees in input file" : "Yes");
177    printf("  P                                Power?%9.5f\n",power);
178    printf("  -      Negative branch lengths allowed?  %s\n",
179           (negallowed ? "Yes" : "No"));
180    printf("  L         Lower-triangular data matrix?  %s\n",
181           (lower ? "Yes" : "No"));
182    printf("  R         Upper-triangular data matrix?  %s\n",
183           (upper ? "Yes" : "No"));
184    printf("  S                        Subreplicates?  %s\n",
185           (replicates ? "Yes" : "No"));
186    if (!usertree) {
187      printf("  J     Randomize input order of species?");
188      if (jumble)
189            printf("  Yes (seed =%8ld,%3ld times)\n", inseed0, njumble);
190      else
191        printf("  No. Use input order\n");
192    }
193    printf("  M           Analyze multiple data sets?");
194    if (mulsets)
195      printf("  Yes, %2ld sets\n", datasets);
196    else
197      printf("  No\n");
198    printf("  0   Terminal type (IBM PC, VT52, ANSI)?  %s\n",
199           (ibmpc ? "IBM PC" :
200            ansi  ? "ANSI"   :
201            vt52  ? "VT52"   :
202                    "(none)"));
203
204    printf("  1    Print out the data at start of run  %s\n",
205           (printdata ? "Yes" : "No"));
206    printf("  2  Print indications of progress of run  %s\n",
207           (progress ? "Yes" : "No"));
208    printf("  3                        Print out tree  %s\n",
209    (treeprint ? "Yes" : "No"));
210   printf("  4       Write out trees onto tree file?  %s\n",
211          (trout ? "Yes" : "No"));
212    printf("\nAre these settings correct?");
213   printf(" (type Y or the letter for one to change)\n");
214    scanf("%c%*[^\n]", &ch);
215    getchar();
216    if (ch == '\n')
217      ch = ' ';
218    uppercase(&ch);
219   if (ch == 'Y')
220     break;
221   if (strchr("JUP-LRSM12340",ch)){
222     switch (ch) {
223
224     case '-':
225       negallowed = !negallowed;
226       break;
227
228     case 'J':
229       jumble = !jumble;
230       if (jumble) {
231         printf("Random number seed (must be odd)?\n");
232         scanf("%ld%*[^\n]", &inseed);
233         getchar();
234         inseed0 = inseed;
235         for (i = 0; i <= 5; i++)
236           seed[i] = 0;
237         i = 0;
238         do {
239           seed[i] = inseed & 63;
240           inseed /= 64;
241           i++;
242         } while (inseed != 0);
243         printf("Number of times to jumble?\n");
244         scanf("%ld%*[^\n]", &njumble);
245         getchar();
246       }
247       else njumble = 1;
248       break;
249
250     case 'L':
251       lower = !lower;
252       break;
253
254     case 'P':
255       printf("New power?\n");
256       scanf("%lf%*[^\n]", &power);
257       getchar();
258       break;
259
260     case 'R':
261       upper = !upper;
262       break;
263
264     case 'S':
265       replicates = !replicates;
266       break;
267
268     case 'U':
269       usertree = !usertree;
270       break;
271
272     case 'M':
273       mulsets = !mulsets;
274       if (mulsets) {
275         done1 = false;
276         do {
277           printf("How many data sets?\n");
278           scanf("%ld%*[^\n]", &datasets);
279           getchar();
280           done1 = (datasets >= 1);
281           if (!done1)
282             printf("BAD DATA SETS NUMBER:  it must be greater than 1\n");
283         } while (done1 != true);
284       }
285       break;
286
287     case '0':
288       if (ibmpc) {
289         ibmpc = false;
290         vt52 = true;
291       } else {
292         if (vt52) {
293           vt52 = false;
294           ansi = true;
295         } else if (ansi)
296           ansi = false;
297         else
298           ibmpc = true;
299       }
300       break;
301
302     case '1':
303       printdata = !printdata;
304       break;
305
306     case '2':
307       progress = !progress;
308       break;
309
310     case '3':
311       treeprint = !treeprint;
312       break;
313
314     case '4':
315       trout = !trout;
316       break;
317     }
318   } else
319     printf("Not a possible option!\n");
320 }
321}  /* getoptions */
322
323
324void doinit()
325{
326  /* initializes variables */
327  long i, j;
328  node *p, *q;
329
330  getnums();
331  getoptions();
332  treenode = (node **)Malloc(numsp2*sizeof(node *));
333  for (i = 0; i < (numsp); i++) {
334    treenode[i] = (node *)Malloc(sizeof(node));
335    treenode[i]->d = (vector)Malloc(numsp2*(sizeof(double)));
336    treenode[i]->w = (vector)Malloc(numsp2*(sizeof(double)));
337  }
338  for (i = numsp; i < (numsp2); i++) {
339    q = NULL;
340    for (j = 1; j <= 3; j++) {
341      p = (node *)Malloc(sizeof(node));
342      p->d = (vector)Malloc(numsp2*(sizeof(double)));
343      p->w = (vector)Malloc(numsp2*(sizeof(double)));
344      p->next = q;
345      q = p;
346    }
347    p->next->next->next = p;
348    treenode[i] = p;
349  }
350  if (!usertree && njumble > 1) {
351    bestree = (node **)Malloc(numsp2*sizeof(node *));
352    for (i = 0; i < (numsp); i++) {
353      bestree[i] = (node *)Malloc(sizeof(node));
354      bestree[i]->d = (vector)Malloc(numsp2*(sizeof(double)));
355      bestree[i]->w = (vector)Malloc(numsp2*(sizeof(double)));
356    }
357    for (i = numsp; i < (numsp2); i++) {
358      q = NULL;
359      for (j = 1; j <= 3; j++) {
360        p = (node *)Malloc(sizeof(node));
361        p->d = (vector)Malloc(numsp2*(sizeof(double)));
362        p->w = (vector)Malloc(numsp2*(sizeof(double)));
363        p->next = q;
364        q = p;
365      }
366      p->next->next->next = p;
367      bestree[i] = p;
368    }
369  }
370
371}  /* doinit */
372
373void inputoptions()
374{
375  /* read options information */
376  Char ch;
377  long cursp;
378
379  if (!firstset) {
380    if (eoln(infile)) {
381      fscanf(infile, "%*[^\n]");
382      getc(infile);
383    }
384    fscanf(infile, "%ld", &cursp);
385    if (cursp != numsp) {
386      printf("\nERROR: INCONSISTENT NUMBER OF SPECIES IN DATA SET %4ld\n",
387             ith);
388      exit(-1);
389    }
390  }
391  while (!eoln(infile)) {
392    ch = getc(infile);
393    if (ch == '\n')
394      ch = ' ';
395    uppercase(&ch);
396    if (ch != ' ') {
397      printf("BAD OPTION CHARACTER: %c\n", ch);
398      exit(-1);
399    }
400  }
401  fprintf(outfile, "                  __ __             2\n");
402  fprintf(outfile, "                  \\  \\   (Obs - Exp)\n");
403  fprintf(outfile, "Sum of squares =  /_ /_  ------------\n");
404  fprintf(outfile, "                               ");
405  if (power == (long)power)
406    fprintf(outfile, "%2ld\n", (long)power);
407  else
408    fprintf(outfile, "%4.1f\n", power);
409  fprintf(outfile, "                   i  j      Obs\n\n");
410  fprintf(outfile, "negative branch lengths");
411  if (!negallowed)
412    fprintf(outfile, " not");
413  fprintf(outfile, " allowed\n\n");
414}  /* inputoptions */
415
416void getinput()
417{
418  /* reads the input data */
419  inputoptions();
420}  /* getinput */
421
422void getdata()
423{
424  /* read in distance matrix */
425  long i, j, k, columns, n;
426  boolean skipit, skipother;
427  double x;
428  node *p;
429
430  columns = replicates ? 4 : 6;
431  if (printdata) {
432    fprintf(outfile, "\nName                       Distances");
433    if (replicates)
434      fprintf(outfile, " (replicates)");
435    fprintf(outfile, "\n----                       ---------");
436    if (replicates)
437      fprintf(outfile, "-------------");
438    fprintf(outfile, "\n\n");
439  }
440  for (i = 1; i <= (numsp2); i++) {
441    treenode[i - 1]->back = NULL;
442    treenode[i - 1]->index = i;
443    treenode[i - 1]->tip = (i <= numsp);
444    treenode[i - 1]->t = 0.0;
445    treenode[i - 1]->sametime = false;
446    if (i > numsp) {
447      p = treenode[i - 1]->next;
448      while (p != treenode[i - 1]) {
449        p->back = NULL;
450        p->tip = false;
451        p->index = i;
452        p = p->next;
453      }
454    }
455  }
456  if (!usertree && njumble > 1)
457    for (i = 1; i <= (numsp2); i++) {
458      bestree[i - 1]->back = NULL;
459      bestree[i - 1]->index = i;
460      bestree[i - 1]->tip = (i <= numsp);
461      bestree[i - 1]->t = 0.0;
462      bestree[i - 1]->sametime = false;
463      if (i > numsp) {
464        p = bestree[i - 1]->next;
465        while (p != bestree[i - 1]) {
466          p->back = NULL;
467          p->tip = false;
468          p->index = i;
469          p = p->next;
470        }
471      }
472    }
473  for (i = 0; i < (numsp); i++) {
474    treenode[i]->d[i] = 0.0;
475    treenode[i]->w[i] = 0.0;
476    treenode[i]->weight = 0.0;
477    fscanf(infile, "%*[^\n]");
478    getc(infile);
479    for (j = 0; j < namelength; j++) {
480      if (eoln(infile))
481        nayms[i][j] = ' ';
482      else {
483        nayms[i][j] = getc(infile);
484        if (nayms[i][j] == '\n')
485          nayms[i][j] = ' ';
486      }
487    }
488    for (j = 1; j <= (numsp); j++) {
489      skipit = ((lower && j >= i + 1) || (upper && j <= i + 1));
490      skipother = ((lower && i + 1 >= j) || (upper && i + 1 <= j));
491      if (!skipit) {
492        if (eoln(infile)) {
493          fscanf(infile, "%*[^\n]");
494          getc(infile);
495        }
496        fscanf(infile, "%lf", &x);
497        treenode[i]->d[j - 1] = x;
498        if (replicates) {
499          if (eoln(infile)) {
500            fscanf(infile, "%*[^\n]");
501            getc(infile);
502          }
503          fscanf(infile, "%ld", &n);
504        } else
505          n = 1;
506        if (n > 0 && x < 0) {
507          printf("NEGATIVE DISTANCE BETWEEN SPECIES%5ld AND %5ld\n",
508                 i + 1, j);
509          exit(-1);
510        }
511        treenode[i]->w[j - 1] = n;
512        if (skipother) {
513          treenode[j - 1]->d[i] = treenode[i]->d[j - 1];
514          treenode[j - 1]->w[i] = treenode[i]->w[j - 1];
515        }
516      }
517    }
518  }
519  fscanf(infile, "%*[^\n]");
520  getc(infile);
521  if (printdata) {
522    for (i = 0; i < (numsp); i++) {
523      for (j = 0; j < namelength; j++)
524        putc(nayms[i][j], outfile);
525      putc(' ', outfile);
526      for (j = 1; j <= (numsp); j++) {
527        fprintf(outfile, "%10.5f", treenode[i]->d[j - 1]);
528        if (replicates)
529          fprintf(outfile, " (%3ld)", (long)treenode[i]->w[j - 1]);
530        if (j % columns == 0 && j < numsp) {
531          putc('\n', outfile);
532          for (k = 1; k <= namelength + 1; k++)
533            putc(' ', outfile);
534        }
535      }
536      putc('\n', outfile);
537    }
538    putc('\n', outfile);
539  }
540  for (i = 0; i < (numsp); i++) {
541    for (j = 0; j < (numsp); j++) {
542      if (i + 1 != j + 1) {
543        if (treenode[i]->d[j] < epsilon)
544          treenode[i]->d[j] = epsilon;
545        treenode[i]->w[j] /= exp(power * log(treenode[i]->d[j]));
546      }
547    }
548  }
549}  /* getdata */
550
551void add(below, newtip, newfork)
552node *below, *newtip, *newfork;
553{
554  /* inserts the nodes newfork and its left descendant, newtip,
555     to the tree.  below becomes newfork's right descendant */
556  if (below != treenode[below->index - 1])
557    below = treenode[below->index - 1];
558  if (below->back != NULL)
559    below->back->back = newfork;
560  newfork->back = below->back;
561  below->back = newfork->next->next;
562  newfork->next->next->back = below;
563  newfork->next->back = newtip;
564  newtip->back = newfork->next;
565  if (root == below)
566    root = newfork;
567  root->back = NULL;
568}  /* add */
569
570void re_move(item, fork)
571node **item, **fork;
572{
573  /* removes nodes item and its ancestor, fork, from the tree.
574     the new descendant of fork's ancestor is made to be
575     fork's second descendant (other than item).  Also
576     returns pointers to the deleted nodes, item and fork */
577  node *p, *q;
578
579  if ((*item)->back == NULL) {
580    *fork = NULL;
581    return;
582  }
583  *fork = treenode[(*item)->back->index - 1];
584  if (root == *fork) {
585    if (*item == (*fork)->next->back)
586      root = (*fork)->next->next->back;
587    else
588      root = (*fork)->next->back;
589  }
590  p = (*item)->back->next->back;
591  q = (*item)->back->next->next->back;
592  if (p != NULL)
593    p->back = q;
594  if (q != NULL)
595    q->back = p;
596  (*fork)->back = NULL;
597  p = (*fork)->next;
598  while (p != *fork) {
599    p->back = NULL;
600    p = p->next;
601  }
602  (*item)->back = NULL;
603}  /* remove */
604
605void scrunchtraverse(u,closest,tmax)
606node *u,**closest;
607double *tmax;
608{
609  /* traverse to find closest node to the current one */
610  if (!u->sametime) {
611    if (u->t > *tmax) {
612      *closest = u;
613      *tmax = u->t;
614    }
615    return;
616  }
617  u->t = treenode[u->back->index - 1]->t;
618  if (!u->tip) {
619    scrunchtraverse(u->next->back, closest,tmax);
620    scrunchtraverse(u->next->next->back, closest,tmax);
621  }
622}  /* scrunchtraverse */
623
624void combine(a, b)
625node *a, *b;
626{
627  /* put node b into the set having the same time as a */
628  if (a->weight + b->weight <= 0.0)
629    a->t = 0.0;
630  else
631    a->t = (a->t * a->weight + b->t * b->weight) / (a->weight + b->weight);
632  a->weight += b->weight;
633  b->sametime = true;
634}  /* combine */
635
636void scrunch(s)
637node *s;
638{
639  /* see if nodes can be combined to prevent negative lengths */
640/* Local variables for scrunch: */
641  double tmax;
642  node *closest;
643  boolean found;
644
645  closest = NULL;
646  tmax = -1.0;
647  do {
648    if (!s->tip) {
649      scrunchtraverse(s->next->back, &closest,&tmax);
650      scrunchtraverse(s->next->next->back, &closest,&tmax);
651    }
652    found = (tmax > s->t);
653    if (found)
654      combine(s, closest);
655    tmax = -1.0;
656  } while (found);
657}  /* scrunch */
658
659void secondtraverse(a,q,u,v,i,j,k,sum)
660node *a,*q,*u,*v;
661long i,j,k;
662double *sum;
663{
664  /* recalculate distances, add to sum */
665  long l;
666  double wil, wjl, wkl, wli, wlj, wlk, TEMP;
667
668  if (!(a->processed || a->tip)) {
669    secondtraverse(a->next->back, q,u,v,i,j,k,sum);
670    secondtraverse(a->next->next->back, q,u,v,i,j,k,sum);
671    return;
672  }
673  if (!(a != q && a->processed))
674    return;
675  l = a->index;
676  wil = u->w[l - 1];
677  wjl = v->w[l - 1];
678  wkl = wil + wjl;
679  wli = a->w[i - 1];
680  wlj = a->w[j - 1];
681  wlk = wli + wlj;
682  q->w[l - 1] = wkl;
683  a->w[k - 1] = wlk;
684  if (wkl <= 0.0)
685    q->d[l - 1] = 0.0;
686  else
687    q->d[l - 1] = (wil * u->d[l - 1] + wjl * v->d[l - 1]) / wkl;
688  if (wlk <= 0.0)
689    a->d[k - 1] = 0.0;
690  else
691    a->d[k - 1] = (wli * a->d[i - 1] + wlj * a->d[j - 1]) / wlk;
692  if (wkl > 0.0) {
693    TEMP = u->d[l - 1] - v->d[l - 1];
694    (*sum) += wil * wjl / wkl * (TEMP * TEMP);
695  }
696  if (wlk > 0.0) {
697    TEMP = a->d[i - 1] - a->d[j - 1];
698    (*sum) += wli * wlj / wlk * (TEMP * TEMP);
699  }
700}  /* secondtraverse */
701
702void firstraverse(q_, r,sum)
703node *q_,*r;
704double *sum;
705{  /* firsttraverse                              */
706   /* go through tree calculating branch lengths */
707  /* Local variables for firstraverse: */
708  node *q;
709  long i, j, k;
710  node *u, *v;
711
712  q = q_;
713  if (q == NULL)
714    return;
715  q->sametime = false;
716  if (!q->tip) {
717    firstraverse(q->next->back, r,sum);
718    firstraverse(q->next->next->back, r,sum);
719  }
720  q->processed = true;
721  if (q->tip)
722    return;
723  u = q->next->back;
724  v = q->next->next->back;
725  i = u->index;
726  j = v->index;
727  k = q->index;
728  if (u->w[j - 1] + v->w[i - 1] <= 0.0)
729    q->t = 0.0;
730  else
731    q->t = (u->w[j - 1] * u->d[j - 1] +
732              v->w[i - 1] * v->d[i - 1]) /
733             (2.0 * (u->w[j - 1] + v->w[i - 1]));
734  q->weight = u->weight + v->weight + u->w[j - 1] + v->w[i - 1];
735  if (!negallowed)
736    scrunch(q);
737  secondtraverse(r,q,u,v,i,j,k,sum);
738}  /* firstraverse */
739
740void sumtraverse(q, sum)
741node *q;
742double *sum;
743{
744  /* traverse to finish computation of sum of squares */
745  long i, j;
746  node *u, *v;
747  double TEMP, TEMP1;
748
749  if (q->tip)
750    return;
751  sumtraverse(q->next->back, sum);
752  sumtraverse(q->next->next->back, sum);
753  u = q->next->back;
754  v = q->next->next->back;
755  i = u->index;
756  j = v->index;
757  TEMP = u->d[j - 1] - 2.0 * q->t;
758  TEMP1 = v->d[i - 1] - 2.0 * q->t;
759  (*sum) += u->w[j - 1] * (TEMP * TEMP) + v->w[i - 1] * (TEMP1 * TEMP1);
760}  /* sumtraverse */
761
762void evaluate(r)
763node *r;
764{
765  /* fill in times and evaluate sum of squares for tree */
766  /* Local variables for evaluate: */
767  double sum;
768  long i;
769  sum = 0.0;
770  for (i = 0; i < (numsp2); i++)
771    treenode[i]->processed = treenode[i]->tip;
772  firstraverse(r, r,&sum);
773  sumtraverse(r, &sum);
774  examined++;
775  if (replicates && (lower || upper))
776    sum /= 2;
777  like = -sum;
778}  /* evaluate */
779
780
781void tryadd(p, item,nufork)
782node *p,**item,**nufork;
783{
784  /* temporarily adds one fork and one tip to the tree.
785     if the location where they are added yields greater
786     "likelihood" than other locations tested up to that
787     time, then keeps that location as there */
788  add(p, *item, *nufork);
789  evaluate(root);
790  if (like > bestyet) {
791    bestyet = like;
792    there = p;
793  }
794  re_move(item, nufork);
795}  /* tryadd */
796
797void addpreorder(p, item, nufork)
798node *p, *item, *nufork;
799{
800  /* traverses a binary tree, calling PROCEDURE tryadd
801     at a node before calling tryadd at its descendants */
802/* Local variables for addpreorder: */
803  if (p == NULL)
804    return;
805  tryadd(p, &item,&nufork);
806  if (!p->tip) {
807    addpreorder(p->next->back, item, nufork);
808    addpreorder(p->next->next->back, item, nufork);
809  }
810}  /* addpreorder */
811
812void tryrearr(p,r,success)
813node *p,**r;
814boolean *success;
815{
816  /* evaluates one rearrangement of the tree.
817     if the new tree has greater "likelihood" than the old
818     one sets success := TRUE and keeps the new tree.
819     otherwise, restores the old tree */
820  node *frombelow, *whereto, *forknode;
821  double oldlike;
822
823  if (p->back == NULL)
824    return;
825  forknode = treenode[p->back->index - 1];
826  if (forknode->back == NULL)
827    return;
828  oldlike = like;
829  if (p->back->next->next == forknode)
830    frombelow = forknode->next->next->back;
831  else
832    frombelow = forknode->next->back;
833  whereto = forknode->back;
834  re_move(&p, &forknode);
835  add(whereto, p, forknode);
836  if ((*r)->back != NULL)
837    *r = treenode[(*r)->back->index - 1];
838  evaluate(*r);
839  if (like > oldlike) {
840    bestyet = like;
841    *success = true;
842    return;
843  }
844  re_move(&p, &forknode);
845  add(frombelow, p, forknode);
846  if ((*r)->back != NULL)
847    *r = treenode[(*r)->back->index - 1];
848  like = oldlike;
849}  /* tryrearr */
850
851void repreorder(p,r,success)
852node *p,**r;
853boolean *success;
854{
855  /* traverses a binary tree, calling PROCEDURE tryrearr
856     at a node before calling tryrearr at its descendants */
857  if (p == NULL)
858    return;
859  tryrearr(p,r,success);
860  if (!p->tip) {
861    repreorder(p->next->back,r,success);
862    repreorder(p->next->next->back,r,success);
863  }
864}  /* repreorder */
865
866void rearrange(r_)
867node **r_;
868{
869  /* traverses the tree (preorder), finding any local
870     rearrangement which decreases the number of steps.
871     if traversal succeeds in increasing the tree's
872     "likelihood", PROCEDURE rearrange runs traversal again */
873/* Local variables for rearrange: */
874  node **r;
875  boolean success;
876  r = r_;
877  success = true;
878  while (success) {
879    success = false;
880    repreorder(*r,r,&success);
881  }
882}  /* rearrange */
883
884void findch(c)
885Char c;
886{
887  /* scan forward until find character c */
888  boolean done;
889
890  done = false;
891  while (!(done)) {
892    if (c == ',') {
893      if (ch == '(' || ch == ')' || ch == ';') {
894        printf("\nERROR IN USER TREE: ");
895        printf("UNMATCHED PARENTHESIS OR MISSING COMMA\n");
896        exit(-1);
897      } else if (ch == ',')
898        done = true;
899    } else if (c == ')') {
900      if (ch == '(' || ch == ',' || ch == ';') {
901        printf("\nERROR IN USER TREE:");
902        printf(" UNMATCHED PARENTHESIS OR NOT BIFURCATED NODE\n");
903        exit(-1);
904      } else {
905        if (ch == ')')
906          done = true;
907      }
908    } else if (c == ';') {
909      if (ch != ';') {
910        printf("\nERROR IN USER TREE:");
911        printf(" UNMATCHED PARENTHESIS OR MISSING SEMICOLON\n");
912        exit(-1);
913      } else
914        done = true;
915    }
916    if (done && ch != ')')   /* was : if (!(done && ch == ')') && (done))  */
917      continue;
918    if (eoln(infile)) {
919      fscanf(infile, "%*[^\n]");
920      getc(infile);
921    }
922    ch = getc(infile);
923    if (ch == '\n')
924      ch = ' ';
925  }
926}  /* findch */
927
928void addelement(p, nextnode,lparens,names)
929node **p;
930long *nextnode,*lparens;
931boolean *names;
932{
933  /* recursive procedure adds nodes to user-defined tree */
934  node *q;
935  long i, n;
936  boolean found;
937  Char str[namelength];
938
939  do {
940    if (eoln(infile)) {
941      fscanf(infile, "%*[^\n]");
942      getc(infile);
943    }
944    ch = getc(infile);
945    if (ch == '\n')
946      ch = ' ';
947  } while (ch == ' ');
948  if (ch == '(' ) {
949    if (*lparens >= numsp - 1) {
950      printf("\nERROR IN USER TREE: TOO MANY LEFT PARENTHESES\n");
951      exit(-1);
952    }
953    (*nextnode)++;
954    (*lparens)++;
955    q = treenode[*nextnode - 1];
956    addelement(&q->next->back, nextnode,lparens,names);
957    q->next->back->back = q->next;
958    findch(',');
959    addelement(&q->next->next->back, nextnode,lparens,names);
960    q->next->next->back->back = q->next->next;
961    findch(')');
962    *p = q;
963    return;
964  }
965
966  for (i = 0; i < namelength; i++)
967    str[i] = ' ';
968  n = 1;
969  do {
970    if (ch == '_')
971      ch = ' ';
972    str[n - 1] = ch;
973    if (eoln(infile)) {
974      fscanf(infile, "%*[^\n]");
975      getc(infile);
976    }
977    ch = getc(infile);
978    if (ch == '\n')
979      ch = ' ';
980    n++;
981  } while (ch != ',' && ch != ')' && ch != ':' &&
982           n <= namelength);
983  n = 1;
984  do {
985    found = true;
986    for (i = 0; i < namelength; i++)
987      found = (found && str[i] == nayms[n - 1][i]);
988    if (found) {
989      if (names[n - 1] == false) {
990        *p = treenode[n - 1];
991        names[n - 1] = true;
992      } else {
993        printf("\nERROR IN USER TREE: DUPLICATE NAME FOUND -- ");
994        for (i = 0; i < namelength; i++)
995          putchar(nayms[n - 1][i]);
996        putchar('\n');
997        exit(-1);
998      }
999    } else
1000      n++;
1001  } while (!(n > numsp || found ));
1002  if (n <= numsp)
1003    return;
1004  printf("CANNOT FIND SPECIES: ");
1005  for (i = 0; i < namelength; i++)
1006    putchar(str[i]);
1007  putchar('\n');
1008}  /* addelement */
1009
1010void treeread()
1011{
1012  /* read in user-defined tree and set it up */
1013  long nextnode, lparens;
1014  boolean *names;
1015  long i;
1016
1017  root = treenode[numsp];
1018  nextnode = numsp;
1019  root->back = NULL;
1020  names = (boolean *)Malloc(numsp*sizeof(boolean));
1021  for (i = 0; i < (numsp); i++)
1022    names[i] = false;
1023  lparens = 0;
1024  addelement(&root, &nextnode,&lparens,names);
1025  findch(';');
1026  fscanf(infile, "%*[^\n]");
1027  getc(infile);
1028}  /* treeread */
1029
1030void coordinates(p, tipy)
1031node *p;
1032long *tipy;
1033{
1034  /* establishes coordinates of nodes */
1035  node *q, *first, *last;
1036
1037  if (p->tip) {
1038    p->xcoord = 0;
1039    p->ycoord = *tipy;
1040    p->ymin = *tipy;
1041    p->ymax = *tipy;
1042    (*tipy) += down;
1043    return;
1044  }
1045  q = p->next;
1046  do {
1047    coordinates(q->back, tipy);
1048    q = q->next;
1049  } while (p != q);
1050  first = p->next->back;
1051  q = p->next;
1052  while (q->next != p)
1053    q = q->next;
1054  last = q->back;
1055  p->xcoord = (long)(over * p->t + 0.5);
1056  p->ycoord = (first->ycoord + last->ycoord) / 2;
1057  p->ymin = first->ymin;
1058  p->ymax = last->ymax;
1059}  /* coordinates */
1060
1061void drawline(i, scale)
1062long i;
1063double scale;
1064{
1065  /* draws one row of the tree diagram by moving up tree */
1066  node *p, *q, *r, *first, *last;
1067  long n, j;
1068  boolean extra, done;
1069
1070  p = root;
1071  q = root;
1072  extra = false;
1073  if (i == p->ycoord && p == root) {
1074    if (p->index - numsp >= 10)
1075      fprintf(outfile, "-%2ld", p->index - numsp);
1076    else
1077      fprintf(outfile, "--%ld", p->index - numsp);
1078    extra = true;
1079  } else
1080    fprintf(outfile, "  ");
1081  do {
1082    if (!p->tip) {
1083      r = p->next;
1084      done = false;
1085      do {
1086        if (i >= r->back->ymin && i <= r->back->ymax) {
1087          q = r->back;
1088          done = true;
1089        }
1090        r = r->next;
1091      } while (!(done || r == p));
1092      first = p->next->back;
1093      r = p->next;
1094      while (r->next != p)
1095        r = r->next;
1096      last = r->back;
1097    }
1098    done = (p == q);
1099    n = (long)(scale * (p->xcoord - q->xcoord) + 0.5);
1100    if (n < 3 && !q->tip)
1101      n = 3;
1102    if (extra) {
1103      n--;
1104      extra = false;
1105    }
1106    if (q->ycoord == i && !done) {
1107      if (p->ycoord != q->ycoord)
1108        putc('+', outfile);
1109      if (!q->tip) {
1110        for (j = 1; j <= n - 2; j++)
1111          putc('-', outfile);
1112        if (q->index - numsp >= 10)
1113          fprintf(outfile, "%2ld", q->index - numsp);
1114        else
1115          fprintf(outfile, "-%ld", q->index - numsp);
1116        extra = true;
1117      } else {
1118        for (j = 1; j < n; j++)
1119          putc('-', outfile);
1120      }
1121    } else if (!p->tip) {
1122      if (last->ycoord > i && first->ycoord < i && i != p->ycoord) {
1123        putc('!', outfile);
1124        for (j = 1; j < n; j++)
1125          putc(' ', outfile);
1126      } else {
1127        for (j = 1; j <= n; j++)
1128          putc(' ', outfile);
1129      }
1130    }
1131    if (p != q)
1132      p = q;
1133  } while (!done);
1134  if (p->ycoord == i && p->tip) {
1135    for (j = 0; j < namelength; j++)
1136      putc(nayms[p->index - 1][j], outfile);
1137  }
1138  putc('\n', outfile);
1139}  /* drawline */
1140
1141void printree()
1142{
1143 /* prints out diagram of the tree */
1144 /* Local variables for printree: */
1145  long tipy;
1146  double scale;
1147  long i;
1148  node *p;
1149
1150  putc('\n', outfile);
1151  if (!treeprint)
1152    return;
1153  putc('\n', outfile);
1154  tipy = 1;
1155  coordinates(root, &tipy);
1156  p = root;
1157  while (!p->tip)
1158    p = p->next->back;
1159  scale = 1.0 / (long)(root->t - p->t + 1.000);
1160  putc('\n', outfile);
1161  for (i = 1; i <= (tipy - down); i++)
1162    drawline(i, scale);
1163  putc('\n', outfile);
1164}  /* printree */
1165
1166void treeout(p)
1167node *p;
1168{
1169  /* write out file with representation of final tree */
1170  long i, n, w;
1171  Char c;
1172  double x;
1173
1174  if (p->tip) {
1175    n = 0;
1176    for (i = 1; i <= namelength; i++) {
1177      if (nayms[p->index - 1][i - 1] != ' ')
1178        n = i;
1179    }
1180    for (i = 0; i < n; i++) {
1181      c = nayms[p->index - 1][i];
1182      if (c == ' ')
1183        c = '_';
1184      putc(c, treefile);
1185    }
1186    col += n;
1187  } else {
1188    putc('(', treefile);
1189    col++;
1190    treeout(p->next->back);
1191    putc(',', treefile);
1192    col++;
1193    if (col > 55) {
1194      putc('\n', treefile);
1195      col = 0;
1196    }
1197    treeout(p->next->next->back);
1198    putc(')', treefile);
1199    col++;
1200  }
1201  if (p != root)
1202    x = treenode[p->back->index - 1]->t - p->t;
1203  if (x > 0.0)
1204    w = (long)(0.43429448222 * log(x));
1205  else if (x == 0.0)
1206    w = 0;
1207  else
1208    w = (long)(0.43429448222 * log(-x)) + 1;
1209  if (w < 0)
1210    w = 0;
1211  if (p == root)
1212    fprintf(treefile, ";\n");
1213  else {
1214    fprintf(treefile, ":%*.5f", (int)(w + 7), x);
1215    col += w + 8;
1216  }
1217}  /* treeout */
1218
1219void dtraverse(q)
1220node *q;
1221{
1222  /* print table of lengths etc. */
1223  long i;
1224
1225  if (!q->tip)
1226    dtraverse(q->next->back);
1227  if (q->back != NULL) {
1228    fprintf(outfile, "%4ld  ", q->back->index - numsp);
1229    if (q->index <= numsp) {
1230      for (i = 0; i < namelength; i++)
1231        putc(nayms[q->index - 1][i], outfile);
1232    } else
1233      fprintf(outfile, "%4ld      ", q->index - numsp);
1234    fprintf(outfile, "%13.5f", treenode[q->back->index - 1]->t - q->t);
1235    fprintf(outfile, "%15.5f\n", root->t - q->t);
1236  }
1237  if (!q->tip)
1238    dtraverse(q->next->next->back);
1239}  /* dtraverse */
1240
1241void describe()
1242{
1243  /* prints table of lengths, times, sum of squares, etc. */
1244  long i, j;
1245  double totalnum;
1246  double TEMP;
1247
1248  fprintf(outfile, "\nSum of squares = %10.3f\n\n", -like);
1249  if (fabs(power - 2) < 0.01) {
1250    totalnum = 0.0;
1251    for (i = 0; i < (numsp); i++) {
1252      for (j = 0; j < (numsp); j++) {
1253        if (i + 1 != j + 1 && treenode[i]->d[j] > 0.0) {
1254          TEMP = treenode[i]->d[j];
1255          totalnum += treenode[i]->w[j] * (TEMP * TEMP);
1256        }
1257      }
1258    }
1259    totalnum -= 2;
1260    if (replicates && (lower || upper))
1261      totalnum /= 2;
1262    fprintf(outfile, "Average percent standard deviation =");
1263    fprintf(outfile, "%10.5f\n\n", 100 * sqrt(-(like / totalnum)));
1264  }
1265  if (!usertree)
1266    fprintf(outfile, "examined %4ld trees\n\n", examined);
1267  fprintf(outfile, "From    To           Length          Time\n");
1268  fprintf(outfile, "----    --           ------          ----\n\n");
1269  dtraverse(root);
1270  putc('\n', outfile);
1271  if (trout) {
1272    col = 0;
1273    treeout(root);
1274  }
1275}  /* describe */
1276
1277
1278void copynode(c, d)
1279node *c, *d;
1280{
1281  /* make a copy of a node */
1282
1283  memcpy(d->d, c->d, numsp2*sizeof(double));
1284  memcpy(d->w, c->w, numsp2*sizeof(double));
1285  d->t = c->t;
1286  d->sametime = c->sametime;
1287  d->weight = c->weight;
1288  d->processed = c->processed;
1289  d->xcoord = c->xcoord;
1290  d->ycoord = c->ycoord;
1291  d->ymin = c->ymin;
1292  d->ymax = c->ymax;
1293}  /* copynode */
1294
1295void copy_(a, b)
1296pointptr a, b;
1297{
1298  /* make a copy of a tree */
1299  short i, j=0;
1300  node *p, *q;
1301
1302  for (i = 0; i < numsp; i++) {
1303    copynode(a[i], b[i]);
1304    if (a[i]->back != NULL) {
1305      if (a[i]->back == a[a[i]->back->index - 1])
1306        b[i]->back = b[a[i]->back->index - 1];
1307      else if (a[i]->back == a[a[i]->back->index - 1]->next)
1308      b[i]->back = b[a[i]->back->index - 1]->next;
1309    else
1310      b[i]->back = b[a[i]->back->index - 1]->next->next;
1311    }
1312    else b[i]->back = NULL;
1313  }
1314  for (i = numsp; i < numsp2; i++) {
1315    p = a[i];
1316    q = b[i];
1317    for (j = 1; j <= 3; j++) {
1318      copynode(p, q);
1319      if (p->back) {
1320        if (p->back == a[p->back->index - 1])
1321          q->back = b[p->back->index - 1];
1322        else if (p->back == a[p->back->index - 1]->next)
1323          q->back = b[p->back->index - 1]->next;
1324        else
1325          q->back = b[p->back->index - 1]->next->next;
1326      }
1327      else
1328        q->back = NULL;
1329      p = p->next;
1330      q = q->next;
1331    }
1332  }
1333}  /* copy */
1334
1335
1336void maketree()
1337{
1338  /* constructs a binary tree from the pointers in treenode.
1339     adds each node at location which yields highest "likelihood"
1340     then rearranges the tree for greatest "likelihood" */
1341  long i, j, k;
1342  double bestlike, bstlike2, gotlike;
1343  boolean lastrearr;
1344  node *item, *nufork;
1345
1346  if (!usertree) {
1347    if (jumb == 1) {
1348      getdata();
1349      examined = 0;
1350    }
1351    for (i = 1; i <= (numsp); i++)
1352      enterorder[i - 1] = i;
1353    if (jumble) {
1354      for (i = 0; i < (numsp); i++) {
1355        j = (long)(randum(seed) * numsp) + 1;
1356        k = enterorder[j - 1];
1357        enterorder[j - 1] = enterorder[i];
1358        enterorder[i] = k;
1359      }
1360    }
1361    root = treenode[enterorder[0] - 1];
1362    add(treenode[enterorder[0] - 1], treenode[enterorder[1] - 1],
1363        treenode[numsp]);
1364    if (progress) {
1365      printf("\nAdding species:\n");
1366      printf("   ");
1367      for (i = 0; i < namelength; i++)
1368        putchar(nayms[enterorder[0] - 1][i]);
1369      printf("\n   ");
1370      for (i = 0; i < namelength; i++)
1371        putchar(nayms[enterorder[1] - 1][i]);
1372      putchar('\n');
1373    }
1374    lastrearr = false;
1375    for (i = 3; i <= (numsp); i++) {
1376      bestyet = -10000000.0;
1377      item = treenode[enterorder[i - 1] - 1];
1378      nufork = treenode[numsp + i - 2];
1379      addpreorder(root, item, nufork);
1380      add(there, item, nufork);
1381      like = bestyet;
1382      rearrange(&root);
1383      evaluate(root);
1384      examined--;
1385      if (progress) {
1386        printf("   ");
1387        for (j = 0; j < namelength; j++)
1388          putchar(nayms[enterorder[i - 1] - 1][j]);
1389        putchar('\n');
1390      }
1391      lastrearr = (i == numsp);
1392      if (lastrearr) {
1393        if (progress) {
1394          printf("\nDoing global rearrangements\n");
1395          printf("  !");
1396          for (j = 1; j <= (numsp2); j++)
1397            putchar('-');
1398          printf("!\n");
1399        }
1400        bestlike = bestyet;
1401        do {
1402          gotlike = bestlike;
1403          if (progress)
1404            printf("   ");
1405          for (j = 0; j < (numsp2); j++) {
1406            there = root;
1407            bestyet = -32000.0;
1408            item = treenode[j];
1409            if (item != root) {
1410              re_move(&item, &nufork);
1411              there = root;
1412              addpreorder(root, item, nufork);
1413              add(there, item, nufork);
1414            }
1415            if (progress){
1416              putchar('.');
1417              fflush(stdout);}
1418          }
1419          if (progress)
1420            putchar('\n');
1421        } while (bestlike > gotlike);
1422        if (njumble > 1) {
1423          if (jumb == 1 || (jumb > 1 && bestlike > bstlike2)) {
1424            copy_(treenode, bestree);
1425            best = bestree[root->index -1];
1426            bstlike2 = bestlike;
1427          }
1428        }
1429      }
1430      if (i == numsp && njumble == jumb) {
1431        if (njumble > 1) {
1432          copy_(bestree, treenode);
1433          root = treenode[best->index - 1];
1434        }
1435        evaluate(root);
1436        printree();
1437        describe();
1438      }
1439    }
1440  } else {
1441    getdata();
1442    fscanf(infile, "%ld%*[^\n]", &numtrees);
1443    getc(infile);
1444    if (treeprint)
1445      fprintf(outfile, "\n\nUser-defined trees:\n\n");
1446    i = 1;
1447    while (i <= numtrees ) {
1448      treeread();
1449      evaluate(root);
1450      printree();
1451      describe();
1452      i++;
1453    }
1454  }
1455  if (jumb == njumble && progress) {
1456    printf("\nOutput written to output file\n\n");
1457    if (trout)
1458      printf("Tree also written onto file\n");
1459    putchar('\n');
1460  }
1461}  /* maketree */
1462
1463
1464main(argc, argv)
1465int argc;
1466Char *argv[];
1467{  /* Fitch-Margoliash criterion with contemporary tips */
1468char infilename[100],outfilename[100],trfilename[100];
1469#ifdef MAC
1470  macsetup("Kitsch","");
1471#endif
1472  /* reads in numsp, options, and the data, then calls maketree to
1473     construct the tree */
1474  openfile(&infile,INFILE,"r",argv[0],infilename);
1475  openfile(&outfile,OUTFILE,"w",argv[0],outfilename);
1476
1477  ibmpc = ibmpc0;
1478  ansi = ansi0;
1479  vt52 = vt520;
1480  mulsets = false;
1481  firstset = true;
1482  datasets = 1;
1483  doinit();
1484  openfile(&treefile,TREEFILE,"w",argv[0],trfilename);
1485  nayms = (naym *)Malloc(numsp*sizeof(naym));
1486  enterorder = (long *)Malloc(numsp*sizeof(long));
1487  for (ith = 1; ith <= datasets; ith++) {
1488    if (datasets > 1) {
1489      fprintf(outfile, "\nData set # %ld:\n",ith);
1490      if (progress)
1491        printf("\nData set # %ld:\n",ith);
1492    }
1493    getinput();
1494    for (jumb = 1; jumb <= njumble; jumb++)
1495      maketree();
1496    firstset = false;
1497    if (eoln(infile)) {
1498      fscanf(infile, "%*[^\n]");
1499      getc(infile);
1500    }
1501  }
1502  FClose(infile);
1503  FClose(outfile);
1504  FClose(treefile);
1505#ifdef MAC
1506  fixmacfile(outfilename);
1507  fixmacfile(trfilename);
1508#endif
1509  exit(0);
1510}  /* Fitch-Margoliash criterion with contemporary tips */
1511
1512
1513int eof(f)
1514FILE *f;
1515{
1516    register int ch;
1517
1518    if (feof(f))
1519        return 1;
1520    if (f == stdin)
1521        return 0;
1522    ch = getc(f);
1523    if (ch == EOF)
1524        return 1;
1525    ungetc(ch, f);
1526    return 0;
1527}
1528
1529
1530int eoln(f)
1531FILE *f;
1532{
1533    register int ch;
1534
1535    ch = getc(f);
1536    if (ch == EOF)
1537        return 1;
1538    ungetc(ch, f);
1539    return (ch == '\n');
1540}
1541
1542void memerror()
1543{
1544printf("Error allocating memory\n");
1545exit(-1);
1546}
1547
1548MALLOCRETURN *mymalloc(x)
1549long x;
1550{
1551MALLOCRETURN *mem;
1552mem = (MALLOCRETURN *)malloc(x);
1553if (!mem)
1554  memerror();
1555else
1556  return (MALLOCRETURN *)mem;
1557}
1558
Note: See TracBrowser for help on using the repository browser.