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