source: trunk/GDE/PHYLIP/clique.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: 35.7 KB
Line 
1#include "phylip.h"
2#include "disc.h"
3
4/* version 3.6. (c) Copyright 1993-2002 by the University of Washington.
5   Written by Joseph Felsenstein, Jerry Shurman, Hisashi Horino,
6   Akiko Fuseki, Sean Lamont, and Andrew Keeffe.  Permission is granted
7   to copy and use this program provided no fee is charged for it and
8   provided that this copyright notice is not removed. */
9
10#define FormWide        80   /* width of outfile page */
11
12typedef boolean *aPtr;
13typedef long *SpPtr, *ChPtr;
14
15typedef struct vecrec {
16  aPtr vec;
17  struct vecrec *next;
18} vecrec;
19
20typedef vecrec **aDataPtr;
21typedef vecrec **Matrix;
22
23#ifndef OLDC
24/* function prototypes */
25void clique_gnu(vecrec **);
26void clique_chuck(vecrec *);
27void nunode(node **);
28void getoptions(void);
29void clique_setuptree(void);
30void allocrest(void);
31void doinit(void);
32void clique_inputancestors(void);
33void clique_printancestors(void);
34void clique_inputfactors(void);
35
36void inputoptions(void);
37void clique_inputdata(void);
38boolean Compatible(long, long);
39void SetUp(vecrec **);
40void Intersect(boolean *, boolean *, boolean *);
41long CountStates(boolean *);
42void Gen1(long , long, boolean *, boolean *, boolean *);
43boolean Ingroupstate(long );
44void makeset(void);
45void Init(long *, long *, long *, aPtr);
46
47void ChSort(long *, long *, long);
48void PrintClique(boolean *);
49void bigsubset(long *, long);
50void recontraverse(node **, long *, long, long);
51void reconstruct(long, long);
52void reroot(node *);
53void clique_coordinates(node *, long *, long);
54void clique_drawline(long);
55void clique_printree(void);
56void DoAll(boolean *, boolean *, boolean *, long);
57
58void Gen2(long, long, boolean *, boolean *, boolean *);
59void GetMaxCliques(vecrec **);
60/* function prototypes */
61#endif
62
63
64
65Char infilename[FNMLNGTH], outfilename[FNMLNGTH], outtreename[FNMLNGTH];
66long ActualChars, Cliqmin, outgrno,
67       col, ith, datasets, setsz;
68boolean ancvar, Clmin, Factors, outgropt, trout, weights, noroot,
69               printcomp, progress, treeprint, mulsets, firstset;
70long nodes;
71
72aPtr ancone;
73Char *Factor;
74long *ActChar, *oldweight;
75aDataPtr Data;
76Matrix global_Comp;     /* the character compatibility matrix      */
77node *root;
78long **grouping;
79pointptr treenode;   /* pointers to all nodes in tree              */
80vecrec *garbage;
81
82/* these variables are to DoAll in the pascal Version. */
83 aPtr global_aChars;
84 boolean *Rarer;
85 long global_n, MaxChars;
86 SpPtr SpOrder;
87 ChPtr global_ChOrder;
88
89/* variables for GetMaxCliques: */
90 vecrec **Comp2;
91 long tcount;
92 aPtr Temp, Processed, Rarer2;
93
94
95void clique_gnu(vecrec **p)
96{  /* this and the following are do-it-yourself garbage collectors.
97     Make a new node or pull one off the garbage list */
98
99 if (garbage != NULL) {
100    *p = garbage;
101    garbage = garbage->next;
102  } else {
103    *p = (vecrec *)Malloc((long)sizeof(vecrec));
104    (*p)->vec = (aPtr)Malloc((long)chars*sizeof(boolean));
105  }
106  (*p)->next = NULL;
107}  /* clique_gnu */
108
109
110void clique_chuck(vecrec *p)
111{  /* collect garbage on p -- put it on front of garbage list */
112
113 p->next = garbage;
114  garbage = p;
115}  /* clique_chuck */
116
117
118void nunode(node **p)
119{  /* replacement for NEW */
120  *p = (node *)Malloc((long)sizeof(node));
121  (*p)->next = NULL;
122  (*p)->tip = false;
123}  /* nunode */
124
125
126void getoptions(void)
127{
128  /* interactively set options */
129  long loopcount, loopcount2;
130  Char ch;
131  boolean done;
132
133  fprintf(outfile, "\nLargest clique program, version %s\n\n",VERSION);
134  putchar('\n');
135  ancvar = false;
136  Clmin = false;
137  Factors = false;
138  outgrno = 1;
139  outgropt = false;
140  trout = true;
141  weights = false;
142  printdata = false;
143  printcomp = false;
144  progress = true;
145  treeprint = true;
146  loopcount = 0;
147  do {
148    cleerhome();
149    printf("\nLargest clique program, version %s\n\n",VERSION);
150    printf("Settings for this run:\n");
151    printf("  A   Use ancestral states in input file?  %s\n",
152           (ancvar ? "Yes" : "No"));
153    printf("  C          Specify minimum clique size?");
154    if (Clmin)
155      printf("  Yes, at size%3ld\n", Cliqmin);
156    else
157      printf("  No\n");
158    printf("  O                        Outgroup root?  %s%3ld\n",
159           (outgropt ? "Yes, at species number" :
160                       "No, use as outgroup species"),outgrno);
161    printf("  M           Analyze multiple data sets?");
162    if (mulsets)
163      printf("  Yes, %2ld sets\n", datasets);
164    else
165      printf("  No\n");
166    printf("  0   Terminal type (IBM PC, ANSI, none)?  %s\n",
167           ibmpc ? "IBM PC" : ansi  ? "ANSI"   : "(none)");
168    printf("  1    Print out the data at start of run  %s\n",
169           (printdata ? "Yes" : "No"));
170    printf("  2  Print indications of progress of run  %s\n",
171           (progress ? "Yes" : "No"));
172    printf("  3        Print out compatibility matrix  %s\n",
173           (printcomp ? "Yes" : "No"));
174    printf("  4                        Print out tree  %s\n",
175           (treeprint ? "Yes" : "No"));
176    printf("  5       Write out trees onto tree file?  %s\n",
177           (trout ? "Yes" : "No"));
178    printf("\n  Y to accept these or type the letter for one to change\n");
179#ifdef WIN32
180    phyFillScreenColor();
181#endif
182    scanf("%c%*[^\n]", &ch);
183    getchar();
184    uppercase(&ch);
185    done = (ch == 'Y');
186    if (!done) {
187      if (strchr("OACM012345",ch) != NULL){
188        switch (ch) {
189
190        case 'A':
191          ancvar = !ancvar;
192          break;
193
194        case 'C':
195          Clmin = !Clmin;
196          if (Clmin) {
197            loopcount2 = 0;
198            do {
199              printf("Minimum clique size:\n");
200#ifdef WIN32
201              phyFillScreenColor();
202#endif
203              scanf("%ld%*[^\n]", &Cliqmin);
204              getchar();
205              countup(&loopcount2, 10);
206            } while (Cliqmin < 0);
207          }
208          break;
209
210        case 'O':
211          outgropt = !outgropt;
212          if (outgropt)
213            initoutgroup(&outgrno, spp);
214          break;
215
216        case 'M':
217          mulsets = !mulsets;
218          if (mulsets)
219            initdatasets(&datasets);
220          break;
221
222        case '0':
223          initterminal(&ibmpc, &ansi);
224          break;
225
226        case '1':
227          printdata = !printdata;
228          break;
229
230        case '2':
231          progress = !progress;
232          break;
233       
234        case '3':
235          printcomp = !printcomp;
236          break;
237
238        case '4':
239          treeprint = !treeprint;
240          break;
241
242        case '5':
243          trout = !trout;
244          break;
245        }
246      } else
247        printf("Not a possible option!\n");
248      countup(&loopcount, 100);
249    }
250  } while (!done);
251}  /* getoptions */
252
253
254void clique_setuptree(void)
255{
256  /* initialization of tree pointers, variables */
257  long i;
258
259  treenode = (pointptr)Malloc((long)spp*sizeof(node *));
260  for (i = 0; i < spp; i++) {
261    treenode[i] = (node *)Malloc((long)sizeof(node));
262    treenode[i]->next = NULL;
263    treenode[i]->back = NULL;
264    treenode[i]->index = i + 1;
265    treenode[i]->tip = false;
266  }
267}  /* clique_setuptree */
268
269
270void allocrest(void)
271{
272  long i;
273
274  Data = (aDataPtr)Malloc((long)spp*sizeof(vecrec *));
275  for (i = 0; i < (spp); i++)
276    clique_gnu(&Data[i]);
277  global_Comp = (Matrix)Malloc((long)chars*sizeof(vecrec *));
278  for (i = 0; i < (chars); i++)
279    clique_gnu(&global_Comp[i]);
280  setsz = (long)ceil(((double)spp+1.0)/(double)SETBITS);
281  ancone = (aPtr)Malloc((long)chars*sizeof(boolean));
282  Factor = (Char *)Malloc((long)chars*sizeof(Char));
283  ActChar = (long *)Malloc((long)chars*sizeof(long));
284  oldweight = (long *)Malloc((long)chars*sizeof(long));
285  weight = (long *)Malloc((long)chars*sizeof(long));
286  nayme = (naym *)Malloc((long)spp*sizeof(naym));
287}  /* allocrest */
288
289
290void doinit(void)
291{
292  /* initializes variables */
293
294  inputnumbersold(&spp, &chars, &nonodes, 1);
295  getoptions();
296  if (printdata)
297    fprintf(outfile, "%2ld species, %3ld  characters\n", spp, chars);
298  clique_setuptree();
299  allocrest();
300}  /* doinit */
301
302
303void clique_inputancestors(void)
304{
305  /* reads the ancestral states for each character */
306  long i;
307  Char ch;
308
309  for (i = 1; i < nmlngth; i++)
310    gettc(infile);
311  for (i = 0; i < (chars); i++) {
312    do {
313      if (eoln(infile)) 
314        scan_eoln(infile);
315      ch = gettc(infile);
316    } while (ch == ' ');
317    switch (ch) {
318   
319    case '1':
320      ancone[i] = true;
321      break;
322
323    case '0':
324      ancone[i] = false;
325      break;
326   
327    default:
328      printf("BAD ANCESTOR STATE: %c AT CHARACTER %4ld\n", ch, i + 1);
329      exxit(-1);
330    }
331  }
332  scan_eoln(infile);
333}  /* clique_inputancestors */
334
335
336void clique_printancestors(void)
337{
338  /* print out list of ancestral states */
339  long i;
340
341  fprintf(outfile, "Ancestral states:\n");
342  for (i = 1; i <= nmlngth + 2; i++)
343    putc(' ', outfile);
344  for (i = 1; i <= (chars); i++) {
345    newline(outfile, i, 55, (long)nmlngth + 1);
346    if (ancone[i - 1])
347      putc('1', outfile);
348    else
349      putc('0', outfile);
350    if (i % 5 == 0)
351      putc(' ', outfile);
352  }
353  fprintf(outfile, "\n\n");
354}  /* clique_printancestors */
355
356
357void clique_inputfactors(void)
358{
359  /* reads the factor symbols */
360  long i;
361
362  ActualChars = 1;
363  for (i = 1; i < nmlngth; i++)
364    gettc(infile);
365  for (i = 1; i <= (chars); i++) {
366    if (eoln(infile)) 
367      scan_eoln(infile);
368    Factor[i - 1] = gettc(infile);
369    if (i > 1) {
370      if (Factor[i - 1] != Factor[i - 2])
371        ActualChars++;
372    }
373    ActChar[i - 1] = ActualChars;
374  }
375  scan_eoln(infile);
376  Factors = true;
377}  /* clique_inputfactors */
378
379
380void inputoptions(void)
381{
382  /* reads the species names and character data */
383  long i, Extranum;
384  Char ch;
385  boolean avar;
386
387  if (!firstset)
388    samenumsp(&chars, ith);
389  avar = false;
390  ActualChars = chars;
391  for (i = 1; i <= (chars); i++)
392    ActChar[i - 1] = i;
393  for (i = 0; i < (chars); i++)
394    oldweight[i] = 1;
395  Extranum = 0;
396  while (!(eoln(infile))) {
397    ch = gettc(infile);
398    uppercase(&ch);
399    if (ch == 'A' || ch == 'F' || ch == 'W')
400      Extranum++;
401    else if (ch != ' ') {
402      printf("BAD OPTION CHARACTER: %c\n", ch);
403      putc('\n', outfile);
404      exxit(-1);
405    }
406  }
407  scan_eoln(infile);
408  for (i = 1; i <= Extranum; i++) {
409    ch = gettc(infile);
410    uppercase(&ch);
411    if (ch != 'A' && ch != 'F' && ch != 'W') {
412      printf("\n\nERROR: Incorrect auxiliary options line");
413      printf(" which starts with %c\n\n", ch);
414      }
415    if (ch == 'A') {
416      avar = true;
417      if (!ancvar) {
418        printf("\n\nERROR: Ancestor option not chosen in menu");
419        printf(" with option %c in input\n\n",ch);
420        exxit(-1);
421      } else
422        clique_inputancestors();
423    }
424    if (ch == 'F')
425      clique_inputfactors();
426    if (ch == 'W')
427      inputweightsold(chars, oldweight, &weights);
428  }
429  if (ancvar && !avar) {
430    printf("\n\nERROR: Ancestor option chosen in menu");
431    printf(" with no option A in input\n\n");
432    exxit(-1);
433  }
434  if (weights && printdata)
435    printweights(outfile, 0, ActualChars, oldweight, "Characters");
436  if (Factors)
437    printfactors(outfile, chars, Factor, "");
438  if (ancvar && avar && printdata)
439    clique_printancestors();
440  noroot = !(outgropt || (ancvar && avar));
441} /* inputoptions */
442
443
444void clique_inputdata(void)
445{
446  long i, j;
447  Char ch;
448
449  j = chars / 2 + (chars / 5 - 1) / 2 - 5;
450  if (j < 0)
451    j = 0;
452  if (j > 27)
453    j = 27;
454  if (printdata) {
455    fprintf(outfile, "Species  ");
456    for (i = 1; i <= j; i++)
457      putc(' ', outfile);
458    fprintf(outfile, "Character states\n");
459    fprintf(outfile, "-------  ");
460    for (i = 1; i <= j; i++)
461      putc(' ', outfile);
462    fprintf(outfile, "--------- ------\n\n");
463  }
464  for (i = 0; i < (spp); i++) {
465    initname(i);
466    if (printdata)
467      for (j = 0; j < nmlngth; j++)
468        putc(nayme[i][j], outfile);
469    if (printdata)
470      fprintf(outfile, "  ");
471    for (j = 1; j <= (chars); j++) {
472      do {
473        if (eoln(infile)) 
474          scan_eoln(infile);
475        ch = gettc(infile);
476      } while (ch == ' ');
477      if (printdata) {
478        putc(ch, outfile);
479        newline(outfile, j, 55, (long)nmlngth + 1);
480        if (j % 5 == 0)
481          putc(' ', outfile);
482      }
483      if (ch != '0' && ch != '1') {
484        printf("\n\nERROR: Bad character state: %c (not 0 or 1)", ch);
485        printf(" at character %ld of species %ld\n\n", j, i + 1);
486        exxit(-1);
487      }
488      Data[i]->vec[j - 1] = (ch == '1');
489    }
490    scan_eoln(infile);
491    if (printdata)
492      putc('\n', outfile);
493  }
494  putc('\n', outfile);
495  for (i = 0; i < (chars); i++) {
496    if (i + 1 == 1 || !Factors)
497      weight[i] = oldweight[i];
498    else if (Factor[i] != Factor[i - 1])
499      weight[ActChar[i] - 1] = oldweight[i];
500  }
501}  /* clique_inputdata */
502
503
504boolean Compatible(long ch1, long ch2)
505{
506  /* TRUE if two characters ch1 < ch2 are compatible */
507  long i, j, k;
508  boolean Compt, Done1, Done2;
509  boolean Info[4];
510
511  Compt = true;
512  j = 1;
513  while (ch1 > ActChar[j - 1])
514    j++;
515  Done1 = (ch1 != ActChar[j - 1]);
516  while (!Done1) {
517    k = j;
518    while (ch2 > ActChar[k - 1])
519      k++;
520    Done2 = (ch2 != ActChar[k - 1]);
521    while (!Done2) {
522      for (i = 0; i <= 3; i++)
523        Info[i] = false;
524      if (ancvar) {
525        if (ancone[j - 1] && ancone[k - 1])
526          Info[0] = true;
527        else if (ancone[j - 1] && !ancone[k - 1])
528          Info[1] = true;
529        else if (!ancone[j - 1] && ancone[k - 1])
530          Info[2] = true;
531        else
532          Info[3] = true;
533      }
534      for (i = 0; i < (spp); i++) {
535        if (Data[i]->vec[j - 1] && Data[i]->vec[k - 1])
536          Info[0] = true;
537        else if (Data[i]->vec[j - 1] && !Data[i]->vec[k - 1])
538          Info[1] = true;
539        else if (!Data[i]->vec[j - 1] && Data[i]->vec[k - 1])
540          Info[2] = true;
541        else
542          Info[3] = true;
543      }
544      Compt = (Compt && !(Info[0] && Info[1] && Info[2] && Info[3]));
545      k++;
546      Done2 = (k > chars);
547      if (!Done2)
548        Done2 = (ch2 != ActChar[k - 1]);
549    }
550    j++;
551    Done1 = (j > chars);
552    if (!Done1)
553      Done1 = (ch1 != ActChar[j - 1]);
554  }
555  return Compt;
556}  /* Compatible */
557
558
559void SetUp(vecrec **Comp)
560{
561  /* sets up the compatibility matrix */
562  long i, j;
563
564  if (printcomp) {
565    if (Factors)
566      fprintf(outfile, "      (For original multistate characters)\n");
567    fprintf(outfile, "Character Compatibility Matrix (1 if compatible)\n");
568    fprintf(outfile, "--------- ------------- ------ -- -- -----------\n\n");
569  }
570  for (i = 0; i < (ActualChars); i++) {
571    if (printcomp) {
572      for (j = 1; j <= ((48 - ActualChars) / 2); j++)
573        putc(' ', outfile);
574      for (j = 1; j < i + 1; j++) {
575        if (Comp[i]->vec[j - 1])
576          putc('1', outfile);
577        else
578          putc('.', outfile);
579        newline(outfile, j, 70, (long)nmlngth + 1);
580      }
581    }
582    Comp[i]->vec[i] = true;
583    if (printcomp)
584      putc('1', outfile);
585    for (j = i + 1; j < (ActualChars); j++) {
586      Comp[i]->vec[j] = Compatible(i + 1, j + 1);
587      if (printcomp) {
588        if (Comp[i]->vec[j])
589          putc('1', outfile);
590        else
591          putc('.', outfile);
592      }
593      Comp[j]->vec[i] = Comp[i]->vec[j];
594    }
595    if (printcomp)
596      putc('\n', outfile);
597  }
598  putc('\n', outfile);
599}  /* SetUp */
600
601
602void Intersect(boolean *V1, boolean *V2, boolean *V3)
603{
604  /* takes the logical intersection V1 AND V2 */
605  long i;
606
607  for (i = 0; i < (ActualChars); i++)
608    V3[i] = (V1[i] && V2[i]);
609}  /* Intersect */
610
611
612long CountStates(boolean *V)
613{
614  /* counts the 1's in V */
615  long i, TempCount;
616
617  TempCount = 0;
618  for (i = 0; i < (ActualChars); i++) {
619    if (V[i])
620      TempCount += weight[i];
621  }
622  return TempCount;
623}  /* CountStates */
624
625
626void Gen1(long i, long CurSize, boolean *aChars, boolean *Candidates,
627                        boolean *Excluded)
628{
629  /* finds largest size cliques and prints them out */
630  long CurSize2, j, k, Actual, Possible;
631  boolean Futile;
632  vecrec *Chars2, *Cands2, *Excl2, *Cprime, *Exprime;
633
634  clique_gnu(&Chars2);
635  clique_gnu(&Cands2);
636  clique_gnu(&Excl2);
637  clique_gnu(&Cprime);
638  clique_gnu(&Exprime);
639  CurSize2 = CurSize;
640  memcpy(Chars2->vec, aChars, chars*sizeof(boolean));
641  memcpy(Cands2->vec, Candidates, chars*sizeof(boolean));
642  memcpy(Excl2->vec, Excluded, chars*sizeof(boolean));
643  j = i;
644  while (j <= ActualChars) {
645    if (Cands2->vec[j - 1]) {
646      Chars2->vec[j - 1] = true;
647      Cands2->vec[j - 1] = false;
648      CurSize2 += weight[j - 1];
649      Possible = CountStates(Cands2->vec);
650      Intersect(Cands2->vec, Comp2[j - 1]->vec, Cprime->vec);
651      Actual = CountStates(Cprime->vec);
652      Intersect(Excl2->vec, Comp2[j - 1]->vec, Exprime->vec);
653      Futile = false;
654      for (k = 0; k <= j - 2; k++) {
655        if (Exprime->vec[k] && !Futile) {
656          Intersect(Cprime->vec, Comp2[k]->vec, Temp);
657          Futile = (CountStates(Temp) == Actual);
658        }
659      }
660      if (CurSize2 + Actual >= Cliqmin && !Futile) {
661        if (Actual > 0)
662          Gen1(j + 1,CurSize2,Chars2->vec,Cprime->vec,Exprime->vec);
663        else if (CurSize2 > Cliqmin) {
664          Cliqmin = CurSize2;
665          if (tcount >= 0)
666            tcount = 1;
667        } else if (CurSize2 == Cliqmin)
668          tcount++;
669      }
670      if (Possible > Actual) {
671        Chars2->vec[j - 1] = false;
672        Excl2->vec[j - 1] = true;
673        CurSize2 -= weight[j - 1];
674      } else
675        j = ActualChars;
676    }
677    j++;
678  }
679  clique_chuck(Chars2);
680  clique_chuck(Cands2);
681  clique_chuck(Excl2);
682  clique_chuck(Cprime);
683  clique_chuck(Exprime);
684}  /* Gen1 */
685
686
687boolean Ingroupstate(long i)
688{
689  /* the ingroup state for the i-th character */
690  boolean outstate;
691
692  if (noroot) {
693    outstate = Data[0]->vec[i - 1];
694    return (!outstate);
695  }
696  if (ancvar)
697    outstate = ancone[i - 1];
698  else
699    outstate = Data[outgrno - 1]->vec[i - 1];
700  return (!outstate);
701}  /* Ingroupstate */
702
703
704void makeset(void)
705{
706  /* make up set of species for given set of characters */
707  long i, j, k, m;
708  boolean instate;
709  long *st;
710
711  st = (long *)Malloc(setsz*sizeof(long));
712  global_n = 0;
713  for (i = 0; i < (MaxChars); i++) {
714    for (j = 0; j < setsz; j++)
715      st[j] = 0;
716    instate = Ingroupstate(global_ChOrder[i]);
717    for (j = 0; j < (spp); j++) {
718      if (Data[SpOrder[j] - 1]->vec[global_ChOrder[i] - 1] == instate) {
719        m = (long)(SpOrder[j]/SETBITS);
720        st[m] = ((long)st[m]) | (1L << (SpOrder[j] % SETBITS));
721      }
722    }
723    memcpy(grouping[++global_n - 1], st, setsz*sizeof(long));
724  }
725  for (i = 0; i < (spp); i++) {
726    k = (long)(SpOrder[i]/SETBITS);
727    grouping[++global_n - 1][k] = 1L << (SpOrder[i] % SETBITS);
728  }
729  free(st);
730}  /* makeset */
731
732
733void Init(long *ChOrder, long *Count, long *local_MaxChars, aPtr aChars)
734{
735  /* initialize vectors and character count */
736  long i, j, temp;
737  boolean instate;
738
739  *local_MaxChars = 0;
740  for (i = 1; i <= (chars); i++) {
741    if (aChars[ActChar[i - 1] - 1]) {
742      (*local_MaxChars)++;
743      ChOrder[*local_MaxChars - 1] = i;
744      instate = Ingroupstate(i);
745      temp = 0;
746      for (j = 0; j < (spp); j++) {
747        if (Data[j]->vec[i - 1] == instate)
748          temp++;
749      }
750      Count[i - 1] = temp;
751    }
752  }
753}  /*Init */
754
755
756void ChSort(long *ChOrder, long *Count, long local_MaxChars)
757{
758  /* sorts the characters by number of ingroup states */
759  long j, temp;
760  boolean ordered;
761
762  ordered = false;
763  while (!ordered) {
764    ordered = true;
765    for (j = 1; j < local_MaxChars; j++) {
766      if (Count[ChOrder[j - 1] - 1] < Count[ChOrder[j] - 1]) {
767        ordered = false;
768        temp = ChOrder[j - 1];
769        ChOrder[j - 1] = ChOrder[j];
770        ChOrder[j] = temp;
771      }
772    }
773  }
774}  /* ChSort */
775
776
777void PrintClique(boolean *aChars)
778{
779  /* prints the characters in a clique */
780  long i, j;
781  fprintf(outfile, "\n\n");
782  if (Factors) {
783    fprintf(outfile, "Actual Characters: (");
784    j = 0;
785    for (i = 1; i <= (ActualChars); i++) {
786      if (aChars[i - 1]) {
787        fprintf(outfile, "%3ld", i);
788        j++;
789        newline(outfile, j, (long)((FormWide - 22) / 3),
790                                (long)nmlngth + 1);
791      }
792    }
793    fprintf(outfile, ")\n");
794  }
795  if (Factors)
796    fprintf(outfile, "Binary ");
797  fprintf(outfile, "Characters: (");
798  j = 0;
799  for (i = 1; i <= (chars); i++) {
800    if (aChars[ActChar[i - 1] - 1]) {
801      fprintf(outfile, "%3ld", i);
802      j++;
803      if (Factors)
804        newline(outfile, j, (long)((FormWide - 22) / 3), 
805                                (long)nmlngth + 1);
806      else
807        newline(outfile, j, (long)((FormWide - 15) / 3), 
808                                (long)nmlngth + 1);
809    }
810  }
811  fprintf(outfile, ")\n\n");
812}  /* PrintClique */
813
814
815void bigsubset(long *st, long n)
816{
817  /* find a maximal subset of st among the groupings */
818  long i, j;
819  long *su;
820  boolean max, same;
821
822  su = (long *)Malloc(setsz*sizeof(long));
823  for (i = 0; i < setsz; i++)
824    su[i] = 0;
825  for (i = 0; i < n; i++) {
826    max = true;
827    for (j = 0; j < setsz; j++)
828      if ((grouping[i][j] & ~st[j]) != 0)
829       max = false;
830    if (max) {
831      same = true;
832      for (j = 0; j < setsz; j++)
833        if (grouping[i][j] != st[j])
834          same = false;
835      if (!same) {
836        for (j = 0; j < setsz; j++)
837          if ((su[j] & ~grouping[i][j]) != 0)
838            max = false;
839        if (max) {
840          same = true;
841          for (j = 0; j < setsz; j++)
842            if (grouping[i][j] != su[j])
843              same = false;
844          if (!same)
845            memcpy(su, grouping[i], setsz*sizeof(long));
846        }
847      }
848    }
849  }
850  memcpy(st, su, setsz*sizeof(long));
851  free(su);
852}  /* bigsubset */
853
854
855void recontraverse(node **p, long *st, long n, long local_MaxChars)
856{
857  /* traverse to reconstruct the tree from the characters */
858  long i, j, k, maxpos;
859  long *tempset, *st2;
860  boolean found, zero, zero2, same;
861  node *q;
862
863  j = k = 0;
864  for (i = 1; i <= (spp); i++) {
865    if (((1L << (i % SETBITS)) & st[(long)(i / SETBITS)]) != 0) {
866      k++;
867      j = i;
868    }
869  }
870  if (k == 1) {
871    *p = treenode[j - 1];
872    (*p)->tip = true;
873    (*p)->index = j;
874    return;
875  }
876  nunode(p);
877  (*p)->index = 0;
878  tempset = (long*)Malloc(setsz*sizeof(long));
879  memcpy(tempset, st, setsz*sizeof(long));
880  q = *p;
881  zero = true;
882  for (i = 0; i < setsz; i++)
883    if (tempset[i] != 0)
884      zero = false;
885  if (!zero)
886    bigsubset(tempset, n);
887  zero = true;
888  zero2 = true;
889  for (i = 0; i < setsz; i++)
890    if (st[i] != 0)
891      zero = false;
892  if (!zero) {
893    for (i = 0; i < setsz; i++)
894      if (tempset[i] != 0)
895        zero2 = false;
896  }
897  st2 = (long *)Malloc(setsz*sizeof(long));
898  memcpy(st2, st, setsz*sizeof(long));
899  while (!zero2) {
900    nunode(&q->next);
901    q = q->next;
902    recontraverse(&q->back, tempset, n,local_MaxChars);
903    i = 1;
904    maxpos = 0;
905    while (i <= local_MaxChars) {
906      same = true;
907      for (j = 0; j < setsz; j++)
908        if (grouping[i - 1][j] != tempset[j])
909          same = false;
910      if (same)
911        maxpos = i;
912      i++;
913    }
914    q->back->maxpos = maxpos;
915    q->back->back = q;
916    for (j = 0; j < setsz; j++)
917      st2[j] &= ~tempset[j];
918    memcpy(tempset, st2, setsz*sizeof(long));
919    found = false;
920    i = 1;
921    while (!found && i <= n) {
922      same = true;
923      for (j = 0; j < setsz; j++)
924        if (grouping[i - 1][j] != tempset[j])
925          same = false;
926      if (same)
927        found = true;
928      else
929        i++;
930    }
931    zero = true;
932    for (j = 0; j < setsz; j++)
933      if (tempset[j] != 0)
934        zero = false;
935    if (!zero && !found)
936      bigsubset(tempset, n);
937    zero = true;
938    zero2 = true;
939    for (j = 0; j < setsz; j++)
940      if (st2[j] != 0)
941        zero = false;
942    if (!zero)
943      for (j = 0; j < setsz; j++)
944        if (tempset[j] != 0)
945          zero2 = false;
946}
947  q->next = *p;
948  free(tempset);
949  free(st2);
950}  /* recontraverse */
951
952
953void reconstruct(long n, long local_MaxChars)
954{  /* reconstruct tree from the subsets */
955  long i;
956  long *s;
957  s = (long *)Malloc(setsz*sizeof(long));
958  for (i = 0; i < setsz; i++) {
959    if (i+1 == setsz) {
960      s[i] = 1L << ((spp % SETBITS) + 1);
961      if (setsz > 1)
962        s[i] -= 1;
963      else s[i] -= 1L << 1;
964    }
965    else if (i == 0) {
966      if (setsz > 1)
967        s[i] = ~0L - 1;
968    }
969    else {
970      if (setsz > 2)
971        s[i] = ~0L;
972    }
973  }
974  recontraverse(&root,s,n,local_MaxChars);
975  free(s);
976}  /* reconstruct */
977
978
979void reroot(node *outgroup)
980{
981  /* reorients tree, putting outgroup in desired position. */
982  long i;
983  boolean nroot;
984  node *p, *q;
985
986  nroot = false;
987  p = root->next;
988  while (p != root) {
989    if (outgroup->back == p) {
990      nroot = true;
991      p = root;
992    } else
993      p = p->next;
994  }
995  if (nroot)
996    return;
997  p = root;
998  i = 0;
999  while (p->next != root) {
1000    p = p->next;
1001    i++;
1002  }
1003  if (i == 2) {
1004    root->next->back->back = p->back;
1005    p->back->back = root->next->back;
1006    q = root->next;
1007  } else {
1008    p->next = root->next;
1009    nunode(&root->next);
1010    q = root->next;
1011    nunode(&q->next);
1012    p = q->next;
1013    p->next = root;
1014    q->tip = false;
1015    p->tip = false;
1016  }
1017  q->back = outgroup;
1018  p->back = outgroup->back;
1019  outgroup->back->back = p;
1020  outgroup->back = q;
1021}  /* reroot */
1022
1023
1024void clique_coordinates(node *p, long *tipy, long local_MaxChars)
1025{
1026  /* establishes coordinates of nodes */
1027  node *q, *first, *last;
1028  long maxx;
1029
1030  if (p->tip) {
1031    p->xcoord = 0;
1032    p->ycoord = *tipy;
1033    p->ymin = *tipy;
1034    p->ymax = *tipy;
1035    (*tipy) += down;
1036    return;
1037  }
1038  q = p->next;
1039  maxx = 0;
1040  while (q != p) {
1041    clique_coordinates(q->back, tipy, local_MaxChars);
1042    if (!q->back->tip) {
1043      if (q->back->xcoord > maxx)
1044        maxx = q->back->xcoord;
1045    }
1046    q = q->next;
1047  }
1048  first = p->next->back;
1049  q = p;
1050  while (q->next != p)
1051    q = q->next;
1052  last = q->back;
1053  p->xcoord = (local_MaxChars - p->maxpos) * 3 - 2;
1054  if (p == root)
1055    p->xcoord += 2;
1056  p->ycoord = (first->ycoord + last->ycoord) / 2;
1057  p->ymin = first->ymin;
1058  p->ymax = last->ymax;
1059}  /* clique_coordinates */
1060
1061
1062void clique_drawline(long i)
1063{
1064  /* draws one row of the tree diagram by moving up tree */
1065  node *p, *q;
1066  long n, m, j, k, l, sumlocpos, size, locpos, branchpos;
1067  long *poslist;
1068  boolean extra, done, plus, found, same;
1069  node *r, *first = NULL, *last = NULL;
1070
1071  poslist = (long *)Malloc((long)(spp + MaxChars)*sizeof(long));
1072  branchpos = 0;
1073  p = root;
1074  q = root;
1075  fprintf(outfile, "  ");
1076  extra = false;
1077  plus = false;
1078  do {
1079    if (!p->tip) {
1080      found = false;
1081      r = p->next;
1082      while (r != p && !found) {
1083        if (i >= r->back->ymin && i <= r->back->ymax) {
1084          q = r->back;
1085          found = true;
1086        } else
1087          r = r->next;
1088      }
1089      first = p->next->back;
1090      r = p;
1091      while (r->next != p)
1092        r = r->next;
1093      last = r->back;
1094    }
1095    done = (p->tip || p == q);
1096    n = p->xcoord - q->xcoord;
1097    m = n;
1098    if (extra) {
1099      n--;
1100      extra = false;
1101    }
1102    if ((long)q->ycoord == i && !done) {
1103      if (!q->tip) {
1104        putc('+', outfile);
1105        plus = true;
1106        j = 1;
1107        for (k = 1; k <= (q->maxpos); k++) {
1108          same = true;
1109          for (l = 0; l < setsz; l++)
1110            if (grouping[k - 1][l] != grouping[q->maxpos - 1][l])
1111              same = false;
1112          if (same) {
1113            poslist[j - 1] = k;
1114            j++;
1115          }
1116        }
1117        size = j - 1;
1118        if (size == 0) {
1119          for (k = 1; k < n; k++)
1120            putc('-', outfile);
1121          sumlocpos = n;
1122        } else {
1123          sumlocpos = 0;
1124          j = 1;
1125          while (j <= size) {
1126            locpos = poslist[j - 1] * 3;
1127            if (j != 1)
1128              locpos -= poslist[j - 2] * 3;
1129            else
1130              locpos -= branchpos;
1131            for (k = 1; k < locpos; k++)
1132              putc('-', outfile);
1133            if (Rarer[global_ChOrder[poslist[j - 1] - 1] - 1])
1134              putc('1', outfile);
1135            else
1136              putc('0', outfile);
1137            sumlocpos += locpos;
1138            j++;
1139          }
1140          for (j = sumlocpos + 1; j < n; j++)
1141            putc('-', outfile);
1142          putc('+', outfile);
1143          if (m > 0)
1144            branchpos += m;
1145          extra = true;
1146        }
1147      } else {
1148        if (!plus) {
1149          putc('+', outfile);
1150          plus = false;
1151        } else
1152          n++;
1153        j = 1;
1154        for (k = 1; k <= (q->maxpos); k++) {
1155          same = true;
1156          for (l = 0; l < setsz; l++)
1157             if (grouping[k - 1][l] != grouping[q->maxpos - 1][l])
1158              same = false;
1159          if (same) {
1160            poslist[j - 1] = k;
1161            j++;
1162          }
1163        }
1164        size = j - 1;
1165        if (size == 0) {
1166          for (k = 1; k <= n; k++)
1167            putc('-', outfile);
1168          sumlocpos = n;
1169        } else {
1170          sumlocpos = 0;
1171          j = 1;
1172          while (j <= size) {
1173            locpos = poslist[j - 1] * 3;
1174            if (j != 1)
1175              locpos -= poslist[j - 2] * 3;
1176            else
1177              locpos -= branchpos;
1178            for (k = 1; k < locpos; k++)
1179              putc('-', outfile);
1180            if (Rarer[global_ChOrder[poslist[j - 1] - 1] - 1])
1181              putc('1', outfile);
1182            else
1183              putc('0', outfile);
1184            sumlocpos += locpos;
1185            j++;
1186          }
1187          for (j = sumlocpos + 1; j <= n; j++)
1188            putc('-', outfile);
1189          if (m > 0)
1190            branchpos += m;
1191        }
1192        putc('-', outfile);
1193      }
1194    } else if (!p->tip && (long)last->ycoord > i && (long)first->ycoord < i &&
1195               (i != (long)p->ycoord || p == root)) {
1196      putc('!', outfile);
1197      for (j = 1; j < n; j++)
1198        putc(' ', outfile);
1199      plus = false;
1200      if (m > 0)
1201        branchpos += m;
1202    } else {
1203      for (j = 1; j <= n; j++)
1204        putc(' ', outfile);
1205      plus = false;
1206      if (m > 0)
1207        branchpos += m;
1208    }
1209    if (q != p)
1210      p = q;
1211  } while (!done);
1212  if (p->ycoord == i && p->tip) {
1213    for (j = 0; j < nmlngth; j++)
1214      putc(nayme[p->index - 1][j], outfile);
1215}
1216  putc('\n', outfile);
1217  free(poslist);
1218}  /* clique_drawline */
1219
1220
1221void clique_printree(void)
1222{
1223  /* prints out diagram of the tree */
1224  long tipy, i;
1225
1226  if (!treeprint)
1227    return;
1228  tipy = 1;
1229  clique_coordinates(root, &tipy, MaxChars);
1230  fprintf(outfile, "\n  Tree and");
1231  if (Factors)
1232    fprintf(outfile, " binary");
1233  fprintf(outfile, " characters:\n\n");
1234  fprintf(outfile, "   ");
1235  for (i = 0; i < (MaxChars); i++)
1236    fprintf(outfile, "%3ld", global_ChOrder[i]);
1237  fprintf(outfile, "\n   ");
1238  for (i = 0; i < (MaxChars); i++) {
1239    if (Rarer[global_ChOrder[i] - 1])
1240      fprintf(outfile, "%3c", '1');
1241    else
1242      fprintf(outfile, "%3c", '0');
1243  }
1244  fprintf(outfile, "\n\n");
1245  for (i = 1; i <= (tipy - down); i++)
1246    clique_drawline(i);
1247  fprintf(outfile, "\nremember: this is an unrooted tree!\n\n");
1248}  /* clique_printree */
1249
1250
1251void DoAll(boolean *Chars_,boolean *local_Processed,boolean *Rarer_,long local_tcount)
1252{
1253  /* print out a clique and its tree */
1254  long i, j;
1255  ChPtr Count;
1256
1257  global_aChars = (aPtr)Malloc((long)chars*sizeof(boolean));
1258  SpOrder = (SpPtr)Malloc((long)spp*sizeof(long));
1259  global_ChOrder = (ChPtr)Malloc((long)chars*sizeof(long));
1260  Count = (ChPtr)Malloc((long)chars*sizeof(long));
1261  memcpy(global_aChars, Chars_, chars*sizeof(boolean));
1262  Rarer = Rarer_;
1263  Init(global_ChOrder, Count, &MaxChars, global_aChars);
1264  ChSort(global_ChOrder, Count, MaxChars);
1265  for (i = 1; i <= (spp); i++)
1266    SpOrder[i - 1] = i;
1267  for (i = 1; i <= (chars); i++) {
1268    if (global_aChars[ActChar[i - 1] - 1]) {
1269      if (!local_Processed[ActChar[i - 1] - 1]) {
1270        Rarer[i - 1] = Ingroupstate(i);
1271        local_Processed[ActChar[i - 1] - 1] = true;
1272      }
1273    }
1274  }
1275  PrintClique(global_aChars);
1276  grouping = (long **)Malloc((long)(spp + MaxChars)*sizeof(long *));
1277  for (i = 0; i < spp + MaxChars; i++) {
1278    grouping[i] = (long *)Malloc(setsz*sizeof(long));
1279    for (j = 0; j < setsz; j++)
1280      grouping[i][j] = 0;
1281  }
1282  makeset();
1283  clique_setuptree();
1284  reconstruct(global_n,MaxChars);
1285  if (noroot)
1286    reroot(treenode[outgrno - 1]);
1287  clique_printree();
1288  if (trout) {
1289    col = 0;
1290    treeout(root, local_tcount+1, &col, root);
1291  }
1292  free(SpOrder);
1293  free(global_ChOrder);
1294  free(Count);
1295  for (i = 0; i < spp + MaxChars; i++)
1296    free(grouping[i]);
1297  free(grouping);
1298}  /* DoAll */
1299
1300
1301void Gen2(long i, long CurSize, boolean *aChars, boolean *Candidates,
1302                        boolean *Excluded)
1303{
1304  /* finds largest size cliques and prints them out */
1305  long CurSize2, j, k, Actual, Possible;
1306  boolean Futile;
1307  vecrec *Chars2, *Cands2, *Excl2, *Cprime, *Exprime;
1308
1309  clique_gnu(&Chars2);
1310  clique_gnu(&Cands2);
1311  clique_gnu(&Excl2);
1312  clique_gnu(&Cprime);
1313  clique_gnu(&Exprime);
1314  CurSize2 = CurSize;
1315  memcpy(Chars2->vec, aChars, chars*sizeof(boolean));
1316  memcpy(Cands2->vec, Candidates, chars*sizeof(boolean));
1317  memcpy(Excl2->vec, Excluded, chars*sizeof(boolean));
1318  j = i;
1319  while (j <= ActualChars) {
1320    if (Cands2->vec[j - 1]) {
1321      Chars2->vec[j - 1] = true;
1322      Cands2->vec[j - 1] = false;
1323      CurSize2 += weight[j - 1];
1324      Possible = CountStates(Cands2->vec);
1325      Intersect(Cands2->vec, Comp2[j - 1]->vec, Cprime->vec);
1326      Actual = CountStates(Cprime->vec);
1327      Intersect(Excl2->vec, Comp2[j - 1]->vec, Exprime->vec);
1328      Futile = false;
1329      for (k = 0; k <= j - 2; k++) {
1330        if (Exprime->vec[k] && !Futile) {
1331          Intersect(Cprime->vec, Comp2[k]->vec, Temp);
1332          Futile = (CountStates(Temp) == Actual);
1333        }
1334      }
1335      if (CurSize2 + Actual >= Cliqmin && !Futile) {
1336        if (Actual > 0)
1337          Gen2(j + 1,CurSize2,Chars2->vec,Cprime->vec,Exprime->vec);
1338        else
1339          DoAll(Chars2->vec,Processed,Rarer2,tcount);
1340      }
1341      if (Possible > Actual) {
1342        Chars2->vec[j - 1] = false;
1343        Excl2->vec[j - 1] = true;
1344        CurSize2 -= weight[j - 1];
1345      } else
1346        j = ActualChars;
1347    }
1348    j++;
1349  }
1350  clique_chuck(Chars2);
1351  clique_chuck(Cands2);
1352  clique_chuck(Excl2);
1353  clique_chuck(Cprime);
1354  clique_chuck(Exprime);
1355}  /* Gen2 */
1356
1357
1358void GetMaxCliques(vecrec **Comp_)
1359{
1360  /* recursively generates the largest cliques */
1361  long i;
1362  aPtr aChars, Candidates, Excluded;
1363
1364  Temp = (aPtr)Malloc((long)chars*sizeof(boolean));
1365  Processed = (aPtr)Malloc((long)chars*sizeof(boolean));
1366  Rarer2 = (aPtr)Malloc((long)chars*sizeof(boolean));
1367  aChars = (aPtr)Malloc((long)chars*sizeof(boolean));
1368  Candidates = (aPtr)Malloc((long)chars*sizeof(boolean));
1369  Excluded = (aPtr)Malloc((long)chars*sizeof(boolean));
1370  Comp2 = Comp_;
1371  putc('\n', outfile);
1372  if (Clmin) {
1373    fprintf(outfile, "Cliques with at least%3ld characters\n", Cliqmin);
1374    fprintf(outfile, "------- ---- -- ----- -- ----------\n");
1375  } else {
1376    Cliqmin = 0;
1377    fprintf(outfile, "Largest Cliques\n");
1378    fprintf(outfile, "------- -------\n");
1379    for (i = 0; i < (ActualChars); i++) {
1380      aChars[i] = false;
1381      Excluded[i] = false;
1382      Candidates[i] = true;
1383    }
1384    tcount = 0;
1385    Gen1(1, 0, aChars, Candidates, Excluded);
1386  }
1387  for (i = 0; i < (ActualChars); i++) {
1388    aChars[i] = false;
1389    Candidates[i] = true;
1390    Processed[i] = false;
1391    Excluded[i] = false;
1392  }
1393  Gen2(1, 0, aChars, Candidates, Excluded);
1394  putc('\n', outfile);
1395  free(Temp);
1396  free(Processed);
1397  free(Rarer2);
1398  free(aChars);
1399  free(Candidates);
1400  free(Excluded);
1401}  /* GetMaxCliques */
1402
1403
1404int main(int argc, Char *argv[])
1405{  /* Main Program */
1406#ifdef MAC
1407   argc = 1;                /* macsetup("Clique","Clique");                */
1408   argv[0] = "Clique";
1409#endif
1410  init(argc, argv);
1411  openfile(&infile,INFILE,"input file", "r",argv[0],infilename);
1412  openfile(&outfile,OUTFILE,"output file", "w",argv[0],outfilename);
1413  openfile(&outtree,OUTTREE,"output tree file", "w",argv[0],outtreename);
1414  ibmpc = IBMCRT;
1415  ansi = ANSICRT;
1416  mulsets = false;
1417  firstset = true;
1418  datasets = 1;
1419  doinit();
1420  for (ith = 1; ith <= (datasets); ith++) {
1421    inputoptions();
1422    clique_inputdata();
1423    firstset = false;
1424    SetUp(global_Comp);
1425    if (datasets > 1) {
1426      fprintf(outfile, "Data set # %ld:\n\n",ith);
1427      if (progress)
1428        printf("\nData set # %ld:\n",ith);
1429    }
1430    GetMaxCliques(global_Comp);
1431    if (progress) {
1432      printf("\nOutput written to file \"%s\"\n",outfilename);
1433      if (trout)
1434        printf("\nTree");
1435        if (tcount > 1)
1436          printf("s");
1437        printf(" written on file \"%s\"\n\n", outtreename);
1438    }
1439  }
1440  FClose(infile);
1441  FClose(outfile);
1442  FClose(outtree);
1443#ifdef MAC
1444  fixmacfile(outfilename);
1445  fixmacfile(outtreename);
1446#endif
1447#ifdef WIN32
1448  phyRestoreConsoleAttributes();
1449#endif
1450  printf("Done.\n\n");
1451  return 0;
1452}
1453
Note: See TracBrowser for help on using the repository browser.