source: trunk/GDE/PHYLIP/dolpenny.c

Last change on this file was 19480, checked in by westram, 15 months ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.5 KB
Line 
1#include "phylip.h"
2#include "disc.h"
3#include "dollo.h"
4
5/* version 3.6. (c) Copyright 1993-2002 by the University of Washington.
6   Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
7   Permission is granted to copy and use this program provided no fee is
8   charged for it and provided that this copyright notice is not removed. */
9
10#define maxtrees        100   /* maximum number of trees to be printed out   */
11#define often           100   /* how often to notify how many trees examined */
12#define many            1000  /* how many multiples of howoften before stop  */
13
14typedef long *treenumbers;
15typedef double *valptr;
16typedef long *placeptr;
17
18#ifndef OLDC
19/* function prototypes */
20void   getoptions(void);
21void   allocrest(void);
22void   doinit(void);
23void   inputoptions(void);
24void   doinput(void);
25void   preorder(node *);
26void   evaluate(node *);
27void   addtraverse(node *, node *, node *, placeptr, valptr, long *);
28void   addit(long);
29void   describe(void);
30void   maketree(void);
31/* function prototypes */
32#endif
33
34Char infilename[FNMLNGTH], outfilename[FNMLNGTH], outtreename[FNMLNGTH],  weightfilename[FNMLNGTH], ancfilename[FNMLNGTH];
35node *root;
36long howmany, howoften, col, msets, ith;
37boolean weights, thresh, ancvar, questions, dollo, simple, trout,
38               progress, treeprint, stepbox, ancseq,
39               mulsets, firstset, justwts;
40boolean *ancone, *anczero, *ancone0, *anczero0;
41pointptr treenode;   /* pointers to all nodes in tree */
42double fracdone, fracinc;
43double threshold;
44double *threshwt;
45boolean *added;
46Char *guess;
47steptr numsteps, numsone, numszero;
48gbit *garbage;
49long **bestorders, **bestrees;
50
51/* Local variables for maketree, propagated globally for C version: */
52long examined, mults;
53boolean firsttime, done;
54double like, bestyet;
55treenumbers current, order;
56long fullset;
57bitptr zeroanc, oneanc;
58bitptr stps;
59
60
61void getoptions()
62{
63  /* interactively set options */
64  long loopcount, loopcount2;
65  Char ch, ch2;
66  boolean local_done;
67
68  fprintf(outfile, "\nPenny algorithm for Dollo or polymorphism");
69  fprintf(outfile, " parsimony, version %s\n",VERSION);
70  fprintf(outfile, " branch-and-bound to find all");
71  fprintf(outfile, " most parsimonious trees\n\n");
72  howoften = often;
73  howmany = many;
74  simple = true;
75  thresh = false;
76  threshold = spp;
77  trout = true;
78  weights = false;
79  justwts = false;
80  ancvar = false;
81  dollo = true;
82  printdata = false;
83  progress = true;
84  treeprint = true;
85  stepbox = false;
86  ancseq = false;
87  loopcount = 0;
88  do {
89    cleerhome();
90    printf("\nPenny algorithm for Dollo or polymorphism parsimony,");
91    printf(" version %s\n",VERSION);
92    printf(" branch-and-bound to find all most parsimonious trees\n\n");
93    printf("Settings for this run:\n");
94    printf("  P                     Parsimony method?  %s\n",
95           (dollo ? "Dollo" : "Polymorphism"));
96    printf("  H        How many groups of %4ld trees:%6ld\n",howoften,howmany);
97    printf("  F        How often to report, in trees:%5ld\n",howoften);
98    printf("  S           Branch and bound is simple?  %s\n",
99           (simple ? "Yes" : "No.  Reconsiders order of species"));
100    printf("  T              Use Threshold parsimony?");
101    if (thresh)
102      printf("  Yes, count steps up to%4.1f per char.\n", threshold);
103    else
104      printf("  No, use ordinary parsimony\n");
105    printf("  A                 Use ancestral states?  %s\n",
106           (ancvar ? "Yes" : "No"));
107    printf("  W                       Sites weighted?  %s\n",
108           (weights ? "Yes" : "No"));
109    printf("  M           Analyze multiple data sets?");
110    if (mulsets)
111        printf("  Yes, %2ld %s\n", msets,
112               (justwts ? "sets of weights" : "data sets"));
113    else
114      printf("  No\n");
115    printf("  0   Terminal type (IBM PC, ANSI, none)?  %s\n",
116           (ibmpc ? "IBM PC" : ansi  ? "ANSI" : "(none)"));
117    printf("  1    Print out the data at start of run  %s\n",
118           (printdata ? "Yes" : "No"));
119    printf("  2  Print indications of progress of run  %s\n",
120           (progress ? "Yes" : "no"));
121    printf("  3                        Print out tree  %s\n",
122           (treeprint ? "Yes": "No"));
123    printf("  4     Print out steps in each character  %s\n",
124           (stepbox ? "Yes" : "No"));
125    printf("  5     Print states at all nodes of tree  %s\n",
126           (ancseq ? "Yes" : "No"));
127    printf("  6       Write out trees onto tree file?  %s\n",
128           (trout ? "Yes" : "No"));
129    if(weights && justwts){
130        printf(
131         "WARNING:  W option and Multiple Weights options are both on.  ");
132        printf(
133         "The W menu option is unnecessary and has no additional effect. \n");
134    }
135    printf("\nAre these settings correct? (type Y or the letter for one to change)\n");
136#ifdef WIN32
137    phyFillScreenColor();
138#endif
139    scanf("%c%*[^\n]", &ch);
140    getchar();
141    uppercase(&ch);
142    local_done = (ch == 'Y');
143    if (!local_done) {
144      if (strchr("WHMSTAPF1234560",ch) != NULL){
145        switch (ch) {
146
147        case 'W':
148        weights = !weights;
149        break;
150
151        case 'H':
152          inithowmany(&howmany, howoften);
153          break;
154
155        case 'F':
156          inithowoften(&howoften);
157          break;
158
159        case 'A':
160          ancvar = !ancvar;
161          break;
162
163        case 'P':
164          dollo = !dollo;
165          break;
166
167        case 'S':
168          simple = !simple;
169          break;
170
171        case 'T':
172          thresh = !thresh;
173          if (thresh)
174            initthreshold(&threshold);
175          break;
176
177        case 'M':
178          mulsets = !mulsets;
179          if (mulsets){
180            printf("Multiple data sets or multiple weights?");
181          loopcount2 = 0;
182          do {
183            printf(" (type D or W)\n");
184#ifdef WIN32
185            phyFillScreenColor();
186#endif
187            scanf("%c%*[^\n]", &ch2);
188            getchar();
189            if (ch2 == '\n')
190              ch2 = ' ';
191            uppercase(&ch2);
192            countup(&loopcount2, 10);
193          } while ((ch2 != 'W') && (ch2 != 'D'));
194          justwts = (ch2 == 'W');
195          if (justwts)
196            justweights(&msets);
197          else
198            initdatasets(&msets);
199          }
200          break;
201
202        case '0':
203          initterminal(&ibmpc, &ansi);
204          break;
205
206        case '1':
207          printdata = !printdata;
208          break;
209
210        case '2':
211          progress = !progress;
212          break;
213
214        case '3':
215          treeprint = !treeprint;
216          break;
217
218        case '4':
219          stepbox = !stepbox;
220          break;
221
222        case '5':
223          ancseq = !ancseq;
224          break;
225
226        case '6':
227          trout = !trout;
228          break;
229        }
230      } else
231        printf("Not a possible option!\n");
232    }
233    countup(&loopcount, 100);
234  } while (!local_done);
235}  /* getoptions */
236
237
238void allocrest()
239{
240  long i;
241
242  extras = (long *)Malloc(chars*sizeof(long));
243  weight = (long *)Malloc(chars*sizeof(long));
244  threshwt = (double *)Malloc(chars*sizeof(double));
245  guess = (Char *)Malloc(chars*sizeof(Char));
246  numsteps = (long *)Malloc(chars*sizeof(long));
247  numszero = (long *)Malloc(chars*sizeof(long));
248  numsone = (long *)Malloc(chars*sizeof(long));
249  bestorders = (long **)Malloc(maxtrees*sizeof(long *));
250  bestrees = (long **)Malloc(maxtrees*sizeof(long *));
251  for (i = 1; i <= maxtrees; i++) {
252    bestorders[i - 1] = (long *)Malloc(spp*sizeof(long));
253    bestrees[i - 1] = (long *)Malloc(spp*sizeof(long));
254  }
255  current = (treenumbers)Malloc(spp*sizeof(long));
256  order = (treenumbers)Malloc(spp*sizeof(long));
257  nayme = (naym *)Malloc(spp*sizeof(naym));
258  added = (boolean *)Malloc(nonodes*sizeof(boolean));
259  ancone = (boolean *)Malloc(chars*sizeof(boolean));
260  anczero = (boolean *)Malloc(chars*sizeof(boolean));
261  ancone0 = (boolean *)Malloc(chars*sizeof(boolean));
262  anczero0 = (boolean *)Malloc(chars*sizeof(boolean));
263  zeroanc = (bitptr)Malloc(words*sizeof(long));
264  oneanc = (bitptr)Malloc(words*sizeof(long));
265}  /* allocrest */
266
267
268void doinit()
269{
270  /* initializes variables */
271
272  inputnumbers(&spp, &chars, &nonodes, 1);
273  words = chars / bits + 1;
274  getoptions();
275  if (printdata)
276    fprintf(outfile, "%2ld species, %3ld characters\n", spp, chars);
277  alloctree(&treenode);
278  setuptree(treenode);
279  allocrest();
280}  /* doinit */
281
282
283void inputoptions()
284{
285  /* input the information on the options */
286  long i;
287
288  if(justwts){
289      if(firstset){
290          scan_eoln(infile);
291          if (ancvar) {
292              inputancestorsnew(anczero0, ancone0);
293          }
294      }
295      for (i = 0; i < (chars); i++)
296          weight[i] = 1;
297      inputweights(chars, weight, &weights);
298  }
299  else {
300      if (!firstset)
301          samenumsp(&chars, ith);
302      scan_eoln(infile);
303      for (i = 0; i < (chars); i++)
304          weight[i] = 1;
305      if (ancvar)
306          inputancestorsnew(anczero0, ancone0);
307      if (weights)
308          inputweights(chars, weight, &weights);
309  }
310  for (i = 0; i < (chars); i++) {
311    if (!ancvar) {
312      anczero[i] = true;
313      ancone[i] = false;
314    } else {
315      anczero[i] = anczero0[i];
316      ancone[i] = ancone0[i];
317    }
318  }
319  questions = false;
320  if (!thresh)
321    threshold = spp;
322  for (i = 0; i < (chars); i++) {
323    questions = (questions || (ancone[i] && anczero[i]));
324    threshwt[i] = threshold * weight[i];
325  }
326}  /* inputoptions */
327
328
329void doinput()
330{
331  /* reads the input data */
332  inputoptions();
333  if(!justwts || firstset)
334      inputdata(treenode, dollo, printdata, outfile);
335}  /* doinput */
336
337
338void preorder(node *p)
339{
340  /* go back up tree setting up and counting interior node
341     states */
342  long i;
343
344  if (!p->tip) {
345    correct(p, fullset, dollo, zeroanc, treenode);
346    preorder(p->next->back);
347    preorder(p->next->next->back);
348  }
349  if (p->back == NULL)
350    return;
351  if (dollo) {
352    for (i = 0; i < (words); i++)
353      stps[i] = (treenode[p->back->index - 1]->stateone[i] & p->statezero[i] &
354                 zeroanc[i]) |
355                (treenode[p->back->index - 1]->statezero[i] & p->stateone[i] &
356                 fullset & (~zeroanc[i]));
357  } else {
358    for (i = 0; i < (words); i++)
359      stps[i] = treenode[p->back->index - 1]->stateone[i] &
360                treenode[p->back->index - 1]->statezero[i] & p->stateone[i] &
361                p->statezero[i];
362  }
363  count(stps, zeroanc, numszero, numsone);
364}  /* preorder */
365
366
367void evaluate(node *r)
368{
369  /* Determines the number of losses or polymorphisms needed
370     for a tree. This is the minimum number needed to evolve
371     chars on this tree */
372  long i, stepnum, smaller;
373  double sum;
374
375  sum = 0.0;
376  for (i = 0; i < (chars); i++) {
377    numszero[i] = 0;
378    numsone[i] = 0;
379  }
380  for (i = 0; i < (words); i++)
381    zeroanc[i] = fullset;
382  postorder(r);
383  preorder(r);
384  for (i = 0; i < (words); i++)
385    zeroanc[i] = 0;
386  postorder(r);
387  preorder(r);
388  for (i = 0; i < (chars); i++) {
389    smaller = spp * weight[i];
390    numsteps[i] = smaller;
391    if (anczero[i]) {
392      numsteps[i] = numszero[i];
393      smaller = numszero[i];
394    }
395    if (ancone[i] && numsone[i] < smaller)
396      numsteps[i] = numsone[i];
397    stepnum = numsteps[i] + extras[i];
398    if (stepnum <= threshwt[i])
399      sum += stepnum;
400    else
401      sum += threshwt[i];
402    guess[i] = '?';
403    if (!ancone[i] || (anczero[i] && numszero[i] < numsone[i]))
404      guess[i] = '0';
405    else if (!anczero[i] || (ancone[i] && numsone[i] < numszero[i]))
406      guess[i] = '1';
407  }
408  if (examined == 0 && mults == 0)
409    bestyet = -1.0;
410  like = sum;
411}  /* evaluate */
412
413
414void addtraverse(node *a, node *b, node *c, placeptr place,
415                valptr valyew, long *n)
416{
417  /* traverse all places to add b */
418  if (done)
419    return;
420  add(a, b, c, &root, treenode);
421  (*n)++;
422  evaluate(root);
423  examined++;
424  if (examined == howoften) {
425    examined = 0;
426    mults++;
427    if (mults == howmany)
428      done = true;
429    if (progress) {
430      printf("%6ld",mults);
431      if (bestyet >= 0)
432        printf("%18.5f", bestyet);
433      else
434        printf("         -        ");
435      printf("%17ld%20.2f\n", nextree - 1, fracdone * 100);
436#ifdef WIN32
437      phyFillScreenColor();
438#endif
439    }
440  }
441  valyew[*n - 1] = like;
442  place[*n - 1] = a->index;
443  re_move(&b, &c, &root, treenode);
444  if (!a->tip) {
445    addtraverse(a->next->back, b, c, place,valyew,n);
446    addtraverse(a->next->next->back, b, c, place,valyew,n);
447  }
448}  /* addtraverse */
449
450
451void addit(long m)
452{
453  /* adds the species one by one, recursively */
454  long n;
455  valptr valyew;
456  placeptr place;
457  long i, j, n1, besttoadd = 0;
458  valptr bestval;
459  placeptr bestplace;
460  double oldfrac, oldfdone, sum, bestsum;
461
462  valyew = (valptr)Malloc(nonodes*sizeof(double));
463  bestval = (valptr)Malloc(nonodes*sizeof(double));
464  place = (placeptr)Malloc(nonodes*sizeof(long));
465  bestplace = (placeptr)Malloc(nonodes*sizeof(long));
466  if (simple && !firsttime) {
467    n = 0;
468    added[order[m - 1] - 1] = true;
469    addtraverse(root, treenode[order[m - 1] - 1], treenode[spp + m - 2],
470                place, valyew, &n);
471    besttoadd = order[m - 1];
472    memcpy(bestplace, place, nonodes*sizeof(long));
473    memcpy(bestval, valyew, nonodes*sizeof(double));
474  } else {
475    bestsum = -1.0;
476    for (i = 1; i <= (spp); i++) {
477      if (!added[i - 1]) {
478        n = 0;
479        added[i - 1] = true;
480        addtraverse(root, treenode[i - 1], treenode[spp + m - 2],
481                    place, valyew, &n);
482        added[i - 1] = false;
483        sum = 0.0;
484        for (j = 0; j < n; j++)
485          sum += valyew[j];
486        if (sum > bestsum) {
487          bestsum = sum;
488          besttoadd = i;
489          memcpy(bestplace, place, nonodes*sizeof(long));
490          memcpy(bestval, valyew, nonodes*sizeof(double));
491        }
492      }
493    }
494  }
495  order[m - 1] = besttoadd;
496  memcpy(place, bestplace, nonodes*sizeof(long));
497  memcpy(valyew, bestval, nonodes*sizeof(double));
498  shellsort(valyew, place, n);
499  oldfrac = fracinc;
500  oldfdone = fracdone;
501  n1 = 0;
502  for (i = 0; i < (n); i++) {
503    if (valyew[i] <= bestyet || bestyet < 0.0)
504      n1++;
505  }
506  if (n1 > 0)
507    fracinc /= n1;
508  for (i = 0; i < n; i++) {
509    if (valyew[i] <=bestyet ||bestyet < 0.0) {
510      current[m - 1] = place[i];
511      add(treenode[place[i] - 1], treenode[besttoadd - 1],
512          treenode[spp + m - 2], &root, treenode);
513      added[besttoadd - 1] = true;
514      if (m < spp)
515        addit(m + 1);
516      else {
517        if (valyew[i] < bestyet || bestyet < 0.0) {
518          nextree = 1;
519          bestyet = valyew[i];
520        }
521        if (nextree <= maxtrees) {
522          memcpy(bestorders[nextree - 1], order,
523                 spp*sizeof(long));
524          memcpy(bestrees[nextree - 1], current,
525                 spp*sizeof(long));
526        }
527        nextree++;
528        firsttime = false;
529      }
530      re_move(&treenode[besttoadd - 1], &treenode[spp + m - 2], &root, treenode);
531      added[besttoadd - 1] = false;
532    }
533    fracdone += fracinc;
534  }
535  fracinc = oldfrac;
536  fracdone = oldfdone;
537  free(valyew);
538  free(bestval);
539  free(place);
540  free(bestplace);
541}  /* addit */
542
543
544void describe()
545{
546  /* prints ancestors, steps and table of numbers of steps in
547     each character */
548  if (stepbox) {
549    putc('\n', outfile);
550    writesteps(weights, dollo, numsteps);
551  }
552  if (questions)
553    guesstates(guess);
554  if (ancseq) {
555    hypstates(fullset, dollo, guess, treenode, root, garbage, zeroanc, oneanc);
556    putc('\n', outfile);
557  }
558  putc('\n', outfile);
559  if (trout) {
560    col = 0;
561    treeout(root, nextree, &col, root);
562  }
563}  /* describe */
564
565
566void maketree()
567{
568  /* tree construction recursively by branch and bound */
569  long i, j, k;
570  node *dummy;
571
572  fullset = (1L << (bits + 1)) - (1L << 1);
573  if (progress) {
574    printf("\nHow many\n");
575    printf("trees looked                                       Approximate\n");
576    printf("at so far      Length of        How many           percentage\n");
577    printf("(multiples     shortest tree    trees this long    searched\n");
578    printf("of %4ld):      found so far     found so far       so far\n",
579           howoften);
580    printf("----------     ------------     ------------       ------------\n");
581#ifdef WIN32
582    phyFillScreenColor();
583#endif
584  }
585  done = false;
586  mults = 0;
587  examined = 0;
588  nextree = 1;
589  root = treenode[0];
590  firsttime = true;
591  for (i = 0; i < (spp); i++)
592    added[i] = false;
593  added[0] = true;
594  order[0] = 1;
595  k = 2;
596  fracdone = 0.0;
597  fracinc = 1.0;
598  bestyet = -1.0;
599  stps = (bitptr)Malloc(words*sizeof(long));
600  addit(k);
601  if (done) {
602    if (progress) {
603      printf("Search broken off!  Not guaranteed to\n");
604      printf(" have found the most parsimonious trees.\n");
605    }
606    if (treeprint) {
607      fprintf(outfile, "Search broken off!  Not guaranteed to\n");
608      fprintf(outfile, " have found the most parsimonious\n");
609      fprintf(outfile, " trees, but here is what we found:\n");
610    }
611  }
612  if (treeprint) {
613    fprintf(outfile, "\nrequires a total of %18.3f\n\n", bestyet);
614    if (nextree == 2)
615      fprintf(outfile, "One most parsimonious tree found:\n");
616    else
617      fprintf(outfile, "%5ld trees in all found\n", nextree - 1);
618  }
619  if (nextree > maxtrees + 1) {
620    if (treeprint)
621      fprintf(outfile, "here are the first%4ld of them\n", (long)maxtrees);
622    nextree = maxtrees + 1;
623  }
624  if (treeprint)
625    putc('\n', outfile);
626  for (i = 0; i < (spp); i++)
627    added[i] = true;
628  for (i = 0; i <= (nextree - 2); i++) {
629    for (j = k; j <= (spp); j++)
630      add(treenode[bestrees[i][j - 1] - 1],
631          treenode[bestorders[i][j - 1] - 1], treenode[spp + j - 2],
632          &root, treenode);
633    evaluate(root);
634    printree(1.0, treeprint, root);
635    describe();
636    for (j = k - 1; j < (spp); j++)
637      re_move(&treenode[bestorders[i][j] - 1], &dummy, &root, treenode);
638  }
639  if (progress) {
640    printf("\nOutput written to file \"%s\"\n\n", outfilename);
641    if (trout)
642      printf("Trees also written onto file \"%s\"\n\n", outtreename);
643  }
644  free(stps);
645  if (ancseq)
646    freegarbage(&garbage);
647}  /* maketree */
648
649
650int main(int argc, Char *argv[])
651{ /* branch-and-bound method for Dollo, polymorphism parsimony */
652  /* Reads in the number of species, number of characters,
653     options and data.  Then finds all most parsimonious trees */
654#ifdef MAC
655  argc = 1;                /* macsetup("Dolpenny","");                */
656  argv[0] = "Dolpenny";
657#endif
658  init(argc, argv);
659  openfile(&infile,INFILE,"input file", "r",argv[0],infilename);
660  openfile(&outfile,OUTFILE,"output file", "w",argv[0],outfilename);
661  ibmpc = IBMCRT;
662  ansi = ANSICRT;
663  garbage = NULL;
664  mulsets = false;
665  msets = 1;
666  firstset = true;
667  bits = 8*sizeof(long) - 1;
668  doinit();
669  if (weights || justwts)
670    openfile(&weightfile,WEIGHTFILE,"weights file","r",argv[0],weightfilename);
671  if (trout)
672    openfile(&outtree,OUTTREE,"output tree file", "w",argv[0],outtreename);
673  if(ancvar)
674      openfile(&ancfile,ANCFILE,"ancestors file", "r",argv[0],ancfilename);
675      fprintf(outfile,"%s parsimony method\n\n",dollo ? "Dollo" : "Polymorphism"); 
676  for (ith = 1; ith <= msets; ith++) {
677    doinput();
678    if (msets > 1 && !justwts) {
679      fprintf(outfile, "Data set # %ld:\n\n",ith);
680      if (progress)
681        printf("\nData set # %ld:\n",ith);
682    } 
683    if (justwts){
684        fprintf(outfile, "Weights set # %ld:\n\n", ith);
685        if (progress)
686            printf("\nWeights set # %ld:\n\n", ith);
687    }
688    if (printdata){
689        if (weights || justwts)
690            printweights(outfile, 0, chars, weight, "Characters");
691        if (ancvar)
692            printancestors(outfile, anczero, ancone);
693    }
694    if (ith == 1)
695      firstset = false;
696    maketree();
697  }
698
699  FClose(infile);
700  FClose(outfile);
701  FClose(outtree);
702#ifdef MAC
703  fixmacfile(outfilename);
704  fixmacfile(outtreename);
705#endif
706#ifdef WIN32
707  phyRestoreConsoleAttributes();
708#endif
709  return 0;
710}  /* branch-and-bound method for Dollo, polymorphism parsimony */
Note: See TracBrowser for help on using the repository browser.