$darkmode
DENOPTIM
CyclicGraphHandler.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2019 Marco Foscato <marco.foscato@uib.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.graph.rings;
20
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.Collections;
24import java.util.HashMap;
25import java.util.Iterator;
26import java.util.List;
27import java.util.Map;
28import java.util.Set;
29import java.util.logging.Level;
30import java.util.logging.Logger;
31
32import javax.vecmath.Point3d;
33
34import org.openscience.cdk.Bond;
35import org.openscience.cdk.graph.ShortestPaths;
36import org.openscience.cdk.graph.matrix.TopologicalMatrix;
37import org.openscience.cdk.interfaces.IAtom;
38import org.openscience.cdk.interfaces.IAtomContainer;
39import org.openscience.cdk.interfaces.IBond;
40import org.openscience.cdk.interfaces.IChemObjectBuilder;
41import org.openscience.cdk.silent.SilentChemObjectBuilder;
42
43import denoptim.constants.DENOPTIMConstants;
44import denoptim.exception.DENOPTIMException;
45import denoptim.fragspace.FragmentSpace;
46import denoptim.graph.APClass;
47import denoptim.graph.AttachmentPoint;
48import denoptim.graph.DGraph;
49import denoptim.graph.Edge;
50import denoptim.graph.Edge.BondType;
51import denoptim.graph.EmptyVertex;
52import denoptim.graph.Fragment;
53import denoptim.graph.Ring;
54import denoptim.graph.Vertex;
55import denoptim.graph.Vertex.BBType;
56import denoptim.utils.ManySMARTSQuery;
57import denoptim.utils.MoleculeUtils;
58import denoptim.utils.ObjectPair;
59import denoptim.utils.RingClosingUtils;
60
61
76{
80 private int recCount = 0;
81 private int maxLng = 0;
82
87
92
96 private Logger logger;
97
101 private static final String NL = DENOPTIMConstants.EOL;
102
103//-----------------------------------------------------------------------------
104
114 {
115 this.settings = settings;
116 this.logger = settings.getLogger();
117 this.fragSpace = fragSpace;
118 }
119
120//-----------------------------------------------------------------------------
121
131 public List<Ring> getRandomCombinationOfRings(IAtomContainer inMol,
132 DGraph molGraph, int maxRingClosures) throws DENOPTIMException
133 {
135 molGraph, maxRingClosures, fragSpace, settings);
136 List<Ring> combOfRings = iter.next();
137 logger.log(Level.FINE,"Random combOfRings: "+combOfRings);
138 return combOfRings;
139 }
140
141//-----------------------------------------------------------------------------
142
151 //TODO: this should use most of the same code of RandomCombOfRingsIterator
152
153 public ArrayList<List<Ring>> getPossibleCombinationOfRings(
154 IAtomContainer mol, DGraph molGraph)
155 throws DENOPTIMException
156 {
157 // All the candidate paths
158 Map<ObjectPair,PathSubGraph> allGoodPaths =
159 new HashMap<ObjectPair,PathSubGraph>();
160 ArrayList<Vertex> rcaVertLst = molGraph.getFreeRCVertices();
161
162 // Get manager of ring size problems
164 rsm.initialize(mol, molGraph);
165
166 // identify compatible pairs of RCA vertices
167 Map<Vertex,ArrayList<Vertex>> compatMap =
168 new HashMap<Vertex,ArrayList<Vertex>>();
169 for (int i=0; i<rcaVertLst.size(); i++)
170 {
171 Vertex vI = rcaVertLst.get(i);
172 for (int j=i+1; j<rcaVertLst.size(); j++)
173 {
174 Vertex vJ = rcaVertLst.get(j);
175 if (!rsm.getCompatibilityOfPair(vI,vJ))
176 {
177 logger.log(Level.FINE, "Rejecting RC-incompatible pair "
178 + vI + " "+ vJ);
179 continue;
180 }
181
182 // make the new candidate RCA pair
183 PathSubGraph subGraph = new PathSubGraph(vI, vJ, molGraph);
184 logger.log(Level.FINE, "Evaluating closability of path "
185 + subGraph);
186 boolean keepRcaPair = PathClosabilityTools.isCloseable(subGraph,
187 mol, settings);
188
189 if (!keepRcaPair)
190 {
191 logger.log(Level.FINE, "Rejecting RCA pair");
192 continue;
193 }
194
195 // finally store this pair as a compatible pair
196 logger.log(Level.FINE, "All compatibility criteria satisfied: "
197 + "Storing verified RCA pair");
198
199 // Store the information that the two vertex are compatible
200 if (compatMap.containsKey(vI))
201 {
202 compatMap.get(vI).add(vJ);
203 }
204 else
205 {
206 ArrayList<Vertex> lst =
207 new ArrayList<Vertex>();
208 lst.add(vJ);
209 compatMap.put(vI,lst);
210 }
211 if (compatMap.containsKey(vJ))
212 {
213 compatMap.get(vJ).add(vI);
214 }
215 else
216 {
217 ArrayList<Vertex> lst =
218 new ArrayList<Vertex>();
219 lst.add(vI);
220 compatMap.put(vJ,lst);
221 }
222
223 // store the RCA pair for further use
224 ObjectPair compatPair;
225 if (vI.getVertexId() > vJ.getVertexId())
226 {
227 compatPair = new ObjectPair(vI,vJ);
228 }
229 else
230 {
231 compatPair = new ObjectPair(vJ,vI);
232 }
233 allGoodPaths.put(compatPair,subGraph);
234 }
235 }
236
237 logger.log(Level.FINE, "Compatibility Map for RCAs: "+NL+compatMap);
238
239 // Identify paths that share bonds (interdependent paths)
240 Map<IBond,List<PathSubGraph>> interdepPaths =
241 new HashMap<IBond,List<PathSubGraph>>();
243 {
244 for (PathSubGraph rpA : allGoodPaths.values())
245 {
246 for (PathSubGraph rpB : allGoodPaths.values())
247 {
248 if (rpA == rpB)
249 {
250 continue;
251 }
252
253 Vertex hA = rpA.getHeadVertex();
254 Vertex tA = rpA.getTailVertex();
255 Vertex hB = rpB.getHeadVertex();
256 Vertex tB = rpB.getTailVertex();
257
258 if ((hA == hB || hA == tB) || (tA == hB || tA == tB))
259 {
260 continue;
261 }
262
263 for (IBond bnd : rpA.getBondPath())
264 {
265 // ignore non-rotatable bonds
266 // NOTE: here we assume that rotatable bonds have been
267 // identified before.
268 Object rotFlg = bnd.getProperty(
270 if (rotFlg==null || !Boolean.valueOf(rotFlg.toString()))
271 {
272 continue;
273 }
274
275 if (rpB.getBondPath().contains(bnd))
276 {
277 if (interdepPaths.containsKey(bnd))
278 {
279 interdepPaths.get(bnd).add(rpA);
280 interdepPaths.get(bnd).add(rpB);
281 }
282 else
283 {
284 List<PathSubGraph> paths =
285 new ArrayList<PathSubGraph>();
286 paths.add(rpA);
287 paths.add(rpB);
288 interdepPaths.put(bnd,paths);
289 }
290 }
291 }
292 }
293 }
294 StringBuilder sb = new StringBuilder();
295 for (IBond bnd : interdepPaths.keySet())
296 {
297 sb.append("Interdependent paths for bond " + bnd);
298 List<PathSubGraph> sop = interdepPaths.get(bnd);
299 for (PathSubGraph p : sop)
300 {
301 sb.append(NL + " -> vA: "+p.getHeadVertex()
302 +" vB: "+p.getTailVertex());
303 }
304 }
305 logger.log(Level.FINE, sb.toString());
306 }
307
308 // Generate all combinations of compatible, closable paths
309 ArrayList<ObjectPair> lstPairs = new ArrayList<ObjectPair>();
310 ArrayList<Long> usedId = new ArrayList<Long>();
311 ArrayList<Vertex> sortedKeys = new ArrayList<Vertex>();
312 for (Vertex keyVert : compatMap.keySet())
313 {
314 sortedKeys.add(keyVert);
315 }
316
317 // All possible ring closing paths will be stored here
318 ArrayList<List<Ring>> allCombsOfRings =
319 new ArrayList<List<Ring>>();
321 sortedKeys,
322 compatMap,
323 lstPairs,
324 usedId,
325 allGoodPaths,
326 interdepPaths,
327 allCombsOfRings);
328 logger.log(Level.FINE, "All possible combination of rings: " +
329 allCombsOfRings);
330 return allCombsOfRings;
331 }
332
333//-----------------------------------------------------------------------------
334
339 private boolean combineCompatPathSubGraphs(int ii0,
340 ArrayList<Vertex> sortedKeys,
341 Map<Vertex,ArrayList<Vertex>> compatMap,
342 ArrayList<ObjectPair> lstPairs,
343 ArrayList<Long> usedId,
344 Map<ObjectPair,PathSubGraph> allGoodPaths,
345 Map<IBond,List<PathSubGraph>> interdepPaths,
346 ArrayList<List<Ring>> allCombsOfRings)
347 throws DENOPTIMException
348 {
349 int objId = this.hashCode();
350 String recLab = new String(new char[recCount]).replace("\0", "-");
351
352 StringBuilder sb = new StringBuilder();
353 sb.append(objId+"-"+recLab+"> Begin of new recursion: "+recCount+NL);
354 sb.append(objId+"-"+recLab+"> sortedKeys= "+sortedKeys+NL);
355 sb.append(objId+"-"+recLab+"> usedId= "+usedId+NL);
356 sb.append(objId+"-"+recLab+"> ii0= "+ii0+NL);
357 sb.append(objId+"-"+recLab+"> lstPairs= "+lstPairs+NL);
358 sb.append(objId+"-"+recLab+"> compatMap= "+compatMap+NL);
359 sb.append(objId+"-"+recLab+"> allCombsOfRings"+NL);
360 for (List<Ring> ringSet : allCombsOfRings)
361 {
362 sb.append(" "+ringSet+NL);
363 }
364 logger.log(Level.FINEST, sb.toString());
365
366 boolean inFound = false;
367 boolean addedNew = false;
368 for (int ii=ii0; ii<sortedKeys.size(); ii++)
369 {
370 Vertex vi = sortedKeys.get(ii);
371 long vIdI = vi.getVertexId();
372
373 logger.log(Level.FINEST, objId+"-"+recLab+"> vIdI= "+vIdI);
374
375 if (usedId.contains(vIdI))
376 {
377 continue;
378 }
379
380 for (Vertex vj : compatMap.get(vi))
381 {
382 long vIdJ = vj.getVertexId();
383
384 logger.log(Level.FINEST, objId+"-"+recLab+"> vIdJ= "+vIdJ);
385
386 if (usedId.contains(vIdJ) || usedId.contains(vIdI))
387 {
388 continue;
389 }
390
391 ObjectPair op;
392 if (vIdI > vIdJ)
393 {
394 op = new ObjectPair(vi,vj);
395 }
396 else
397 {
398 op = new ObjectPair(vj,vi);
399 }
400 lstPairs.add(op);
401 usedId.add(vIdI);
402 usedId.add(vIdJ);
403
404 if (lstPairs.size() > maxLng)
405 {
406 maxLng = lstPairs.size();
407 }
408 recCount++;
409 inFound = combineCompatPathSubGraphs(ii+1,
410 sortedKeys,
411 compatMap,
412 lstPairs,
413 usedId,
414 allGoodPaths,
415 interdepPaths,
416 allCombsOfRings);
417 recCount--;
418
419 logger.log(Level.FINEST, objId+"-"+recLab+"> lstPairs.size() "
420 + "& maxLng= "+lstPairs.size() +" " +maxLng);
421
422 if (!inFound && lstPairs.size() == maxLng)
423 {
424 logger.log(Level.FINEST, objId+"-"+recLab+"> in A");
425
426 boolean closable = true;
428 hasInterdependentPaths(lstPairs, interdepPaths))
429 {
431 lstPairs,
432 interdepPaths,
433 allGoodPaths);
434 }
435 if (closable)
436 {
437 logger.log(Level.FINEST, objId+"-"+recLab+"> in B");
438
439 List<Ring> ringsComb = new ArrayList<Ring>();
440 for (ObjectPair opFinal : lstPairs)
441 {
442 PathSubGraph path = allGoodPaths.get(opFinal);
443 ArrayList<Vertex> arrLst =
444 new ArrayList<Vertex>();
445 arrLst.addAll(path.getVertecesPath());
446
447 Ring ring = new Ring(arrLst);
448
449 List<Edge> es = path.getEdgesPath();
450 BondType btH = es.get(0).getBondType();
451 BondType btT = es.get(es.size()-1).getBondType();
452 if (btH != btT)
453 {
454 String s = "Attempt to close rings is not "
455 + "compatible to the different bond type "
456 + "specified by the head and tail APs: ("
457 + btH + "!=" + btT + " for vertices "
458 + path.getHeadVertex() + " "
459 + path.getTailVertex() + ")";
460 throw new DENOPTIMException(s);
461 }
462 ring.setBondType(btH);
463
464 ringsComb.add(ring);
465
466 logger.log(Level.FINEST, objId+"-"+recLab
467 +"> added ringComb: "+ring);
468 }
469
470 boolean notNewCmb = false;
471 for(List<Ring> oldCmb : allCombsOfRings)
472 {
473 StringBuilder sb2 = new StringBuilder();
474 sb2.append(objId+"-"+recLab
475 +"> Comparing ring sets: ");
476 sb2.append("o> old: "+oldCmb);
477 sb2.append("o> new: "+ringsComb);
478 logger.log(Level.FINEST, sb2.toString());
479
480 notNewCmb = RingClosingUtils.areSameRingsSet(oldCmb,
481 ringsComb);
482
483 logger.log(Level.FINEST,"o> result: "+notNewCmb);
484
485 if (notNewCmb)
486 {
487 break;
488 }
489 }
490
491 if (!notNewCmb)
492 {
493 logger.log(Level.FINEST, objId+"-"+recLab
494 +"> adding to all combs of ring.");
495 allCombsOfRings.add(ringsComb);
496 addedNew = true;
497 }
498 }
499 }
500 if (!inFound)
501 {
502 logger.log(Level.FINEST, objId+"-"+recLab+"> in C");
503
504 ArrayList<ObjectPair> toDel = new ArrayList<ObjectPair>();
505 for (int ir = recCount; ir<lstPairs.size(); ir++)
506 {
507 ObjectPair opToRemove = lstPairs.get(ir);
508 Vertex delVA = (Vertex) opToRemove.getFirst();
509 Vertex delVB = (Vertex) opToRemove.getSecond();
510 usedId.remove(usedId.indexOf(delVA.getVertexId()));
511 usedId.remove(usedId.indexOf(delVB.getVertexId()));
512 toDel.add(opToRemove);
513 }
514 lstPairs.removeAll(toDel);
515
516 logger.log(Level.FINEST, objId+"-"+recLab
517 +"> in C: after removal usedId: "+usedId+NL
518 +objId+"-"+recLab
519 +"> in C: after removal lstPairs: "+lstPairs);
520 }
521
522 if (lstPairs.contains(op))
523 {
524 logger.log(Level.FINEST, objId+"-"+recLab+"> in D");
525
526 lstPairs.remove(op);
527 usedId.remove(usedId.indexOf(vIdI));
528 usedId.remove(usedId.indexOf(vIdJ));
529
530 logger.log(Level.FINEST, objId+"-"+recLab
531 +"> in D: after removal usedId: "+usedId
532 +objId+"-"+recLab
533 +"> in D: after removal lstPairs: "+lstPairs);
534 }
535 }
536 }
537
538 logger.log(Level.FINEST, objId+"-"+recLab+"> returning= "+addedNew);
539
540 return addedNew;
541 }
542
543//-----------------------------------------------------------------------------
544
550 private boolean hasInterdependentPaths(ArrayList<ObjectPair> lstPairs,
551 Map<IBond,List<PathSubGraph>> interdepPaths)
552 {
553 boolean result = false;
554
555 for (IBond bnd : interdepPaths.keySet())
556 {
557 List<PathSubGraph> psgSet = interdepPaths.get(bnd);
558 for (PathSubGraph psg : psgSet)
559 {
560 Vertex va1 = psg.getHeadVertex();
561 Vertex va2 = psg.getTailVertex();
562
563 for (ObjectPair op : lstPairs)
564 {
565 Vertex vb1 = (Vertex) op.getFirst();
566 Vertex vb2 = (Vertex) op.getSecond();
567
568 if ((va1 == vb1 && va2 == vb2) ||
569 (va1 == vb2 && va2 == vb1))
570 {
571 result = true;
572 break;
573 }
574 }
575 if (result)
576 break;
577 }
578 if (result)
579 break;
580 }
581 return result;
582 }
583
584//-----------------------------------------------------------------------------
585
593 ArrayList<ObjectPair> lstPairs,
594 Map<IBond,List<PathSubGraph>> interdepPaths,
595 Map<ObjectPair,PathSubGraph> allGoodPaths)
596 {
597 // Identify the interdependent sets of paths
598 List<ArrayList<ObjectPair>> listOfIntrDepPaths =
599 new ArrayList<ArrayList<ObjectPair>>();
600 for (IBond bnd : interdepPaths.keySet())
601 {
602 ArrayList<ObjectPair> locSop = new ArrayList<ObjectPair>();
603 List<PathSubGraph> psgSet = interdepPaths.get(bnd);
604 for (PathSubGraph psg : psgSet)
605 {
606 Vertex va1 = psg.getHeadVertex();
607 Vertex va2 = psg.getTailVertex();
608
609 for (ObjectPair op : lstPairs)
610 {
611 Vertex vb1 = (Vertex) op.getFirst();
612 Vertex vb2 = (Vertex) op.getSecond();
613
614 if ((va1 == vb1 && va2 == vb2) ||
615 (va1 == vb2 && va2 == vb1))
616 {
617 locSop.add(op);
618 }
619 }
620 }
621 if (locSop.size() > 1)
622 {
623 listOfIntrDepPaths.add(locSop);
624 }
625 }
626
627 // Verify simultaneous closeness of each group of interdependent paths
628 boolean closable = true;
629 for (ArrayList<ObjectPair> grpIntrdepPaths : listOfIntrDepPaths)
630 {
631 // Per each closable conf. of the first path stores the paths
632 // that have a simultaneously closable conf.
633 Map<ClosableConf,List<ObjectPair>> mapOcPathsWithCC =
634 new HashMap<ClosableConf,List<ObjectPair>>();
635
636 // Per each closable conf. of a path lists the simultaneously
637 // closable confs of the other interdependent paths
638 Map<ClosableConf,List<ClosableConf>> mapOfClosableConfs =
639 new HashMap<ClosableConf,List<ClosableConf>>();
640
641 // For the first path just put all closable conf in the list
642 ObjectPair firstOp = grpIntrdepPaths.get(0);
643 PathSubGraph firstPsg = allGoodPaths.get(firstOp);
644 RingClosingConformations firstRcc = firstPsg.getRCC();
645
646 for (ArrayList<Double> ccAngls : firstRcc.getListOfConformations())
647 {
648 ClosableConf cc = new ClosableConf(firstPsg.getBondPath(),
649 ccAngls);
650 // Container for cc of other paths
651 List<ClosableConf> scc = new ArrayList<ClosableConf>();
652 mapOfClosableConfs.put(cc,scc);
653 // Container for other paths
654 List<ObjectPair> sop = new ArrayList<ObjectPair>();
655 sop.add(firstOp);
656 mapOcPathsWithCC.put(cc,sop);
657 }
658
659 // For other paths put only the closable confs (CC) that are
660 // simultaneously closable with previously listed CCs
661 for (int iOp=1; iOp<grpIntrdepPaths.size(); iOp++)
662 {
663 ObjectPair locOp = grpIntrdepPaths.get(iOp);
664 PathSubGraph locPath = allGoodPaths.get(locOp);
665 RingClosingConformations rccOfLocPath = locPath.getRCC();
666
667 // try with each closable conf of the local path
668 for (ArrayList<Double> ccAngles :
669 rccOfLocPath.getListOfConformations())
670 {
671 ClosableConf locCC = new ClosableConf(
672 locPath.getBondPath(), ccAngles);
673 // Compare the locCC with CC of the first path
674 for (ClosableConf frstCC : mapOfClosableConfs.keySet())
675 {
676 if (frstCC.shareBond(locCC) &&
677 frstCC.canCoexistWith(locCC))
678 {
679 // CC of loc path is simultaneously closable with
680 // this CC of first path (frstCC)
681 if (mapOfClosableConfs.get(frstCC).size() == 0)
682 {
683 // the list of CC simultaneously closable with
684 // the key CC (frstCC) is empty, so just
685 // add locCC for future needs
686 mapOfClosableConfs.get(frstCC).add(locCC);
687 // add to Set wont add if is already there
688 mapOcPathsWithCC.get(frstCC).add(locOp);
689 }
690 else
691 {
692 // the list of CC simultaneously closable with
693 // the key CC (frstCC) has already one or more
694 // entries: we need to compare this locCC with
695 // all these entries
696 boolean canCoexistWithAll = true;
697 for (ClosableConf lstCC :
698 mapOfClosableConfs.get(frstCC))
699 {
700 if (lstCC.shareBond(locCC) &&
701 !lstCC.canCoexistWith(locCC))
702 {
703 // Sorry, locCC cannot coexist
704 canCoexistWithAll = false;
705 break;
706 }
707 }
708 if (canCoexistWithAll)
709 {
710 mapOfClosableConfs.get(frstCC).add(locCC);
711 // add to Set wont add if is already there
712 mapOcPathsWithCC.get(frstCC).add(locOp);
713 }
714 }
715 }
716 }
717 }
718
719 boolean goon = true;
720 for (ClosableConf frstCC : mapOfClosableConfs.keySet())
721 {
722 if (!mapOcPathsWithCC.get(frstCC).contains(locOp))
723 {
724 goon = false;
725 break;
726 }
727 }
728 if (!goon)
729 {
730 break;
731 }
732 }
733
734 // Now check if there is at least one set of simultaneously
735 // closable conformations for all members of this group
736 // of interdependent paths
737 boolean foundOneSetFullyClosable = false;
738 for (ClosableConf cc : mapOfClosableConfs.keySet())
739 {
740 int numPathWithSimCC = mapOcPathsWithCC.get(cc).size();
741 int numInterdepPaths = grpIntrdepPaths.size();
742 if (numPathWithSimCC == numInterdepPaths)
743 {
744 foundOneSetFullyClosable = true;
745 break;
746 }
747 }
748 if (!foundOneSetFullyClosable)
749 {
750 closable = false;
751 break;
752 }
753 }
754
755 return closable;
756 }
757
758//-----------------------------------------------------------------------------
759
766 private class ClosableConf
767 {
768 private List<IBond> bonds;
769 private ArrayList<Double> angs;
770
771 //---------------------------------------------------------------------
772
773 public ClosableConf(List<IBond> bonds, ArrayList<Double> dihedrals)
774 {
775 this.bonds = bonds;
776 this.angs = dihedrals;
777 }
778
779 //---------------------------------------------------------------------
780
781 public boolean shareBond(ClosableConf other)
782 {
783 boolean shareBnd = false;
784 for (IBond tBnd : this.bonds)
785 {
786 if (other.bonds.contains(tBnd))
787 {
788 shareBnd = true;
789 break;
790 }
791 }
792 return shareBnd;
793 }
794
795 //---------------------------------------------------------------------
796 public boolean canCoexistWith(ClosableConf other)
797 {
798 boolean canCoexist = true;
799 double thrs = settings.getPathConfSearchStep() / 2.0;
800 for (int i=0; i<this.bonds.size(); i++)
801 {
802 IBond tBnd = this.bonds.get(i);
803 for (int j=0; j<other.bonds.size(); j++)
804 {
805 IBond oBnd = other.bonds.get(j);
806 if (tBnd == oBnd)
807 {
808 double diff = this.angs.get(i) - other.angs.get(j);
809 diff = Math.abs(diff);
810 if (diff > thrs)
811 {
812 canCoexist = false;
813 break;
814 }
815 }
816 }
817 if (!canCoexist)
818 break;
819 }
820
821 return canCoexist;
822 }
823
824 //---------------------------------------------------------------------
825 public String toString()
826 {
827 String s = " ClosableConf [nBonds: " + bonds.size()
828 + " bonds: ";
829 for (IBond bnd : bonds)
830 {
831 s = s + bnd.getAtom(0).getSymbol() + "-"
832 + bnd.getAtom(1).getSymbol() + " ";
833 }
834
835 s = s + " dihedrals: " + angs + "]";
836
837 return s;
838 }
839 }
840
841//-----------------------------------------------------------------------------
842
850 public boolean checkChelatesGraph(DGraph molGraph, List<Ring> ringsSet)
851 {
852 logger.log(Level.FINE, "Checking conditions for chelates");
853
854//TODO: here we assume that the scaffold is a metal and the first layer of
855// vertices (level = 0) are the coordinating atoms.
856// Also, the APclass of the ap connecting the candidate orphan is hard coded!
857// This is a temporary solution. Need a general approach and tunable by
858// options/parameters
859
860 for (Vertex vert : molGraph.getVertexList())
861 {
862 long vId = vert.getVertexId();
863
864 Fragment vertFrag = null;
865 if (vert instanceof Fragment)
866 vertFrag = (Fragment) vert;
867
868
869 // check for orphan coordinating atoms:
870 // they have RCAs but none of them is included in a rings
871 int levelOfVert = molGraph.getLevel(vert);
872 if (levelOfVert == 0
873 && vertFrag.getBuildingBlockType() == BBType.FRAGMENT)
874 {
875 Edge edgeToParnt = molGraph.getEdgeWithParent(vId);
876 APClass apClassToScaffold = edgeToParnt.getTrgAPClass();
878 apClassToScaffold))
879 {
880 continue;
881 }
882
883 boolean isOrphan = false;
884 for (Vertex cVrtx : vert.getChilddren())
885 {
886 if (cVrtx.isRCV() && !molGraph.isVertexInRing(cVrtx))
887 {
888 isOrphan = true;
889 break;
890 }
891 }
892 if (isOrphan)
893 {
894 logger.log(Level.FINE, "Found orphan: " + vert
895 + " RingSet: " + ringsSet);
896 return false;
897 }
898 }
899
900 // check for not fully coordinating multidentate bridges
901//TODO: make the full-denticity requirement optional for same/all APclasses
902 if (levelOfVert > 0)
903 {
904 Map<String,ArrayList<Vertex>> rcasOnThisVertex =
905 new HashMap<String,ArrayList<Vertex>>();
906 for (Vertex cVrtx : vert.getChilddren())
907 {
908 if (cVrtx.isRCV())
909 {
910 AttachmentPoint ap =
911 cVrtx.getAttachmentPoints().get(0);
912 String apCls = ap.getAPClass().toString();
913 if (rcasOnThisVertex.keySet().contains(apCls))
914 {
915 rcasOnThisVertex.get(apCls).add(cVrtx);
916 }
917 else
918 {
919 ArrayList<Vertex> sameClsRCA =
920 new ArrayList<Vertex>();
921 sameClsRCA.add(cVrtx);
922 rcasOnThisVertex.put(apCls,sameClsRCA);
923 }
924 }
925 }
926
927 for (String apCls : rcasOnThisVertex.keySet())
928 {
929 int usedDenticity = 0;
930 for (Vertex rcaVrtx : rcasOnThisVertex.get(apCls))
931 {
932 if (molGraph.isVertexInRing(rcaVrtx))
933 {
934 usedDenticity++;
935 }
936 }
937
938 if (usedDenticity < rcasOnThisVertex.get(apCls).size())
939 {
940 logger.log(Level.FINE, "Full-denticity is not "
941 + "satisfied for apclas: " + apCls
942 + "in vertex " + vert
943 + " with set of rings " + ringsSet
944 + "check graph: " + molGraph);
945 return false;
946 }
947 }
948 }
949 }
950
951 return true;
952 }
953
954//-----------------------------------------------------------------------------
955
956}
General set of constants used in DENOPTIM.
static final String EOL
new line character
static final String BONDPROPROTATABLE
String tag of Bond's property used to store the property of being rotatable.
Class defining a space of building blocks.
String toString()
Do not use this to make SDF representations.
Definition: APClass.java:352
An attachment point (AP) is a possibility to attach a Vertex onto the vertex holding the AP (i....
APClass getAPClass()
Returns the Attachment Point class.
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:102
List< Vertex > getVertexList()
Definition: DGraph.java:719
int getLevel(Vertex v)
Calculates the level of a vertex in this graph.
Definition: DGraph.java:5326
boolean isVertexInRing(Vertex v)
Definition: DGraph.java:940
Edge getEdgeWithParent(long l)
Looks for an edge that points to a vertex with the given vertex id.
Definition: DGraph.java:3273
This class represents the edge between two vertices.
Definition: Edge.java:38
APClass getTrgAPClass()
Definition: Edge.java:157
Class representing a continuously connected portion of chemical object holding attachment points.
Definition: Fragment.java:61
This class represents the closure of a ring in a spanning tree.
Definition: Ring.java:40
void setBondType(BondType bndType)
Set the bond type (i.e., bond order) of the chord connecting the head and the tail vertices.
Definition: Ring.java:158
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
Vertex.BBType getBuildingBlockType()
Definition: Vertex.java:298
ArrayList< Vertex > getChilddren()
Looks into the edges that use any of the APs that belong to this vertex and returns the list of verti...
Definition: Vertex.java:1085
Object getProperty(Object property)
Definition: Vertex.java:1136
Utility class to handle the simultaneous closeness condition.
ClosableConf(List< IBond > bonds, ArrayList< Double > dihedrals)
This is a tool to identify and manage vertices' connections not included in the DGraph,...
boolean hasInterdependentPaths(ArrayList< ObjectPair > lstPairs, Map< IBond, List< PathSubGraph > > interdepPaths)
Checks whether the combination of RCA's pairs leads to interdependent paths, that is,...
List< Ring > getRandomCombinationOfRings(IAtomContainer inMol, DGraph molGraph, int maxRingClosures)
Identifies a random combination of ring closing paths and returns it as list of DENOPTIMRings ready t...
boolean checkChelatesGraph(DGraph molGraph, List< Ring > ringsSet)
Evaluates the combination of a DENOPTIMGraph and a set of DENOPTIMRings and decides whether it's a pr...
RingClosureParameters settings
Parameters.
ArrayList< List< Ring > > getPossibleCombinationOfRings(IAtomContainer mol, DGraph molGraph)
Identifies all possible ring closing paths and returns them as list of DENOPTIMRings ready to be appe...
CyclicGraphHandler(RingClosureParameters settings, FragmentSpace fragSpace)
Constructor from data structure.
boolean combineCompatPathSubGraphs(int ii0, ArrayList< Vertex > sortedKeys, Map< Vertex, ArrayList< Vertex > > compatMap, ArrayList< ObjectPair > lstPairs, ArrayList< Long > usedId, Map< ObjectPair, PathSubGraph > allGoodPaths, Map< IBond, List< PathSubGraph > > interdepPaths, ArrayList< List< Ring > > allCombsOfRings)
Recursive method to identify all the combination of rings.
int recCount
variables needed by recursive methods
static final String NL
New line character.
boolean checkClosabilityOfInterdependentPaths(ArrayList< ObjectPair > lstPairs, Map< IBond, List< PathSubGraph > > interdepPaths, Map< ObjectPair, PathSubGraph > allGoodPaths)
This method checks whether the interdependent paths are simultaneously closable.
FragmentSpace fragSpace
Fragment space definition.
Tool box for determining whether a chain of atoms, i.e., a path, can be folded as to form a ring-clos...
static boolean isCloseable(PathSubGraph subGraph, IAtomContainer mol, RingClosureParameters settings)
Method to evaluate the closability of a single path in a graph.
This object represents a path in a DGraph.
List< IBond > getBondPath()
Returns the list of bonds in the path between the head and the tail.
RingClosingConformations getRCC()
Returns the ring closing conformations.
List< Vertex > getVertecesPath()
Returns the list of verteces involved.
Vertex getHeadVertex()
Returns the vertex representing the head of the chain.
Vertex getTailVertex()
Returns the vertex representing the tail of the chain.
List< Edge > getEdgesPath()
Returns the list of edges involved.
A class for iterating over sets of ring combinations generated by considering any constrain and setti...
Serializable object to store/get a list of conformations that allow to close a ring from an open chai...
ArrayList< ArrayList< Double > > getListOfConformations()
Parameters and setting related to handling ring closures.
Set< APClass > metalCoordinatingAPClasses
List of metal-coordinating APClasses.
Utility class to calculate and manage the alternative ring sizes achievable by formation of Rings.
boolean getCompatibilityOfPair(Vertex vI, Vertex vJ)
void initialize(IAtomContainer origMol, DGraph graph)
Makes this ring size manager work on a specific system that has a molecular representation and a DENO...
Logger getLogger()
Get the name of the program specific logger.
This class is the equivalent of the Pair data structure used in C++ Although AbstractMap....
Definition: ObjectPair.java:30
Toolbox useful when dealing with Ring Closing Attractors and ring closures.
static boolean areSameRingsSet(List< Ring > oldCmb, List< Ring > ringsComb)
Compares two combinations of DENOPTIMRingss and evaluates whether these correspond to the same combin...
Possible chemical bond types an edge can represent.
Definition: Edge.java:303
The type of building block.
Definition: Vertex.java:86