1 /* ring detection routines written by Pat Walters */
2
3 #include "bbltyp.h"
4
find_rings(ums_type * mol,ring_struct * rings)5 int find_rings(ums_type *mol, ring_struct *rings)
6 {
7 spanning_tree *tree1, *tree2, *tree3, *common_tree;
8 connect_type *rca;
9 int frj;
10 int ring_count;
11 int i,l;
12 path path1,path2;
13 ring_struct temp_list;
14 set_type **set2, **set3, *common_set;
15 int common;
16 int path_size;
17
18 frj = Bonds - Atoms + 1;
19
20 rings->ring_list = (path *)malloc(4 * Atoms * sizeof(path));
21 rings->count = 0;
22 rca = (connect_type *)malloc(frj * sizeof(connect_type));
23 memset(rca,0,frj * sizeof(connect_type));
24 tree1 = (spanning_tree *)malloc((Atoms+1) * sizeof(spanning_tree));
25 tree2 = (spanning_tree *)malloc((Atoms+1) * sizeof(spanning_tree));
26 tree3 = (spanning_tree *)malloc((Atoms+1) * sizeof(spanning_tree));
27 common_tree = (spanning_tree *)malloc((Atoms) * sizeof(spanning_tree));
28 common_set = init_set_minbits(Atoms);
29 set2 = (set_type **)malloc((Atoms) * sizeof(set_type *));
30 set3 = (set_type **)malloc((Atoms) * sizeof(set_type *));
31
32 for (i = 0; i < Atoms; i++)
33 {
34 set2[i] = init_set_minbits(Atoms);
35 set3[i] = init_set_minbits(Atoms);
36 }
37
38 path1.path_atoms = (int *)malloc((Atoms) * sizeof(int));
39 path1.path_set = init_set_minbits(Atoms);
40 path2.path_atoms = (int *)malloc((Atoms) * sizeof(int));
41 path2.path_set = init_set_minbits(Atoms);
42
43 temp_list.ring_list = (path *)malloc(Atoms * sizeof(path));
44 memset(temp_list.ring_list,0,Atoms * sizeof(path));
45
46 build_spanning_tree(mol,1,tree1);
47
48 ring_count = find_closure_bonds(mol,tree1,rca);
49
50
51 #ifndef ULTRIX
52 qsort(rca,ring_count,sizeof(connect_type),QSORT_PROTO sort_rca);
53 #else
54 qsort(rca,ring_count,sizeof(connect_type), sort_rca);
55 #endif
56
57 for (i = 0; i < ring_count; i++)
58 {
59 build_restricted_tree(mol,rca[i].start,rca[i].end,tree2);
60 tree_to_sets(mol,tree2,set2);
61 build_restricted_tree(mol,rca[i].end,rca[i].start,tree3);
62 tree_to_sets(mol,tree3,set3);
63
64 find_common_atom(mol,set2,set3,common_set);
65 path_size = build_common_array(common_set,tree3,common_tree);
66 common = 0;
67
68 for (l = 0;l < path_size; l++)
69 {
70 common = common_tree[l].ancestor;
71 init_path(Atoms,&path1);
72 init_path(Atoms,&path2);
73 path_to_root(tree2,common,&path1);
74 path_to_root(tree3,common,&path2);
75 paths_to_ring(path1,path2,&temp_list.ring_list[l],mol->num_atoms);
76 }
77 sort_rings(temp_list.ring_list,l);
78 find_bogus_rings(temp_list.ring_list,l,mol->num_atoms);
79 save_good_rings(rings,&temp_list,l,TRUE);
80 }
81
82 sort_rings(rings->ring_list,rings->count);
83 find_bogus_rings2(mol,rings->ring_list,rings->count,frj);
84
85 i = rings->count;
86 rings->count = 0;
87 save_good_rings(rings,rings,i,TRUE);
88
89 rings->ring_list = (path *)realloc(rings->ring_list,
90 (sizeof(path) * rings->count));
91
92 if (rca) free(rca);
93 if (tree1) free(tree1);
94 if (tree2) free(tree2);
95 if (tree3) free(tree3);
96 if (common_tree) free(common_tree);
97 free_set(common_set);
98
99 for (i = 0;i < Atoms;i++)
100 {
101 free_set(set2[i]);
102 free_set(set3[i]);
103 }
104 free(set2);
105 free(set3);
106
107 if (path1.path_atoms) free(path1.path_atoms);
108 if (path2.path_atoms) free(path2.path_atoms);
109 free_set(path1.path_set);
110 free_set(path2.path_set);
111
112 free(temp_list.ring_list);
113
114 if (rings->count != frj)
115 {
116 printf("ring count != frerejaque number\n");
117 printf("Atoms = %d Bonds = %d ring count = %d frj = %d\n",
118 Atoms,Bonds,rings->count,frj);
119 exit(0);
120 }
121
122 return(rings->count);
123 }
124
tree_to_sets(ums_type * mol,spanning_tree * the_tree,set_type * the_set[])125 void tree_to_sets(ums_type *mol,spanning_tree *the_tree,set_type *the_set[])
126 {
127 int i;
128
129 for (i = 0;i < Atoms;i++)
130 setclear(the_set[i]);
131
132 for (i = 1; i <= Atoms; i++)
133 {
134 if (the_tree[i].level >= 0)
135 biton(the_set[the_tree[i].level],i);
136 }
137 }
138
139
find_common_atom(ums_type * mol,set_type * set1[],set_type * set2[],set_type * set3)140 void find_common_atom(ums_type *mol,set_type *set1[], set_type *set2[], set_type *set3)
141 {
142 int i,j;
143 set_type *temp;
144
145 setclear(set3);
146
147 temp = init_set_minbits(Atoms);
148
149 for (i = 0;i < Atoms; i++)
150 {
151 for (j = 0; j <= i; j++)
152 {
153 setand(set1[i],set2[j],temp);
154 setor(temp,set3,set3);
155 }
156 for (j = 0; j <= i; j++)
157 {
158 setand(set2[i],set1[j],temp);
159 setor(temp,set3,set3);
160 }
161 }
162 free_set(temp);
163
164 }
165
166
167 void
print_tree_set(ums_type * mol,set_type * the_set[])168 print_tree_set(ums_type *mol,set_type *the_set[])
169 {
170 int i;
171 char the_str[10];
172
173 for (i = 0; i < Atoms; i++)
174 {
175 if (setcount(the_set[i]) > 0)
176 {
177 sprintf(the_str,"level %d",i);
178 setprint(the_set[i],the_str);
179 }
180 }
181 }
182
sort_rca(connect_type * a,connect_type * b)183 int sort_rca(connect_type *a, connect_type *b)
184 {
185 if (a->bond_order > b->bond_order)
186 return 1;
187 if (a->bond_order < b->bond_order)
188 return -1;
189 else
190 return 0;
191 }
192
193
build_spanning_tree(ums_type * mol,int root,spanning_tree * tree)194 void build_spanning_tree(ums_type *mol, int root, spanning_tree *tree)
195 {
196 int i,j,k;
197
198
199 for (i = 0; i <= Atoms; i++)
200 {
201 Redo(i) = 0;
202 tree[i].level = 0;
203 tree[i].ancestor = 0;
204 }
205
206 Redo(root) = 1;
207
208 for (i = 1; i <= Atoms; i++)
209 {
210 for (j = 1; j <= Atoms; j++)
211 if (Redo(j) == i)
212 {
213 for (k = 0; k < Valence(j); k++)
214 if (Redo(Connection(j,k)) == 0)
215 {
216 (Redo(Connection(j,k)) = i + 1);
217 tree[Connection(j,k)].level = i + 1;
218 tree[Connection(j,k)].ancestor = j;
219 }
220 }
221 }
222 }
223
224
build_restricted_tree(ums_type * mol,int root,int other,spanning_tree * tree)225 void build_restricted_tree(ums_type *mol, int root, int other, spanning_tree *tree)
226 {
227 int level = 0;
228 int i,j;
229 int next;
230
231 set_type *level_set1, *level_set2, *found_set;
232
233 level_set1 = init_set_minbits(Atoms);
234 level_set2 = init_set_minbits(Atoms);
235 found_set = init_set_minbits(Atoms);
236
237 tree[root].level = 0;
238 tree[other].level = -1;
239
240 biton(level_set1,root);
241 biton(found_set,root);
242 biton(found_set,other);
243
244 for (i = 0; i <= Atoms; i++)
245 {
246 tree[i].level = 0;
247 tree[i].ancestor = 0;
248 }
249
250 while (setcount(level_set1) != 0)
251 {
252 level++;
253 setclear(level_set2);
254 next = 0;
255 while (next != -1)
256 {
257 next = NextBit(level_set1,next);
258 if (next != -1)
259 for (i = 0; i < Valence(next); i++)
260 {
261 j = Connection(next,i);
262 if (bit_is_on(found_set,j) == FALSE)
263 {
264 tree[j].level = level;
265 tree[j].ancestor = next;
266 biton(level_set2,j);
267 biton(found_set,j);
268 }
269 }
270 }
271 setcopy(level_set1,level_set2);
272 }
273 for (i = 0; i <= Atoms; i++)
274 if ((tree[i].ancestor == 0) && (i != root))
275 tree[i].level = -1;
276 free_set(found_set);
277 free_set(level_set1);
278 free_set(level_set2);
279 }
280
281
print_spanning_tree(ums_type * mol,spanning_tree * tree)282 void print_spanning_tree(ums_type *mol,spanning_tree *tree)
283 {
284 int do_return;
285 int i,j;
286
287 for (i = 0; i <= Atoms; i++)
288 {
289 do_return = FALSE;
290 for (j = 1; j <= Atoms; j++)
291 {
292 if (tree[j].level == i)
293 {
294 printf("%4d (%d) ",j,tree[j].ancestor);
295 do_return = TRUE;
296 }
297 }
298 if (do_return == TRUE)
299 printf("\n");
300 }
301 }
302
find_closure_bonds(ums_type * mol,spanning_tree * tree,connect_type * rca)303 int find_closure_bonds(ums_type *mol,spanning_tree *tree, connect_type *rca)
304 {
305 int closure;
306 int i,j;
307 int ring_count = 0;
308
309 for (i = 0; i < Bonds; i++)
310 {
311 closure = TRUE;
312 for (j = 1; j <= Atoms; j++)
313 {
314 if (((Start(i) == j) && (End(i) == tree[j].ancestor)) ||
315 ((End(i) == j) && (Start(i) == tree[j].ancestor)))
316 closure = FALSE;
317 }
318 if (closure == TRUE)
319 {
320 /* printf("Bond %d - %d is a ring closure bond \n",Start(i),End(i)); */
321 rca[ring_count].start = Start(i);
322 rca[ring_count].end = End(i);
323 ring_count ++;
324 }
325 }
326 return(ring_count);
327 }
328
path_to_root(spanning_tree * tree,int atom,path * the_path)329 void path_to_root(spanning_tree *tree, int atom, path *the_path)
330 {
331 the_path->path_atoms[the_path->length] = atom;
332 biton(the_path->path_set,atom);
333
334 the_path->length++;
335 if (tree[atom].ancestor == 0)
336 {
337 return;
338 }
339 else
340 {
341 path_to_root(tree,tree[atom].ancestor,the_path);
342 }
343 }
344
345
init_path(int atoms,path * the_path)346 void init_path(int atoms, path *the_path)
347 {
348 int i;
349
350 the_path->length = 0;
351 the_path->bogus = FALSE;
352 the_path->closure = 0;
353 the_path->found = FALSE;
354 for (i = 0; i < atoms; i++)
355 the_path->path_atoms[i] = -1;
356
357 setclear(the_path->path_set);
358 }
359
360
print_path(path * the_path)361 void print_path(path *the_path)
362 {
363 int i;
364
365 for (i = 0; i < the_path->length; i++)
366 printf("%d ",the_path->path_atoms[i]);
367 printf("\n");
368
369 }
370
paths_to_ring(path path1,path path2,path * the_ring,int atoms)371 void paths_to_ring(path path1, path path2, path *the_ring,int atoms)
372 {
373 int ring_size;
374 int i,j;
375
376 ring_size = path1.length + path2.length - 1;
377 the_ring->path_atoms = (int *)malloc(ring_size * sizeof(int));
378 the_ring->length = ring_size;
379 the_ring->path_set = init_set_minbits(atoms);
380 j = 0;
381 for (i = (path2.length - 1); i >= 0; i--)
382 {
383 the_ring->path_atoms[j] = path2.path_atoms[i];
384 biton(the_ring->path_set,path2.path_atoms[i]);
385 j++;
386 }
387 for (i = 1; i < path1.length; i++)
388 {
389 the_ring->path_atoms[j] = path1.path_atoms[i];
390 biton(the_ring->path_set,path1.path_atoms[i]);
391 j++;
392 }
393 }
394
show_rings(path * ring_set,int ring_count)395 void show_rings(path *ring_set, int ring_count)
396 {
397 int i,j,good_rings = 0;
398
399 for (i = 0; i < ring_count; i++)
400 {
401 if (ring_set[i].bogus == FALSE)
402 {
403 for (j = 0; j < ring_set[i].length; j++)
404 {
405 printf("%d ", ring_set[i].path_atoms[j]);
406 }
407 printf("---- %d \n", ring_set[i].length);
408 good_rings++;
409 }
410 }
411
412 printf("Total rings = %d\n",good_rings);
413 }
414
sort_rings(path * ring_set,int ring_count)415 void sort_rings(path *ring_set, int ring_count)
416 {
417 #ifndef ULTRIX
418 qsort(ring_set, ring_count, sizeof(path),QSORT_PROTO comp_rings);
419 #else
420 qsort(ring_set, ring_count, sizeof(path), comp_rings);
421 #endif
422 }
423
comp_rings(path * p1,path * p2)424 int comp_rings(path *p1, path *p2)
425 {
426 if (p1->length > p2->length) return(1);
427 if (p2->length > p1->length) return(-1);
428 return(0);
429 }
430
find_bogus_rings(path * ring_set,int ring_count,int atoms)431 void find_bogus_rings(path *ring_set, int ring_count,int atoms)
432 {
433 int i,j;
434 set_type *temp;
435
436 temp = init_set_minbits(atoms);
437
438 for (i = 0; i < ring_count; i++)
439 ring_set[i].bogus = FALSE;
440 for (i = 0; i < ring_count; i++)
441 for (j = i; j < ring_count; j++)
442 {
443 if ((ring_set[i].bogus == FALSE) && (i != j))
444 {
445 setand(ring_set[i].path_set,ring_set[j].path_set,temp);
446 if (setcount(temp) == ring_set[i].length)
447 ring_set[j].bogus = TRUE;
448 }
449 }
450 free_set(temp);
451 }
452
find_bogus_rings2(ums_type * mol,path * ring_set,int ring_count,int frj)453 void find_bogus_rings2(ums_type *mol,path *ring_set, int ring_count, int frj)
454 {
455 int i,j;
456 set_type *used, *same;
457 int size;
458 int zapped = 0;
459
460 used = init_set_minbits(Atoms);
461 same = init_set_minbits(Atoms);
462
463 for (i = ring_count - 1; i >= 0; i--)
464 {
465 setclear(used);
466 size = ring_set[i].length;
467 for (j = 0; j < ring_count; j++)
468 {
469 if (ring_set[j].bogus == FALSE)
470 if (ring_set[j].length <= size && i != j)
471 setor(used,ring_set[j].path_set,used);
472 }
473 setand(ring_set[i].path_set,used,same);
474
475 if (ring_count - zapped == frj)
476 break;
477
478 if (setcount(same) == setcount(ring_set[i].path_set))
479 {
480 ring_set[i].bogus = TRUE;
481 zapped++;
482 }
483 }
484
485 free_set(used);
486 free_set(same);
487 }
488
489
490
show_ring(path ring_path)491 void show_ring(path ring_path)
492 {
493 int i;
494
495 printf("the ring is ");
496 for (i = 0; i < ring_path.length; i++)
497 printf(" %d ",ring_path.path_atoms[i]);
498 printf("\n");
499 }
500
501
is_good_ring(path new_ring,path * ring_list,int ring_count)502 int is_good_ring(path new_ring, path* ring_list, int ring_count)
503 {
504 int i;
505 set_type *temp;
506
507 temp = init_set_setlen(new_ring.path_set->setlen);
508
509 for (i = 0; i < ring_count; i++)
510 {
511 setand(ring_list[i].path_set,new_ring.path_set,temp);
512 if (setcount(temp) == ring_list[i].length)
513 {
514 return(FALSE);
515 }
516 }
517
518 free_set(temp);
519 return(TRUE);
520 }
521
522
523
build_common_array(set_type * common_set,spanning_tree * the_tree,spanning_tree * common_array)524 int build_common_array(set_type *common_set, spanning_tree *the_tree,spanning_tree *common_array)
525 {
526 int size;
527 int next = 0, k = 0;
528
529 size = setcount(common_set);
530 while (next != -1)
531 {
532 next = NextBit(common_set,next);
533 if (next != -1)
534 {
535 common_array[k].ancestor = next;
536 common_array[k].level = the_tree[next].level;
537 k++;
538 }
539 }
540
541 #ifndef ULTRIX
542 qsort(common_array,size,sizeof(spanning_tree),QSORT_PROTO sort_common);
543 #else
544 qsort(common_array,size,sizeof(spanning_tree),sort_common);
545 #endif
546
547 return(size);
548 }
549
sort_common(spanning_tree * a,spanning_tree * b)550 int sort_common(spanning_tree *a, spanning_tree *b)
551 {
552 if (a->level > b->level)
553 return(1);
554 else
555 if (a->level < b->level)
556 return(-1);
557 else
558 return(0);
559 }
560
561
make_ring_ums(ums_type * mol,ums_type * new_mol,path rng)562 void make_ring_ums(ums_type *mol, ums_type *new_mol, path rng)
563 {
564 int i;
565
566 new_mol->num_atoms = rng.length;
567 new_mol->num_bonds = rng.length;
568 initialize_ums(&new_mol);
569 for (i = 1; i <= new_mol->num_atoms; i++)
570 {
571 strcpy(new_mol->atoms[i].type,Type(rng.path_atoms[i-1]));
572 new_mol->atoms[i].point.x = X(rng.path_atoms[i-1]);
573 new_mol->atoms[i].point.y = Y(rng.path_atoms[i-1]);
574 new_mol->atoms[i].point.z = Z(rng.path_atoms[i-1]);
575 }
576 for (i = 0; i < (new_mol->num_atoms - 1); i++)
577 {
578 new_mol->connections[i].start = i+1;
579 new_mol->connections[i].end = i+2;
580 }
581 new_mol->connections[new_mol->num_atoms - 1].start = new_mol->num_atoms;
582 new_mol->connections[new_mol->num_atoms - 1].end = 1;
583 dissect_connection_table(new_mol);
584 }
585
586 void
save_good_rings(ring_struct * good,ring_struct * bad,int count,int dupe_ck)587 save_good_rings(ring_struct *good,ring_struct *bad,int count,int dupe_ck)
588 {
589 int i,j,k,*tmp;
590 set_type *set;
591 int duplicate;
592
593 j = good->count;
594 for (i = 0; i < count; i++)
595 {
596 duplicate = FALSE;
597 for (k = 0;k < j;k++)
598 if ((setcmp(good->ring_list[k].path_set,bad->ring_list[i].path_set)) && dupe_ck)
599 duplicate = TRUE;
600
601 if (!bad->ring_list[i].bogus && !duplicate)
602 {
603 tmp = bad->ring_list[i].path_atoms;
604 set = bad->ring_list[i].path_set;
605
606 bad->ring_list[i].path_atoms = NULL;
607 bad->ring_list[i].path_set = NULL;
608
609 good->ring_list[j] = bad->ring_list[i];
610 good->ring_list[j].path_atoms = tmp;
611 good->ring_list[j].path_set = set;
612 j++;
613 }
614 else
615 {
616 if (bad->ring_list[i].path_atoms)
617 free(bad->ring_list[i].path_atoms);
618 free_set(bad->ring_list[i].path_set);
619 }
620 }
621
622 good->count = j;
623 }
624
625