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 | |
---|
12 | typedef boolean *aPtr; |
---|
13 | typedef long *SpPtr, *ChPtr; |
---|
14 | |
---|
15 | typedef struct vecrec { |
---|
16 | aPtr vec; |
---|
17 | struct vecrec *next; |
---|
18 | } vecrec; |
---|
19 | |
---|
20 | typedef vecrec **aDataPtr; |
---|
21 | typedef vecrec **Matrix; |
---|
22 | |
---|
23 | #ifndef OLDC |
---|
24 | /* function prototypes */ |
---|
25 | void clique_gnu(vecrec **); |
---|
26 | void clique_chuck(vecrec *); |
---|
27 | void nunode(node **); |
---|
28 | void getoptions(void); |
---|
29 | void clique_setuptree(void); |
---|
30 | void allocrest(void); |
---|
31 | void doinit(void); |
---|
32 | void clique_inputancestors(void); |
---|
33 | void clique_printancestors(void); |
---|
34 | void clique_inputfactors(void); |
---|
35 | |
---|
36 | void inputoptions(void); |
---|
37 | void clique_inputdata(void); |
---|
38 | boolean Compatible(long, long); |
---|
39 | void SetUp(vecrec **); |
---|
40 | void Intersect(boolean *, boolean *, boolean *); |
---|
41 | long CountStates(boolean *); |
---|
42 | void Gen1(long , long, boolean *, boolean *, boolean *); |
---|
43 | boolean Ingroupstate(long ); |
---|
44 | void makeset(void); |
---|
45 | void Init(long *, long *, long *, aPtr); |
---|
46 | |
---|
47 | void ChSort(long *, long *, long); |
---|
48 | void PrintClique(boolean *); |
---|
49 | void bigsubset(long *, long); |
---|
50 | void recontraverse(node **, long *, long, long); |
---|
51 | void reconstruct(long, long); |
---|
52 | void reroot(node *); |
---|
53 | void clique_coordinates(node *, long *, long); |
---|
54 | void clique_drawline(long); |
---|
55 | void clique_printree(void); |
---|
56 | void DoAll(boolean *, boolean *, boolean *, long); |
---|
57 | |
---|
58 | void Gen2(long, long, boolean *, boolean *, boolean *); |
---|
59 | void GetMaxCliques(vecrec **); |
---|
60 | /* function prototypes */ |
---|
61 | #endif |
---|
62 | |
---|
63 | |
---|
64 | |
---|
65 | Char infilename[FNMLNGTH], outfilename[FNMLNGTH], outtreename[FNMLNGTH]; |
---|
66 | long ActualChars, Cliqmin, outgrno, |
---|
67 | col, ith, datasets, setsz; |
---|
68 | boolean ancvar, Clmin, Factors, outgropt, trout, weights, noroot, |
---|
69 | printcomp, progress, treeprint, mulsets, firstset; |
---|
70 | long nodes; |
---|
71 | |
---|
72 | aPtr ancone; |
---|
73 | Char *Factor; |
---|
74 | long *ActChar, *oldweight; |
---|
75 | aDataPtr Data; |
---|
76 | Matrix global_Comp; /* the character compatibility matrix */ |
---|
77 | node *root; |
---|
78 | long **grouping; |
---|
79 | pointptr treenode; /* pointers to all nodes in tree */ |
---|
80 | vecrec *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 | |
---|
95 | void 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 | |
---|
110 | void 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 | |
---|
118 | void 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 | |
---|
126 | void 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 | |
---|
254 | void 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 | |
---|
270 | void 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 | |
---|
290 | void 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 | |
---|
303 | void 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 | |
---|
336 | void 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 | |
---|
357 | void 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 | |
---|
380 | void 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 | |
---|
444 | void 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 | |
---|
504 | boolean 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 | |
---|
559 | void 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 | |
---|
602 | void 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 | |
---|
612 | long 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 | |
---|
626 | void 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 | |
---|
687 | boolean 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 | |
---|
704 | void 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 | |
---|
733 | void 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 | |
---|
756 | void 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 | |
---|
777 | void 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 | |
---|
815 | void 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 | |
---|
855 | void 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 | |
---|
953 | void 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 | |
---|
979 | void 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 | |
---|
1024 | void 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 | |
---|
1062 | void 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 | |
---|
1221 | void 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 | |
---|
1251 | void 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 | |
---|
1301 | void 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 | |
---|
1358 | void 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 | |
---|
1404 | int 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 | |
---|