$darkmode
DENOPTIM
EAUtils.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2019 Vishwesh Venkatraman <vishwesh.venkatraman@ntnu.no> and
4 * Marco Foscato <marco.foscato@uib.no>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published
8 * by the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20package denoptim.ga;
21
22import java.io.File;
23import java.io.IOException;
24import java.text.DecimalFormat;
25import java.text.NumberFormat;
26import java.util.ArrayList;
27import java.util.Arrays;
28import java.util.Comparator;
29import java.util.HashMap;
30import java.util.HashSet;
31import java.util.Iterator;
32import java.util.List;
33import java.util.Locale;
34import java.util.Map;
35import java.util.Set;
36import java.util.concurrent.atomic.AtomicInteger;
37import java.util.logging.Level;
38import java.util.logging.Logger;
39
40import org.apache.commons.io.FileUtils;
41import org.apache.commons.io.FilenameUtils;
42import org.openscience.cdk.graph.ShortestPaths;
43import org.openscience.cdk.interfaces.IAtom;
44import org.openscience.cdk.interfaces.IAtomContainer;
45import org.openscience.cdk.isomorphism.Mappings;
46
47import java.util.stream.IntStream;
48
49import denoptim.constants.DENOPTIMConstants;
50import denoptim.exception.DENOPTIMException;
51import denoptim.fitness.FitnessParameters;
52import denoptim.fragmenter.BridgeHeadFindingRule;
53import denoptim.fragmenter.FragmenterTools;
54import denoptim.fragmenter.ScaffoldingPolicy;
55import denoptim.fragspace.FragmentSpace;
56import denoptim.fragspace.FragmentSpaceParameters;
57import denoptim.graph.APClass;
58import denoptim.graph.AttachmentPoint;
59import denoptim.graph.Candidate;
60import denoptim.graph.DGraph;
61import denoptim.graph.Edge.BondType;
62import denoptim.graph.EmptyVertex;
63import denoptim.graph.Fragment;
64import denoptim.graph.GraphPattern;
65import denoptim.graph.RelatedAPPair;
66import denoptim.graph.Ring;
67import denoptim.graph.SymmetricAPs;
68import denoptim.graph.SymmetricSet;
69import denoptim.graph.SymmetricSetWithMode;
70import denoptim.graph.Template;
71import denoptim.graph.Template.ContractLevel;
72import denoptim.graph.Vertex;
73import denoptim.graph.Vertex.BBType;
74import denoptim.graph.rings.CyclicGraphHandler;
75import denoptim.graph.rings.RingClosureParameters;
76import denoptim.graph.rings.RingClosuresArchive;
77import denoptim.io.DenoptimIO;
78import denoptim.logging.CounterID;
79import denoptim.logging.Monitor;
80import denoptim.molecularmodeling.ThreeDimTreeBuilder;
81import denoptim.programs.RunTimeParameters.ParametersType;
82import denoptim.programs.denovo.GAParameters;
83import denoptim.programs.fragmenter.CuttingRule;
84import denoptim.programs.fragmenter.FragmenterParameters;
85import denoptim.utils.DummyAtomHandler;
86import denoptim.utils.GeneralUtils;
87import denoptim.utils.GraphUtils;
88import denoptim.utils.ManySMARTSQuery;
89import denoptim.utils.MoleculeUtils;
90import denoptim.utils.Randomizer;
91import denoptim.utils.RotationalSpaceUtils;
92import denoptim.utils.SizeControlledSet;
93import denoptim.utils.StatUtils;
94
95
101public class EAUtils
102{
103 // cluster the fragments based on their #APs
104 protected static HashMap<Integer, ArrayList<Integer>> fragmentPool;
105
109 private static Locale enUsLocale = new Locale("en", "US");
110
114 private static DecimalFormat df = initialiseFormatter();
115 private static DecimalFormat initialiseFormatter() {
116 DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(
117 enUsLocale);
118 df.setGroupingUsed(false);
119 return df;
120 }
121
122 // for each fragment store the reactions associated with it
123 protected static HashMap<Integer, ArrayList<String>> lstFragmentClass;
124
128 public enum CandidateSource {
129 CROSSOVER, MUTATION, CONSTRUCTION, MANUAL;
130 }
131
132 private static final String NL =System.getProperty("line.separator");
133 private static final String FSEP = System.getProperty("file.separator");
134
135//------------------------------------------------------------------------------
136
143 protected static void createFolderForGeneration(int genId,
144 GAParameters settings)
145 {
146 denoptim.files.FileUtils.createDirectory(
147 EAUtils.getPathNameToGenerationFolder(genId, settings));
148 }
149
150//------------------------------------------------------------------------------
151
158 SizeControlledSet uniqueIDsSet, GAParameters settings)
159 throws DENOPTIMException, IOException
160 {
161 Population population = new Population(settings);
162
163 // Read existing or previously visited UIDs
164 HashSet<String> lstUID = new HashSet<>(1024);
165 if (!settings.getUIDFileIn().equals(""))
166 {
167 EAUtils.readUID(settings.getUIDFileIn(),lstUID);
168 for (String uid : lstUID)
169 {
170 uniqueIDsSet.addNewUniqueEntry(uid);
171 }
172 settings.getLogger().log(Level.INFO, "Read " + lstUID.size()
173 + " known UIDs from " + settings.getUIDFileIn());
174 }
175
176 // Read existing graphs
177 int numFromInitGraphs = 0;
178 String initPopFile = settings.getInitialPopulationFile();
179 if (initPopFile.length() > 0)
180 {
181 EAUtils.getPopulationFromFile(initPopFile, population, uniqueIDsSet,
183 settings);
184 numFromInitGraphs = population.size();
185 settings.getLogger().log(Level.INFO, "Imported " + numFromInitGraphs
186 + " candidates (as graphs) from " + initPopFile);
187 }
188
189 return population;
190 }
191
192//------------------------------------------------------------------------------
193
203 {
205 settings.getCrossoverWeight(),
206 settings.getMutationWeight(),
207 settings.getConstructionWeight(),
208 settings.getRandomizer());
209 }
210
211//------------------------------------------------------------------------------
212
219 public static int chooseNumberOfSitesToMutate(double[] multiSiteMutationProb,
220 double hit)
221 {
222 double tot = 0;
223 for (int i=0; i<multiSiteMutationProb.length; i++)
224 tot = tot + multiSiteMutationProb[i];
225
226 double scaledHit = hit * tot;
227
228 double min = 0;
229 double max = 0;
230 int choice = 0;
231 for (int i=0; i<multiSiteMutationProb.length; i++)
232 {
233 max = max + multiSiteMutationProb[i];
234 if (min < scaledHit && scaledHit <= max)
235 {
236 choice = i;
237 break;
238 }
239 min = Math.max(min,min+multiSiteMutationProb[i]);
240 }
241 return choice;
242 }
243
244//------------------------------------------------------------------------------
245
259 double xoverWeight, double mutWeight, double newWeight,
260 Randomizer randomizer)
261 {
262 double hit = randomizer.nextDouble()
263 * (xoverWeight + mutWeight + newWeight);
264 if (hit <= xoverWeight)
265 {
267 } else if (xoverWeight < hit && hit <= (mutWeight+xoverWeight))
268 {
270 } else {
272 }
273 }
274
275//------------------------------------------------------------------------------
276
288 protected static List<Candidate> buildCandidatesByXOver(
289 List<Candidate> eligibleParents, Population population,
290 Monitor mnt, GAParameters settings) throws DENOPTIMException
291 {
292 return buildCandidatesByXOver(eligibleParents, population, mnt,
293 null, -1, -1, settings, settings.maxOffsprintFromXover());
294 }
295
296//------------------------------------------------------------------------------
297
309 List<Candidate> eligibleParents, Population population,
310 Monitor mnt, GAParameters settings) throws DENOPTIMException
311 {
312 return buildCandidateByXOver(eligibleParents, population, mnt,
313 null, -1, -1, settings);
314 }
315
316//------------------------------------------------------------------------------
317
343 List<Candidate> eligibleParents, Population population,
344 Monitor mnt, int[] choiceOfParents, int choiceOfXOverSites,
345 int choiceOfOffstring, GAParameters settings)
346 throws DENOPTIMException
347 {
348 List<Candidate> cands = buildCandidatesByXOver(eligibleParents,
349 population, mnt,
350 choiceOfParents, choiceOfXOverSites, choiceOfOffstring,
351 settings, 1);
352 if (cands.size()>0)
353 return cands.get(0);
354 else
355 return null;
356 }
357
358//------------------------------------------------------------------------------
359
387 protected static List<Candidate> buildCandidatesByXOver(
388 List<Candidate> eligibleParents, Population population,
389 Monitor mnt, int[] choiceOfParents, int choiceOfXOverSites,
390 int choiceOfOffstring, GAParameters settings,
391 int maxCandidatesToReturn) throws DENOPTIMException
392 {
394 if (settings.containsParameters(ParametersType.FS_PARAMS))
395 {
396 fsParams = (FragmentSpaceParameters)settings.getParameters(
398 }
399 FragmentSpace fragSpace = fsParams.getFragmentSpace();
400
401 mnt.increase(CounterID.XOVERATTEMPTS);
402 mnt.increase(CounterID.NEWCANDIDATEATTEMPTS);
403
404 int numatt = 1;
405
406 // Identify a pair of parents that can do crossover, and a pair of
407 // vertexes from which we can define a subgraph (or a branch) to swap
408 XoverSite xos = null;
409 boolean foundPars = false;
410 while (numatt < settings.getMaxGeneticOpAttempts())
411 {
412 if (fragSpace.useAPclassBasedApproach())
413 {
414 xos = EAUtils.performFBCC(eligibleParents,
415 population, choiceOfParents, choiceOfXOverSites,
416 settings);
417 if (xos == null)
418 {
419 numatt++;
420 continue;
421 }
422 } else {
423 //TODO: make it reproducible using choiceOfParents and choiceOfXOverSites
425 eligibleParents, 2, settings);
426 if (parents[0] == null || parents[1] == null)
427 {
428 numatt++;
429 continue;
430 }
431 //NB: this does not go into templates!
432 DGraph gpA = parents[0].getGraph();
433 List<Vertex> subGraphA = new ArrayList<Vertex>();
435 gpA, settings.getRandomizer()),subGraphA);
436
437 DGraph gpB = parents[1].getGraph();
438 List<Vertex> subGraphB = new ArrayList<Vertex>();
440 gpB, settings.getRandomizer()),subGraphB);
441 }
442 foundPars = true;
443 break;
444 }
445 mnt.increaseBy(CounterID.XOVERPARENTSEARCH, numatt);
446
447 if (!foundPars)
448 {
450 mnt.increase(CounterID.FAILEDXOVERATTEMPTS);
451 return new ArrayList<Candidate>();
452 }
453
454 Candidate cA = null, cB = null;
455 Vertex vA = null, vB = null;
456 vA = xos.getA().get(0);
457 vB = xos.getB().get(0);
458 DGraph gA = vA.getGraphOwner();
460 DGraph gB = vB.getGraphOwner();
462
463 String candIdA = cA.getName();
464 String candIdB = cB.getName();
465 int gid1 = gA.getGraphId();
466 int gid2 = gB.getGraphId();
467
468 // Start building the offspring
469 XoverSite xosOnClones = xos.projectToClonedGraphs();
470 DGraph gAClone = xosOnClones.getA().get(0).getGraphOwner();
471 DGraph gBClone = xosOnClones.getB().get(0).getGraphOwner();
472
473 try
474 {
475 if (!GraphOperations.performCrossover(xosOnClones, fragSpace,
476 settings.maxAPMappingCombinations))
477 {
479 mnt.increase(CounterID.FAILEDXOVERATTEMPTS);
480 return new ArrayList<Candidate>();
481 }
482 } catch (Throwable t) {
483 if (!settings.xoverFailureTolerant)
484 {
485 t.printStackTrace();
486 ArrayList<DGraph> parents = new ArrayList<DGraph>();
487 parents.add(gA);
488 parents.add(gB);
489 DenoptimIO.writeGraphsToSDF(new File(settings.getDataDirectory()
490 + "_failed_xover.sdf"), parents, true,
491 settings.getLogger(), settings.getRandomizer());
492 throw new DENOPTIMException("Error while performing crossover! "+NL
493 + "XOverSite: " + xos.toString() + NL
494 + "XOverSite(C): " + xosOnClones.toString() + NL
495 + " Please, report this to the authors ",t);
496 }
498 mnt.increase(CounterID.FAILEDXOVERATTEMPTS);
499 return new ArrayList<Candidate>();
500 }
503 String lstIdVA = "";
504 for (Vertex v : xos.getA())
505 lstIdVA = lstIdVA + "_" + v.getVertexId();
506 String lstIdVB = "";
507 for (Vertex v : xos.getB())
508 lstIdVB = lstIdVB + "_" + v.getVertexId();
509 String[] msgs = new String[2];
510 msgs[0] = "Xover: "
511 + "Gen:" + cA.getGeneration() + " Cand:" + candIdA
512 + "|" + gid1 + "|" + lstIdVA
513 + " X "
514 + "Gen:" + cB.getGeneration() + " Cand:" + candIdB
515 + "|" + gid2 + "|" + lstIdVB;
516 msgs[1] = "Xover: "
517 + "Gen:" + cB.getGeneration() + " Cand:" + candIdB
518 + "|" + gid2 + "|" + lstIdVB
519 + " X "
520 + "Gen:" + cA.getGeneration() + " Cand:" + candIdA
521 + "|" + gid1 + "|" + lstIdVA;
522
523 DGraph[] graphsAffectedByXover = new DGraph[2];
524 graphsAffectedByXover[0] = gAClone;
525 graphsAffectedByXover[1] = gBClone;
526
527 List<Candidate> validOffspring = new Population(settings);
528 for (int ig=0; ig<graphsAffectedByXover.length; ig++)
529 {
530 DGraph g = graphsAffectedByXover[ig];
531
532 // It makes sense to do this on the possibly embedded graph and not
533 // on their embedding owners because there cannot be any new cycle
534 // affecting the latter, but there can be ones affecting the first.
535 if (!EAUtils.setupRings(null, g, settings))
536 {
538 continue;
539 }
540
541 // Finalize the graph that is at the outermost level
542 DGraph gOutermost = g.getOutermostGraphOwner();
543 gOutermost.addCappingGroups(fragSpace);
544 gOutermost.renumberGraphVertices();
545 gOutermost.setLocalMsg(msgs[ig]);
546
547 // Consider if the result can be used to define a new candidate
548 Object[] res = null;
549 try
550 {
551 res = gOutermost.checkConsistency(settings);
552 } catch (NullPointerException|IllegalArgumentException e)
553 {
554 if (!settings.xoverGraphFailedEvalTolerant)
555 {
556 ArrayList<DGraph> parents = new ArrayList<DGraph>();
557 parents.add(gA);
558 parents.add(gB);
559 parents.add(gAClone);
560 parents.add(gBClone);
561 DenoptimIO.writeGraphsToSDF(new File(settings.getDataDirectory()
562 + "_failed_xover-ed_check.sdf"), parents, true,
563 settings.getLogger(), settings.getRandomizer());
564 throw e;
565 } else {
566 res = null;
567 }
568 }
569 if (res != null)
570 {
571 if (!EAUtils.setupRings(res, gOutermost, settings))
572 {
574 res = null;
575 }
576 } else {
578 }
579
580 // Check if the chosen combination gives rise to forbidden ends
581 for (Vertex rcv : gOutermost.getFreeRCVertices())
582 {
583 APClass apc = rcv.getEdgeToParent().getSrcAP().getAPClass();
584 if (fragSpace.getCappingMap().get(apc)==null
585 && fragSpace.getForbiddenEndList().contains(apc))
586 {
588 res = null;
589 }
590 }
591 if (res == null)
592 {
593 mnt.increase(CounterID.FAILEDXOVERATTEMPTS);
594 gOutermost.cleanup();
595 gOutermost = null;
596 continue;
597 }
598
599 // OK: we can now use it to make a new candidate
600 Candidate offspring = new Candidate(gOutermost);
601 offspring.setUID(res[0].toString().trim());
602 offspring.setSmiles(res[1].toString().trim());
603 offspring.setChemicalRepresentation((IAtomContainer) res[2]);
604
605 validOffspring.add(offspring);
606 }
607
608 if (validOffspring.size() == 0)
609 {
610 mnt.increase(CounterID.FAILEDXOVERATTEMPTS);
611 return new ArrayList<Candidate>();
612 }
613
614 if (maxCandidatesToReturn==1)
615 {
616 Candidate chosenOffspring = null;
617 if (choiceOfOffstring<0)
618 {
619 chosenOffspring = settings.getRandomizer().randomlyChooseOne(
620 validOffspring);
621 chosenOffspring.setName("M" + GeneralUtils.getPaddedString(
624 } else {
625 chosenOffspring = validOffspring.get(choiceOfOffstring);
626 }
627 validOffspring.retainAll(Arrays.asList(chosenOffspring));
628 } else {
629 for (Candidate cand : validOffspring)
630 {
634 }
635 }
636 return validOffspring;
637 }
638
639//------------------------------------------------------------------------------
640
642 List<Candidate> eligibleParents, Monitor mnt,
643 GAParameters settings) throws DENOPTIMException
644 {
646 if (settings.containsParameters(ParametersType.FS_PARAMS))
647 {
648 fsParams = (FragmentSpaceParameters)settings.getParameters(
650 }
651 FragmentSpace fragSpace = fsParams.getFragmentSpace();
652
653 mnt.increase(CounterID.MUTATTEMPTS);
654 mnt.increase(CounterID.NEWCANDIDATEATTEMPTS);
655
656 int numatt = 0;
657 Candidate parent = null;
658 while (numatt < settings.getMaxGeneticOpAttempts())
659 {
660 parent = EAUtils.selectBasedOnFitness(eligibleParents,1, settings)[0];
661 if (parent == null)
662 {
663 numatt++;
664 continue;
665 }
666 break;
667 }
668 mnt.increaseBy(CounterID.MUTPARENTSEARCH,numatt);
669 if (parent == null)
670 {
671 mnt.increase(CounterID.FAILEDMUTATTEMTS);
672 return null;
673 }
674
675 DGraph graph = parent.getGraph().clone();
676 graph.renumberGraphVertices();
677
678 String parentMolName = FilenameUtils.getBaseName(parent.getSDFFile());
679 int parentGraphId = parent.getGraph().getGraphId();
680 graph.setLocalMsg("Mutation:"
681 + " Gen:" + parent.getGeneration() + " Cand:" + parentMolName
682 + "|" + parentGraphId);
683
684 if (!GraphOperations.performMutation(graph, mnt, settings))
685 {
687 mnt.increase(CounterID.FAILEDMUTATTEMTS);
688 return null;
689 }
690
692
693 graph.addCappingGroups(fragSpace);
694
695 Object[] res = null;
696 try
697 {
698 res = graph.checkConsistency(settings);
699 } catch (NullPointerException|IllegalArgumentException e)
700 {
701 if (!settings.mutatedGraphFailedEvalTolerant)
702 {
703 settings.getLogger().log(Level.INFO, "WRITING DEBUG FILE for "
704 + graph.getLocalMsg());
705 DenoptimIO.writeGraphToSDF(new File("debug_evalGrp_parent.sdf"),
706 parent.getGraph(),false, settings.getLogger(),
707 settings.getRandomizer());
708 DenoptimIO.writeGraphToSDF(new File("debug_evalGrp_curr.sdf"),
709 graph,false, settings.getLogger(),
710 settings.getRandomizer());
711 throw e;
712 } else {
713 res = null;
714 mnt.increase(CounterID.FAILEDMUTATTEMTS_EVAL);
715 }
716 }
717
718 if (res != null)
719 {
720 if (!EAUtils.setupRings(res,graph,settings))
721 {
722 res = null;
724 }
725 } else {
726 mnt.increase(CounterID.FAILEDMUTATTEMTS_EVAL);
727 }
728
729 // Check if the chosen combination gives rise to forbidden ends
730 //TODO this should be considered already when making the list of
731 // possible combination of rings
732 for (Vertex rcv : graph.getFreeRCVertices())
733 {
734 APClass apc = rcv.getEdgeToParent().getSrcAP().getAPClass();
735 if (fragSpace.getCappingMap().get(apc)==null
736 && fragSpace.getForbiddenEndList().contains(apc))
737 {
738 res = null;
740 }
741 }
742
743 if (res == null)
744 {
745 graph.cleanup();
746 graph = null;
747 mnt.increase(CounterID.FAILEDMUTATTEMTS);
748 return null;
749 }
750
751 Candidate offspring = new Candidate(graph);
752 offspring.setUID(res[0].toString().trim());
753 offspring.setSmiles(res[1].toString().trim());
754 offspring.setChemicalRepresentation((IAtomContainer) res[2]);
755 offspring.setName("M" + GeneralUtils.getPaddedString(
758
759 return offspring;
760 }
761
762//------------------------------------------------------------------------------
763
764 //TODO: move to IO class
765 protected static Candidate readCandidateFromFile(File srcFile, Monitor mnt,
766 GAParameters settings) throws DENOPTIMException
767 {
768 mnt.increase(CounterID.MANUALADDATTEMPTS);
769 mnt.increase(CounterID.NEWCANDIDATEATTEMPTS);
770
771 ArrayList<DGraph> graphs;
772 try
773 {
774 graphs = DenoptimIO.readDENOPTIMGraphsFromFile(srcFile);
775 } catch (Exception e)
776 {
777 e.printStackTrace();
779 String msg = "Could not read graphs from file " + srcFile
780 + ". No candidate generated!";
781 settings.getLogger().log(Level.SEVERE, msg);
782 return null;
783 }
784 if (graphs.size() == 0 || graphs.size() > 1)
785 {
787 String msg = "Found " + graphs.size() + " graphs in file " + srcFile
788 + ". I expect one and only one graph. "
789 + "No candidate generated!";
790 settings.getLogger().log(Level.SEVERE, msg);
791 return null;
792 }
793
794 DGraph graph = graphs.get(0);
795 if (graph == null)
796 {
798 String msg = "Null graph from file " + srcFile
799 + ". Expected one and only one graph. "
800 + "No candidate generated!";
801 settings.getLogger().log(Level.SEVERE, msg);
802 return null;
803 }
804 graph.setLocalMsg("MANUAL_ADD");
805
806 // We expect users to know what they ask for. Therefore, we do
807 // evaluate the graph, but in a permissive manner, meaning that
808 // several filters are disabled to permit the introduction of graphs
809 // that cannot be generated automatically.
810 Object[] res = graph.checkConsistency(settings, true);
811
812 if (res == null)
813 {
814 graph.cleanup();
817 return null;
818 }
819
820 Candidate candidate = new Candidate(graph);
821 candidate.setUID(res[0].toString().trim());
822 candidate.setSmiles(res[1].toString().trim());
823 candidate.setChemicalRepresentation((IAtomContainer) res[2]);
824
825 candidate.setName("M" + GeneralUtils.getPaddedString(
828
829 String msg = "Candidate " + candidate.getName() + " is imported from "
830 + srcFile;
831 settings.getLogger().log(Level.INFO, msg);
832
833 return candidate;
834 }
835
836//------------------------------------------------------------------------------
837
839 GAParameters settings)
840 throws DENOPTIMException
841 {
843 if (settings.containsParameters(ParametersType.FS_PARAMS))
844 {
845 fsParams = (FragmentSpaceParameters)settings.getParameters(
847 }
848 FragmentSpace fragSpace = fsParams.getFragmentSpace();
849
850 mnt.increase(CounterID.BUILDANEWATTEMPTS);
851 mnt.increase(CounterID.NEWCANDIDATEATTEMPTS);
852
853 DGraph graph = EAUtils.buildGraph(settings);
854 if (graph == null)
855 {
857 mnt.increase(CounterID.FAILEDBUILDATTEMPTS);
858 return null;
859 }
860 graph.setLocalMsg("NEW");
861
862 Object[] res = graph.checkConsistency(settings);
863
864 if (res != null)
865 {
866 if (!EAUtils.setupRings(res,graph, settings))
867 {
868 graph.cleanup();
870 mnt.increase(CounterID.FAILEDBUILDATTEMPTS);
871 return null;
872 }
873 } else {
874 graph.cleanup();
876 mnt.increase(CounterID.FAILEDBUILDATTEMPTS);
877 return null;
878 }
879
880 // Check if the chosen combination gives rise to forbidden ends
881 //TODO: this should be considered already when making the list of
882 // possible combination of rings
883 for (Vertex rcv : graph.getFreeRCVertices())
884 {
885 // Also exclude any RCV that is not bound to anything?
886 if (rcv.getEdgeToParent() == null)
887 {
888 res = null;
890 }
891 if (rcv.getEdgeToParent() == null)
892 {
893 // RCV as scaffold! Ignore special case
894 continue;
895 }
896 APClass apc = rcv.getEdgeToParent().getSrcAP().getAPClass();
897 if (fragSpace.getCappingMap().get(apc)==null
898 && fragSpace.getForbiddenEndList().contains(apc))
899 {
900 res = null;
902 }
903 }
904
905 if (res == null)
906 {
907 graph.cleanup();
908 mnt.increase(CounterID.FAILEDBUILDATTEMPTS);
909 return null;
910 }
911
912 Candidate candidate = new Candidate(graph);
913 candidate.setUID(res[0].toString().trim());
914 candidate.setSmiles(res[1].toString().trim());
915 candidate.setChemicalRepresentation((IAtomContainer) res[2]);
916
917 candidate.setName("M" + GeneralUtils.getPaddedString(
920
921 return candidate;
922 }
923
924//------------------------------------------------------------------------------
925
939 public static Candidate buildCandidateByFragmentingMolecule(IAtomContainer mol,
940 Monitor mnt, GAParameters settings, int index) throws DENOPTIMException
941 {
943 if (settings.containsParameters(ParametersType.FS_PARAMS))
944 {
945 fsParams = (FragmentSpaceParameters) settings.getParameters(
947 }
948 FragmentSpace fragSpace = fsParams.getFragmentSpace();
949
951 if (settings.containsParameters(ParametersType.FRG_PARAMS))
952 {
953 frgParams = (FragmenterParameters) settings.getParameters(
955 }
956
957 if (frgParams.getCuttingRules()==null
958 || frgParams.getCuttingRules().isEmpty())
959 {
960 throw new DENOPTIMException("Request to generate candidates by "
961 + "fragmentation but no cutting rules provided. Please,"
962 + "add FRG-CUTTINGRULESFILE=path/to/your/file to the "
963 + "input.");
964 }
965 mnt.increase(CounterID.CONVERTBYFRAGATTEMPTS);
966 mnt.increase(CounterID.NEWCANDIDATEATTEMPTS);
967
968 // Adjust molecular representation to our settings
969 if (!FragmenterTools.prepareMolToFragmentation(mol, frgParams, index))
970 return null;
971
972 // Do actual fragmentation
973 DGraph graph = null;
974 try {
976 frgParams.getCuttingRules(), settings.getLogger(),
977 frgParams.getScaffoldingPolicy(),
978 frgParams.getLinearAngleLimit(),
979 frgParams.embedRingsInTemplate(),
980 frgParams.getEmbeddedRingsContract(),
981 fragSpace, mnt);
982 } catch (DENOPTIMException de)
983 {
984 String msg = "Unable to convert molecule (" + mol.getAtomCount()
985 + " atoms) to DENOPTIM graph. " + de.getMessage();
986 settings.getLogger().log(Level.WARNING, msg);
987 }
988 if (graph == null)
989 {
991 return null;
992 }
993
994 graph.setLocalMsg("INITIAL_MOL_FRAGMENTED");
995
996 Object[] res = graph.checkConsistency(settings);
997 if (res == null)
998 {
999 graph.cleanup();
1001 return null;
1002 }
1003
1004 Candidate candidate = new Candidate(graph);
1005 candidate.setUID(res[0].toString().trim());
1006 candidate.setSmiles(res[1].toString().trim());
1007 candidate.setChemicalRepresentation((IAtomContainer) res[2]);
1008
1009 candidate.setName("M" + GeneralUtils.getPaddedString(
1012
1013 return candidate;
1014 }
1015
1016//------------------------------------------------------------------------------
1017
1029 public static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol,
1030 List<CuttingRule> cuttingRules, Logger logger,
1031 ScaffoldingPolicy scaffoldingPolicy)
1032 throws DENOPTIMException
1033 {
1034 return makeGraphFromFragmentationOfMol(mol, cuttingRules, logger,
1035 scaffoldingPolicy, 190, new FragmentSpace());
1036 // NB: and angle of 190 means we are not adding Du on linearities
1037 // because the max possible bond angle is 180.
1038 }
1039
1040//------------------------------------------------------------------------------
1041
1055 public static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol,
1056 List<CuttingRule> cuttingRules, Logger logger,
1057 ScaffoldingPolicy scaffoldingPolicy, double linearAngleLimit)
1058 throws DENOPTIMException
1059 {
1060 return makeGraphFromFragmentationOfMol(mol, cuttingRules, logger,
1061 scaffoldingPolicy, linearAngleLimit, new FragmentSpace());
1062 }
1063
1064//------------------------------------------------------------------------------
1065
1079 public static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol,
1080 List<CuttingRule> cuttingRules, Logger logger,
1081 ScaffoldingPolicy scaffoldingPolicy, FragmentSpace fragSpace)
1082 throws DENOPTIMException
1083 {
1084 return makeGraphFromFragmentationOfMol(mol, cuttingRules, logger,
1085 scaffoldingPolicy, 190, fragSpace);
1086 // NB: and angle of 190 means we are not adding Du on linearities
1087 // because the max possible bond angle is 180.
1088 }
1089
1090//------------------------------------------------------------------------------
1091
1107 public static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol,
1108 List<CuttingRule> cuttingRules, Logger logger,
1109 ScaffoldingPolicy scaffoldingPolicy, double linearAngleLimit,
1110 FragmentSpace fragSpace)
1111 throws DENOPTIMException
1112 {
1113 return makeGraphFromFragmentationOfMol(mol, cuttingRules, logger,
1114 scaffoldingPolicy, linearAngleLimit, false, null,
1115 fragSpace, null);
1116 }
1117
1118//------------------------------------------------------------------------------
1119
1141 public static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol,
1142 List<CuttingRule> cuttingRules, Logger logger,
1143 ScaffoldingPolicy scaffoldingPolicy, double linearAngleLimit,
1144 boolean embedRingsInTemplates, ContractLevel ringTmplContract,
1145 FragmentSpace fragSpace, Monitor monitor)
1146 throws DENOPTIMException
1147 {
1149 frgParams.setCuttingRules(cuttingRules);
1150 frgParams.setScaffoldingPolicy(scaffoldingPolicy);
1151 frgParams.setLinearAngleLimit(linearAngleLimit);
1152 frgParams.setEmbedRingsInTemplate(embedRingsInTemplates);
1153 frgParams.setEmbeddedRingsContract(ringTmplContract);
1154 return makeGraphFromFragmentationOfMol(mol, frgParams, fragSpace, monitor);
1155 }
1156
1157//------------------------------------------------------------------------------
1158
1166 public static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol,
1167 FragmenterParameters frgParams) throws DENOPTIMException
1168 {
1169 FragmentSpace fragSpace = null;
1170 if (frgParams.containsParameters(ParametersType.FS_PARAMS))
1171 {
1172 fragSpace = ((FragmentSpaceParameters) frgParams.getParameters(
1173 ParametersType.FS_PARAMS)).getFragmentSpace();
1174 } else {
1175 fragSpace = new FragmentSpace();
1176 }
1177 return makeGraphFromFragmentationOfMol(mol, frgParams, fragSpace, null);
1178 }
1179
1180//------------------------------------------------------------------------------
1181
1203 public static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol,
1204 FragmenterParameters frgParams, FragmentSpace fragSpace, Monitor monitor)
1205 throws DENOPTIMException
1206 {
1207 double linearAngleLimit = frgParams.getLinearAngleLimit();
1208 boolean embedRingsInTemplates = frgParams.embedRingsInTemplate();
1209 ContractLevel ringTmplContract = frgParams.getEmbeddedRingsContract();
1210 ScaffoldingPolicy scaffoldingPolicy = frgParams.getScaffoldingPolicy();
1211
1212 // We expect only Fragments here.
1213 List<Vertex> fragments = FragmenterTools.fragmentation(mol, frgParams);
1214
1215 for (Vertex v : fragments)
1216 {
1217 Fragment frag = (Fragment) v;
1218
1219 // This is done to set the symmetry relations in each vertex
1220 frag.updateAPs();
1221
1222 // Add linearity-breaking dummy atoms
1223 DummyAtomHandler.addDummiesOnLinearities(frag, linearAngleLimit);
1224 }
1225 if (fragments.size()==0)
1226 {
1227 if (monitor!=null)
1228 {
1230 }
1231 throw new DENOPTIMException("Fragmentation of molecule with "
1232 + mol.getAtomCount() + " atoms produced 0 fragments.");
1233 }
1234
1235 // Define which fragment is the scaffold
1236 Vertex scaffold = null;
1237 switch (scaffoldingPolicy)
1238 {
1239 case ELEMENT:
1240 {
1241 for (Vertex v : fragments)
1242 {
1243 if (v instanceof Fragment)
1244 {
1245 boolean setAsScaffold = false;
1246 IAtomContainer iac = v.getIAtomContainer();
1247 for (IAtom atm : iac.atoms())
1248 {
1249 if (scaffoldingPolicy.label.equals(
1251 {
1252 setAsScaffold = true;
1253 break;
1254 }
1255 }
1256 if (setAsScaffold)
1257 {
1258 scaffold = v;
1259 break;
1260 }
1261 }
1262 }
1263 break;
1264 }
1265
1266 default:
1267 case LARGEST_FRAGMENT:
1268 {
1269 try {
1270 scaffold = fragments.stream()
1271 .max(Comparator.comparing(
1273 .get();
1274 } catch (Exception e)
1275 {
1276 if (monitor!=null)
1277 {
1279 }
1280 throw new DENOPTIMException("Cannot get largest fragment "
1281 + "among " + fragments.size() + " fragments.", e);
1282 }
1283 break;
1284 }
1285 }
1286 if (scaffold==null)
1287 {
1288 if (monitor!=null)
1289 {
1291 }
1292 throw new DENOPTIMException("No fragment matches criteria to be "
1293 + "identified as the "
1294 + BBType.SCAFFOLD.toString().toLowerCase() + ".");
1295 }
1296 scaffold.setVertexId(0);
1298
1299 // Build the graph
1300 DGraph graph = new DGraph();
1301 graph.addVertex(scaffold);
1302 AtomicInteger vId = new AtomicInteger(1);
1303 for (int i=1; i<fragments.size(); i++)
1304 {
1305 appendVertexesToGraphFollowingEdges(graph, vId, fragments);
1306 }
1307
1308 // Set symmetry relations: these depend on which scaffold we have chosen
1309 graph.detectSymVertexSets();
1310
1311 // Identify capping groups, i.e., fragments that reflect the capping
1312 // groups found in the fragment space, if any.
1313 if (fragSpace!=null && fragSpace.getCappingMap()!=null)
1314 {
1315 for (Vertex v : graph.getVertexList())
1316 {
1317 if (v.getAttachmentPoints().size()!=1 || v.isRCV())
1318 continue;
1319
1320 APClass srcAPC = v.getAP(0).getLinkedAPThroughout().getAPClass();
1321 APClass capAPC = fragSpace.getAPClassOfCappingVertex(srcAPC);
1322 Vertex cap = fragSpace.getCappingVertexWithAPClass(capAPC);
1323 if (cap==null)
1324 continue;
1325
1326 if (!(v instanceof Fragment && cap instanceof Fragment))
1327 continue;
1328
1329 Fragment f = (Fragment) v;
1330 // NB: here we ignore APClasses and Du atoms
1331 if (f.isIsomorphicTo(cap, true))
1332 {
1334 v.getAP(0).setAPClass(capAPC);
1335 }
1336 }
1337 }
1338
1339 if (embedRingsInTemplates)
1340 {
1341 try {
1343 fragSpace, ringTmplContract);
1344 } catch (DENOPTIMException e) {
1345 graph.cleanup();
1346 if (monitor!=null)
1347 {
1349 }
1350 return null;
1351 }
1352 }
1353
1354 return graph;
1355 }
1356
1357//------------------------------------------------------------------------------
1358
1360 AtomicInteger vId, List<Vertex> vertexes) throws DENOPTIMException
1361 {
1362 // We seek for the last and non-RCV vertex added to the graph
1363 Vertex lastlyAdded = null;
1364 for (int i=-1; i>-4; i--)
1365 {
1366 lastlyAdded = graph.getVertexList().get(
1367 graph.getVertexList().size()+i);
1368 if (!lastlyAdded.isRCV())
1369 break;
1370 }
1371 for (AttachmentPoint apI : lastlyAdded.getAttachmentPoints())
1372 {
1373 if (!apI.isAvailable())
1374 continue;
1375
1376 for (int j=0; j<vertexes.size(); j++)
1377 {
1378 Vertex fragJ = vertexes.get(j);
1379
1380 boolean ringClosure = false;
1381 if (graph.containsVertex(fragJ))
1382 {
1383 ringClosure = true;
1384 }
1385 for (AttachmentPoint apJ : fragJ.getAttachmentPoints())
1386 {
1387 if (apI==apJ)
1388 continue;
1389
1390 if (!apI.isAvailable() || !apJ.isAvailable())
1391 continue;
1392
1393 if (apI.getCutId()==apJ.getCutId())
1394 {
1395 if (ringClosure)
1396 {
1399 BondType.ANY));
1401 rcvI.setVertexId(vId.getAndIncrement());
1402 graph.appendVertexOnAP(apI, rcvI.getAP(0));
1403
1407 rcvJ.setVertexId(vId.getAndIncrement());
1408 graph.appendVertexOnAP(apJ, rcvJ.getAP(0));
1409 graph.addRing(rcvI, rcvJ);
1410 } else {
1412 fragJ.setVertexId(vId.getAndIncrement());
1413 graph.appendVertexOnAP(apI, apJ);
1414
1415 // Recursion into the branch of the graph that is
1416 // rooted onto the lastly added vertex
1418 vertexes);
1419 }
1420 }
1421 }
1422 }
1423 }
1424 }
1425
1426//------------------------------------------------------------------------------
1427
1438 public static void outputPopulationDetails(Population population,
1439 String filename, GAParameters settings, boolean printpathNames)
1440 throws DENOPTIMException
1441 {
1442 StringBuilder sb = new StringBuilder(512);
1444 sb.append(NL);
1445
1446 df.setMaximumFractionDigits(settings.getPrecisionLevel());
1447 df.setMinimumFractionDigits(settings.getPrecisionLevel());
1448
1449 // NB: we consider the configured size of the population, not the actual
1450 // size of list representing the population.
1451 String stats = "";
1452 synchronized (population)
1453 {
1454 List<Candidate> popMembers = new ArrayList<Candidate>();
1455 for (int i=0; i<settings.getPopulationSize(); i++)
1456 {
1457 Candidate mol = population.get(i);
1458 popMembers.add(mol);
1459 if (mol != null)
1460 {
1461 String mname = new File(mol.getSDFFile()).getName();
1462 if (mname != null)
1463 sb.append(String.format("%-20s", mname));
1464
1465 sb.append(String.format("%-20s",
1466 mol.getGraph().getGraphId()));
1467 sb.append(String.format("%-30s", mol.getUID()));
1468 sb.append(df.format(mol.getFitness()));
1469
1470 if (printpathNames)
1471 {
1472 sb.append(" ").append(mol.getSDFFile());
1473 }
1474
1475 sb.append(System.getProperty("line.separator"));
1476 }
1477 }
1478
1479 // calculate descriptive statistics for the population
1480 stats = getSummaryStatistics(population, settings);
1481
1482 if (settings.savePopFile())
1483 {
1484 File dest = new File(filename.replaceAll("\\.txt$", ".sdf"));
1485 DenoptimIO.writeCandidatesToFile(dest, popMembers, false);
1486 }
1487 }
1488 if (stats.trim().length() > 0)
1489 sb.append(stats);
1490 DenoptimIO.writeData(filename, sb.toString(), false);
1491
1492 sb.setLength(0);
1493 }
1494
1495//------------------------------------------------------------------------------
1496
1497 private static String getSummaryStatistics(Population popln,
1498 GAParameters settings)
1499 {
1500 double[] fitness = getFitnesses(popln);
1501 double sdev = StatUtils.stddev(fitness, true);
1502 String res = "";
1503 df.setMaximumFractionDigits(settings.getPrecisionLevel());
1504
1505 StringBuilder sb = new StringBuilder(128);
1506 sb.append(NL+NL+"#####POPULATION SUMMARY#####"+NL);
1507 int n = popln.size();
1508 sb.append(String.format("%-30s", "SIZE:"));
1509 sb.append(String.format("%12s", n));
1510 sb.append(NL);
1511 double f;
1512 f = StatUtils.max(fitness);
1513 sb.append(String.format("%-30s", "MAX:")).append(df.format(f));
1514 sb.append(NL);
1515 f = StatUtils.min(fitness);
1516 sb.append(String.format("%-30s", "MIN:")).append(df.format(f));
1517 sb.append(NL);
1518 f = StatUtils.mean(fitness);
1519 sb.append(String.format("%-30s", "MEAN:")).append(df.format(f));
1520 sb.append(NL);
1521 f = StatUtils.median(fitness);
1522 sb.append(String.format("%-30s", "MEDIAN:")).append(df.format(f));
1523 sb.append(NL);
1524 f = StatUtils.stddev(fitness, true);
1525 sb.append(String.format("%-30s", "STDDEV:")).append(df.format(f));
1526 sb.append(NL);
1527 if (sdev > 0.0001)
1528 {
1529 f = StatUtils.skewness(fitness, true);
1530 sb.append(String.format("%-30s", "SKEW:")).append(df.format(f));
1531 sb.append(NL);
1532 } else {
1533 sb.append(String.format("%-30s", "SKEW:")).append(" NaN (sdev too small)");
1534 sb.append(NL);
1535 }
1536
1537 res = sb.toString();
1538 sb.setLength(0);
1539
1540 return res;
1541 }
1542
1543//------------------------------------------------------------------------------
1544
1555 List<Candidate> eligibleParents, int number, GAParameters settings)
1556 {
1557 Candidate[] mates = new Candidate[number];
1558 switch (settings.getSelectionStrategyType())
1559 {
1560 case 1:
1561 mates = SelectionHelper.performTournamentSelection(eligibleParents,
1562 number, settings);
1563 break;
1564 case 2:
1565 mates = SelectionHelper.performRWS(eligibleParents, number, settings);
1566 break;
1567 case 3:
1568 mates = SelectionHelper.performSUS(eligibleParents, number, settings);
1569 break;
1570 case 4:
1571 mates = SelectionHelper.performRandomSelection(eligibleParents, number,
1572 settings);
1573 break;
1574 }
1575
1576 if (settings.recordMateSelection())
1577 {
1578 String matesStr="";
1579 for (int i=0; i < mates.length; i++)
1580 {
1581 if (i>0)
1582 matesStr = matesStr + settings.NL;
1583 matesStr = matesStr + mates[i].getUID();
1584 }
1585 try
1586 {
1587 DenoptimIO.writeData(settings.getMonitorFile()+".mates",
1588 matesStr, true);
1589 } catch (DENOPTIMException e)
1590 {
1591 // TODO Auto-generated catch block
1592 e.printStackTrace();
1593 }
1594 }
1595
1596 return mates;
1597 }
1598
1599//------------------------------------------------------------------------------
1600
1605 Randomizer randomizer)
1606 {
1607 List<Vertex> candidates = new ArrayList<Vertex>(
1608 g.getVertexList());
1609 candidates.removeIf(v ->
1610 v.getBuildingBlockType() == BBType.SCAFFOLD
1611 || v.getBuildingBlockType() == BBType.CAP);
1612 return randomizer.randomlyChooseOne(candidates);
1613 }
1614
1615//------------------------------------------------------------------------------
1616
1632 protected static XoverSite performFBCC(
1633 List<Candidate> eligibleParents, Population population,
1634 int[] choiceOfParents, int choiceOfXOverSites, GAParameters settings)
1635 {
1636 Candidate parentA = null;
1637 if (choiceOfParents==null)
1638 parentA = selectBasedOnFitness(eligibleParents, 1, settings)[0];
1639 else
1640 parentA = eligibleParents.get(choiceOfParents[0]);
1641
1642 if (parentA == null)
1643 return null;
1644
1647 {
1648 fsParams = (FragmentSpaceParameters)settings.getParameters(
1650 }
1651 FragmentSpace fragSpace = fsParams.getFragmentSpace();
1652 List<Candidate> matesCompatibleWithFirst = population.getXoverPartners(
1653 parentA, eligibleParents, fragSpace);
1654 if (matesCompatibleWithFirst.size() == 0)
1655 return null;
1656
1657 Candidate parentB = null;
1658 if (choiceOfParents==null)
1659 {
1660 parentB = selectBasedOnFitness(matesCompatibleWithFirst, 1,
1661 settings)[0];
1662 } else {
1663 parentB = eligibleParents.get(choiceOfParents[1]);
1664 }
1665 if (parentB == null)
1666 return null;
1667
1668 XoverSite result = null;
1669 if (choiceOfXOverSites<0)
1670 {
1671 result = settings.getRandomizer().randomlyChooseOne(
1672 population.getXoverSites(parentA, parentB));
1673 } else {
1674 result = population.getXoverSites(parentA, parentB).get(
1675 choiceOfXOverSites);
1676 }
1677 return result;
1678 }
1679
1680//------------------------------------------------------------------------------
1681
1682 public static String getPathNameToGenerationFolder(int genID,
1683 GAParameters settings)
1684 {
1685 StringBuilder sb = new StringBuilder(32);
1686
1687 int ndigits = String.valueOf(settings.getNumberOfGenerations()).length();
1688
1689 sb.append(settings.getDataDirectory()).append(FSEP).append(
1691 .append(GeneralUtils.getPaddedString(ndigits, genID));
1692
1693 return sb.toString();
1694 }
1695
1696//------------------------------------------------------------------------------
1697
1698 public static String getPathNameToGenerationDetailsFile(int genID,
1699 GAParameters settings)
1700 {
1701 StringBuilder sb = new StringBuilder(32);
1702
1703 int ndigits = String.valueOf(settings.getNumberOfGenerations()).length();
1704
1705 sb.append(settings.getDataDirectory()).append(FSEP)
1707 .append(GeneralUtils.getPaddedString(ndigits, genID))
1708 .append(FSEP)
1710 .append(GeneralUtils.getPaddedString(ndigits, genID))
1711 .append(".txt");
1712
1713 return sb.toString();
1714 }
1715
1716//------------------------------------------------------------------------------
1717
1719 {
1720 StringBuilder sb = new StringBuilder(32);
1721 sb.append(settings.getDataDirectory()).append(FSEP).append("Final");
1722 return sb.toString();
1723 }
1724
1725//------------------------------------------------------------------------------
1726
1728 GAParameters settings)
1729 {
1730 StringBuilder sb = new StringBuilder(32);
1731 sb.append(settings.getDataDirectory()).append(FSEP).append("Final")
1732 .append(FSEP).append("Final.txt");
1733 return sb.toString();
1734 }
1735
1736//------------------------------------------------------------------------------
1737
1748 protected static void outputFinalResults(Population popln,
1749 GAParameters settings) throws DENOPTIMException
1750 {
1751 String dirName = EAUtils.getPathNameToFinalPopulationFolder(settings);
1752 denoptim.files.FileUtils.createDirectory(dirName);
1753 File fileDir = new File(dirName);
1754
1755 boolean intermediateCandidatesAreOnDisk =
1756 ((FitnessParameters) settings.getParameters(
1757 ParametersType.FIT_PARAMS)).writeCandidatesOnDisk();
1758
1759 for (int i=0; i<popln.size(); i++)
1760 {
1761 Candidate c = popln.get(i);
1762 String sdfile = c.getSDFFile();
1763 String imgfile = c.getImageFile();
1764
1765 try {
1766 if (intermediateCandidatesAreOnDisk && sdfile!=null)
1767 {
1768 FileUtils.copyFileToDirectory(new File(sdfile), fileDir);
1769 } else {
1770 File candFile = new File(fileDir, c.getName()
1772 c.setSDFFile(candFile.getAbsolutePath());
1773 DenoptimIO.writeCandidateToFile(candFile, c, false);
1774 }
1775 } catch (IOException ioe) {
1776 throw new DENOPTIMException("Failed to copy file '"
1777 + sdfile + "' to '" + fileDir + "' for candidate "
1778 + c.getName(), ioe);
1779 }
1780 if (imgfile != null && intermediateCandidatesAreOnDisk)
1781 {
1782 try {
1783 FileUtils.copyFileToDirectory(new File(imgfile), fileDir);
1784 } catch (IOException ioe) {
1785 throw new DENOPTIMException("Failed to copy file '"
1786 + imgfile + "' to '" + fileDir + "' for candidate "
1787 + c.getName(), ioe);
1788 }
1789 }
1790 }
1793 settings, true);
1794 }
1795
1796//------------------------------------------------------------------------------
1797
1806 protected static void getPopulationFromFile(String filename,
1807 Population population, SizeControlledSet uniqueIDsSet,
1808 String genDir, GAParameters settings)
1809 throws DENOPTIMException, IOException
1810 {
1811 List<Candidate> candidates = DenoptimIO.readCandidates(
1812 new File(filename), true);
1813 if (candidates.size() == 0)
1814 {
1815 String msg = "Found 0 candidates in file " + filename;
1816 settings.getLogger().log(Level.SEVERE, msg);
1817 throw new DENOPTIMException(msg);
1818 }
1819
1820 for (Candidate candidate : candidates)
1821 {
1822 if (uniqueIDsSet.addNewUniqueEntry(candidate.getUID()))
1823 {
1825 int gctr = GraphUtils.getUniqueGraphIndex();
1826
1827 String molName = "M" + GeneralUtils.getPaddedString(8, ctr);
1828 candidate.setName(molName);
1829 candidate.getGraph().setGraphId(gctr);
1830 candidate.getGraph().setLocalMsg("INITIAL_POPULATION");
1831 String sdfPathName = genDir + System.getProperty("file.separator")
1833 candidate.setSDFFile(sdfPathName);
1834 candidate.setImageFile(null);
1835
1836 // Write the candidate to file as if it had been processed by fitness provider
1837 DenoptimIO.writeCandidateToFile(new File(sdfPathName),
1838 candidate, false);
1839
1840 population.add(candidate);
1841 } else {
1842 settings.getLogger().log(Level.WARNING, "Candidate from intial "
1843 + "population file '" + filename
1844 + "' is rejected because its identifier is "
1845 + "already listed among the previously visited "
1846 + "identifiers.");
1847 }
1848 }
1849
1850 if (population.isEmpty())
1851 {
1852 String msg = "Population is still empty after having processes "
1853 + candidates.size() + " candidates from file " + filename;
1854 settings.getLogger().log(Level.SEVERE, msg);
1855 throw new DENOPTIMException(msg);
1856 }
1857
1858 setVertexCounterValue(population);
1859 }
1860
1861//------------------------------------------------------------------------------
1862
1863 protected static void writeUID(String outfile, HashSet<String> lstInchi,
1864 boolean append) throws DENOPTIMException
1865 {
1866 StringBuilder sb = new StringBuilder(256);
1867 Iterator<String> iter = lstInchi.iterator();
1868
1869 boolean first = true;
1870 while(iter.hasNext())
1871 {
1872 if (first)
1873 {
1874 sb.append(iter.next());
1875 first = false;
1876 }
1877 else
1878 {
1879 sb.append(NL).append(iter.next());
1880 }
1881 }
1882
1883 DenoptimIO.writeData(outfile, sb.toString(), append);
1884 sb.setLength(0);
1885 }
1886
1887//------------------------------------------------------------------------------
1888
1896 protected static void setVertexCounterValue(Population population)
1897 throws DENOPTIMException
1898 {
1899 long val = Long.MIN_VALUE;
1900 for (Candidate popln1 : population)
1901 {
1902 DGraph g = popln1.getGraph();
1903 val = Math.max(val, g.getMaxVertexId());
1904 }
1906 }
1907
1908//------------------------------------------------------------------------------
1909
1917 protected static DGraph buildGraph(GAParameters settings)
1918 throws DENOPTIMException
1919 {
1921 if (settings.containsParameters(ParametersType.FS_PARAMS))
1922 {
1923 fsParams = (FragmentSpaceParameters)settings.getParameters(
1925 }
1926 FragmentSpace fragSpace = fsParams.getFragmentSpace();
1927
1928 DGraph graph = new DGraph();
1930
1931 // building a molecule starts by selecting a random scaffold
1932 Vertex scafVertex = fragSpace.makeRandomScaffold();
1933
1934 // add the scaffold as a vertex
1935 graph.addVertex(scafVertex);
1936 graph.setLocalMsg("NEW");
1937
1938 if (scafVertex instanceof Template
1939 && !((Template) scafVertex).getContractLevel().equals(
1941 {
1942 Monitor mnt = new Monitor();
1943 mnt.name = "IntraTemplateBuild";
1944 List<Vertex> initialMutableSites = graph.getMutableSites(
1945 settings.getExcludedMutationTypes());
1946 for (Vertex mutableSite : initialMutableSites)
1947 {
1948 // This accounts for the possibility that a mutation changes a
1949 // branch of the initial graph or deletes vertexes.
1950 if (!graph.containsOrEmbedsVertex(mutableSite))
1951 continue;
1952
1953 // TODO: need to discriminate between EmptyVertexes that
1954 // represent placeholders and those that represent property carriers
1955 // The first should always be mutated (as it happens now), but
1956 // the latter should be kept intact.
1957 // Possibly this is a case for subclassing the EmptyVertex.
1958
1959 if (!GraphOperations.performMutation(mutableSite, mnt,
1960 settings))
1961 {
1964 return null;
1965 }
1966 }
1967 }
1968
1969 // get settings //TODO: this should happen inside RunTimeParameters
1971 if (settings.containsParameters(ParametersType.RC_PARAMS))
1972 {
1973 rcParams = (RingClosureParameters)settings.getParameters(
1975 }
1976//TODO this works only for scaffolds at the moment. make the preference for
1977// fragments that lead to known closable chains operate also when fragments are
1978// the "turning point".
1981 scafVertex.getBuildingBlockId()));
1982
1983 if (scafVertex.hasFreeAP())
1984 {
1985 GraphOperations.extendGraph(scafVertex, true, false, settings);
1986 }
1987
1988 if (!(scafVertex instanceof Template)
1989 && graph.getVertexCount() == 0)
1990 {
1991 return null;
1992 }
1993
1994 graph.addCappingGroups(fragSpace);
1995 return graph;
1996 }
1997
1998//------------------------------------------------------------------------------
1999
2012 protected static boolean setupRings(Object[] res, DGraph molGraph,
2013 GAParameters settings) throws DENOPTIMException
2014 {
2015 // get settings //TODO: this should happen inside RunTimeParameters
2017 if (settings.containsParameters(ParametersType.RC_PARAMS))
2018 {
2019 rcParams = (RingClosureParameters)settings.getParameters(
2021 }
2023 if (settings.containsParameters(ParametersType.FS_PARAMS))
2024 {
2025 fsParams = (FragmentSpaceParameters)settings.getParameters(
2027 }
2028 FragmentSpace fragSpace = fsParams.getFragmentSpace();
2029
2030 if (!fragSpace.useAPclassBasedApproach())
2031 return true;
2032
2033 if (!rcParams.allowRingClosures())
2034 return true;
2035
2036 // get a atoms/bonds molecular representation (no 3D needed)
2037 ThreeDimTreeBuilder t3d = new ThreeDimTreeBuilder(settings.getLogger(),
2038 settings.getRandomizer());
2039 t3d.setAlignBBsIn3D(false);
2040 IAtomContainer mol = t3d.convertGraphTo3DAtomContainer(molGraph,true);
2041
2042 // Set rotatability property as property of IBond
2043 String rotoSpaceFile = "";
2044 if (settings.containsParameters(ParametersType.FS_PARAMS))
2045 {
2046 rotoSpaceFile = ((FragmentSpaceParameters) settings.getParameters(
2047 ParametersType.FS_PARAMS)).getRotSpaceDefFile();
2048 }
2049 RotationalSpaceUtils.defineRotatableBonds(mol, rotoSpaceFile, true,
2050 true, settings.getLogger());
2051
2052 // get the set of possible RCA combinations = ring closures
2053 CyclicGraphHandler cgh = new CyclicGraphHandler(rcParams,fragSpace);
2054
2055 //TODO: remove hard-coded variable that exclude considering all
2056 // combination of rings
2057 boolean onlyRandomCombOfRings = true;
2058
2059 if (onlyRandomCombOfRings)
2060 {
2061 List<Ring> combsOfRings = cgh.getRandomCombinationOfRings(
2062 mol, molGraph, rcParams.getMaxRingClosures());
2063 if (combsOfRings.size() > 0)
2064 {
2065 for (Ring ring : combsOfRings)
2066 {
2067 // Consider the crowding probability
2068 double shot = settings.getRandomizer().nextDouble();
2069 int crowdOnH = EAUtils.getCrowdedness(
2070 ring.getHeadVertex().getEdgeToParent().getSrcAP(),
2071 true);
2072 int crowdOnT = EAUtils.getCrowdedness(
2073 ring.getTailVertex().getEdgeToParent().getSrcAP(),
2074 true);
2075 double crowdProbH = EAUtils.getCrowdingProbability(crowdOnH,
2076 settings);
2077 double crowdProbT = EAUtils.getCrowdingProbability(crowdOnT,
2078 settings);
2079
2080 if (shot < crowdProbH && shot < crowdProbT)
2081 {
2082 molGraph.addRing(ring);
2083 }
2084 }
2085 }
2086 }
2087 else
2088 {
2089 ArrayList<List<Ring>> allCombsOfRings =
2090 cgh.getPossibleCombinationOfRings(mol, molGraph);
2091
2092 // Keep closable chains that are relevant for chelate formation
2093 if (rcParams.buildChelatesMode())
2094 {
2095 ArrayList<List<Ring>> toRemove = new ArrayList<>();
2096 for (List<Ring> setRings : allCombsOfRings)
2097 {
2098 if (!cgh.checkChelatesGraph(molGraph,setRings))
2099 {
2100 toRemove.add(setRings);
2101 }
2102 }
2103
2104 allCombsOfRings.removeAll(toRemove);
2105 if (allCombsOfRings.isEmpty())
2106 {
2107 String msg = "Setup Rings: no combination of rings.";
2108 settings.getLogger().log(Level.INFO, msg);
2109 return false;
2110 }
2111 }
2112
2113 // Select a combination, if any still available
2114 int sz = allCombsOfRings.size();
2115 if (sz > 0)
2116 {
2117 List<Ring> selected = new ArrayList<>();
2118 if (sz == 1)
2119 {
2120 selected = allCombsOfRings.get(0);
2121 }
2122 else
2123 {
2124 int selId = settings.getRandomizer().nextInt(sz);
2125 selected = allCombsOfRings.get(selId);
2126 }
2127
2128 // append new rings to existing list of rings in graph
2129 for (Ring ring : selected)
2130 {
2131 molGraph.addRing(ring);
2132 }
2133 }
2134 }
2135
2136 // Update the IAtomContainer representation
2137 //DENOPTIMMoleculeUtils.removeUsedRCA(mol,molGraph);
2138 // Done already at t3d.convertGraphTo3DAtomContainer
2139 if (res!=null)
2140 {
2141 res[2] = mol;
2142 }
2143 // Update the SMILES representation
2144 if (res!=null)
2145 {
2146 String molsmiles = MoleculeUtils.getSMILESForMolecule(mol,
2147 settings.getLogger());
2148 if (molsmiles == null)
2149 {
2150 String msg = "Evaluation of graph: SMILES is null! "
2151 + molGraph.toString();
2152 settings.getLogger().log(Level.INFO, msg);
2153 molsmiles = "FAIL: NO SMILES GENERATED";
2154 }
2155 res[1] = molsmiles;
2156 }
2157
2158 // Update the INCHI key representation
2159 if (res!=null)
2160 {
2161 String inchikey = MoleculeUtils.getInChIKeyForMolecule(mol,
2162 settings.getLogger());
2163 if (inchikey == null)
2164 {
2165 String msg = "Evaluation of graph: INCHI is null!";
2166 settings.getLogger().log(Level.INFO, msg);
2167 inchikey = "UNDEFINED";
2168 }
2169 res[0] = inchikey;
2170 }
2171
2172 return true;
2173 }
2174
2175//------------------------------------------------------------------------------
2176
2184 protected static boolean containsMolecule(Population mols, String molcode)
2185 {
2186 if(mols.isEmpty())
2187 return false;
2188
2189 for (Candidate mol : mols)
2190 {
2191 if (mol.getUID().compareToIgnoreCase(molcode) == 0)
2192 {
2193 return true;
2194 }
2195 }
2196 return false;
2197 }
2198
2199//------------------------------------------------------------------------------
2200
2207 protected static double[] getFitnesses(Population mols)
2208 {
2209 int k = mols.size();
2210 double[] arr = new double[k];
2211
2212 for (int i=0; i<k; i++)
2213 {
2214 arr[i] = mols.get(i).getFitness();
2215 }
2216 return arr;
2217 }
2218
2219//------------------------------------------------------------------------------
2220
2228 protected static double getPopulationSD(Population molPopulation)
2229 {
2230 double[] fitvals = getFitnesses(molPopulation);
2231 return StatUtils.stddev(fitvals, true);
2232 }
2233
2234//------------------------------------------------------------------------------
2235
2248 public static double getGrowthProbabilityAtLevel(int level, int scheme,
2249 double lambda, double sigmaOne, double sigmaTwo)
2250 {
2251 return getProbability(level, scheme, lambda, sigmaOne, sigmaTwo);
2252 }
2253
2254//------------------------------------------------------------------------------
2255
2268 public static double getMolSizeProbability(DGraph graph,
2269 GAParameters settings)
2270 {
2271 if (!settings.useMolSizeBasedProb())
2272 return 1.0;
2273 int scheme = settings.getMolGrowthProbabilityScheme();
2274 double lambda =settings.getMolGrowthMultiplier();
2275 double sigmaOne = settings.getMolGrowthFactorSteepSigma();
2276 double sigmaTwo = settings.getMolGrowthFactorMiddleSigma();
2277 return getMolSizeProbability(graph, scheme, lambda, sigmaOne, sigmaTwo);
2278 }
2279
2280//------------------------------------------------------------------------------
2281
2294 public static double getMolSizeProbability(DGraph graph,
2295 int scheme, double lambda, double sigmaOne, double sigmaTwo)
2296 {
2297 return getProbability(graph.getHeavyAtomsCount(), scheme, lambda,
2298 sigmaOne, sigmaTwo);
2299 }
2300
2301//------------------------------------------------------------------------------
2302
2313 public static double getProbability(double value,
2314 int scheme, double lambda, double sigmaOne, double sigmaTwo)
2315 {
2316 double prob = 1.0;
2317 if (scheme == 0)
2318 {
2319 double f = Math.exp(-1.0 * value * lambda);
2320 prob = 1 - ((1-f)/(1+f));
2321 }
2322 else if (scheme == 1)
2323 {
2324 prob = 1.0 - Math.tanh(lambda * value);
2325 }
2326 else if (scheme == 2)
2327 {
2328 prob = 1.0-1.0/(1.0 + Math.exp(-sigmaOne * (value - sigmaTwo)));
2329 }
2330 else if (scheme == 3)
2331 {
2332 prob = 1.0;
2333 }
2334 return prob;
2335 }
2336
2337//------------------------------------------------------------------------------
2338
2345 public static double getGrowthByLevelProbability(int level,
2346 GAParameters settings)
2347 {
2348 if (!settings.useLevelBasedProb())
2349 return 1.0;
2350 int scheme = settings.getGrowthProbabilityScheme();
2351 double lambda =settings.getGrowthMultiplier();
2352 double sigmaOne = settings.getGrowthFactorSteepSigma();
2353 double sigmaTwo = settings.getGrowthFactorMiddleSigma();
2354 return getGrowthProbabilityAtLevel(level, scheme, lambda, sigmaOne,
2355 sigmaTwo);
2356 }
2357
2358//------------------------------------------------------------------------------
2359
2369 GAParameters settings)
2370 {
2371 int scheme = settings.getCrowdingProbabilityScheme();
2372 double lambda =settings.getCrowdingMultiplier();
2373 double sigmaOne = settings.getCrowdingFactorSteepSigma();
2374 double sigmaTwo = settings.getCrowdingFactorMiddleSigma();
2375 return getCrowdingProbability(ap, scheme, lambda, sigmaOne, sigmaTwo);
2376 }
2377
2378//------------------------------------------------------------------------------
2379
2393 public static double getCrowdingProbability(int crowdedness,
2394 GAParameters settings)
2395 {
2396 int scheme = settings.getCrowdingProbabilityScheme();
2397 double lambda =settings.getCrowdingMultiplier();
2398 double sigmaOne = settings.getCrowdingFactorSteepSigma();
2399 double sigmaTwo = settings.getCrowdingFactorMiddleSigma();
2400 return getCrowdingProbabilityForCrowdedness(crowdedness, scheme, lambda,
2401 sigmaOne, sigmaTwo);
2402 }
2403
2404//------------------------------------------------------------------------------
2405
2413 public static int getCrowdedness(AttachmentPoint ap)
2414 {
2415 return getCrowdedness(ap,false);
2416 }
2417
2418//------------------------------------------------------------------------------
2419
2429 public static int getCrowdedness(AttachmentPoint ap,
2430 boolean ignoreFreeRCVs)
2431 {
2432 if (ap.getOwner() instanceof EmptyVertex)
2433 {
2434 return 0;
2435 }
2436 int crowdness = 0;
2437 DGraph g = ap.getOwner().getGraphOwner();
2439 {
2440 if (oap.getAtomPositionNumber() == ap.getAtomPositionNumber()
2441 && !oap.isAvailableThroughout()
2442 && oap.getLinkedAP().getOwner()
2443 .getBuildingBlockType() != BBType.CAP)
2444 {
2445 if (ignoreFreeRCVs && oap.getLinkedAP().getOwner().isRCV())
2446 {
2447 if (g.getUsedRCVertices().contains(oap.getLinkedAP().getOwner()))
2448 crowdness = crowdness + 1;
2449 } else {
2450 crowdness = crowdness + 1;
2451 }
2452 }
2453 }
2454 return crowdness;
2455 }
2456
2457//------------------------------------------------------------------------------
2458
2471 public static double getCrowdingProbability(AttachmentPoint ap,
2472 int scheme,
2473 double lambda, double sigmaOne, double sigmaTwo)
2474 {
2475 //Applies only to molecular fragments
2476 if (ap.getOwner() instanceof Fragment == false)
2477 {
2478 return 1.0;
2479 }
2480 int crowdness = getCrowdedness(ap);
2481 return getCrowdingProbabilityForCrowdedness(crowdness, scheme, lambda,
2482 sigmaOne, sigmaTwo);
2483 }
2484
2485//------------------------------------------------------------------------------
2486
2496 public static double getCrowdingProbabilityForCrowdedness(int crowdedness,
2497 int scheme,
2498 double lambda, double sigmaOne, double sigmaTwo)
2499 {
2500 return getProbability(crowdedness, scheme, lambda, sigmaOne, sigmaTwo);
2501 }
2502
2503//------------------------------------------------------------------------------
2504
2513 protected static boolean foundForbiddenEnd(DGraph molGraph,
2514 FragmentSpaceParameters fsParams)
2515 {
2516 List<Vertex> vertices = molGraph.getVertexList();
2517 Set<APClass> classOfForbEnds = fsParams.getFragmentSpace()
2519 for (Vertex vtx : vertices)
2520 {
2521 List<AttachmentPoint> daps = vtx.getAttachmentPoints();
2522 for (AttachmentPoint dp : daps)
2523 {
2524 if (dp.isAvailable())
2525 {
2526 APClass apClass = dp.getAPClass();
2527 if (classOfForbEnds.contains(apClass))
2528 {
2529 String msg = "Forbidden free AP for Vertex: "
2530 + vtx.getVertexId()
2531 + " MolId: " + (vtx.getBuildingBlockId() + 1)
2532 + " Ftype: " + vtx.getBuildingBlockType()
2533 + "\n"+ molGraph+" \n "
2534 + " AP class: " + apClass;
2535 fsParams.getLogger().log(Level.WARNING, msg);
2536 return true;
2537 }
2538 }
2539 }
2540 }
2541 return false;
2542 }
2543
2544//------------------------------------------------------------------------------
2545
2546 protected static void readUID(String infile, HashSet<String> lstInchi)
2547 throws DENOPTIMException
2548 {
2549 ArrayList<String> lst = DenoptimIO.readList(infile);
2550 for (String str:lst)
2551 lstInchi.add(str);
2552 lst.clear();
2553 }
2554
2555//------------------------------------------------------------------------------
2556
2582 //NB: we return a List to retain ordering of the items, but the list must
2583 // not contain redundancies, i.e., lists of AP pairs that are made of the
2584 // same set of AP pairs.
2585 public static List<List<RelatedAPPair>> searchRingFusionSites(
2586 DGraph graph, GAParameters gaParams) throws DENOPTIMException
2587 {
2589 if (gaParams.containsParameters(ParametersType.RC_PARAMS))
2590 {
2591 rcParams = (RingClosureParameters)gaParams.getParameters(
2593 }
2595 if (gaParams.containsParameters(ParametersType.FS_PARAMS))
2596 {
2597 fsParams = (FragmentSpaceParameters)gaParams.getParameters(
2599 }
2600 FragmentSpace fragSpace = fsParams.getFragmentSpace();
2601 Randomizer rng = gaParams.getRandomizer();
2602 boolean projectOnSymmetricAPs = rng.nextBoolean(
2603 gaParams.getSymmetryProbability());
2604 // NB: imposeSymmetryOnAPsOfClass is evaluated inside the
2605 // method searchRingFusionSites
2606 Logger logger = gaParams.getLogger();
2607 return searchRingFusionSites(graph, fragSpace, rcParams,
2608 projectOnSymmetricAPs, logger, rng);
2609 }
2610
2611//------------------------------------------------------------------------------
2612
2638 //NB: we return a List to retain ordering of the items, but the list must
2639 // not contain redundancies, i.e., lists of AP pairs that are made of the
2640 // same set of AP pairs.
2641 public static List<List<RelatedAPPair>> searchRingFusionSites(
2642 DGraph graph, FragmentSpace fragSpace,
2643 RingClosureParameters rcParams, boolean projectOnSymmetricAPs,
2644 Logger logger, Randomizer rng) throws DENOPTIMException
2645 {
2646 // Prepare the empty collector of combinations
2647 List<List<RelatedAPPair>> result = new ArrayList<List<RelatedAPPair>>();
2648
2649 // Most of the work is done on a clone to prevent any modification of the
2650 // 3D molecular representation of the graph, which is here rebuilt in
2651 // a crude way because we only need the connectivity.
2652 DGraph tmpGraph = graph.clone();
2653
2654 // Keep track of which vertexes come from the original graph. We need
2655 // to distinguish them from the capping groups we add here.
2656 Set<Long> originalVertexIDs = new HashSet<Long>();
2657 tmpGraph.getVertexList().stream()
2658 .forEach(v -> originalVertexIDs.add(v.getVertexId()));
2659
2660 // We add capping groups to facilitate the search for substructures
2661 // otherwise we have to write SMARTS that match systems with potentially
2662 // unsaturated valences, and that is a mess.
2663 // Here we change both graph and molecular representation, but it all
2664 // happens on the tmp copy, so the original graph and mol representation
2665 // remain intact. Also, note that the order of atoms does not have a
2666 // role because we only use the position of the atom in the list of atoms
2667 // within the tmp system, and then we use the reference to the
2668 // AP to project the information back into the original system.
2669 tmpGraph.addCappingGroups(fragSpace);
2670
2671 // Get a molecular representation
2672 ThreeDimTreeBuilder t3d = new ThreeDimTreeBuilder(logger, rng);
2673 t3d.setAlignBBsIn3D(false); //3D not needed
2674 IAtomContainer mol = t3d.convertGraphTo3DAtomContainer(tmpGraph, true);
2675
2676 // Search for potential half-ring environments, i.e., sets of atoms
2677 // that belongs to a cyclic system and could hold a chord that would
2678 // define the fused ring.
2679 Map<String, String> smarts = new HashMap<String, String>();
2680 for (BridgeHeadFindingRule rule : rcParams.getBridgeHeadFindingRules())
2681 {
2682 smarts.put(rule.getName(), rule.getSMARTS());
2683 }
2684
2685 ManySMARTSQuery msq = new ManySMARTSQuery(mol, smarts);
2686 if (msq.hasProblems())
2687 {
2688 logger.warning("Could not apply bridgehead finding rules: "
2689 + msq.getMessage() + ". Returning no match.");
2690 return result;
2691 }
2692 Map<SymmetricSetWithMode,List<RelatedAPPair>> symmRelatedBridgeHeadAPs =
2693 new HashMap<SymmetricSetWithMode,List<RelatedAPPair>>();
2694 List<RelatedAPPair> symBridgeHeadAPs = new ArrayList<RelatedAPPair>();
2695 List<RelatedAPPair> asymBridgeHeadAPs = new ArrayList<RelatedAPPair>();
2696 for (BridgeHeadFindingRule rule : rcParams.getBridgeHeadFindingRules())
2697 {
2698 if (msq.getNumMatchesOfQuery(rule.getName()) == 0)
2699 {
2700 continue;
2701 }
2702
2703 // Get bridge-head atoms
2704 Mappings halfRingAtms = msq.getMatchesOfSMARTS(rule.getName());
2705 // We use a string to facilitate detection of pairs of ids
2706 // irrespectively on the order of ids, i.e., 1-2 vs. 2-1.
2707 Set<String> doneIdPairs = new HashSet<String>();
2708 for (int[] idSubstructure : halfRingAtms)
2709 {
2710 if (idSubstructure.length<2)
2711 {
2712 throw new Error("SMARTS for matching half-ring pattern '"
2713 + rule.getName()
2714 + "' has identified " + idSubstructure.length
2715 + " atoms "
2716 + "instead of at least 2. Modify rule to make it "
2717 + "find 2 or more atoms.");
2718 }
2719
2720 // Potential bridge-head atoms
2721 int[] ids = new int[] {
2722 idSubstructure[rule.getBridgeHeadPositions()[0]],
2723 idSubstructure[rule.getBridgeHeadPositions()[1]]};
2724
2725 IAtom bhA = mol.getAtom(ids[0]);
2726 IAtom bhB = mol.getAtom(ids[1]);
2727
2728 // Avoid duplicate pairs with inverted AP identity
2729 String idPairIdentifier = "";
2730 if (ids[0]<ids[1])
2731 idPairIdentifier = ids[0]+"_"+ids[1];
2732 else
2733 idPairIdentifier = ids[1]+"_"+ids[0];
2734 if (doneIdPairs.contains(idPairIdentifier))
2735 continue;
2736 doneIdPairs.add(idPairIdentifier);
2737
2738 // Bridge-head atoms must have attachment points
2739 if (bhA.getProperty(DENOPTIMConstants.ATMPROPAPS)==null
2740 || bhB.getProperty(DENOPTIMConstants.ATMPROPAPS)==null)
2741 continue;
2742 if (bhA.getProperty(DENOPTIMConstants.ATMPROPVERTEXID)==null
2743 || bhB.getProperty(DENOPTIMConstants.ATMPROPVERTEXID)==null)
2744 throw new IllegalStateException("Atoms in 3d molecular "
2745 + "models of graph objects must have the "
2746 + DENOPTIMConstants.ATMPROPVERTEXID + " property.");
2747
2748 long vrtxIdA = (Long)
2749 bhA.getProperty(DENOPTIMConstants.ATMPROPVERTEXID);
2750 long vrtxIdB = (Long)
2751 bhB.getProperty(DENOPTIMConstants.ATMPROPVERTEXID);
2752
2753 // Each AP on each side can be used
2754 @SuppressWarnings("unchecked")
2755 List<AttachmentPoint> apsOnA = (List<AttachmentPoint>)
2756 bhA.getProperty(DENOPTIMConstants.ATMPROPAPS);
2757 @SuppressWarnings("unchecked")
2758 List<AttachmentPoint> apsOnB = (List<AttachmentPoint>)
2759 bhB.getProperty(DENOPTIMConstants.ATMPROPAPS);
2760 for (int iAPA=0; iAPA<apsOnA.size(); iAPA++)
2761 {
2762 AttachmentPoint copyOfApA = apsOnA.get(iAPA);
2763
2764 // for extreme debug only
2765 /*
2766 System.out.println(rule.getName()+" "+idPairIdentifier+" "
2767 +MoleculeUtils.getAtomRef(bhA, mol)+"-"
2768 +MoleculeUtils.getAtomRef(bhB, mol)+" "
2769 +copyOfApA.getIndexInOwner()
2770 +" in "+copyOfApA.getOwner());
2771 */
2772
2773 if (!canBeUsedForRingFusion(copyOfApA, originalVertexIDs,
2774 fragSpace))
2775 continue;
2776 for (int iAPB=0; iAPB<apsOnB.size(); iAPB++)
2777 {
2778 AttachmentPoint copyOfApB = apsOnB.get(iAPB);
2779
2780 // for extreme debug only
2781 /*
2782 System.out.println(" "+idPairIdentifier+" "
2783 +MoleculeUtils.getAtomRef(bhA, mol)+"-"
2784 +MoleculeUtils.getAtomRef(bhB, mol)+" "
2785 +copyOfApA.getIndexInOwner()
2786 +" in "+copyOfApA.getOwner()
2787 + "--- "
2788 +copyOfApB.getIndexInOwner()
2789 +" in "+copyOfApB.getOwner());
2790 */
2791
2792 if (!canBeUsedForRingFusion(copyOfApB, originalVertexIDs,
2793 fragSpace))
2794 continue;
2795
2796 // Now take the references to the actual APs
2797 AttachmentPoint apA = tmpGraph.getVertexWithId(vrtxIdA)
2798 .getAPWithId(copyOfApA.getID());
2799 AttachmentPoint apB = tmpGraph.getVertexWithId(vrtxIdB)
2800 .getAPWithId(copyOfApB.getID());
2801 if (apA==null || apB==null)
2802 continue;
2803
2804 // Skip pairs that are the same AP
2805 if (apA == apB)
2806 continue;
2807
2808 // Now we have identified a pair of APs suitable to ring fusion
2809 RelatedAPPair pair = new RelatedAPPair(apA, apB, rule,
2810 rule.getName());
2811
2812 //Record symmetric relations
2813 SymmetricAPs symInA = apA.getOwner().getSymmetricAPs(apA);
2814 SymmetricAPs symInB = apB.getOwner().getSymmetricAPs(apB);
2815 if (symInA.size()!=0 && symInB.size()!=0)
2816 {
2817 if (symInA==symInB)
2818 {
2819 storePairsSymmetricRelations(pair, symInA,
2820 symmRelatedBridgeHeadAPs);
2821 } else {
2822 storePairsSymmetricRelations(pair, symInA,
2823 symmRelatedBridgeHeadAPs);
2824 storePairsSymmetricRelations(pair, symInB,
2825 symmRelatedBridgeHeadAPs);
2826 }
2827 symBridgeHeadAPs.add(pair);
2828 } else {
2829 asymBridgeHeadAPs.add(pair);
2830 }
2831 }
2832 }
2833 }
2834 }
2835 if (asymBridgeHeadAPs.size()==0 && symBridgeHeadAPs.size()==0)
2836 {
2837 return result;
2838 }
2839
2840 // Collect potential set of pairs of APs that can be used to create
2841 // fused ring systems accounting for symmetric AP relations.
2842 List<List<RelatedAPPair>> candidateBridgeHeadAPPairs =
2843 new ArrayList<List<RelatedAPPair>>();
2844 if (symmRelatedBridgeHeadAPs.size()>0)
2845 {
2846 for (SymmetricSetWithMode key : symmRelatedBridgeHeadAPs.keySet())
2847 {
2848 List<RelatedAPPair> chosenSymSet =
2849 symmRelatedBridgeHeadAPs.get(key);
2850
2851 @SuppressWarnings("unchecked")
2852 SymmetricSet<AttachmentPoint> symmRelatedAPs =
2853 (SymmetricSet<AttachmentPoint>) key.getItems();
2854 boolean apcImposedSymm = fragSpace.imposeSymmetryOnAPsOfClass(
2855 symmRelatedAPs.get(0).getAPClass());
2856
2857 if (projectOnSymmetricAPs || apcImposedSymm)
2858 {
2859 // We try to get the biggest combination (k is the size)
2860 // but we do limit to avoid combinatorial explosion.
2861 for (int k=Math.min(chosenSymSet.size(), 6); k>0; k--)
2862 {
2863 // Generate combinations that use non-overlapping pairs of APs
2864 List<List<RelatedAPPair>> combs = combineRelatedAPPair(
2865 chosenSymSet, k, 50);
2866 //TODO: make limit of combinations tuneable?
2867
2868 if (combs.size()>0)
2869 {
2870 // We keep only combinations that are not already
2871 // among previously known ones
2872 for (List<RelatedAPPair> comb : combs)
2873 {
2874 boolean isNew = true;
2875 for (List<RelatedAPPair> knownComb :
2876 candidateBridgeHeadAPPairs)
2877 {
2878 if (knownComb.containsAll(comb)
2879 && comb.containsAll(knownComb))
2880 {
2881 isNew = false;
2882 break;
2883 }
2884 }
2885 if (isNew)
2886 {
2887 candidateBridgeHeadAPPairs.add(comb);
2888 for (RelatedAPPair pair : comb)
2889 symBridgeHeadAPs.remove(pair);
2890 }
2891 }
2892 break;
2893 }
2894 }
2895 }
2896 }
2897 // Add left over pairs, if any.
2898 for (RelatedAPPair pair : symBridgeHeadAPs)
2899 {
2900 List<RelatedAPPair> single = new ArrayList<RelatedAPPair>();
2901 single.add(pair);
2902 candidateBridgeHeadAPPairs.add(single);
2903 }
2904 }
2905 for (RelatedAPPair pair : asymBridgeHeadAPs)
2906 {
2907 List<RelatedAPPair> single = new ArrayList<RelatedAPPair>();
2908 single.add(pair);
2909 candidateBridgeHeadAPPairs.add(single);
2910 }
2911
2912 // Project ring fusions into the actual graph (considering symmetry)
2913 for (List<RelatedAPPair> combOnTmpGraph : candidateBridgeHeadAPPairs)
2914 {
2915 List<RelatedAPPair> combOnOriginalGraph =
2916 new ArrayList<RelatedAPPair>();
2917 for (RelatedAPPair pairOnTmpGraph : combOnTmpGraph)
2918 {
2919 // if head and tail are symmetric to each other, we now
2920 // get the sem set of vertexec to loop over and, thus, an
2921 // attempt to use the same APs both as head and tail.
2922 // Therefore, we skip the pair
2923 if (tmpGraph.getSymSetForVertex(
2924 pairOnTmpGraph.apA.getOwner()).contains(
2925 pairOnTmpGraph.apB.getOwner()))
2926 {
2927 continue;
2928 }
2929 Vertex headVertexOnGraph = graph.getVertexAtPosition(
2930 tmpGraph.indexOf(pairOnTmpGraph.apA.getOwner()));
2931 int apHeadID = pairOnTmpGraph.apA.getIndexInOwner();
2932 List<Vertex> symHeadVrts = graph.getSymVerticesForVertex(
2933 headVertexOnGraph);
2934 if (symHeadVrts.size()==0)
2935 symHeadVrts.add(headVertexOnGraph);
2936
2937 Vertex tailVertexOnGraph = graph.getVertexAtPosition(
2938 tmpGraph.indexOf(pairOnTmpGraph.apB.getOwner()));
2939 int apTailID = pairOnTmpGraph.apB.getIndexInOwner();
2940 List<Vertex> symTailVrts = graph.getSymVerticesForVertex(
2941 tailVertexOnGraph);
2942 if (symTailVrts.size()==0)
2943 symTailVrts.add(tailVertexOnGraph);
2944
2945 int numPairs = Math.min(symHeadVrts.size(), symTailVrts.size());
2946 for (int iPair=0; iPair<numPairs; iPair++)
2947 {
2948 AttachmentPoint apH = symHeadVrts.get(iPair).getAP(apHeadID);
2949 AttachmentPoint apT = symTailVrts.get(iPair).getAP(apTailID);
2950 if (apH == apT)
2951 {
2952 // This should never happen, but we keep it as safeguard
2953 continue;
2954 }
2955 RelatedAPPair pairOnOriginalGraph = new RelatedAPPair(
2956 apH, apT,
2957 pairOnTmpGraph.property,
2958 pairOnTmpGraph.propID);
2959 // Symmetry projection of non-overlapping tmp pairs can
2960 // still reuse the same APs across projected pairs.
2961 if (shareAPs(pairOnOriginalGraph, combOnOriginalGraph))
2962 {
2963 continue;
2964 }
2965 combOnOriginalGraph.add(pairOnOriginalGraph);
2966 }
2967 }
2968 if (combOnOriginalGraph.size() != 0
2969 && !apPairsAreOverlapping(combOnOriginalGraph))
2970 {
2971 result.add(combOnOriginalGraph);
2972 }
2973 }
2974 return result;
2975 }
2976
2977//------------------------------------------------------------------------------
2978
2979 private static List<List<RelatedAPPair>> combineRelatedAPPair(
2980 List<RelatedAPPair> pool, int k, int limit)
2981 {
2982 List<RelatedAPPair> tmp = new ArrayList<RelatedAPPair>();
2983 List<List<RelatedAPPair>> allCombs = new ArrayList<List<RelatedAPPair>>();
2984 combineRelatedAPPairUtil(pool, 0, k, tmp, allCombs, limit);
2985 return allCombs;
2986 }
2987
2988//------------------------------------------------------------------------------
2989
2990 private static void combineRelatedAPPairUtil(List<RelatedAPPair> pool,
2991 int left, int k,
2992 List<RelatedAPPair> tmp,
2993 List<List<RelatedAPPair>> allCombs, int limit)
2994 {
2995 // PRevent combinatorial explosion: stop if the number of combinations
2996 // grown above the limit
2997 if (allCombs.size()>=limit)
2998 return;
2999
3000 // For last iteration: save answer
3001 if (k == 0)
3002 {
3003 if (!apPairsAreOverlapping(tmp))
3004 {
3005 List<RelatedAPPair> oneComb = new ArrayList<RelatedAPPair>(tmp);
3006 allCombs.add(oneComb);
3007 }
3008 return;
3009 }
3010 // In normal iteration, do recursion
3011 for (int i=left; i<pool.size(); ++i)
3012 {
3013 RelatedAPPair next = pool.get(i);
3014 if (shareAPs(next, tmp))
3015 {
3016 continue;
3017 }
3018 tmp.add(next);
3019 combineRelatedAPPairUtil(pool, i + 1, k-1, tmp, allCombs, limit);
3020 tmp.remove(tmp.size() - 1);
3021 }
3022 }
3023
3024//------------------------------------------------------------------------------
3025
3027 SymmetricAPs symAPs,
3028 Map<SymmetricSetWithMode,List<RelatedAPPair>> storage)
3029 {
3030 SymmetricSetWithMode key = new SymmetricSetWithMode(symAPs, pair.propID);
3031 if (storage.containsKey(key))
3032 {
3033 storage.get(key).add(pair);
3034 } else {
3035 List<RelatedAPPair> lst = new ArrayList<RelatedAPPair>();
3036 lst.add(pair);
3037 storage.put(key, lst);
3038 }
3039 }
3040
3041//------------------------------------------------------------------------------
3042
3051 public static Boolean apPairsAreOverlapping(Iterable<RelatedAPPair> pairs)
3052 {
3053 Set<AttachmentPoint> aps = new HashSet<AttachmentPoint>();
3054
3055 for (RelatedAPPair pair : pairs)
3056 {
3057 if (pair.apA == pair.apB
3058 ||aps.contains(pair.apA) || aps.contains(pair.apB))
3059 {
3060 return true;
3061 }
3062 aps.add(pair.apA);
3063 aps.add(pair.apB);
3064 }
3065 return false;
3066 }
3067
3068//------------------------------------------------------------------------------
3069
3078 public static Boolean shareAPs(RelatedAPPair pairA,
3079 Iterable<RelatedAPPair> lstB)
3080 {
3081 Set<AttachmentPoint> aps = new HashSet<AttachmentPoint>();
3082 for (RelatedAPPair pairB : lstB)
3083 {
3084 aps.add(pairB.apA);
3085 aps.add(pairB.apB);
3086 }
3087 return aps.contains(pairA.apA) || aps.contains(pairA.apB);
3088 }
3089
3090//------------------------------------------------------------------------------
3091
3114 private static boolean canBeUsedForRingFusion(AttachmentPoint ap,
3115 Set<Long> originalVertexIDs, FragmentSpace fs)
3116 {
3117 if (ap.isAvailableThroughout()
3118 || !originalVertexIDs.contains(
3120 {
3121 if (fs.getRCCompatibilityMatrix().containsKey(ap.getAPClass()))
3122 return true;
3123 }
3124 return false;
3125 }
3126
3127//------------------------------------------------------------------------------
3128
3141 public static List<Vertex> getUsableAromaticBridges(
3142 String elInIncomingFrag, int[] allowedLengths,
3143 FragmentSpace fragSpace)
3144 {
3145 List<Vertex> usableBridgesOriginals =
3146 fragSpace.getVerticesWithAPClassStartingWith(elInIncomingFrag);
3147 List<Vertex> usableBridges = new ArrayList<Vertex>();
3148 final String rootAPC = elInIncomingFrag;
3149 for (Vertex bridge : usableBridgesOriginals)
3150 {
3151 IAtomContainer iacFrag = bridge.getIAtomContainer();
3152 List<Integer> atomIDs = new ArrayList<Integer>();
3153 bridge.getAttachmentPoints()
3154 .stream()
3155 .filter(ap -> ap.getAPClass().getRule().startsWith(
3156 rootAPC))
3157 .forEach(ap -> atomIDs.add(ap.getAtomPositionNumber()));
3158 ShortestPaths sp = new ShortestPaths(iacFrag, iacFrag.getAtom
3159 (atomIDs.get(0)));
3160 List<IAtom> path = new ArrayList<IAtom>(Arrays.asList(
3161 sp.atomsTo(atomIDs.get(1))));
3162 if (IntStream.of(allowedLengths).anyMatch(x -> x == path.size()))
3163 {
3164 Vertex clone = bridge.clone();
3166 path.size());
3167 usableBridges.add(clone);
3168 }
3169 }
3170 return usableBridges;
3171 }
3172
3173//------------------------------------------------------------------------------
3174
3185 public static List<Vertex> getUsableAliphaticBridges(APClass apcA,
3186 APClass apcB, int[] allowedLengths, FragmentSpace fragSpace)
3187 {
3188 List<Vertex> usableBridges = new ArrayList<Vertex>();
3189
3190 List<APClass> compatApClassesA = fragSpace.getCompatibleAPClasses(apcA);
3191 List<APClass> compatApClassesB = fragSpace.getCompatibleAPClasses(apcB);
3192 for (APClass compatA : compatApClassesA)
3193 {
3194 for (APClass compatB : compatApClassesB)
3195 {
3196 boolean sameAPC = compatA.equals(compatB);
3197 Map<APClass,Integer> apFingerprint =
3198 new HashMap<APClass,Integer>();
3199 if (sameAPC)
3200 {
3201 apFingerprint.put(compatA,2);
3202 } else {
3203 apFingerprint.put(compatA,1);
3204 apFingerprint.put(compatB,1);
3205 }
3206 for (Vertex bridge : fragSpace.getVerticesWithAPFingerprint(
3207 apFingerprint))
3208 {
3209 IAtomContainer iacFrag = bridge.getIAtomContainer();
3210
3211 // Identify APs that can be used for each side
3212 List<AttachmentPoint> apsForA = new ArrayList<AttachmentPoint>();
3213 List<AttachmentPoint> apsForB = new ArrayList<AttachmentPoint>();
3214 for (AttachmentPoint apOnBridge : bridge.getAttachmentPoints())
3215 {
3216 if (compatA.equals(apOnBridge.getAPClass()))
3217 apsForA.add(apOnBridge);
3218 if (compatB.equals(apOnBridge.getAPClass()))
3219 apsForB.add(apOnBridge);
3220 }
3221
3222 // Find combinations of usable APs
3223 for (AttachmentPoint apForA : apsForA)
3224 {
3225 ShortestPaths sp = new ShortestPaths(iacFrag,
3226 iacFrag.getAtom(apForA.getAtomPositionNumber()));
3227 for (AttachmentPoint apForB : apsForB)
3228 {
3229 if (apForA.equals(apForB))
3230 continue;
3231 // Retains only combinations of allowed length
3232 List<IAtom> path = new ArrayList<IAtom>(
3233 Arrays.asList(sp.atomsTo(
3234 apForB.getAtomPositionNumber())));
3235 if (IntStream.of(allowedLengths).anyMatch(
3236 x -> x == path.size()))
3237 {
3238 Vertex clone = bridge.clone();
3239 clone.setProperty(
3241 path.size());
3242 clone.setProperty(
3244 apForA.getIndexInOwner());
3245 clone.setProperty(
3247 apForB.getIndexInOwner());
3248 usableBridges.add(clone);
3249 }
3250 }
3251 }
3252 }
3253 }
3254 }
3255 return usableBridges;
3256 }
3257
3258//------------------------------------------------------------------------------
3259
3260}
General set of constants used in DENOPTIM.
static final String VRTPROPBRIDGELENGTH
Name of Vertex property used to record how long a ring-closing bridge is.
static final String ATMPROPAPS
String tag of Atom property used to store attachment points.
static final String VRTPROPBRIDGEEND_B
Name of Vertex property used to record which AP is selected for bridge formation on side 'B'.
static final String ATMPROPVERTEXID
String tag of Atom property used to store the unique ID of the Vertex corresponding to the molecular ...
static final String GAGENSUMMARYHEADER
Header of text files collection generation details.
static final String GAGENDIRNAMEROOT
Prefix for generation folders.
static final String FITFILENAMEEXTOUT
Ending and extension of output file of external fitness provider.
static final String VRTPROPBRIDGEEND_A
Name of Vertex property used to record which AP is selected for bridge formation on side 'A'.
Settings defining the calculation of fitness.
SMARTS-based rules to identify potential bridge head atoms for ring fusion operations.
static boolean prepareMolToFragmentation(IAtomContainer mol, FragmenterParameters settings, int index)
Do any pre-processing on a IAtomContainer meant to be fragmented.
static List< Vertex > fragmentation(IAtomContainer mol, FragmenterParameters settings)
Performs fragmentation according to the given settings.
static Vertex getRCVForAP(AttachmentPoint ap, APClass rcvApClass)
Class defining a space of building blocks.
boolean useAPclassBasedApproach()
Check usage of APClass-based approach, i.e., uses attachment points with annotated data (i....
List< Vertex > getVerticesWithAPClassStartingWith(String root)
Extracts vertexes from the collection of vertexes defined by this FragmentSpace.
HashMap< APClass, ArrayList< APClass > > getRCCompatibilityMatrix()
Returns the compatibility matrix for ring closing fragment-fragment connections or null if not provid...
Vertex makeRandomScaffold()
Randomly select a scaffold and return a fully configured clone of it.
HashMap< APClass, APClass > getCappingMap()
ArrayList< APClass > getCompatibleAPClasses(APClass apc)
Returns a list of APClasses compatible with the given APClass.
List< Vertex > getVerticesWithAPFingerprint(Map< APClass, Integer > apcCounts)
Returns the list of vertexes that have the specified number of AttachmentPoints with the given APClas...
Parameters defining the fragment space.
Helper methods for the genetic algorithm.
Definition: EAUtils.java:102
static Boolean shareAPs(RelatedAPPair pairA, Iterable< RelatedAPPair > lstB)
Evaluates if a RelatedAPPair involves the same AttachmentPoint present in a collection.
Definition: EAUtils.java:3078
static void outputFinalResults(Population popln, GAParameters settings)
Saves the final results to disk.
Definition: EAUtils.java:1748
static List< Candidate > buildCandidatesByXOver(List< Candidate > eligibleParents, Population population, Monitor mnt, int[] choiceOfParents, int choiceOfXOverSites, int choiceOfOffstring, GAParameters settings, int maxCandidatesToReturn)
Generates up to a pair of new offspring by performing a crossover operation.
Definition: EAUtils.java:387
static CandidateSource pickNewCandidateGenerationMode(double xoverWeight, double mutWeight, double newWeight, Randomizer randomizer)
Takes a decision on which CandidateSource method to use for generating a new Candidate.
Definition: EAUtils.java:258
static double getGrowthByLevelProbability(int level, GAParameters settings)
Calculates the probability of adding a fragment to the given level.
Definition: EAUtils.java:2345
static double getCrowdingProbability(int crowdedness, GAParameters settings)
Calculated the probability of using and attachment point rooted on an atom that is holding other atta...
Definition: EAUtils.java:2393
static int chooseNumberOfSitesToMutate(double[] multiSiteMutationProb, double hit)
Takes a decision on how many sites to mutate on a candidate.
Definition: EAUtils.java:219
static void appendVertexesToGraphFollowingEdges(DGraph graph, AtomicInteger vId, List< Vertex > vertexes)
Definition: EAUtils.java:1359
static Candidate readCandidateFromFile(File srcFile, Monitor mnt, GAParameters settings)
Definition: EAUtils.java:765
static Candidate[] selectBasedOnFitness(List< Candidate > eligibleParents, int number, GAParameters settings)
Selects a number of members from the given population.
Definition: EAUtils.java:1554
static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol, List< CuttingRule > cuttingRules, Logger logger, ScaffoldingPolicy scaffoldingPolicy, double linearAngleLimit)
Converts a molecule into a DGraph by fragmentation and re-assembling of the fragments.
Definition: EAUtils.java:1055
static boolean setupRings(Object[] res, DGraph molGraph, GAParameters settings)
Evaluates the possibility of closing rings in a given graph and if any ring can be closed,...
Definition: EAUtils.java:2012
static Candidate buildCandidateByXOver(List< Candidate > eligibleParents, Population population, Monitor mnt, GAParameters settings)
Generates a new offspring by performing a crossover operation.
Definition: EAUtils.java:308
static List< Candidate > buildCandidatesByXOver(List< Candidate > eligibleParents, Population population, Monitor mnt, GAParameters settings)
Generates a pair of new offspring by performing a crossover operation.
Definition: EAUtils.java:288
static boolean canBeUsedForRingFusion(AttachmentPoint ap, Set< Long > originalVertexIDs, FragmentSpace fs)
Decides if an AttachmentPoint can be considered for making a ring fusion operation,...
Definition: EAUtils.java:3114
static final String NL
Definition: EAUtils.java:132
static void getPopulationFromFile(String filename, Population population, SizeControlledSet uniqueIDsSet, String genDir, GAParameters settings)
Reconstruct the molecular population from the file.
Definition: EAUtils.java:1806
static void writeUID(String outfile, HashSet< String > lstInchi, boolean append)
Definition: EAUtils.java:1863
static HashMap< Integer, ArrayList< String > > lstFragmentClass
Definition: EAUtils.java:123
static double getGrowthProbabilityAtLevel(int level, int scheme, double lambda, double sigmaOne, double sigmaTwo)
Calculates the probability of adding a fragment to the given level.
Definition: EAUtils.java:2248
static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol, List< CuttingRule > cuttingRules, Logger logger, ScaffoldingPolicy scaffoldingPolicy)
Converts a molecule into a DGraph by fragmentation and re-assembling of the fragments.
Definition: EAUtils.java:1029
static double getProbability(double value, int scheme, double lambda, double sigmaOne, double sigmaTwo)
Calculated a probability given parameters defining the shape of the probability function and a single...
Definition: EAUtils.java:2313
static List< Vertex > getUsableAliphaticBridges(APClass apcA, APClass apcB, int[] allowedLengths, FragmentSpace fragSpace)
Finds all vertexes that can be used as aliphatic bridge.
Definition: EAUtils.java:3185
static XoverSite performFBCC(List< Candidate > eligibleParents, Population population, int[] choiceOfParents, int choiceOfXOverSites, GAParameters settings)
Perform fitness-based, class-compatible selection of parents that can do crossover operations.
Definition: EAUtils.java:1632
static String getPathNameToFinalPopulationFolder(GAParameters settings)
Definition: EAUtils.java:1718
static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol, List< CuttingRule > cuttingRules, Logger logger, ScaffoldingPolicy scaffoldingPolicy, double linearAngleLimit, FragmentSpace fragSpace)
Converts a molecule into a DGraph by fragmentation and re-assembling of the fragments.
Definition: EAUtils.java:1107
static CandidateSource chooseGenerationMethod(GAParameters settings)
Choose one of the methods to make new Candidates.
Definition: EAUtils.java:202
static Locale enUsLocale
Locale used to write reports.
Definition: EAUtils.java:109
static double getCrowdingProbability(AttachmentPoint ap, GAParameters settings)
Calculated the probability of using and attachment point rooted on an atom that is holding other atta...
Definition: EAUtils.java:2368
static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol, List< CuttingRule > cuttingRules, Logger logger, ScaffoldingPolicy scaffoldingPolicy, double linearAngleLimit, boolean embedRingsInTemplates, ContractLevel ringTmplContract, FragmentSpace fragSpace, Monitor monitor)
Converts a molecule into a DGraph by fragmentation and re-assembling of the fragments.
Definition: EAUtils.java:1141
static boolean foundForbiddenEnd(DGraph molGraph, FragmentSpaceParameters fsParams)
Check if there are forbidden ends: free attachment points that are not suitable for capping and not a...
Definition: EAUtils.java:2513
static List< List< RelatedAPPair > > searchRingFusionSites(DGraph graph, GAParameters gaParams)
Definition: EAUtils.java:2585
static void setVertexCounterValue(Population population)
Set the Vertex counter value according to the largest value found in the given population.
Definition: EAUtils.java:1896
static Candidate buildCandidateByMutation(List< Candidate > eligibleParents, Monitor mnt, GAParameters settings)
Definition: EAUtils.java:641
static Candidate buildCandidateByFragmentingMolecule(IAtomContainer mol, Monitor mnt, GAParameters settings, int index)
Generates a candidate by fragmenting a molecule and generating the graph that reconnects all fragment...
Definition: EAUtils.java:939
static DGraph buildGraph(GAParameters settings)
Graph construction starts with selecting a random core/scaffold.
Definition: EAUtils.java:1917
static Candidate buildCandidateByXOver(List< Candidate > eligibleParents, Population population, Monitor mnt, int[] choiceOfParents, int choiceOfXOverSites, int choiceOfOffstring, GAParameters settings)
Generates a new offspring by performing a crossover operation.
Definition: EAUtils.java:342
static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol, FragmenterParameters frgParams)
Converts a molecule into a DGraph by fragmentation and re-assembling of the fragments.
Definition: EAUtils.java:1166
static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol, FragmenterParameters frgParams, FragmentSpace fragSpace, Monitor monitor)
Converts a molecule into a DGraph by fragmentation and re-assembling of the fragments.
Definition: EAUtils.java:1203
static double[] getFitnesses(Population mols)
Get the fitness values for the list of molecules.
Definition: EAUtils.java:2207
static String getSummaryStatistics(Population popln, GAParameters settings)
Definition: EAUtils.java:1497
static void createFolderForGeneration(int genId, GAParameters settings)
Creates a folder meant to hold all the data generated during a generation.
Definition: EAUtils.java:143
static double getMolSizeProbability(DGraph graph, int scheme, double lambda, double sigmaOne, double sigmaTwo)
Calculated the probability of extending a graph based on the current size of the molecular representa...
Definition: EAUtils.java:2294
static DecimalFormat initialiseFormatter()
Definition: EAUtils.java:115
static int getCrowdedness(AttachmentPoint ap)
Calculate the current crowdedness of the given attachment point.
Definition: EAUtils.java:2413
static int getCrowdedness(AttachmentPoint ap, boolean ignoreFreeRCVs)
Calculate the current crowdedness of the given attachment point.
Definition: EAUtils.java:2429
static HashMap< Integer, ArrayList< Integer > > fragmentPool
Definition: EAUtils.java:104
static List< List< RelatedAPPair > > combineRelatedAPPair(List< RelatedAPPair > pool, int k, int limit)
Definition: EAUtils.java:2979
static void combineRelatedAPPairUtil(List< RelatedAPPair > pool, int left, int k, List< RelatedAPPair > tmp, List< List< RelatedAPPair > > allCombs, int limit)
Definition: EAUtils.java:2990
static void outputPopulationDetails(Population population, String filename, GAParameters settings, boolean printpathNames)
Write out summary for the current GA population.
Definition: EAUtils.java:1438
static List< Vertex > getUsableAromaticBridges(String elInIncomingFrag, int[] allowedLengths, FragmentSpace fragSpace)
Finds all vertexes that can be used as aromatic bridge, i.e., can be used to create an aromatic ring ...
Definition: EAUtils.java:3141
static Vertex selectNonScaffoldNonCapVertex(DGraph g, Randomizer randomizer)
Chose randomly a vertex that is neither scaffold or capping group.
Definition: EAUtils.java:1604
static double getCrowdingProbabilityForCrowdedness(int crowdedness, int scheme, double lambda, double sigmaOne, double sigmaTwo)
Calculated the crowding probability for a given level of crowdedness.
Definition: EAUtils.java:2496
static String getPathNameToGenerationFolder(int genID, GAParameters settings)
Definition: EAUtils.java:1682
static double getPopulationSD(Population molPopulation)
Check if fitness values have significant standard deviation.
Definition: EAUtils.java:2228
static String getPathNameToFinalPopulationDetailsFile(GAParameters settings)
Definition: EAUtils.java:1727
static Candidate buildCandidateFromScratch(Monitor mnt, GAParameters settings)
Definition: EAUtils.java:838
static double getCrowdingProbability(AttachmentPoint ap, int scheme, double lambda, double sigmaOne, double sigmaTwo)
Calculated the probability of using and attachment point rooted on an atom that is holding other atta...
Definition: EAUtils.java:2471
static boolean containsMolecule(Population mols, String molcode)
Check if the population contains the specified InChi code.
Definition: EAUtils.java:2184
static DecimalFormat df
Format for decimal fitness numbers that overwrites Locale to en_US.
Definition: EAUtils.java:114
static DGraph makeGraphFromFragmentationOfMol(IAtomContainer mol, List< CuttingRule > cuttingRules, Logger logger, ScaffoldingPolicy scaffoldingPolicy, FragmentSpace fragSpace)
Converts a molecule into a DGraph by fragmentation and re-assembling of the fragments.
Definition: EAUtils.java:1079
static List< List< RelatedAPPair > > searchRingFusionSites(DGraph graph, FragmentSpace fragSpace, RingClosureParameters rcParams, boolean projectOnSymmetricAPs, Logger logger, Randomizer rng)
Definition: EAUtils.java:2641
static void storePairsSymmetricRelations(RelatedAPPair pair, SymmetricAPs symAPs, Map< SymmetricSetWithMode, List< RelatedAPPair > > storage)
Definition: EAUtils.java:3026
static void readUID(String infile, HashSet< String > lstInchi)
Definition: EAUtils.java:2546
static final String FSEP
Definition: EAUtils.java:133
static String getPathNameToGenerationDetailsFile(int genID, GAParameters settings)
Definition: EAUtils.java:1698
static double getMolSizeProbability(DGraph graph, GAParameters settings)
Calculated the probability of extending a graph based on the current size of the molecular representa...
Definition: EAUtils.java:2268
static Population importInitialPopulation(SizeControlledSet uniqueIDsSet, GAParameters settings)
Reads unique identifiers and initial population file according to the GAParameters.
Definition: EAUtils.java:157
static Boolean apPairsAreOverlapping(Iterable< RelatedAPPair > pairs)
Evaluates if any pair of AttachmentPoint pairs involve the same AttachmentPoint, i....
Definition: EAUtils.java:3051
Collection of operators meant to alter graphs and associated utilities.
static boolean extendGraph(Vertex curVertex, boolean extend, boolean symmetryOnAps, GAParameters settings)
function that will keep extending the graph according to the growth/substitution probability.
static boolean performMutation(DGraph graph, Monitor mnt, GAParameters settings)
Tries to do mutate the given graph.
static boolean performCrossover(XoverSite site, FragmentSpace fragSpace)
Performs the crossover that swaps the two subgraphs defining the given XoverSite.
A collection of candidates.
Definition: Population.java:48
List< XoverSite > getXoverSites(Candidate parentA, Candidate parentB)
Returns a list of crossover sites between the two given parents.
List< Candidate > getXoverPartners(Candidate memberA, List< Candidate > eligibleParents, FragmentSpace fragSpace)
Returns a list of population members that can do crossover with the specified member.
Class that offers methods to performs fitness-driven selection of candidates.
static Candidate[] performRandomSelection(List< Candidate > population, int sz, RunTimeParameters settings)
Randomly select k individuals from the population.
static Candidate[] performRWS(List< Candidate > population, int sz, RunTimeParameters settings)
Roulette wheel selection is implemented as follows:
static Candidate[] performSUS(List< Candidate > population, int sz, RunTimeParameters settings)
Stochastic Uniform Sampling Note: this implementation is based on the WATCHMAKER framework http://wat...
static Candidate[] performTournamentSelection(List< Candidate > eligibleParents, int sz, GAParameters settings)
Select a number individuals at random (i.e., tournamentSize).
This class collects the data identifying the subgraphs that would be swapped by a crossover event.
Definition: XoverSite.java:36
XoverSite projectToClonedGraphs()
Creates a new instance of this class that contains the list of vertexes that correspond to those cont...
Definition: XoverSite.java:275
String toString()
Produced a string for showing what this object is.
Definition: XoverSite.java:349
List< Vertex > getA()
Returns the collection of vertexes belonging to the first subgraph.
Definition: XoverSite.java:187
List< Vertex > getB()
Returns the collection of vertexes belonging to the second subgraph.
Definition: XoverSite.java:198
static final APClass RCACLASSMINUS
Conventional class of attachment points on ring-closing vertexes.
Definition: APClass.java:92
static final String ATPLUS
String defining a conventional APClass.
Definition: APClass.java:69
static APClass make(String ruleAndSubclass)
Creates an APClass if it does not exist already, or returns the reference to the existing instance.
Definition: APClass.java:164
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.
int getID()
Returns a unique integer that is used to sort list of attachment points.
int getAtomPositionNumber()
The index of the source atom in the atom list of the fragment.
boolean isAvailableThroughout()
Check availability of this attachment point throughout the graph level, i.e., check also across the i...
AttachmentPoint getLinkedAPThroughout()
Gets the attachment point (AP) that is connected to this AP via the edge user or in any edge user tha...
A candidate is the combination of a denoptim graph with molecular representation and may include also...
Definition: Candidate.java:40
void setSDFFile(String molFile)
Definition: Candidate.java:445
void setSmiles(String smiles)
Definition: Candidate.java:473
void setUID(String uid)
Definition: Candidate.java:466
int getGeneration()
The generation this candidate belong to is that in which it was generated.
Definition: Candidate.java:578
void setName(String name)
Definition: Candidate.java:495
void setChemicalRepresentation(IAtomContainer iac)
Just place the argument in the IAtomContainer field of this object.
Definition: Candidate.java:378
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:104
void setCandidateClosableChains(ArrayList< ClosableChain > closableChains)
Definition: DGraph.java:935
void addVertex(Vertex vertex)
Appends a vertex to this graph without creating any edge.
Definition: DGraph.java:1391
DGraph embedPatternsInTemplates(GraphPattern pattern, FragmentSpace fragSpace)
Searches for the given pattern type and generated a new graph where each set of (clones of) vertexes ...
Definition: DGraph.java:5316
void getChildrenTree(Vertex vertex, List< Vertex > children)
Gets all the children of the current vertex recursively.
Definition: DGraph.java:3421
String getLocalMsg()
Definition: DGraph.java:289
void setGraphId(int id)
Definition: DGraph.java:266
ArrayList< Vertex > getFreeRCVertices()
Search for unused ring closing vertices: vertices that contain only a RingClosingAttractor and are no...
Definition: DGraph.java:1258
Object[] checkConsistency(RunTimeParameters settings)
Peeks into this graph to derive a preliminary chemical representation with SMILES and InChIKey.
Definition: DGraph.java:6053
List< Vertex > getVertexList()
Returns the list of vertexes without entering Templates.
Definition: DGraph.java:973
DGraph clone()
Returns almost "deep-copy" of this graph.
Definition: DGraph.java:3836
void renumberGraphVertices()
Reassign vertex IDs to all vertices of this graph.
Definition: DGraph.java:5983
boolean containsOrEmbedsVertex(Vertex v)
Check if the specified vertex is contained in this graph as a node or in any inner graphs that may be...
Definition: DGraph.java:3179
DGraph getOutermostGraphOwner()
Definition: DGraph.java:7647
void addCappingGroups(FragmentSpace fragSpace)
Add a capping groups on free unused attachment points.
Definition: DGraph.java:4819
void cleanup()
Wipes the data in this graph.
Definition: DGraph.java:4018
Candidate getCandidateOwner()
Returns the reference of the candidate item that is defined by this graph.
Definition: DGraph.java:259
ArrayList< Vertex > getUsedRCVertices()
Search for used ring closing vertices: vertices that contain only a RingClosingAttractor and are part...
Definition: DGraph.java:1281
int getHeavyAtomsCount()
Calculate the number of atoms from the graph representation.
Definition: DGraph.java:4603
List< Vertex > getMutableSites()
A list of mutation sites from within this graph.
Definition: DGraph.java:7296
void setLocalMsg(String msg)
Definition: DGraph.java:281
boolean detectSymVertexSets()
Detects and groups symmetric sets of Vertexes in the graph based on unique identification and path en...
Definition: DGraph.java:370
An empty vertex has the behaviors of a vertex, but has no molecular structure.
Class representing a continuously connected portion of chemical object holding attachment points.
Definition: Fragment.java:61
boolean isIsomorphicTo(Vertex other)
Checks for isomorphism of the graph representation of this and another fragment.
Definition: Fragment.java:1066
void updateAPs()
Changes the properties of each APs as to reflect the current atom list.
Definition: Fragment.java:511
This class represents the closure of a ring in a spanning tree.
Definition: Ring.java:40
A collection of AttachmentPoints that are related by a relation that we call "symmetry",...
Class representing a list of references pointing to instances that are related by some conventional c...
Class coupling a reference to a SymmetricSet with a string that we call "mode" and can is used to sto...
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
abstract Vertex clone()
Returns a deep-copy of this vertex.
int getBuildingBlockId()
Returns the index of the building block that should correspond to the position of the building block ...
Definition: Vertex.java:304
void setVertexId(long vertexId2)
Definition: Vertex.java:281
DGraph getGraphOwner()
Returns the graph this vertex belongs to or null.
Definition: Vertex.java:851
abstract List< AttachmentPoint > getAttachmentPoints()
SymmetricAPs getSymmetricAPs(AttachmentPoint ap)
For the given attachment point index locate the symmetric partners i.e.
Definition: Vertex.java:353
abstract int getHeavyAtomsCount()
void setBuildingBlockType(Vertex.BBType buildingBlockType)
Definition: Vertex.java:325
abstract IAtomContainer getIAtomContainer()
boolean hasFreeAP()
Definition: Vertex.java:520
void setProperty(Object key, Object property)
Definition: Vertex.java:1235
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
Definition: Vertex.java:1007
This is a tool to identify and manage vertices' connections not included in the DGraph,...
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...
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...
Parameters and setting related to handling ring closures.
boolean buildChelatesMode
Flag activating procedures favoring formation of chelates.
Data structure to store and handle information about sub-structures (i.e., chains of fragments) and r...
ArrayList< ClosableChain > getCCFromTurningPointId(int tpId)
Returns the library of closable chains having the given turning point (i.e., the fragments involved i...
Utility methods for input/output.
static ArrayList< Candidate > readCandidates(File file)
Reads SDF files that represent one or more tested candidates.
static void writeGraphsToSDF(File file, List< DGraph > graphs, Logger logger, Randomizer randomizer)
Writes the graphs to SDF file.
static void writeCandidateToFile(File file, Candidate candidate, boolean append)
Writes one candidate item to file.
static void writeGraphToSDF(File file, DGraph graph, boolean append, boolean make3D, Logger logger, Randomizer randomizer)
Writes the graph to SDF file.
static ArrayList< DGraph > readDENOPTIMGraphsFromFile(File inFile)
Reads a list of DGraphs from file.
static ArrayList< String > readList(String fileName)
Read list of data as text.
static void writeData(String fileName, String data, boolean append)
Write text-like data file.
static void writeCandidatesToFile(File file, List< Candidate > popMembers, boolean append)
Writes candidate items to file.
A collection of counters user to count actions taken by the evolutionary algorithm.
Definition: Monitor.java:37
void increase(CounterID cid)
Definition: Monitor.java:149
Tool to build build three-dimensional (3D) tree-like molecular structures from DGraph.
void setAlignBBsIn3D(boolean align)
Sets the flag that controls whether building blocks have to be aligned according to the AP vectors or...
IAtomContainer convertGraphTo3DAtomContainer(DGraph graph)
Created a three-dimensional molecular representation from a given DGraph.
boolean containsParameters(ParametersType type)
RunTimeParameters getParameters(ParametersType type)
Logger getLogger()
Get the name of the program specific logger.
final String NL
New line character.
Randomizer getRandomizer()
Returns the current program-specific randomizer.
Parameters for genetic algorithm.
boolean useMolSizeBasedProb
Flag recording the intention to use molecular size-controlled graph extension probability.
boolean recordMateSelection
Flag defining whether we record which mates are selected or not.
boolean useLevelBasedProb
Flag recording the intention to use level-controlled graph extension probability.
Parameters controlling execution of the fragmenter.
void setEmbeddedRingsContract(ContractLevel embeddedRingsContract)
void setCuttingRules(List< CuttingRule > cuttingRules)
Assigns the cutting rules loaded from the input.
void setLinearAngleLimit(double linearAngleLimit)
Sets the upper limit for an angle before it is treated as "flat" angle, i.e., close enough to 180 DEG...
void setEmbedRingsInTemplate(boolean embedRingsInTemplate)
boolean embedRingsInTemplate
Flag that enables the embedding of rings in templates upon conversion of molecules into DGraph.
Toll to add/remove dummy atoms from linearities or multi-hapto sites.
static void addDummiesOnLinearities(Fragment frag, double angLim)
Append dummy atoms on otherwise linear arrangements of atoms.
static String getPaddedString(int count, int number)
returns the padded string with zeroes placed to the left of 'number' up to reach the desired number o...
Utilities for graphs.
Definition: GraphUtils.java:40
static synchronized void ensureVertexIDConsistency(long l)
Method used to ensure consistency between internal atomic integer and vertex id from imported graphs.
Definition: GraphUtils.java:55
static synchronized int getUniqueMoleculeIndex()
Unique counter for the number of molecules generated.
static synchronized int getUniqueGraphIndex()
Unique counter for the number of graphs generated.
Container of lists of atoms matching a list of SMARTS.
Mappings getMatchesOfSMARTS(String ref)
int getNumMatchesOfQuery(String query)
Utilities for molecule conversion.
static String getInChIKeyForMolecule(IAtomContainer mol, Logger logger)
Generates the InChI key for the given atom container.
static String getSMILESForMolecule(IAtomContainer mol, Logger logger)
Returns the SMILES representation of the molecule.
static String getSymbolOrLabel(IAtom atm)
Gets either the elemental symbol (for standard atoms) of the label (for pseudo-atoms).
Tool to generate random numbers and random decisions.
Definition: Randomizer.java:36
boolean nextBoolean()
Returns the next pseudo-random, uniformly distributed boolean value from this random number generator...
public< T > T randomlyChooseOne(Collection< T > c)
Chooses one member among the given collection.
double nextDouble()
Returns the next pseudo-random, uniformly distributed double value between 0.0 and 1....
Tool box for definition and management of the rotational space, which is given by the list of rotatab...
static ArrayList< ObjectPair > defineRotatableBonds(IAtomContainer mol, String defRotBndsFile, boolean addIterfragBonds, boolean excludeRings, Logger logger)
Define the rotational space (a.k.a.
Class meant to collect unique strings without leading to memory overflow.
Utilities for calculating basic statistics.
Definition: StatUtils.java:26
static double mean(double[] numbers)
Returns the mean number in the numbers list.
Definition: StatUtils.java:53
static double stddev(double[] numbers, boolean biasCorrected)
Returns the standard deviation of the numbers.
Definition: StatUtils.java:107
static double skewness(double[] m, boolean biasCorrected)
Computes the skewness of the available values.
Definition: StatUtils.java:246
static double median(double[] m)
Calculates median value of a sorted list.
Definition: StatUtils.java:172
static double min(double[] numbers)
Returns the minimum value among the numbers .
Definition: StatUtils.java:67
static double max(double[] numbers)
Returns the maximum value among the numbers .
Definition: StatUtils.java:85
Defines how to define the scaffold vertex of a graph.
String label
Label defining additional details, such as which label to search for in case of elemental symbol-base...
A chosen method for generation of new Candidates.
Definition: EAUtils.java:128
Possible chemical bond types an edge can represent.
Definition: Edge.java:305
Enum specifying to what extent the template's inner graph can be changed.
Definition: Template.java:104
FIXED
Inner graphs are effectively equivalent to the Fragment class, as no change in the inner structure is...
Definition: Template.java:116
The type of building block.
Definition: Vertex.java:86
Identifier of a counter.
Definition: CounterID.java:29
FS_PARAMS
Parameters pertaining the definition of the fragment space.
FRG_PARAMS
Parameters controlling the fragmenter.
FIT_PARAMS
Parameters pertaining the calculation of fitness (i.e., the fitness provider).
RC_PARAMS
Parameters pertaining to ring closures in graphs.