source: tags/initial/GDE/PHYLIP/clique.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: 38.9 KB
Line 
1#include "phylip.h"
2
3/* version 3.52c. (c) Copyright 1993 by Joseph Felsenstein.
4   Written by Joseph Felsenstein, Jerry Shurman, Hisashi Horino,
5   Akiko Fuseki, Sean Lamont, and Andrew Keeffe.  Permission is granted
6   to copy and use this program provided no fee is charged for it and
7   provided that this copyright notice is not removed. */
8
9#define NmLngth         10   /* number of characters in a name */
10#define FormWide        80   /* width of outfile page */
11
12#define ibmpc0          false
13#define ansi0           true
14#define vt520           false
15#define down            2
16typedef boolean *aPtr;
17typedef long *SpPtr;
18typedef long *ChPtr;
19
20typedef struct vecrec {
21  aPtr vec;
22  struct vecrec *next;
23} vecrec;
24
25typedef Char **NamePtr;
26typedef vecrec **aDataPtr;
27typedef vecrec **Matrix;      /* nodes will form a binary tree         */
28typedef struct node {         /* describes a tip species or an ancestor*/
29  struct node *next, *back;   /* pointers to nodes                     */
30  long index;                 /* number of the node                    */
31  long maxpos;                /*                                       */
32  boolean tip;                /* present species are tips of tree      */
33  long nodeset;               /* used by accumulate                    */
34  long xcoord, ycoord, ymin;  /* used by printree                      */
35  long ymax;
36} node;
37
38typedef node **pointptr;
39char infilename[100],outfilename[100],trfilename[100];
40
41Static long NumSpp, NumChars, ActualChars, Cliqmin, outgrno, col, datasets,
42             ith, j, setsz;
43Static boolean ancvar, Clmin, Factors, outgropt, trout, weights,
44               noroot, printdata, printcomp, progress, treeprint, mulsets,
45               ibmpc, vt52, ansi, firstset;
46Static NamePtr Nayme;
47Static aPtr ancone;
48Static Char *Factor;
49Static long *ActChar, *oldweight, *weight;
50Static aDataPtr Data;
51Static Matrix Comp;            /* the character compatibility matrix      */
52Static FILE *infile, *outfile, *treefile;
53Static node *root;
54Static long **grouping;
55Static pointptr treenode;   /* pointers to all nodes in tree              */
56Static vecrec *garbage;
57
58/* these variables are local to DoAll in the pascal Version. */
59Static  aPtr aChars;
60Static  boolean *Rarer;
61Static  long n, MaxChars;
62Static  SpPtr SpOrder;
63Static  ChPtr ChOrder;
64
65/* Local variables for GetMaxCliques: */
66Static  vecrec **Comp2;
67Static  long tcount;
68Static  aPtr Temp, Processed, Rarer2;
69
70openfile(fp,filename,mode,application,perm)
71FILE **fp;
72char *filename;
73char *mode;
74char *application;
75char *perm;
76{
77  FILE *of;
78  char file[100];
79  strcpy(file,filename);
80  while (1){
81    of = fopen(file,mode);
82    if (of)
83      break;
84    else {
85      switch (*mode){
86      case 'r':
87        printf("%s:  can't read %s\n",application,file);
88        file[0] = '\0';
89        while (file[0] =='\0'){
90          printf("Please enter a new filename>");
91          gets(file);}
92        break;
93      case 'w':
94        printf("%s: can't write %s\n",application,file);
95        file[0] = '\0';
96        while (file[0] =='\0'){
97          printf("Please enter a new filename>");
98          gets(file);}
99        break;
100      }
101    }
102  }
103  *fp=of;
104  if (perm != NULL)
105    strcpy(perm,file);
106}
107
108Static Void gnu(p)
109vecrec **p;
110{  /* this and the following are do-it-yourself garbage collectors.
111     Make a new node or pull one off the garbage list */
112
113 if (garbage != NULL) {
114    *p = garbage;
115    garbage = garbage->next;
116  } else {
117    *p = (vecrec *)Malloc((long)sizeof(vecrec));
118    (*p)->vec = (aPtr)Malloc((long)NumChars*sizeof(boolean));
119  }
120  (*p)->next = NULL;
121}  /* gnu */
122
123
124Static Void chuck(p)
125vecrec *p;
126{  /* collect garbage on p -- put it on front of garbage list */
127
128 p->next = garbage;
129  garbage = p;
130}  /* chuck */
131
132
133void nunode(p)
134node **p;
135{  /* replacement for NEW */
136  *p = (node *)Malloc((long)sizeof(node));
137  (*p)->next = NULL;
138  (*p)->tip = false;
139}  /* nunode */
140
141
142void NewLine(i, j)
143long i, j;
144{
145  /* goes to new line if i MOD j is zero */
146  long k;
147
148  if (i % j != 0)
149    return;
150  putc('\n', outfile);
151  for (k = 1; k <= NmLngth + 1; k++)
152    putc(' ', outfile);
153}  /* NewLine */
154
155
156void uppercase(ch)
157Char *ch;
158{  /* convert a character to upper case -- either ASCII or EBCDIC */
159   *ch = (islower(*ch) ?  toupper(*ch) : (*ch));
160}  /* uppercase */
161
162void inputnumbers()
163{
164  /* set variables */
165  fscanf(infile, "%ld%ld", &NumSpp, &NumChars);
166  if (printdata)
167    fprintf(outfile, "%2ld species, %3ld character states\n\n",
168            NumSpp, NumChars);
169}  /* inputnumbers */
170
171void getoptions()
172{
173  /* interactively set options */
174  Char ch;
175  boolean done, done1;
176
177  fprintf(outfile, "\nLargest clique program, version %s\n\n",VERSION);
178  putchar('\n');
179  ancvar = false;
180  Clmin = false;
181  Factors = false;
182  outgrno = 1;
183  outgropt = false;
184  trout = true;
185  weights = false;
186  printdata = false;
187  printcomp = false;
188  progress = true;
189  treeprint = true;
190  do {
191    printf((ansi) ? "\033[2J\033[H" :
192           (vt52) ? "\033E\033H"    : "\n");
193    printf("\nLargest clique program, version %s\n\n",VERSION);
194    printf("Settings for this run:\n");
195    printf("  A   Use ancestral states in input file?  %s\n",
196           (ancvar ? "Yes" : "No"));
197    printf("  C          Specify minimum clique size?");
198    if (Clmin)
199      printf("  Yes, at size%3ld\n", Cliqmin);
200    else
201      printf("  No\n");
202    printf("  O                        Outgroup root?  %s%3ld\n",
203           (outgropt ? "Yes, at species number" :
204                       "No, use as outgroup species"),outgrno);
205    printf("  M           Analyze multiple data sets?");
206    if (mulsets)
207      printf("  Yes, %2ld sets\n", datasets);
208    else
209      printf("  No\n");
210    printf("  0   Terminal type (IBM PC, VT52, ANSI)?  %s\n",
211           ibmpc ? "IBM PC" :
212           ansi  ? "ANSI"   :
213           vt52  ? "VT52"   : "(none)");
214    printf("  1    Print out the data at start of run  %s\n",
215           (printdata ? "Yes" : "No"));
216    printf("  2  Print indications of progress of run  %s\n",
217           (progress ? "Yes" : "No"));
218    printf("  3        Print out compatibility matrix  %s\n",
219           (printcomp ? "Yes" : "No"));
220    printf("  4                        Print out tree  %s\n",
221           (treeprint ? "Yes" : "No"));
222    printf("  5       Write out trees onto tree file?  %s\n",
223           (trout ? "Yes" : "No"));
224    printf("\nAre these settings correct? (type Y or the letter for one to change)\n");
225    scanf("%c%*[^\n]", &ch);
226    getchar();
227    uppercase(&ch);
228    done = (ch == 'Y');
229    if (!done) {
230      if (strchr("OACM012345",ch)){
231        switch (ch) {
232
233        case 'A':
234          ancvar = !ancvar;
235          break;
236
237        case 'C':
238          Clmin = !Clmin;
239          if (Clmin) {
240            do {
241              printf("Minimum clique size:\n");
242              scanf("%ld%*[^\n]", &Cliqmin);
243              getchar();
244            } while (Cliqmin < 0);
245          }
246          break;
247
248        case 'O':
249          outgropt = !outgropt;
250          if (outgropt) {
251            done1 = true;
252            do {
253              printf("Type number of the outgroup:\n");
254              scanf("%ld%*[^\n]", &outgrno);
255              getchar();
256              done1 = (outgrno >= 1 && outgrno <= NumSpp);
257              if (!done1) {
258                printf("BAD OUTGROUP NUMBER: %4ld\n", outgrno);
259                printf("  Must be in range 1 -%2ld\n", NumSpp);
260              }
261            } while (done1 != true);
262          }
263          break;
264
265        case 'M':
266          mulsets = !mulsets;
267          if (mulsets) {
268            done1 = false;
269            do {
270              printf("How many data sets?\n");
271              scanf("%ld%*[^\n]", &datasets);
272              getchar();
273              done1 = (datasets >= 1);
274              if (!done1)
275                printf("BAD DATA SETS NUMBER:  it must be greater than 1\n");
276            } while (done1 != true);
277          }
278          break;
279
280        case '0':
281          if (ibmpc) {
282            ibmpc = false;
283            vt52 = true;
284          } else {
285            if (vt52) {
286              vt52 = false;
287              ansi = true;
288            } else if (ansi)
289              ansi = false;
290            else
291              ibmpc = true;
292          }
293          break;
294
295        case '1':
296          printdata = !printdata;
297          break;
298
299        case '2':
300          progress = !progress;
301          break;
302       
303        case '3':
304          printcomp = !printcomp;
305          break;
306
307        case '4':
308          treeprint = !treeprint;
309          break;
310
311        case '5':
312          trout = !trout;
313          break;
314        }
315      } else
316        printf("Not a possible option!\n");
317    }
318  } while (!done);
319}  /* getoptions */
320
321
322Static Void setuptree()
323{
324  /* initialization of tree pointers, variables */
325  long i;
326
327  treenode = (pointptr)Malloc((long)NumSpp*sizeof(node *));
328  for (i = 0; i < NumSpp; i++) {
329    treenode[i] = (node *)Malloc((long)sizeof(node));
330    treenode[i]->next = NULL;
331    treenode[i]->back = NULL;
332    treenode[i]->index = i + 1;
333    treenode[i]->tip = false;
334  }
335}  /* setuptree */
336
337Static Void doinit()
338{
339  /* initializes variables */
340  long i;
341
342  inputnumbers();
343  getoptions();
344  setuptree();
345  Data = (aDataPtr)Malloc((long)NumSpp*sizeof(vecrec *));
346  for (i = 0; i < (NumSpp); i++)
347    gnu(&Data[i]);
348  Comp = (Matrix)Malloc((long)NumChars*sizeof(vecrec *));
349  for (i = 0; i < (NumChars); i++)
350    gnu(&Comp[i]);
351}  /* doinit */
352
353
354Local Void inputancestors()
355{
356  /* reads the ancestral states for each character */
357  long i;
358  Char ch;
359
360  for (i = 1; i < NmLngth; i++)
361    ch = getc(infile);
362  for (i = 0; i < (NumChars); i++) {
363    do {
364      if (eoln(infile)) {
365        fscanf(infile, "%*[^\n]");
366        getc(infile);
367      }
368      ch = getc(infile);
369    } while (ch == ' ');
370    if (ch == '0' || ch == '1') {
371      switch (ch) {
372
373      case '1':
374        ancone[i] = true;
375        break;
376
377      case '0':
378        ancone[i] = false;
379        break;
380      }
381    } else {
382      printf("BAD ANCESTOR STATE: %c AT CHARACTER %4ld\n", ch, i + 1);
383      exit(-1);
384    }
385  }
386  fscanf(infile, "%*[^\n]");
387  getc(infile);
388}  /* inputancestors */
389
390Local Void printancestors()
391{
392  /* print out list of ancestral states */
393  long i;
394
395  fprintf(outfile, "Ancestral states:\n");
396  for (i = 1; i <= NmLngth + 2; i++)
397    putc(' ', outfile);
398  for (i = 1; i <= (NumChars); i++) {
399    NewLine(i, 55);
400    if (ancone[i - 1])
401      putc('1', outfile);
402    else
403      putc('0', outfile);
404    if (i % 5 == 0)
405      putc(' ', outfile);
406  }
407  fprintf(outfile, "\n\n");
408}  /* printancestor */
409
410Local Void inputfactors()
411{
412  /* reads the factor symbols */
413  long i;
414  Char ch;
415
416  ActualChars = 1;
417  for (i = 1; i < NmLngth; i++)
418    ch = getc(infile);
419  for (i = 1; i <= (NumChars); i++) {
420    if (eoln(infile)) {
421      fscanf(infile, "%*[^\n]");
422      getc(infile);
423    }
424    Factor[i - 1] = getc(infile);
425    if (i > 1) {
426      if (Factor[i - 1] != Factor[i - 2])
427        ActualChars++;
428    }
429    ActChar[i - 1] = ActualChars;
430  }
431  fscanf(infile, "%*[^\n]");
432  getc(infile);
433  Factors = true;
434}  /* inputfactors */
435
436Local Void printfactors()
437{
438  /* print out list of factor symbols */
439  long i;
440
441  fprintf(outfile, "Factors:");
442  for (i = 1; i <= NmLngth - 6; i++)
443    putc(' ', outfile);
444  for (i = 1; i <= (NumChars); i++) {
445    NewLine(i, 50);
446    putc(Factor[i - 1], outfile);
447    if (i % 5 == 0)
448      putc(' ', outfile);
449  }
450  fprintf(outfile, "\n\n");
451
452}  /* printfactors */
453
454Local Void inputweights()
455{
456  /* input the character weights, 0-9 and A-Z for weights 0 - 35 */
457  Char ch;
458  long i;
459
460  for (i = 1; i < NmLngth; i++)
461    ch = getc(infile);
462  for (i = 0; i < (NumChars); i++) {
463    do {
464      if (eoln(infile)) {
465        fscanf(infile, "%*[^\n]");
466        getc(infile);
467      }
468      ch = getc(infile);
469    } while (ch == ' ');
470    oldweight[i] = 1;
471    if (isdigit(ch))
472      oldweight[i] = ch - '0';
473    else if (isalpha(ch)) {
474      uppercase(&ch);
475      if (ch >= 'A' && ch <= 'I')
476        oldweight[i] = ch - 55;
477      else if (ch >= 'J' && ch <= 'R')
478        oldweight[i] = ch - 55;
479      else
480        oldweight[i] = ch - 55;
481    } else {
482      printf("BAD WEIGHT CHARACTER: %c\n", ch);
483      exit(-1);
484    }
485  }
486  fscanf(infile, "%*[^\n]");
487  getc(infile);
488  weights = true;
489}  /* inputweights */
490
491Local Void printweights()
492{
493  /* print out the weights of characters */
494  long i, j, k;
495
496  fprintf(outfile, "   Characters are weighted as follows:\n");
497  fprintf(outfile, "       ");
498  for (i = 0; i <= 9; i++)
499    fprintf(outfile, "%3ld", i);
500  fprintf(outfile, "\n     *---------------------------------\n");
501  for (j = 0; j <= (ActualChars / 10); j++) {
502    fprintf(outfile, "%5ld! ", j * 10);
503    for (i = 0; i <= 9; i++) {
504      k = j * 10 + i;
505      if (k > 0 && k <= ActualChars)
506        fprintf(outfile, "%3ld", oldweight[k - 1]);
507      else
508        fprintf(outfile, "   ");
509    }
510    putc('\n', outfile);
511  }
512  putc('\n', outfile);
513}  /* printweights */
514
515
516Static Void ReadData()
517{
518  /* reads the species names and character data */
519  long i, j, Extranum;
520  Char ch;
521  boolean avar;
522  long cursp, curchs;
523
524  if (!firstset) {
525    if (eoln(infile)) {
526      fscanf(infile, "%*[^\n]");
527      getc(infile);
528    }
529    fscanf(infile, "%ld%ld", &cursp, &curchs);
530    if (cursp != NumSpp) {
531      printf("\nERROR: INCONSISTENT NUMBER OF SPECIES IN DATA SET %4ld\n", ith);
532      exit(-1);
533    }
534    NumChars = curchs;
535  }
536  avar = false;
537  ActualChars = NumChars;
538  for (i = 1; i <= (NumChars); i++)
539    ActChar[i - 1] = i;
540  for (i = 0; i < (NumChars); i++)
541    oldweight[i] = 1;
542  Extranum = 0;
543  while (!(eoln(infile))) {
544    ch = getc(infile);
545    uppercase(&ch);
546    if (ch == 'A' || ch == 'F' || ch == 'W')
547      Extranum++;
548    else if (ch != ' ') {
549      printf("BAD OPTION CHARACTER: %c\n", ch);
550      putc('\n', outfile);
551      exit(-1);
552    }
553  }
554  fscanf(infile, "%*[^\n]");
555  getc(infile);
556  for (i = 1; i <= Extranum; i++) {
557    ch = getc(infile);
558    uppercase(&ch);
559    if (ch != 'A' && ch != 'F' && ch != 'W') {
560      printf("ERROR: INCORRECT AUXILIARY OPTIONS LINE");
561      printf(" WHICH STARTS WITH %c\n", ch);
562      }
563    if (ch == 'A') {
564      avar = true;
565      if (!ancvar) {
566        printf("ERROR: ANCESTOR OPTION NOT CHOSEN IN MENU");
567        printf(" WITH OPTION %c IN INPUT\n",ch);
568        exit(-1);
569      } else
570        inputancestors();
571    }
572    if (ch == 'F')
573      inputfactors();
574    if (ch == 'W')
575      inputweights();
576  }
577  if (ancvar && !avar) {
578    printf("ERROR: ANCESTOR OPTION CHOSEN IN MENU");
579    printf(" WITH NO OPTION A IN INPUT\n");
580    exit(-1);
581  }
582  if (weights && printdata)
583    printweights();
584  if (Factors)
585    printfactors();
586  if (ancvar && avar && printdata)
587    printancestors();
588  noroot = !(outgropt || (ancvar && avar));
589  j = NumChars / 2 + (NumChars / 5 - 1) / 2 - 5;
590  if (j < 0)
591    j = 0;
592  if (j > 27)
593    j = 27;
594  if (printdata) {
595    fprintf(outfile, "Species  ");
596    for (i = 1; i <= j; i++)
597      putc(' ', outfile);
598    fprintf(outfile, "Character states\n");
599    fprintf(outfile, "-------  ");
600    for (i = 1; i <= j; i++)
601      putc(' ', outfile);
602    fprintf(outfile, "--------- ------\n\n");
603  }
604  for (i = 0; i < (NumSpp); i++) {
605    for (j = 0; j < NmLngth; j++) {
606      if (eof(infile) || eoln(infile)){
607        printf("ERROR: END-OF-LINE OR END-OF-FILE IN");
608        printf(" THE MIDDLE OF A SPECIES NAME\n");
609        exit(-1);}
610      Nayme[i][j] = getc(infile);
611      if (printdata)
612        putc(Nayme[i][j], outfile);
613    }
614    if (printdata)
615      fprintf(outfile, "  ");
616    for (j = 1; j <= (NumChars); j++) {
617      do {
618        if (eoln(infile)) {
619          fscanf(infile, "%*[^\n]");
620          getc(infile);
621        }
622        ch = getc(infile);
623      } while (ch == ' ');
624      if (printdata) {
625        putc(ch, outfile);
626        NewLine(j, 55);
627        if (j % 5 == 0)
628          putc(' ', outfile);
629      }
630      if (ch != '0' && ch != '1') {
631        printf("BAD CHARACTER STATE: %c (NOT 0 OR 1)");
632        printf("AT CHARACTER%3ld OF SPECIES%3ld\n", ch, j, i + 1);
633        exit(-1);
634      }
635      Data[i]->vec[j - 1] = (ch == '1');
636    }
637    fscanf(infile, "%*[^\n]");
638    getc(infile);
639    if (printdata)
640      putc('\n', outfile);
641  }
642  putc('\n', outfile);
643  for (i = 0; i < (NumChars); i++) {
644    if (i + 1 == 1 || !Factors)
645      weight[i] = oldweight[i];
646    else if (Factor[i] != Factor[i - 1])
647      weight[ActChar[i] - 1] = oldweight[i];
648  }
649}  /* ReadData */
650
651
652Local boolean Compatible(ch1, ch2)
653long ch1, ch2;
654{
655  /* TRUE if two characters ch1 < ch2 are compatible */
656  long i, j, k;
657  boolean Compt, Done1, Done2;
658  boolean Info[4];
659
660  Compt = true;
661  j = 1;
662  while (ch1 > ActChar[j - 1])
663    j++;
664  Done1 = (ch1 != ActChar[j - 1]);
665  while (!Done1) {
666    k = j;
667    while (ch2 > ActChar[k - 1])
668      k++;
669    Done2 = (ch2 != ActChar[k - 1]);
670    while (!Done2) {
671      for (i = 0; i <= 3; i++)
672        Info[i] = false;
673      if (ancvar) {
674        if (ancone[j - 1] && ancone[k - 1])
675          Info[0] = true;
676        else if (ancone[j - 1] && !ancone[k - 1])
677          Info[1] = true;
678        else if (!ancone[j - 1] && ancone[k - 1])
679          Info[2] = true;
680        else
681          Info[3] = true;
682      }
683      for (i = 0; i < (NumSpp); i++) {
684        if (Data[i]->vec[j - 1] && Data[i]->vec[k - 1])
685          Info[0] = true;
686        else if (Data[i]->vec[j - 1] && !Data[i]->vec[k - 1])
687          Info[1] = true;
688        else if (!Data[i]->vec[j - 1] && Data[i]->vec[k - 1])
689          Info[2] = true;
690        else
691          Info[3] = true;
692      }
693      Compt = (Compt && !(Info[0] && Info[1] && Info[2] && Info[3]));
694      k++;
695      Done2 = (k > NumChars);
696      if (!Done2)
697        Done2 = (ch2 != ActChar[k - 1]);
698    }
699    j++;
700    Done1 = (j > NumChars);
701    if (!Done1)
702      Done1 = (ch1 != ActChar[j - 1]);
703  }
704  return Compt;
705}  /* Compatible */
706
707
708Static Void SetUp(Comp)
709vecrec **Comp;
710{
711  /* sets up the compatibility matrix */
712  long i, j;
713
714  if (printcomp) {
715    if (Factors)
716      fprintf(outfile, "      (For original multistate characters)\n");
717    fprintf(outfile, "Character Compatibility Matrix (1 if compatible)\n");
718    fprintf(outfile, "--------- ------------- ------ -- -- -----------\n\n");
719  }
720  for (i = 0; i < (ActualChars); i++) {
721    if (printcomp) {
722      for (j = 1; j <= ((48 - ActualChars) / 2); j++)
723        putc(' ', outfile);
724      for (j = 1; j < i + 1; j++) {
725        if (Comp[i]->vec[j - 1])
726          putc('1', outfile);
727        else
728          putc('.', outfile);
729        NewLine(j, 70);
730      }
731    }
732    Comp[i]->vec[i] = true;
733    if (printcomp)
734      putc('1', outfile);
735    for (j = i + 1; j < (ActualChars); j++) {
736      Comp[i]->vec[j] = Compatible(i + 1, j + 1);
737      if (printcomp) {
738        if (Comp[i]->vec[j])
739          putc('1', outfile);
740        else
741          putc('.', outfile);
742      }
743      Comp[j]->vec[i] = Comp[i]->vec[j];
744    }
745    if (printcomp)
746      putc('\n', outfile);
747  }
748  putc('\n', outfile);
749}  /* Setup */
750
751
752
753
754
755Local Void Intersect(V1, V2, V3)
756boolean *V1, *V2, *V3;
757{
758  /* takes the logical intersection V1 AND V2 */
759  long i;
760
761  for (i = 0; i < (ActualChars); i++)
762    V3[i] = (V1[i] && V2[i]);
763}  /* Intersect */
764
765Local long CountStates(V)
766boolean *V;
767{
768  /* counts the 1's in V */
769  long i, TempCount;
770
771  TempCount = 0;
772  for (i = 0; i < (ActualChars); i++) {
773    if (V[i])
774      TempCount += weight[i];
775  }
776  return TempCount;
777}  /* CountStates */
778
779Local Void Gen1(i, CurSize, aChars, Candidates, Excluded)
780long i, CurSize;
781boolean *aChars, *Candidates, *Excluded;
782{
783  /* finds largest size cliques and prints them out */
784  long CurSize2, j, k, Actual, Possible;
785  boolean Futile;
786  vecrec *Chars2, *Cands2, *Excl2, *Cprime, *Exprime;
787
788  gnu(&Chars2);
789  gnu(&Cands2);
790  gnu(&Excl2);
791  gnu(&Cprime);
792  gnu(&Exprime);
793  CurSize2 = CurSize;
794  memcpy(Chars2->vec, aChars, NumChars*sizeof(boolean));
795  memcpy(Cands2->vec, Candidates, NumChars*sizeof(boolean));
796  memcpy(Excl2->vec, Excluded, NumChars*sizeof(boolean));
797  j = i;
798  while (j <= ActualChars) {
799    if (Cands2->vec[j - 1]) {
800      Chars2->vec[j - 1] = true;
801      Cands2->vec[j - 1] = false;
802      CurSize2 += weight[j - 1];
803      Possible = CountStates(Cands2->vec);
804      Intersect(Cands2->vec, Comp2[j - 1]->vec, Cprime->vec);
805      Actual = CountStates(Cprime->vec);
806      Intersect(Excl2->vec, Comp2[j - 1]->vec, Exprime->vec);
807      Futile = false;
808      for (k = 0; k <= j - 2; k++) {
809        if (Exprime->vec[k] && !Futile) {
810          Intersect(Cprime->vec, Comp2[k]->vec, Temp);
811          Futile = (CountStates(Temp) == Actual);
812        }
813      }
814      if (CurSize2 + Actual >= Cliqmin && !Futile) {
815        if (Actual > 0)
816          Gen1(j + 1,CurSize2,Chars2->vec,Cprime->vec,Exprime->vec);
817        else if (CurSize2 > Cliqmin) {
818          Cliqmin = CurSize2;
819          if (tcount >= 0)
820            tcount = 1;
821        } else if (CurSize2 == Cliqmin)
822          tcount++;
823      }
824      if (Possible > Actual) {
825        Chars2->vec[j - 1] = false;
826        Excl2->vec[j - 1] = true;
827        CurSize2 -= weight[j - 1];
828      } else
829        j = ActualChars;
830    }
831    j++;
832  }
833  chuck(Chars2);
834  chuck(Cands2);
835  chuck(Excl2);
836  chuck(Cprime);
837  chuck(Exprime);
838}  /* Gen1 */
839
840
841Local boolean Ingroupstate(i)
842long i;
843{
844  /* the ingroup state for the i-th character */
845  boolean outstate;
846
847  if (noroot) {
848    outstate = Data[0]->vec[i - 1];
849    return (!outstate);
850  }
851  if (ancvar)
852    outstate = ancone[i - 1];
853  else
854    outstate = Data[outgrno - 1]->vec[i - 1];
855  return (!outstate);
856}  /* Ingroupstate */
857
858Local Void makeset()
859{
860  /* make up set of species for given set of characters */
861  long i, j, k, l, m;
862  boolean instate;
863  long *st;
864
865  st = (long *)Malloc(setsz*sizeof(long));
866  n = 0;
867  for (i = 0; i < (MaxChars); i++) {
868    for (j = 0; j < setsz; j++)
869      st[j] = 0;
870    instate = Ingroupstate(ChOrder[i]);
871    for (j = 0; j < (NumSpp); j++) {
872      k = (long)((j+1)/SETBITS);
873      if (Data[SpOrder[j] - 1]->vec[ChOrder[i] - 1] == instate) {
874        m = (long)(SpOrder[j]/SETBITS);
875        st[m] = ((long)st[m]) | (1L << (SpOrder[j] % SETBITS));
876      }
877    }
878    memcpy(grouping[++n - 1], st, setsz*sizeof(long));
879  }
880  for (i = 0; i < (NumSpp); i++) {
881    k = (long)(SpOrder[i]/SETBITS);
882    grouping[++n - 1][k] = 1L << (SpOrder[i] % SETBITS);
883  }
884  free(st);
885}  /* makeset */
886
887Local Void Init(ChOrder, Count, MaxChars,aChars)
888long *ChOrder, *Count;
889long *MaxChars;
890aPtr aChars;
891{
892  /* initialize vectors and character count */
893  long i, j, temp;
894  boolean instate;
895
896  *MaxChars = 0;
897  for (i = 1; i <= (NumChars); i++) {
898    if (aChars[ActChar[i - 1] - 1]) {
899      (*MaxChars)++;
900      ChOrder[*MaxChars - 1] = i;
901      instate = Ingroupstate(i);
902      temp = 0;
903      for (j = 0; j < (NumSpp); j++) {
904        if (Data[j]->vec[i - 1] == instate)
905          temp++;
906      }
907      Count[i - 1] = temp;
908    }
909  }
910}  /*Init */
911
912Local Void ChSort(ChOrder, Count, MaxChars)
913long *ChOrder, *Count;
914long MaxChars;
915{
916  /* sorts the characters by number of ingroup states */
917  long j, temp;
918  boolean ordered;
919
920  ordered = false;
921  while (!ordered) {
922    ordered = true;
923    for (j = 1; j < MaxChars; j++) {
924      if (Count[ChOrder[j - 1] - 1] < Count[ChOrder[j] - 1]) {
925        ordered = false;
926        temp = ChOrder[j - 1];
927        ChOrder[j - 1] = ChOrder[j];
928        ChOrder[j] = temp;
929      }
930    }
931  }
932}  /* ChSort */
933
934Local Void PrintClique(aChars)
935boolean *aChars;
936{
937  /* prints the characters in a clique */
938  long i, j;
939  fprintf(outfile, "\n\n");
940  if (Factors) {
941    fprintf(outfile, "Actual Characters: (");
942    j = 0;
943    for (i = 1; i <= (ActualChars); i++) {
944      if (aChars[i - 1]) {
945        fprintf(outfile, "%3ld", i);
946        j++;
947        NewLine(j, (long)((FormWide - 22) / 3));
948      }
949    }
950    fprintf(outfile, ")\n");
951  }
952  if (Factors)
953    fprintf(outfile, "Binary ");
954  fprintf(outfile, "Characters: (");
955  j = 0;
956  for (i = 1; i <= (NumChars); i++) {
957    if (aChars[ActChar[i - 1] - 1]) {
958      fprintf(outfile, "%3ld", i);
959      j++;
960      if (Factors)
961        NewLine(j, (long)((FormWide - 22) / 3));
962      else
963        NewLine(j, (long)((FormWide - 15) / 3));
964    }
965  }
966  fprintf(outfile, ")\n\n");
967}  /* PrintClique */
968
969
970Local Void bigsubset(st, n)
971long *st;
972long n;
973{
974  /* find a maximal subset of st among the groupings */
975  long i, j;
976  long *su;
977  boolean max, same;
978
979  su = (long *)Malloc(setsz*sizeof(long));
980  for (i = 0; i < setsz; i++)
981    su[i] = 0;
982  for (i = 0; i < n; i++) {
983    max = true;
984    for (j = 0; j < setsz; j++)
985      if ((grouping[i][j] & ~st[j]) != 0)
986       max = false;
987    if (max) {
988      same = true;
989      for (j = 0; j < setsz; j++)
990        if (grouping[i][j] != st[j])
991          same = false;
992      if (!same) {
993        for (j = 0; j < setsz; j++)
994          if ((su[j] & ~grouping[i][j]) != 0)
995            max = false;
996        if (max) {
997          same = true;
998          for (j = 0; j < setsz; j++)
999            if (grouping[i][j] != su[j])
1000              same = false;
1001          if (!same)
1002            memcpy(su, grouping[i], setsz*sizeof(long));
1003        }
1004      }
1005    }
1006  }
1007  memcpy(st, su, setsz*sizeof(long));
1008  free(su);
1009}  /* bigsubset */
1010
1011Local Void recontraverse(p, st, n, MaxChars)
1012node **p;
1013long *st;
1014long n;
1015long MaxChars;
1016{
1017  /* traverse to reconstruct the tree from the characters */
1018  long i, j, k, maxpos;
1019  long *tempset, *st2;
1020  boolean found, zero, zero2, same;
1021  node *q;
1022
1023  j = k = 0;
1024  for (i = 1; i <= (NumSpp); i++) {
1025    if (((1L << (i % SETBITS)) & st[(long)(i / SETBITS)]) != 0) {
1026      k++;
1027      j = i;
1028    }
1029  }
1030  if (k == 1) {
1031    *p = treenode[j - 1];
1032    (*p)->tip = true;
1033    (*p)->index = j;
1034    return;
1035  }
1036  nunode(p);
1037  (*p)->index = 0;
1038  tempset = (long*)Malloc(setsz*sizeof(long));
1039  memcpy(tempset, st, setsz*sizeof(long));
1040  q = *p;
1041  zero = true;
1042  for (i = 0; i < setsz; i++)
1043    if (tempset[i] != 0)
1044      zero = false;
1045  if (!zero)
1046    bigsubset(tempset, n);
1047  zero = true;
1048  zero2 = true;
1049  for (i = 0; i < setsz; i++)
1050    if (st[i] != 0)
1051      zero = false;
1052  if (!zero) {
1053    for (i = 0; i < setsz; i++)
1054      if (tempset[i] != 0)
1055        zero2 = false;
1056  }
1057  st2 = (long *)Malloc(setsz*sizeof(long));
1058  memcpy(st2, st, setsz*sizeof(long));
1059  while (!zero2) {
1060    nunode(&q->next);
1061    q = q->next;
1062    recontraverse(&q->back, tempset, n,MaxChars);
1063    i = 1;
1064    maxpos = 0;
1065    while (i <= MaxChars) {
1066      same = true;
1067      for (j = 0; j < setsz; j++)
1068        if (grouping[i - 1][j] != tempset[j])
1069          same = false;
1070      if (same)
1071        maxpos = i;
1072      i++;
1073    }
1074    q->back->maxpos = maxpos;
1075    q->back->back = q;
1076    for (j = 0; j < setsz; j++)
1077      st2[j] &= ~tempset[j];
1078    memcpy(tempset, st2, setsz*sizeof(long));
1079    found = false;
1080    i = 1;
1081    while (!found && i <= n) {
1082      same = true;
1083      for (j = 0; j < setsz; j++)
1084        if (grouping[i - 1][j] != tempset[j])
1085          same = false;
1086      if (same)
1087        found = true;
1088      else
1089        i++;
1090    }
1091    zero = true;
1092    for (j = 0; j < setsz; j++)
1093      if (tempset[j] != 0)
1094        zero = false;
1095    if (!zero && !found)
1096      bigsubset(tempset, n);
1097    zero = true;
1098    zero2 = true;
1099    for (j = 0; j < setsz; j++)
1100      if (st2[j] != 0)
1101        zero = false;
1102    if (!zero)
1103      for (j = 0; j < setsz; j++)
1104        if (tempset[j] != 0)
1105          zero2 = false;
1106}
1107  q->next = *p;
1108  free(tempset);
1109  free(st2);
1110}  /* recontraverse */
1111
1112Local Void reconstruct(n,MaxChars)
1113long n,MaxChars;
1114{  /* reconstruct tree from the subsets */
1115  long i;
1116  long *s;
1117  s = (long *)Malloc(setsz*sizeof(long));
1118  for (i = 0; i < setsz; i++) {
1119    if (i+1 == setsz) {
1120      s[i] = 1L << ((NumSpp % SETBITS) + 1);
1121      if (setsz > 1)
1122        s[i] -= 1;
1123      else s[i] -= 1L << 1;
1124    }
1125    else if (i == 0) {
1126      if (setsz > 1)
1127        s[i] = ~0L - 1;
1128    }
1129    else {
1130      if (setsz > 2)
1131        s[i] = ~0L;
1132    }
1133  }
1134  recontraverse(&root,s,n,MaxChars);
1135  free(s);
1136}  /* reconstruct */
1137
1138Local Void reroot(outgroup)
1139node *outgroup;
1140{
1141  /* reorients tree, putting outgroup in desired position. */
1142  long i;
1143  boolean nroot;
1144  node *p, *q;
1145
1146  nroot = false;
1147  p = root->next;
1148  while (p != root) {
1149    if (outgroup->back == p) {
1150      nroot = true;
1151      p = root;
1152    } else
1153      p = p->next;
1154  }
1155  if (nroot)
1156    return;
1157  p = root;
1158  i = 0;
1159  while (p->next != root) {
1160    p = p->next;
1161    i++;
1162  }
1163  if (i == 2) {
1164    root->next->back->back = p->back;
1165    p->back->back = root->next->back;
1166    q = root->next;
1167  } else {
1168    p->next = root->next;
1169    nunode(&root->next);
1170    q = root->next;
1171    nunode(&q->next);
1172    p = q->next;
1173    p->next = root;
1174    q->tip = false;
1175    p->tip = false;
1176  }
1177  q->back = outgroup;
1178  p->back = outgroup->back;
1179  outgroup->back->back = p;
1180  outgroup->back = q;
1181}  /* reroot */
1182
1183Local Void coordinates(p, tipy,MaxChars)
1184node *p;
1185long *tipy;
1186long MaxChars;
1187{
1188  /* establishes coordinates of nodes */
1189  node *q, *first, *last;
1190  long maxx;
1191
1192  if (p->tip) {
1193    p->xcoord = 0;
1194    p->ycoord = *tipy;
1195    p->ymin = *tipy;
1196    p->ymax = *tipy;
1197    (*tipy) += down;
1198    return;
1199  }
1200  q = p->next;
1201  maxx = 0;
1202  while (q != p) {
1203    coordinates(q->back,tipy,MaxChars);
1204    if (!q->back->tip) {
1205      if (q->back->xcoord > maxx)
1206        maxx = q->back->xcoord;
1207    }
1208    q = q->next;
1209  }
1210  first = p->next->back;
1211  q = p;
1212  while (q->next != p)
1213    q = q->next;
1214  last = q->back;
1215  p->xcoord = (MaxChars - p->maxpos) * 3 - 2;
1216  if (p == root)
1217    p->xcoord += 2;
1218  p->ycoord = (first->ycoord + last->ycoord) / 2;
1219  p->ymin = first->ymin;
1220  p->ymax = last->ymax;
1221}  /* coordinates */
1222
1223Local Void drawline(i)
1224long i;
1225{
1226  /* draws one row of the tree diagram by moving up tree */
1227  node *p, *q;
1228  long n, m, j, k, l, sumlocpos, size, locpos, branchpos;
1229  long *poslist;
1230  boolean extra, done, plus, found, same;
1231  node *r, *first, *last;
1232
1233  poslist = (long *)Malloc(((long)NumSpp + MaxChars)*sizeof(long));
1234  branchpos = 0;
1235  p = root;
1236  q = root;
1237  fprintf(outfile, "  ");
1238  extra = false;
1239  plus = false;
1240  do {
1241    if (!p->tip) {
1242      found = false;
1243      r = p->next;
1244      while (r != p && !found) {
1245        if (i >= r->back->ymin && i <= r->back->ymax) {
1246          q = r->back;
1247          found = true;
1248        } else
1249          r = r->next;
1250      }
1251      first = p->next->back;
1252      r = p;
1253      while (r->next != p)
1254        r = r->next;
1255      last = r->back;
1256    }
1257    done = (p->tip || p == q);
1258    n = p->xcoord - q->xcoord;
1259    m = n;
1260    if (extra) {
1261      n--;
1262      extra = false;
1263    }
1264    if (q->ycoord == i && !done) {
1265      if (!q->tip) {
1266        putc('+', outfile);
1267        plus = true;
1268        j = 1;
1269        for (k = 1; k <= (q->maxpos); k++) {
1270          same = true;
1271          for (l = 0; l < setsz; l++)
1272            if (grouping[k - 1][l] != grouping[q->maxpos - 1][l])
1273              same = false;
1274          if (same) {
1275            poslist[j - 1] = k;
1276            j++;
1277          }
1278        }
1279        size = j - 1;
1280        if (size == 0) {
1281          for (k = 1; k < n; k++)
1282            putc('-', outfile);
1283          sumlocpos = n;
1284        } else {
1285          sumlocpos = 0;
1286          j = 1;
1287          while (j <= size) {
1288            locpos = poslist[j - 1] * 3;
1289            if (j != 1)
1290              locpos -= poslist[j - 2] * 3;
1291            else
1292              locpos -= branchpos;
1293            for (k = 1; k < locpos; k++)
1294              putc('-', outfile);
1295            if (Rarer[ChOrder[poslist[j - 1] - 1] - 1])
1296              putc('1', outfile);
1297            else
1298              putc('0', outfile);
1299            sumlocpos += locpos;
1300            j++;
1301          }
1302          for (j = sumlocpos + 1; j < n; j++)
1303            putc('-', outfile);
1304          putc('+', outfile);
1305          if (m > 0)
1306            branchpos += m;
1307          extra = true;
1308        }
1309      } else {
1310        if (!plus) {
1311          putc('+', outfile);
1312          plus = false;
1313        } else
1314          n++;
1315        j = 1;
1316        for (k = 1; k <= (q->maxpos); k++) {
1317          same = true;
1318          for (l = 0; l < setsz; l++)
1319            if (grouping[k - 1][l] != grouping[q->maxpos - 1][l])
1320              same = false;
1321          if (same) {
1322            poslist[j - 1] = k;
1323            j++;
1324          }
1325        }
1326        size = j - 1;
1327        if (size == 0) {
1328          for (k = 1; k <= n; k++)
1329            putc('-', outfile);
1330          sumlocpos = n;
1331        } else {
1332          sumlocpos = 0;
1333          j = 1;
1334          while (j <= size) {
1335            locpos = poslist[j - 1] * 3;
1336            if (j != 1)
1337              locpos -= poslist[j - 2] * 3;
1338            else
1339              locpos -= branchpos;
1340            for (k = 1; k < locpos; k++)
1341              putc('-', outfile);
1342            if (Rarer[ChOrder[poslist[j - 1] - 1] - 1])
1343              putc('1', outfile);
1344            else
1345              putc('0', outfile);
1346            sumlocpos += locpos;
1347            j++;
1348          }
1349          for (j = sumlocpos + 1; j <= n; j++)
1350            putc('-', outfile);
1351          if (m > 0)
1352            branchpos += m;
1353        }
1354        putc('-', outfile);
1355      }
1356    } else if (!p->tip && last->ycoord > i && first->ycoord < i &&
1357               (i != p->ycoord || p == root)) {
1358      putc('!', outfile);
1359      for (j = 1; j < n; j++)
1360        putc(' ', outfile);
1361      plus = false;
1362      if (m > 0)
1363        branchpos += m;
1364    } else {
1365      for (j = 1; j <= n; j++)
1366        putc(' ', outfile);
1367      plus = false;
1368      if (m > 0)
1369        branchpos += m;
1370    }
1371    if (q != p)
1372      p = q;
1373  } while (!done);
1374  if (p->ycoord == i && p->tip) {
1375    for (j = 0; j < NmLngth; j++)
1376      putc(Nayme[p->index - 1][j], outfile);
1377}
1378  putc('\n', outfile);
1379  free(poslist);
1380}  /* drawline */
1381
1382Local Void printree()
1383{
1384  /* prints out diagram of the tree */
1385  long tipy;
1386  long i;
1387
1388  if (!treeprint)
1389    return;
1390  tipy = 1;
1391  coordinates(root, &tipy,MaxChars);
1392  fprintf(outfile, "\n  Tree and");
1393  if (Factors)
1394    fprintf(outfile, " binary");
1395  fprintf(outfile, " characters:\n\n");
1396  fprintf(outfile, "   ");
1397  for (i = 0; i < (MaxChars); i++)
1398    fprintf(outfile, "%3ld", ChOrder[i]);
1399  fprintf(outfile, "\n   ");
1400  for (i = 0; i < (MaxChars); i++) {
1401    if (Rarer[ChOrder[i] - 1])
1402      fprintf(outfile, "%3c", '1');
1403    else
1404      fprintf(outfile, "%3c", '0');
1405  }
1406  fprintf(outfile, "\n\n");
1407  for (i = 1; i <= (tipy - down); i++)
1408    drawline(i);
1409  fprintf(outfile, "\nremember: this is an unrooted tree!\n\n");
1410}  /* printree */
1411
1412Local Void treeout(p, tcount)
1413node *p;
1414long tcount;
1415{
1416  /* write out file with representation of final tree */
1417  long i, n;
1418  Char c;
1419  node *q;
1420
1421  if (p->tip) {
1422    n = 0;
1423    for (i = 1; i <= NmLngth; i++) {
1424      if (Nayme[p->index - 1][i - 1] != ' ')
1425        n = i;
1426    }
1427    for (i = 0; i < n; i++) {
1428      c = Nayme[p->index - 1][i];
1429      if (c == ' ')
1430        c = '_';
1431      putc(c, treefile);
1432    }
1433    col += n;
1434  } else {
1435    q = p->next;
1436    putc('(', treefile);
1437    col++;
1438    while (q != p) {
1439      treeout(q->back, tcount);
1440      q = q->next;
1441      if (q == p)
1442        break;
1443      putc(',', treefile);
1444      col++;
1445      if (col > 72) {
1446        col = 0;
1447        putc('\n', treefile);
1448      }
1449    }
1450    putc(')', treefile);
1451    col++;
1452  }
1453  if (p != root)
1454    return;
1455  putc(';', treefile);
1456  if (tcount <= 1)
1457    putc('\n', treefile);
1458  else
1459    fprintf(treefile, "%7.4llf\n", 1.0 / tcount);
1460}  /* treeout */
1461
1462Local Void DoAll(Chars_, Processed, Rarer_, tcount)
1463boolean *Chars_, *Processed, *Rarer_;
1464long tcount;
1465{
1466  /* print out a clique and its tree */
1467  long i, j;
1468  ChPtr Count;
1469
1470  aChars = (aPtr)Malloc((long)NumChars*sizeof(boolean));
1471  SpOrder = (SpPtr)Malloc((long)NumSpp*sizeof(long));
1472  ChOrder = (ChPtr)Malloc((long)NumChars*sizeof(long));
1473  Count = (ChPtr)Malloc((long)NumChars*sizeof(long));
1474  memcpy(aChars, Chars_, NumChars*sizeof(boolean));
1475  Rarer = Rarer_;
1476  Init(ChOrder, Count, &MaxChars, aChars);
1477  ChSort(ChOrder, Count, MaxChars);
1478  for (i = 1; i <= (NumSpp); i++)
1479    SpOrder[i - 1] = i;
1480  for (i = 1; i <= (NumChars); i++) {
1481    if (aChars[ActChar[i - 1] - 1]) {
1482      if (!Processed[ActChar[i - 1] - 1]) {
1483        Rarer[i - 1] = Ingroupstate(i);
1484        Processed[ActChar[i - 1] - 1] = true;
1485      }
1486    }
1487  }
1488  PrintClique(aChars);
1489  grouping = (long **)Malloc(((long)(NumSpp + MaxChars))*sizeof(long *));
1490  for (i = 0; i < NumSpp + MaxChars; i++) {
1491    grouping[i] = (long *)Malloc(setsz*sizeof(long));
1492    for (j = 0; j < setsz; j++)
1493      grouping[i][j] = 0;
1494  }
1495  makeset();
1496  setuptree();
1497  reconstruct(n,MaxChars);
1498  if (noroot)
1499    reroot(treenode[outgrno - 1]);
1500  printree();
1501  if (trout) {
1502    col = 0;
1503    treeout(root, tcount);
1504  }
1505  free(SpOrder);
1506  free(ChOrder);
1507  free(Count);
1508  for (i = 0; i < NumSpp + MaxChars; i++)
1509    free(grouping[i]);
1510  free(grouping);
1511}  /* DoAll */
1512
1513Local Void Gen2(i, CurSize, aChars, Candidates, Excluded)
1514long i, CurSize;
1515boolean *aChars, *Candidates, *Excluded;
1516{
1517  /* finds largest size cliques and prints them out */
1518  long CurSize2, j, k, Actual, Possible;
1519  boolean Futile;
1520  vecrec *Chars2, *Cands2, *Excl2, *Cprime, *Exprime;
1521
1522  gnu(&Chars2);
1523  gnu(&Cands2);
1524  gnu(&Excl2);
1525  gnu(&Cprime);
1526  gnu(&Exprime);
1527  CurSize2 = CurSize;
1528  memcpy(Chars2->vec, aChars, NumChars*sizeof(boolean));
1529  memcpy(Cands2->vec, Candidates, NumChars*sizeof(boolean));
1530  memcpy(Excl2->vec, Excluded, NumChars*sizeof(boolean));
1531  j = i;
1532  while (j <= ActualChars) {
1533    if (Cands2->vec[j - 1]) {
1534      Chars2->vec[j - 1] = true;
1535      Cands2->vec[j - 1] = false;
1536      CurSize2 += weight[j - 1];
1537      Possible = CountStates(Cands2->vec);
1538      Intersect(Cands2->vec, Comp2[j - 1]->vec, Cprime->vec);
1539      Actual = CountStates(Cprime->vec);
1540      Intersect(Excl2->vec, Comp2[j - 1]->vec, Exprime->vec);
1541      Futile = false;
1542      for (k = 0; k <= j - 2; k++) {
1543        if (Exprime->vec[k] && !Futile) {
1544          Intersect(Cprime->vec, Comp2[k]->vec, Temp);
1545          Futile = (CountStates(Temp) == Actual);
1546        }
1547      }
1548      if (CurSize2 + Actual >= Cliqmin && !Futile) {
1549        if (Actual > 0)
1550          Gen2(j + 1,CurSize2,Chars2->vec,Cprime->vec,Exprime->vec);
1551        else
1552          DoAll(Chars2->vec,Processed,Rarer2,tcount);
1553      }
1554      if (Possible > Actual) {
1555        Chars2->vec[j - 1] = false;
1556        Excl2->vec[j - 1] = true;
1557        CurSize2 -= weight[j - 1];
1558      } else
1559        j = ActualChars;
1560    }
1561    j++;
1562  }
1563  chuck(Chars2);
1564  chuck(Cands2);
1565  chuck(Excl2);
1566  chuck(Cprime);
1567  chuck(Exprime);
1568}  /* Gen2 */
1569
1570
1571Static Void GetMaxCliques(Comp_)
1572vecrec **Comp_;
1573{
1574  /* recursively generates the largest cliques */
1575  long i;
1576  aPtr aChars, Candidates, Excluded;
1577
1578  Temp = (aPtr)Malloc((long)NumChars*sizeof(boolean));
1579  Processed = (aPtr)Malloc((long)NumChars*sizeof(boolean));
1580  Rarer2 = (aPtr)Malloc((long)NumChars*sizeof(boolean));
1581  aChars = (aPtr)Malloc((long)NumChars*sizeof(boolean));
1582  Candidates = (aPtr)Malloc((long)NumChars*sizeof(boolean));
1583  Excluded = (aPtr)Malloc((long)NumChars*sizeof(boolean));
1584  Comp2 = Comp_;
1585  putc('\n', outfile);
1586  if (Clmin) {
1587    fprintf(outfile, "Cliques with at least%3ld characters\n", Cliqmin);
1588    fprintf(outfile, "------- ---- -- ----- -- ----------\n");
1589  } else {
1590    Cliqmin = 0;
1591    fprintf(outfile, "Largest Cliques\n");
1592    fprintf(outfile, "------- -------\n");
1593    for (i = 0; i < (ActualChars); i++) {
1594      aChars[i] = false;
1595      Excluded[i] = false;
1596      Candidates[i] = true;
1597    }
1598    tcount = 0;
1599    Gen1(1, 0, aChars, Candidates, Excluded);
1600  }
1601  for (i = 0; i < (ActualChars); i++) {
1602    aChars[i] = false;
1603    Candidates[i] = true;
1604    Processed[i] = false;
1605    Excluded[i] = false;
1606  }
1607  Gen2(1, 0, aChars, Candidates, Excluded);
1608  putc('\n', outfile);
1609  free(Temp);
1610  free(Processed);
1611  free(Rarer2);
1612  free(aChars);
1613  free(Candidates);
1614  free(Excluded);
1615}  /* GetMaxCliques */
1616
1617
1618main(argc, argv)
1619int argc;
1620Char *argv[];
1621{  /* Main Program */
1622char infilename[100],outfilename[100],trfilename[100];
1623#ifdef MAC
1624   macsetup("Clique","Clique");
1625#endif
1626  openfile(&infile,INFILE,"r",argv[0],infilename);
1627  openfile(&outfile,OUTFILE,"w",argv[0],outfilename);
1628  openfile(&treefile,TREEFILE,"w",argv[0],trfilename);
1629  ibmpc = ibmpc0;
1630  ansi = ansi0;
1631  vt52 = vt520;
1632  mulsets = false;
1633  firstset = true;
1634  datasets = 1;
1635  doinit();
1636  setsz = (short)ceil(((double)NumSpp+1.0)/(double)SETBITS);
1637  ancone = (aPtr)Malloc((long)NumChars*sizeof(boolean));
1638  Factor = (Char *)Malloc((long)NumChars*sizeof(Char));
1639  ActChar = (long *)Malloc((long)NumChars*sizeof(long));
1640  oldweight = (long *)Malloc((long)NumChars*sizeof(long));
1641  weight = (long *)Malloc((long)NumChars*sizeof(long));
1642  Nayme = (Char **)Malloc((long)NumSpp*sizeof(Char *));
1643  for (j = 0; j < NumSpp; j++)
1644    Nayme[j] = (Char *)Malloc((long)NmLngth*sizeof(Char));
1645  for (ith = 1; ith <= (datasets); ith++) {
1646    ReadData();
1647    firstset = false;
1648    SetUp(Comp);
1649    if (datasets > 1) {
1650      fprintf(outfile, "Data set # %ld:\n\n",ith);
1651      if (progress)
1652        printf("\nData set # %ld:\n",ith);
1653    }
1654    GetMaxCliques(Comp);
1655    if (progress) {
1656      printf("\nOutput written to output file\n");
1657      if (trout)
1658        printf("\nTree(s) written on tree file\n\n");
1659    }
1660  }
1661  FClose(infile);
1662  FClose(outfile);
1663  FClose(treefile);
1664#ifdef MAC
1665  fixmacfile(outfilename);
1666  fixmacfile(trfilename);
1667#endif
1668  exit(0);
1669}
1670
1671
1672int eof(f)
1673FILE *f;
1674{
1675    register long ch;
1676
1677    if (feof(f))
1678        return 1;
1679    if (f == stdin)
1680        return 0;
1681    ch = getc(f);
1682    if (ch == EOF)
1683        return 1;
1684    ungetc(ch, f);
1685    return 0;
1686}
1687
1688
1689int eoln(f)
1690FILE *f;
1691{
1692    register long ch;
1693
1694    ch = getc(f);
1695    if (ch == EOF)
1696        return 1;
1697    ungetc(ch, f);
1698    return (ch == '\n');
1699}
1700
1701void memerror()
1702{
1703printf("Error allocating memory\n");
1704exit(-1);
1705}
1706
1707
1708MALLOCRETURN *mymalloc(x)
1709long x;
1710{
1711MALLOCRETURN *mem;
1712mem = (MALLOCRETURN *)malloc((size_t)x);
1713if (!mem)
1714  memerror();
1715else
1716  return (MALLOCRETURN *)mem;
1717}
1718
Note: See TracBrowser for help on using the repository browser.