$darkmode
DENOPTIM
EAUtilsTest.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2022 Marco Foscato <marco.foscato@uib.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.ga;
20
21import static org.junit.jupiter.api.Assertions.assertEquals;
22import static org.junit.jupiter.api.Assertions.assertFalse;
23import static org.junit.jupiter.api.Assertions.assertNotNull;
24import static org.junit.jupiter.api.Assertions.assertTrue;
25
26import java.io.File;
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.HashMap;
30import java.util.HashSet;
31import java.util.Iterator;
32import java.util.List;
33import java.util.Map;
34import java.util.Set;
35import java.util.logging.Logger;
36import java.util.stream.Collectors;
37
38import javax.vecmath.Point3d;
39
40import org.junit.jupiter.api.Test;
41import org.junit.jupiter.api.io.TempDir;
42import org.openscience.cdk.Atom;
43import org.openscience.cdk.interfaces.IAtom;
44import org.openscience.cdk.interfaces.IAtomContainer;
45import org.openscience.cdk.interfaces.IBond;
46import org.openscience.cdk.interfaces.IChemObjectBuilder;
47import org.openscience.cdk.layout.StructureDiagramGenerator;
48import org.openscience.cdk.silent.Bond;
49import org.openscience.cdk.silent.SilentChemObjectBuilder;
50import org.openscience.cdk.smiles.SmilesParser;
51
52import denoptim.constants.DENOPTIMConstants;
53import denoptim.exception.DENOPTIMException;
54import denoptim.fragmenter.ScaffoldingPolicy;
55import denoptim.fragspace.FragmentSpace;
56import denoptim.fragspace.FragmentSpaceParameters;
57import denoptim.ga.EAUtils.CandidateSource;
58import denoptim.graph.APClass;
59import denoptim.graph.AttachmentPoint;
60import denoptim.graph.Candidate;
61import denoptim.graph.DGraph;
62import denoptim.graph.DGraphTest;
63import denoptim.graph.Edge.BondType;
64import denoptim.graph.EmptyVertex;
65import denoptim.graph.Fragment;
66import denoptim.graph.GraphPattern;
67import denoptim.graph.RelatedAPPair;
68import denoptim.graph.SymmetricVertexes;
69import denoptim.graph.Template;
70import denoptim.graph.Template.ContractLevel;
71import denoptim.graph.Vertex;
72import denoptim.graph.Vertex.BBType;
73import denoptim.graph.rings.RingClosureParameters;
74import denoptim.io.DenoptimIO;
75import denoptim.logging.Monitor;
76import denoptim.programs.denovo.GAParameters;
77import denoptim.programs.fragmenter.CuttingRule;
78import denoptim.utils.MoleculeUtils;
79import denoptim.utils.Randomizer;
80
87public class EAUtilsTest
88{
89
90 private static APClass APCA, APCB, APCC;
91 private static String a="A", b="B", c="C";
92
93 private static final String SEP = System.getProperty("file.separator");
94 private static final String NL = System.getProperty("line.separator");
95
99 private IChemObjectBuilder builder = SilentChemObjectBuilder.getInstance();
100
101 @TempDir
102 static File tempDir;
103
104//------------------------------------------------------------------------------
105
107 {
111
112 HashMap<APClass,ArrayList<APClass>> cpMap =
113 new HashMap<APClass,ArrayList<APClass>>();
114 ArrayList<APClass> lstA = new ArrayList<APClass>();
115 lstA.add(APCA);
116 cpMap.put(APCA, lstA);
117 ArrayList<APClass> lstB = new ArrayList<APClass>();
118 lstB.add(APCB);
119 lstB.add(APCC);
120 cpMap.put(APCB, lstB);
121 ArrayList<APClass> lstC = new ArrayList<APClass>();
122 lstC.add(APCB);
123 lstC.add(APCC);
124 cpMap.put(APCC, lstC);
125
126 /* Compatibility matrix
127 *
128 * | A | B | C |
129 * -------------------------
130 * A | T | | |
131 * -------------------------
132 * B | | T | T |
133 * -------------------------
134 * C | | T | T |
135 * -------------------------
136 */
137
138 HashMap<APClass,APClass> capMap = new HashMap<APClass,APClass>();
139 HashSet<APClass> forbEnds = new HashSet<APClass>();
140
142 FragmentSpace fs = new FragmentSpace(fsp,
143 new ArrayList<Vertex>(),
144 new ArrayList<Vertex>(),
145 new ArrayList<Vertex>(),
146 cpMap, capMap, forbEnds, cpMap);
148
149 EmptyVertex v1 = new EmptyVertex();
151 v1.addAP(APCB);
152 v1.addAP(APCB);
154
155 EmptyVertex v2 = new EmptyVertex();
157 v2.addAP(APCC);
158 v2.addAP(APCC);
160
161 EmptyVertex rcv = new EmptyVertex();
163 rcv.addAP(APCC);
164 rcv.setAsRCV(true);
166
167 DGraph graphForTemplate = new DGraph();
169 BBType.FRAGMENT, fs);
170 graphForTemplate.addVertex(vg1);
171 for (int i=1; i<6; i++)
172 {
174 BBType.FRAGMENT, fs);
175 Vertex vgi_1 = graphForTemplate.getVertexAtPosition(i-1);
176 graphForTemplate.appendVertexOnAP(vgi_1.getAP(1), vgi.getAP(0));
177 }
179 BBType.FRAGMENT, fs);
180 graphForTemplate.appendVertexOnAP(
181 graphForTemplate.getVertexAtPosition(5).getAP(1),rcv1.getAP(0));
183 BBType.FRAGMENT, fs);
184 graphForTemplate.appendVertexOnAP(
185 graphForTemplate.getVertexAtPosition(0).getAP(0),rcv2.getAP(0));
186 graphForTemplate.addRing(rcv1, rcv2);
187
188 Template template = new Template(BBType.SCAFFOLD);
189 template.setInnerGraph(graphForTemplate);
190 template.setContractLevel(ContractLevel.FIXED_STRUCT);
192 fs.getScaffoldLibrary());
193
194 return fsp;
195 }
196
197//------------------------------------------------------------------------------
198
199 @Test
200 public void testBuildGraphFromTemplateScaffold() throws Exception
201 {
203 GAParameters gaParams = new GAParameters();
204 gaParams.setParameters(fsp);
205 DGraph g = EAUtils.buildGraph(gaParams);
206
207 if (g == null)
208 assertTrue(false,"faild construction of graph");
209
211
212 //NB: we want to not allow access to the inner graph from outside the
213 // template, but this means we cannot easily explore the inner graph.
214 // Looking at the mutation sites is a dirty trick to get a look inside
215 // this template, that has contract level "free" (meaning that the
216 // content of the template can change).
217
218 boolean foundChange = false;
219 for (Vertex v : t.getMutationSites())
220 {
221 if (v.getBuildingBlockId() != 0)
222 foundChange = true;
223 }
224 assertTrue(foundChange,"The initial inner graph has changed.");
225 }
226
227//------------------------------------------------------------------------------
228
229 @Test
230 public void testAvoidRedundantXOver() throws Exception
231 {
232 DGraph g1 = new DGraph();
233 EmptyVertex s = new EmptyVertex();
234 s.addAP();
235 s.addAP();
237
238 EmptyVertex v = new EmptyVertex();
239 v.addAP();
241
242 g1.addVertex(s);
243 g1.appendVertexOnAP(s.getAP(0), v.getAP(0));
244
245 Candidate c1 = new Candidate(g1);
246
247 DGraph g2 = g1.clone();
248 Candidate c2 = new Candidate(g2);
249
251 GAParameters gaParams = new GAParameters();
252 gaParams.setParameters(fsp);
253
254 ArrayList<Candidate> eligibleParents = new ArrayList<Candidate>();
255 eligibleParents.add(c1);
256 eligibleParents.add(c2);
257 Population population = new Population(gaParams);
258 population.add(c1);
259 population.add(c2);
260 Monitor mnt = new Monitor();
261
262 Candidate offspring = EAUtils.buildCandidateByXOver(eligibleParents,
263 population, mnt, gaParams);
264
265 assertTrue(offspring==null, "Redundat xover is not done");
266 }
267
268//------------------------------------------------------------------------------
269
270 @Test
271 public void testBuildByXOver_SubGraph() throws Exception
272 {
274 Population population = new Population(gaparams);
275
276 /*
277 * -(A)v0(A)-(A)v1(A)-(A)v2(A)-(A)v3(B)-(B)v4(B)-(B)v5(B)-
278 */
280 Candidate cA = new Candidate("CA",gA);
281 cA.setFitness(1.23);
282 population.add(cA);
283
284 /*
285 * v0(B)-(B)v1(A)-(A)v2(B)-(B)v3(A)-(A)v4(B)-(B)v5
286 */
288 Candidate cE = new Candidate("CE",gE);
289 cE.setFitness(2.34);
290 population.add(cE);
291
292 ArrayList<Candidate> eligibleParents = new ArrayList<Candidate>();
293 eligibleParents.add(cA);
294 eligibleParents.add(cE);
295
296 Monitor mnt = new Monitor();
297
298 Candidate offspring0 = EAUtils.buildCandidateByXOver(eligibleParents,
299 population, mnt, new int[]{0,1}, 3, 0, gaparams);
300
301 Candidate offspring1 = EAUtils.buildCandidateByXOver(eligibleParents,
302 population, mnt, new int[]{0,1}, 3, 1, gaparams);
303
304 DGraph g0 = offspring0.getGraph();
305 assertEquals(4,g0.getVertexCount());
306 assertEquals(3,g0.getEdgeCount());
307 int maxLength = -1;
308 for (Vertex v : g0.getVertexList())
309 {
310 ArrayList<Vertex> childTree = new ArrayList<Vertex>();
311 g0.getChildrenTree(v, childTree);
312 if (childTree.size()>maxLength)
313 {
314 maxLength = childTree.size();
315 }
316 }
317 assertEquals(3,maxLength);
318
319 DGraph g1 = offspring1.getGraph();
320 assertEquals(8,g1.getVertexCount());
321 assertEquals(7,g1.getEdgeCount());
322 maxLength = -1;
323 for (Vertex v : g1.getVertexList())
324 {
325 ArrayList<Vertex> childTree = new ArrayList<Vertex>();
326 g1.getChildrenTree(v, childTree);
327 if (childTree.size()>maxLength)
328 {
329 maxLength = childTree.size();
330 }
331 }
332 assertEquals(7,maxLength);
333 }
334
335//------------------------------------------------------------------------------
336
347 @Test
348 public void testBuildByXOver_Embedded_Free() throws Exception
349 {
351 Population population = new Population(gaparams);
352
354 DGraph gA = pair[0];
355 DGraph gB = pair[1];
356 ((Template)gA.getVertexAtPosition(1)).setContractLevel(
358 ((Template)gB.getVertexAtPosition(1)).setContractLevel(
360
361 Candidate cA = new Candidate("CA",gA);
362 population.add(cA);
363
364 Candidate cB = new Candidate("CB",gB);
365 population.add(cB);
366
367 ArrayList<Candidate> eligibleParents = new ArrayList<Candidate>();
368 eligibleParents.add(cA);
369 eligibleParents.add(cB);
370
371 Monitor mnt = new Monitor();
372
373 Candidate offspring0 = EAUtils.buildCandidateByXOver(eligibleParents,
374 population, mnt, new int[]{0,1}, 8, 0, gaparams);
375
376 Candidate offspring1 = EAUtils.buildCandidateByXOver(eligibleParents,
377 population, mnt, new int[]{0,1}, 8, 1, gaparams);
378
379 DGraph g0xo = offspring0.getGraph();
380 DGraph g1xo = offspring1.getGraph();
381
383 DGraph expected0 = expectedPair[0];
384 DGraph expected1 = expectedPair[1];
385 ((Template)expected0.getVertexAtPosition(1)).setContractLevel(
387 ((Template)expected1.getVertexAtPosition(1)).setContractLevel(
389
390 assertTrue(expected0.sameAs(g0xo, new StringBuilder()));
391 assertTrue(expected1.sameAs(g1xo, new StringBuilder()));
392 }
393
394//------------------------------------------------------------------------------
395
406 @Test
407 public void testBuildByXOver_Embedded_FreeBackwards() throws Exception
408 {
410 Population population = new Population(gaparams);
411
413 DGraph gA = pair[0];
414 DGraph gB = pair[1];
415 ((Template)gA.getVertexAtPosition(1)).setContractLevel(
417 ((Template)gB.getVertexAtPosition(1)).setContractLevel(
419
420 Candidate cA = new Candidate("CA",gA);
421 population.add(cA);
422
423 Candidate cB = new Candidate("CB",gB);
424 population.add(cB);
425
426 ArrayList<Candidate> eligibleParents = new ArrayList<Candidate>();
427 eligibleParents.add(cA);
428 eligibleParents.add(cB);
429
430 Monitor mnt = new Monitor();
431
432 Candidate offspring0 = EAUtils.buildCandidateByXOver(eligibleParents,
433 population, mnt, new int[]{0,1}, 17, 0, gaparams);
434
435 Candidate offspring1 = EAUtils.buildCandidateByXOver(eligibleParents,
436 population, mnt, new int[]{0,1}, 17, 1, gaparams);
437
438 DGraph g0xo = offspring0.getGraph();
439 DGraph g1xo = offspring1.getGraph();
440
442 DGraph expected0 = expectedPair[0];
443 DGraph expected1 = expectedPair[1];
444 ((Template)expected0.getVertexAtPosition(1)).setContractLevel(
446 ((Template)expected1.getVertexAtPosition(1)).setContractLevel(
448
449 assertTrue(expected0.sameAs(g0xo, new StringBuilder()));
450 assertTrue(expected1.sameAs(g1xo, new StringBuilder()));
451 }
452
453//------------------------------------------------------------------------------
454
455 @Test
456 public void testBuildByXOver_Embedded_FixedStructure() throws Exception
457 {
459 Population population = new Population(gaparams);
460
462 DGraph gA = pair[0];
463 DGraph gB = pair[1];
464 Template embeddedTmplA = (Template) gA.getVertexAtPosition(1);
466 DGraph embeddedGraphA = embeddedTmplA.getInnerGraph();
467 Template embeddedTmplB = (Template) gB.getVertexAtPosition(1);
469 DGraph embeddedGraphB = embeddedTmplB.getInnerGraph();
470
471 // Make vertexes unique so, even though they are empty, they will be
472 // seen as non equal and crossover will be seen as non-redundant.
473 String propName = "uniquefier";
474 int i=0;
475 for (Vertex v : embeddedGraphA.getVertexList())
476 {
477 v.setUniquefyingProperty(propName);
478 v.setProperty(propName, i);
479 i++;
480 }
481
482 Candidate cA = new Candidate("CA",gA);
483 population.add(cA);
484 Candidate cB = new Candidate("CB",gB);
485 population.add(cB);
486 ArrayList<Candidate> eligibleParents = new ArrayList<Candidate>();
487 eligibleParents.add(cA);
488 eligibleParents.add(cB);
489
490 Monitor mnt = new Monitor();
491 boolean embeddedGraphHasBeenAlteredA = false;
492 boolean embeddedGraphHasBeenAlteredB = false;
493 for (int ixo=0; ixo<11; ixo++)
494 {
495 Candidate offspring0 = null;
496 Candidate offspring1 = null;
497 try
498 {
499 offspring0 = EAUtils.buildCandidateByXOver(eligibleParents,
500 population, mnt, new int[]{0,1}, ixo, 0, gaparams);
501 offspring1 = EAUtils.buildCandidateByXOver(eligibleParents,
502 population, mnt, new int[]{0,1}, ixo, 1, gaparams);
503 } catch (IndexOutOfBoundsException e)
504 {
505 if (e.getMessage().contains("Index 10 out of bounds"))
506 {
507 // All good! We intentionally triggered this exception to
508 // verify that the list of xover points has the right size.
509 break;
510 }
511 throw e;
512 }
513
514 DGraph g0xo = offspring0.getGraph();
515 DGraph g1xo = offspring1.getGraph();
516 Template t0 = null;
517 Template t1 = null;
518 for (Vertex v : g0xo.getVertexList())
519 {
520 if (v instanceof Template)
521 {
522 t0 = (Template) v;
523 break;
524 }
525 }
526 for (Vertex v : g1xo.getVertexList())
527 {
528 if (v instanceof Template)
529 {
530 t1 = (Template) v;
531 break;
532 }
533 }
534 assertNotNull(t0);
535 assertNotNull(t1);
536
537 DGraph embeddedGraph0 = t0.getInnerGraph();
538 DGraph embeddedGraph1 = t1.getInnerGraph();
539
540 // Ensure there has been a change
541 if (!embeddedGraphA.isIsomorphicTo(embeddedGraph0)
542 && !embeddedGraphA.isIsomorphicTo(embeddedGraph1))
543 {
544 embeddedGraphHasBeenAlteredA = true;
545 }
546 if (!embeddedGraphB.isIsomorphicTo(embeddedGraph0)
547 && !embeddedGraphB.isIsomorphicTo(embeddedGraph1))
548 {
549 embeddedGraphHasBeenAlteredB = true;
550 }
551
552 // Ensure consistency with "fixed-structure" contract
553 assertTrue(embeddedGraphA.isIsostructuralTo(embeddedGraph0)
554 || embeddedGraphB.isIsostructuralTo(embeddedGraph0));
555 assertTrue(embeddedGraphA.isIsostructuralTo(embeddedGraph1)
556 || embeddedGraphB.isIsostructuralTo(embeddedGraph1));
557 }
558 assertTrue(embeddedGraphHasBeenAlteredA);
559 assertTrue(embeddedGraphHasBeenAlteredB);
560 }
561
562//------------------------------------------------------------------------------
563
564 @Test
565 public void testCandidateGenerationMethod() throws Exception
566 {
567 int ix = 0, im=0, ic=0, tot=1000;
568 double wx = 2, wm = 0.6, wc=0.05;
569 double wtot = wx + wm + wc;
570 Randomizer rng = new Randomizer();
571 for (int i=0; i<tot; i++)
572 {
574 wx, wm, wc, rng);
575 switch (mode)
576 {
577 case CROSSOVER:
578 ix++;
579 break;
580 case MUTATION:
581 im++;
582 break;
583 case CONSTRUCTION:
584 ic++;
585 break;
586 default:
587 assertTrue(false,"Unexpected generation mode "+mode);
588 break;
589 }
590 }
591 double x = ((double)ix) / tot;
592 double m = ((double)im) / tot;
593 double c = ((double)ic) / tot;
594
595 double thld = 0.05;
596
597 assertTrue(Math.abs(x-(wx/wtot)) < thld, "#Xover cases are off!");
598 assertTrue(Math.abs(m-(wm/wtot)) < thld, "#Mutation cases are off!");
599 assertTrue(Math.abs(c-(wc/wtot)) < thld, "#Built cases are off!");
600 }
601
602//------------------------------------------------------------------------------
603
604 @Test
605 public void testCandidateGenerationMethodReproducibility() throws Exception
606 {
607 int tot = 100000;
608 long seed = 1234567;
609 long otherSeed = 987654321;
610 double wx = 2, wm = 0.6, wc=0.05;
611
612 Randomizer rng = new Randomizer(seed);
613 List<CandidateSource> resultsA = new ArrayList<CandidateSource>();
614 for (int i=0; i<tot; i++)
615 {
616 resultsA.add(EAUtils.pickNewCandidateGenerationMode(wx,wm,wc,rng));
617 }
618
619 Randomizer rng2 = new Randomizer(otherSeed);
620 List<CandidateSource> resultsB = new ArrayList<CandidateSource>();
621 for (int i=0; i<tot; i++)
622 {
623 resultsB.add(EAUtils.pickNewCandidateGenerationMode(wx,wm,wc,rng2));
624 }
625
626 rng = new Randomizer(seed);
627 List<CandidateSource> resultsC = new ArrayList<CandidateSource>();
628 for (int i=0; i<tot; i++)
629 {
630 resultsC.add(EAUtils.pickNewCandidateGenerationMode(wx,wm,wc,rng));
631 }
632
633 boolean different = false;
634 for (int i=0; i<tot; i++)
635 {
636 if (resultsA.get(i) != resultsB.get(i))
637 {
638 different = true;
639 break;
640 }
641 }
642 assertTrue(different);
643
644 for (int i=0; i<tot; i++)
645 {
646 assertEquals(resultsA.get(i),resultsC.get(i),
647 "Inconsistent sequence of random decisions");
648 }
649 }
650
651//------------------------------------------------------------------------------
652
653 @Test
654 public void testCrowdingProbability() throws Exception
655 {
657 double t = 0.001;
658 double p = 0.0;
660 {
661 p = EAUtils.getCrowdingProbability(ap,3,1.0,1.0,1.0);
662 assertTrue(Math.abs(1.0 - p)<t,
663 "Scheme 3 should return always 1.0 but was "+p);
664 }
666 p = EAUtils.getCrowdingProbability(ap3,0,1.0,10,1.0);
667 assertTrue(Math.abs(1.0 - p)<t, "Scheme 0 on ap3: 1.0 != "+p);
668 p = EAUtils.getCrowdingProbability(ap3,1,1.0,10,1.0);
669 assertTrue(Math.abs(1.0 - p)<t, "Scheme 1 on ap3: 1.0 != "+p);
670 p = EAUtils.getCrowdingProbability(ap3,2,1.0,10,1.0);
671 assertTrue(Math.abs(1.0 - p)<t, "Scheme 2 on ap3: 1.0 != "+p);
672
674 p = EAUtils.getCrowdingProbability(ap2,2,1.0,10,1.0);
675 assertTrue(Math.abs(0.5 - p)<t, "Scheme 2 on ap2");
676 }
677
678//------------------------------------------------------------------------------
679
680 @Test
681 public void testSelectNonScaffoldNonCapVertex() throws Exception
682 {
683 DGraph g = new DGraph();
684 EmptyVertex s = new EmptyVertex();
685 s.addAP();
686 s.addAP();
688
689 EmptyVertex v = new EmptyVertex();
690 v.addAP();
691 v.addAP();
692 v.addAP();
693 v.addAP();
695
696 EmptyVertex c1 = new EmptyVertex();
697 c1.addAP();
699
700 EmptyVertex c2 = new EmptyVertex();
701 c2.addAP();
703
704 EmptyVertex c3 = new EmptyVertex();
705 c3.addAP();
707
708 EmptyVertex c4 = new EmptyVertex();
709 c4.addAP();
711
712 g.addVertex(s);
713 g.appendVertexOnAP(s.getAP(0), v.getAP(0));
714 g.appendVertexOnAP(s.getAP(1), c1.getAP(0));
715 g.appendVertexOnAP(v.getAP(1), c2.getAP(0));
716 g.appendVertexOnAP(v.getAP(2), c3.getAP(0));
717 g.appendVertexOnAP(v.getAP(3), c4.getAP(0));
718
719 Randomizer rng = new Randomizer(1234L);
720 Vertex expected = v;
721 for (int i=0; i<5; i++)
722 {
724 assertEquals(expected, chosen, "Index of the only choosable vertex");
725 }
726 }
727
728//------------------------------------------------------------------------------
729
730 @Test
731 public void testChooseNumberOfSitesToMutate() throws Exception
732 {
733 double[] weights = new double[] {0,0,0,0,1};
734 assertEquals(4,EAUtils.chooseNumberOfSitesToMutate(weights,1.0));
735 assertEquals(4,EAUtils.chooseNumberOfSitesToMutate(weights,0.00000001));
736
737 weights = new double[] {1,0,0,0,1};
738 assertEquals(4,EAUtils.chooseNumberOfSitesToMutate(weights,1.0));
739 assertEquals(0,EAUtils.chooseNumberOfSitesToMutate(weights,0.00000001));
740
741 weights = new double[] {1,1,1,1,1};
742 assertEquals(4,EAUtils.chooseNumberOfSitesToMutate(weights,1.0));
743 assertEquals(4,EAUtils.chooseNumberOfSitesToMutate(weights,0.800001));
744 assertEquals(3,EAUtils.chooseNumberOfSitesToMutate(weights,0.799999));
745 assertEquals(3,EAUtils.chooseNumberOfSitesToMutate(weights,0.600001));
746 assertEquals(2,EAUtils.chooseNumberOfSitesToMutate(weights,0.599999));
747 assertEquals(2,EAUtils.chooseNumberOfSitesToMutate(weights,0.400001));
748 assertEquals(1,EAUtils.chooseNumberOfSitesToMutate(weights,0.399999));
749 assertEquals(1,EAUtils.chooseNumberOfSitesToMutate(weights,0.200001));
750 assertEquals(0,EAUtils.chooseNumberOfSitesToMutate(weights,0.199999));
751 assertEquals(0,EAUtils.chooseNumberOfSitesToMutate(weights,0.000001));
752 }
753
754//------------------------------------------------------------------------------
755
756 @Test
757 public void testMakeGraphFromFragmentationOfMol() throws Exception
758 {
759 // We use a hard-coded molecule to ensure the 3D geometry is fixed
760 assertTrue(tempDir.isDirectory(),"Should be a directory ");
761 String structureFile = tempDir.getAbsolutePath() + SEP + "mol.sdf";
762 DenoptimIO.writeData(structureFile,
763 "" + NL
764 + " OpenBabel03302310043D" + NL
765 + "" + NL
766 + " 33 35 0 0 0 0 0 0 0 0999 V2000" + NL
767 + " -1.5455 1.4965 3.4529 O 0 0 0 0 0 0 0 0 0 0 0 0" + NL
768 + " -1.1783 1.0876 2.3182 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
769 + " -1.8597 -0.0221 1.6796 N 0 0 0 0 0 0 0 0 0 0 0 0" + NL
770 + " -3.0535 -0.6083 2.2978 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
771 + " 0.0153 1.7383 1.6547 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
772 + " -0.1038 1.5947 0.1342 C 0 0 1 0 0 0 0 0 0 0 0 0" + NL
773 + " 0.9646 2.2439 -0.5585 O 0 0 0 0 0 0 0 0 0 0 0 0" + NL
774 + " 2.0315 1.3700 -0.8940 C 0 0 2 0 0 0 0 0 0 0 0 0" + NL
775 + " 3.0842 2.1330 -1.6910 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
776 + " 3.5659 3.1894 -0.9391 F 0 0 0 0 0 0 0 0 0 0 0 0" + NL
777 + " 4.1344 1.2898 -2.0067 F 0 0 0 0 0 0 0 0 0 0 0 0" + NL
778 + " 2.5295 2.6237 -2.8597 F 0 0 0 0 0 0 0 0 0 0 0 0" + NL
779 + " 1.5529 0.2692 -1.6691 O 0 0 0 0 0 0 0 0 0 0 0 0" + NL
780 + " 0.4699 -0.4528 -1.1881 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
781 + " -0.3192 0.1414 -0.2151 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
782 + " -1.2683 -0.6053 0.4932 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
783 + " -1.5222 -1.9320 0.0906 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
784 + " -0.8092 -2.5038 -0.9766 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
785 + " -1.1169 -3.8201 -1.3518 O 0 0 0 0 0 0 0 0 0 0 0 0" + NL
786 + " -0.4725 -4.5263 -2.4070 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
787 + " 0.2040 -1.7556 -1.6127 C 0 0 0 0 0 0 0 0 0 0 0 0" + NL
788 + " -3.7666 -0.9444 1.5155 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
789 + " -3.5865 0.1389 2.9228 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
790 + " -2.7606 -1.4709 2.9321 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
791 + " 0.9449 1.2474 2.0144 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
792 + " 0.0550 2.8163 1.9227 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
793 + " -1.0337 2.1265 -0.1667 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
794 + " 2.5075 0.9860 0.0372 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
795 + " -2.2462 -2.5403 0.6157 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
796 + " -0.6162 -3.9902 -3.3689 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
797 + " -0.9204 -5.5374 -2.4930 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
798 + " 0.6107 -4.6349 -2.1878 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
799 + " 0.8117 -2.1861 -2.3969 H 0 0 0 0 0 0 0 0 0 0 0 0" + NL
800 + " 1 2 2 0 0 0 0" + NL
801 + " 2 3 1 0 0 0 0" + NL
802 + " 2 5 1 0 0 0 0" + NL
803 + " 3 4 1 0 0 0 0" + NL
804 + " 4 22 1 0 0 0 0" + NL
805 + " 4 23 1 0 0 0 0" + NL
806 + " 4 24 1 0 0 0 0" + NL
807 + " 5 6 1 0 0 0 0" + NL
808 + " 5 25 1 0 0 0 0" + NL
809 + " 5 26 1 0 0 0 0" + NL
810 + " 6 7 1 0 0 0 0" + NL
811 + " 6 27 1 6 0 0 0" + NL
812 + " 7 8 1 0 0 0 0" + NL
813 + " 8 9 1 0 0 0 0" + NL
814 + " 8 13 1 0 0 0 0" + NL
815 + " 8 28 1 1 0 0 0" + NL
816 + " 9 10 1 0 0 0 0" + NL
817 + " 9 11 1 0 0 0 0" + NL
818 + " 9 12 1 0 0 0 0" + NL
819 + " 13 14 1 0 0 0 0" + NL
820 + " 14 15 2 0 0 0 0" + NL
821 + " 15 16 1 0 0 0 0" + NL
822 + " 15 6 1 0 0 0 0" + NL
823 + " 16 17 2 0 0 0 0" + NL
824 + " 16 3 1 0 0 0 0" + NL
825 + " 17 18 1 0 0 0 0" + NL
826 + " 17 29 1 0 0 0 0" + NL
827 + " 18 19 1 0 0 0 0" + NL
828 + " 18 21 2 0 0 0 0" + NL
829 + " 19 20 1 0 0 0 0" + NL
830 + " 20 30 1 0 0 0 0" + NL
831 + " 20 31 1 0 0 0 0" + NL
832 + " 20 32 1 0 0 0 0" + NL
833 + " 21 14 1 0 0 0 0" + NL
834 + " 21 33 1 0 0 0 0" + NL
835 + "M END" + NL
836 + "$$$$", false);
837 IAtomContainer mol = DenoptimIO.readSDFFile(structureFile).get(0);
838 GAParameters settings = new GAParameters();
839
840 List<CuttingRule> cuttingRules = new ArrayList<CuttingRule>();
841 cuttingRules.add(new CuttingRule("cC", "[c]", "[C]", "~", 0,
842 new ArrayList<String>()));
843 cuttingRules.add(new CuttingRule("cN", "[c]", "[#7]", "~", 1,
844 new ArrayList<String>()));
845 cuttingRules.add(new CuttingRule("cO", "[c]", "[#8]", "~", 2,
846 new ArrayList<String>()));
847 cuttingRules.add(new CuttingRule("OC", "[O]", "[C]", "-", 3,
848 new ArrayList<String>()));
849 cuttingRules.add(new CuttingRule("CF", "[C]", "[F]", "-", 4,
850 new ArrayList<String>()));
851 cuttingRules.add(new CuttingRule("NC", "[N]", "[C]", "-", 5,
852 new ArrayList<String>()));
853
855 cuttingRules, settings.getLogger(),
857
858 assertEquals(16, graph.getVertexCount());
859 assertEquals(15, graph.getEdgeCount());
860 assertEquals(2, graph.getRingCount());
861 assertEquals(0, graph.getVertexList()
862 .stream()
863 .filter(v -> v instanceof Template)
864 .count());
865
866 DGraph graphWithTemplate = graph.embedPatternsInTemplates(
868
869 assertEquals(7, graphWithTemplate.getVertexCount());
870 assertEquals(6, graphWithTemplate.getEdgeCount());
871 assertEquals(0, graphWithTemplate.getRingCount());
872 List<Vertex> templates = graphWithTemplate.getVertexList()
873 .stream()
874 .filter(v -> v instanceof Template)
875 .collect(Collectors.toList());
876 assertEquals(1, templates.size());
877 Template tmpl = (Template) templates.get(0);
878 assertEquals(BBType.SCAFFOLD, tmpl.getBuildingBlockType());
879 assertEquals(ContractLevel.FIXED, tmpl.getContractLevel());
880 assertEquals(2, tmpl.getInnerGraph().getRingCount());
881 }
882
883//------------------------------------------------------------------------------
884
885 @Test
887 throws Exception
888 {
889 SmilesParser p = new SmilesParser(builder);
890 IAtomContainer mol = p.parseSmiles("c1ccccc1OCN(CC)(C)[Ru](N)(N)C#O");
891
892 GAParameters settings = new GAParameters();
893
894 List<CuttingRule> cuttingRules = new ArrayList<CuttingRule>();
895 cuttingRules.add(new CuttingRule("C-O", "[#6]", "[#8]", "-", 2,
896 new ArrayList<String>()));
897 cuttingRules.add(new CuttingRule("N-C", "[#7]", "[#6]", "-", 5,
898 new ArrayList<String>()));
899 cuttingRules.add(new CuttingRule("Ru-Any", "[Ru]", "[$([*])]", "~", 5,
900 new ArrayList<String>()));
901
903 cuttingRules, settings.getLogger(),
905
906 assertEquals(10, graph1.getVertexCount());
907 assertEquals(9, graph1.getEdgeCount());
908 assertEquals(0, graph1.getRingCount());
909 List<Vertex> scaffolds = graph1.getVertexList()
910 .stream()
911 .filter(v -> BBType.SCAFFOLD == v.getBuildingBlockType())
912 .collect(Collectors.toList());
913 assertEquals(1, scaffolds.size());
914 Vertex scaffold = scaffolds.get(0);
915 IAtomContainer iacScaffold = scaffold.getIAtomContainer();
916 assertEquals(6, iacScaffold.getAtomCount());
917
919 policy.label = "Ru";
920
922 cuttingRules, settings.getLogger(), policy);
923
924 assertEquals(10, graph2.getVertexCount());
925 assertEquals(9, graph2.getEdgeCount());
926 assertEquals(0, graph2.getRingCount());
927 scaffolds = graph2.getVertexList()
928 .stream()
929 .filter(v -> BBType.SCAFFOLD == v.getBuildingBlockType())
930 .collect(Collectors.toList());
931 assertEquals(1, scaffolds.size());
932 scaffold = scaffolds.get(0);
933 iacScaffold = scaffold.getIAtomContainer();
934 assertEquals(1, iacScaffold.getAtomCount());
935 assertEquals("Ru", iacScaffold.getAtom(0).getSymbol());
936 }
937
938//------------------------------------------------------------------------------
939
940 @Test
941 public void testMakeGraphFromFragmentationOfMol_Symmetry() throws Exception
942 {
943 SmilesParser p = new SmilesParser(builder);
944 IAtomContainer mol = p.parseSmiles(
945 "Oc1cc(O)cc(O)c1CN(CC)(CC)[Ru](N)(Nc1c(F)cc(F)cc1(Cl))C#O");
946
947 GAParameters settings = new GAParameters();
948
949 List<CuttingRule> cuttingRules = new ArrayList<CuttingRule>();
950 cuttingRules.add(new CuttingRule("C-F", "[#6]", "[#9]", "-", 1,
951 new ArrayList<String>()));
952 cuttingRules.add(new CuttingRule("C-O", "[#6]", "[#8]", "-", 2,
953 new ArrayList<String>()));
954 cuttingRules.add(new CuttingRule("N-C", "[#7]", "[#6]", "-", 5,
955 new ArrayList<String>()));
956 cuttingRules.add(new CuttingRule("Ru-Any", "[Ru]", "[$([*])]", "~", 5,
957 new ArrayList<String>()));
958
960 cuttingRules, settings.getLogger(),
962
963 assertEquals(14, graph1.getVertexCount());
964 assertEquals(13, graph1.getEdgeCount());
965 assertEquals(0, graph1.getRingCount());
966 assertEquals(4, graph1.getSymmetricSetCount());
967 boolean foundO = false;
968 boolean foundF = false;
969 Iterator<SymmetricVertexes> iter = graph1.getSymSetsIterator();
970 while (iter.hasNext())
971 {
972 SymmetricVertexes ss = iter.next();
973 String el = ss.get(0).getIAtomContainer().getAtom(0).getSymbol();
974 if ("O".equals(el))
975 foundO = true;
976 else if ("F".equals(el))
977 foundF = true;
978 }
979 assertTrue(foundO);
980 assertTrue(foundF);
981
983 policy.label = "Cl";
984
986 cuttingRules, settings.getLogger(), policy);
987
988 assertEquals(14, graph2.getVertexCount());
989 assertEquals(13, graph2.getEdgeCount());
990 assertEquals(0, graph2.getRingCount());
991 assertEquals(4, graph2.getSymmetricSetCount());
992 foundO = false;
993 foundF = false;
994 iter = graph2.getSymSetsIterator();
995 while (iter.hasNext())
996 {
997 SymmetricVertexes ss = iter.next();
998 String el = ss.get(0).getIAtomContainer().getAtom(0).getSymbol();
999 if ("O".equals(el))
1000 foundO = true;
1001 else if ("F".equals(el))
1002 foundF = true;
1003 }
1004 assertTrue(foundO);
1005 assertTrue(foundF);
1006
1007
1008 policy = ScaffoldingPolicy.ELEMENT;
1009 policy.label = "F";
1010
1012 cuttingRules, settings.getLogger(), policy);
1013
1014 assertEquals(14, graph3.getVertexCount());
1015 assertEquals(13, graph3.getEdgeCount());
1016 assertEquals(0, graph3.getRingCount());
1017 assertEquals(3, graph3.getSymmetricSetCount());
1018 foundO = false;
1019 foundF = false;
1020 iter = graph3.getSymSetsIterator();
1021 while (iter.hasNext())
1022 {
1023 SymmetricVertexes ss = iter.next();
1024 String el = ss.get(0).getIAtomContainer().getAtom(0).getSymbol();
1025 if ("O".equals(el))
1026 foundO = true;
1027 else if ("F".equals(el))
1028 foundF = true;
1029 }
1030 assertTrue(foundO);
1031 assertFalse(foundF);
1032 }
1033
1034//------------------------------------------------------------------------------
1035
1036 @Test
1038 throws Exception
1039 {
1040 SmilesParser p = new SmilesParser(builder);
1041 IAtomContainer mol = p.parseSmiles("C#C-C#C-C#N");
1042
1043 // 2D is enough to get linearities. No need to waste time getting 3D
1044 StructureDiagramGenerator sdg = new StructureDiagramGenerator();
1045 sdg.generateCoordinates(mol);
1046
1047 GAParameters settings = new GAParameters();
1048
1049 List<CuttingRule> cuttingRules = new ArrayList<CuttingRule>();
1050 cuttingRules.add(new CuttingRule("C-C", "[#6]", "[#6]", "-", 2,
1051 new ArrayList<String>()));
1052 cuttingRules.add(new CuttingRule("C-X", "[#6]", "[#9,#17,#35,#53]", "~",
1053 3, new ArrayList<String>()));
1054
1055 // Must add du on linearities
1057 cuttingRules, settings.getLogger(),
1059
1060 assertEquals(3, graph.getVertexCount());
1061 assertEquals(2, graph.getEdgeCount());
1062 assertEquals(0, graph.getRingCount());
1063 int duAtmCount = 0;
1064 for (Vertex v : graph.getVertexList())
1065 {
1066 for (IAtom a : v.getIAtomContainer().atoms())
1067 {
1070 duAtmCount++;
1071 }
1072
1073 }
1074 assertEquals(4, duAtmCount);
1075
1076 // Without linearities
1077 IAtomContainer molNonLinear = p.parseSmiles("C(Cl)(F)Br");
1078 sdg.generateCoordinates(molNonLinear);
1079
1080 DGraph graph1 = EAUtils.makeGraphFromFragmentationOfMol(molNonLinear,
1081 cuttingRules, settings.getLogger(),
1083
1084 assertEquals(4, graph1.getVertexCount());
1085 assertEquals(3, graph1.getEdgeCount());
1086 assertEquals(0, graph1.getRingCount());
1087 duAtmCount = 0;
1088 for (Vertex v : graph1.getVertexList())
1089 {
1090 for (IAtom a : v.getIAtomContainer().atoms())
1091 {
1094 duAtmCount++;
1095 }
1096
1097 }
1098 assertEquals(0, duAtmCount);
1099
1100 // there are linearities but we do not want Du on linearities
1102 cuttingRules, settings.getLogger(),
1104 // By default we do not add Du on linearities
1105
1106 assertEquals(3, graph2.getVertexCount());
1107 assertEquals(2, graph2.getEdgeCount());
1108 assertEquals(0, graph2.getRingCount());
1109 duAtmCount = 0;
1110 for (Vertex v : graph2.getVertexList())
1111 {
1112 for (IAtom a : v.getIAtomContainer().atoms())
1113 {
1116 duAtmCount++;
1117 }
1118
1119 }
1120 assertEquals(0, duAtmCount);
1121 }
1122
1123//------------------------------------------------------------------------------
1124
1133 @Test
1135 {
1136 SmilesParser p = new SmilesParser(builder);
1137 IAtomContainer mol = p.parseSmiles(
1138 "P123C(OC[SiH2]O1)(OC[SiH2]O2)OC[SiH2]O3");
1139 GAParameters settings = new GAParameters();
1140
1141 List<CuttingRule> cuttingRules = new ArrayList<CuttingRule>();
1142 cuttingRules.add(new CuttingRule("PC-O", "[$(CP)]", "[O]", "-", -1,
1143 new ArrayList<String>()));
1144 cuttingRules.add(new CuttingRule("C-O", "[C]", "[O]", "-", 0,
1145 new ArrayList<String>()));
1146 cuttingRules.add(new CuttingRule("C-Si", "[C]", "[Si]", "-", 1,
1147 new ArrayList<String>()));
1148 cuttingRules.add(new CuttingRule("Si-O", "[Si]", "[O]", "-", 2,
1149 new ArrayList<String>()));
1150 cuttingRules.add(new CuttingRule("P-C", "[P]", "[C]", "-", 3,
1151 new ArrayList<String>()));
1152 cuttingRules.add(new CuttingRule("P-O", "[P]", "[O]", "-", 4,
1153 new ArrayList<String>()));
1154
1156 scaffoldOnP.label = "P";
1158 cuttingRules, settings.getLogger(),
1159 scaffoldOnP, 170);
1160
1161 assertEquals(6, graph.getSymmetricSetCount());
1162 List<List<Integer>> expected = new ArrayList<List<Integer>>();
1163 expected.add(Arrays.asList(3, 9, 15));
1164 expected.add(Arrays.asList(5, 11, 17));
1165 expected.add(Arrays.asList(7, 13, 19));
1166 expected.add(Arrays.asList(4, 10, 16));
1167 expected.add(Arrays.asList(2, 8, 14));
1168 expected.add(Arrays.asList(6, 12, 18));
1169 for (List<Integer> vrtxIDs : expected)
1170 {
1172 graph.getVertexWithId(vrtxIDs.get(0)));
1173 assertFalse(sv0.isEmpty());
1174 for (int i=1; i<vrtxIDs.size(); i++)
1175 {
1177 graph.getVertexWithId(vrtxIDs.get(i)));
1178 assertTrue(sv0 == svI);
1179 }
1180 }
1181
1182 IAtomContainer mol2 = p.parseSmiles(
1183 "C1C(C(C(F)(F)(F))(C(F)(F)(F)))OCCC1((N(C([H])([H])C3=C"
1184 + "(C(=C(C(=C3[H])[H])[F])[F]))(C([H])([H])C3=C(C(=C(C"
1185 + "(=C3[H])[H])[F])[F]))))");
1186
1187 cuttingRules = new ArrayList<CuttingRule>();
1188 cuttingRules.add(new CuttingRule("C-C", "[#6]", "[#6]", "-!@", -1,
1189 new ArrayList<String>()));
1190 cuttingRules.add(new CuttingRule("C-X", "[#6]", "[#9]", "-", 0,
1191 new ArrayList<String>()));
1192 cuttingRules.add(new CuttingRule("C-N", "[#6]", "[N]", "-", 1,
1193 new ArrayList<String>()));
1194
1196
1198 cuttingRules, settings.getLogger(),
1199 scaffold, 170);
1200
1201 assertEquals(5, graph.getSymmetricSetCount());
1202 expected = new ArrayList<List<Integer>>();
1203 expected.add(Arrays.asList(11, 15));
1204 expected.add(Arrays.asList(2, 6));
1205 expected.add(Arrays.asList(3, 4, 5, 7, 8, 9));
1206 expected.add(Arrays.asList(13, 14, 17, 18));
1207 expected.add(Arrays.asList(12, 16));
1208 for (List<Integer> vrtxIDs : expected)
1209 {
1211 graph.getVertexWithId(vrtxIDs.get(0)));
1212 assertFalse(sv0.isEmpty());
1213 for (int i=1; i<vrtxIDs.size(); i++)
1214 {
1216 graph.getVertexWithId(vrtxIDs.get(i)));
1217 assertTrue(sv0 == svI);
1218 }
1219 }
1220
1221 }
1222
1223
1224//------------------------------------------------------------------------------
1225
1226 @Test
1228 throws Exception
1229 {
1230 SmilesParser p = new SmilesParser(builder);
1231 IAtomContainer mol = p.parseSmiles("Cc1cnc(Cl)cc1O");
1233
1234 // 2D is enough to get linearities. No need to waste time getting 3D
1235 StructureDiagramGenerator sdg = new StructureDiagramGenerator();
1236 sdg.generateCoordinates(mol);
1237
1238 GAParameters settings = new GAParameters();
1239
1240 List<CuttingRule> cuttingRules = new ArrayList<CuttingRule>();
1241 cuttingRules.add(new CuttingRule("sAr", "[c]", "[*]", "-", 2,
1242 new ArrayList<String>()));
1243 cuttingRules.add(new CuttingRule("Ox", "[O]", "[*]", "-", 3,
1244 new ArrayList<String>()));
1245
1246 APClass hyd1 = APClass.make("hyd:1");
1247 APClass sAr0 = APClass.make("sAr:0");
1248 APClass ox0 = APClass.make("Ox:0");
1249 Fragment capH = new Fragment();
1250 capH.addAtom(new Atom("H", new Point3d()));
1251 capH.addAP(0, hyd1, new Point3d(1.0,0,0));
1252
1253 ArrayList<Vertex> cappingGroups = new ArrayList<Vertex>();
1254 cappingGroups.add(capH);
1255
1256 HashMap<APClass, APClass> capMap = new HashMap<APClass, APClass>();
1257 capMap.put(sAr0, hyd1);
1258 capMap.put(ox0, hyd1);
1259
1261 FragmentSpace fragSpace = new FragmentSpace(fsp,
1262 new ArrayList<Vertex>(), //no scaffolds
1263 new ArrayList<Vertex>(), //no fragments
1264 cappingGroups, //H as capping
1265 new HashMap<APClass,ArrayList<APClass>>(),
1266 capMap,
1267 new HashSet<APClass>(),
1268 new HashMap<APClass,ArrayList<APClass>>());
1269 fragSpace.setAPclassBasedApproach(true);
1270
1271 settings.setParameters(fsp);
1272
1273 // Without a fragment space we do not identify capping groups
1275 cuttingRules, settings.getLogger(),
1277 assertEquals(7, graph.getVertexCount());
1278 graph.removeCappingGroups();
1279 assertEquals(7, graph.getVertexCount());
1280
1282 cuttingRules, settings.getLogger(),
1283 ScaffoldingPolicy.LARGEST_FRAGMENT, 170, fragSpace);
1284 assertEquals(7, graph.getVertexCount());
1285 //In case you want to take a look ar the results
1286 // DenoptimIO.writeGraphToSDF(new File("/tmp/graph.sdf"), graph, false,
1287 // true, settings.getLogger(), settings.getRandomizer());
1288 graph.removeCappingGroups();
1289 assertEquals(4, graph.getVertexCount());
1290 }
1291
1292//------------------------------------------------------------------------------
1293
1294 @Test
1295 public void testSearchForApPairsSuitableToRingFusion() throws Exception
1296 {
1297 APClass apcA = APClass.make("apcA:1");
1298 APClass apcB = APClass.make("apcB:1");
1299 APClass apcC = APClass.make("apcC:1");
1300 APClass apcD = APClass.make("apcD:1");
1301 APClass apcE = APClass.make("apcE:1");
1302 APClass apcF = APClass.make("apcF:1");
1303 APClass apcG = APClass.make("apcG:1");
1304 APClass apcNotFusable = APClass.make("apcNotFusable:0");
1305 APClass apcFusedBridge = APClass.make("apcFusedBridge:0");
1306 APClass hyd = APClass.make("hyd:1");
1307
1308 // Utilities
1309 Logger logger = Logger.getLogger("DummyLogger");
1310 Randomizer rng = new Randomizer();
1311
1312 // Make a fragment space that saturates all valences
1313 HashMap<APClass,APClass> capMap = new HashMap<APClass,APClass>();
1314 capMap.put(apcA,hyd);
1315 capMap.put(apcB,hyd);
1316 capMap.put(apcC,hyd);
1317 capMap.put(apcD,hyd);
1318 capMap.put(apcE,hyd);
1319 capMap.put(apcF,hyd);
1320 capMap.put(apcG,hyd);
1321 capMap.put(apcNotFusable,hyd);
1322
1323 ArrayList<Vertex> cappingGroups = new ArrayList<Vertex>();
1324 Fragment capH = new Fragment();
1325 capH.addAtom(new Atom("H", new Point3d()));
1326 capH.addAP(0, new Point3d(1.0, 0, 0), hyd);
1327 cappingGroups.add(capH);
1328
1329 // Allows some ring closures via APClass compatibility
1330 HashMap<APClass,ArrayList<APClass>> rcCMap =
1331 new HashMap<APClass,ArrayList<APClass>>();
1332 rcCMap.put(apcA, new ArrayList<APClass>(Arrays.asList(apcFusedBridge)));
1333 rcCMap.put(apcB, new ArrayList<APClass>(Arrays.asList(apcFusedBridge)));
1334 rcCMap.put(apcC, new ArrayList<APClass>(Arrays.asList(apcFusedBridge)));
1335 rcCMap.put(apcD, new ArrayList<APClass>(Arrays.asList(apcFusedBridge)));
1336 rcCMap.put(apcE, new ArrayList<APClass>(Arrays.asList(apcFusedBridge)));
1337 rcCMap.put(apcF, new ArrayList<APClass>(Arrays.asList(apcFusedBridge)));
1338 rcCMap.put(apcG, new ArrayList<APClass>(Arrays.asList(apcFusedBridge)));
1339 // NB: apcNotFusable is intentionally not added to RC-CPMap!
1340
1342 FragmentSpace fragSpace = new FragmentSpace(fsp,
1343 new ArrayList<Vertex>(), //no scaffolds
1344 new ArrayList<Vertex>(), //no fragments
1345 cappingGroups, //H as capping
1346 new HashMap<APClass,ArrayList<APClass>>(),
1347 capMap, new HashSet<APClass>(),
1348 rcCMap);
1349 fragSpace.setAPclassBasedApproach(true);
1350
1352
1353 //
1354 // Case 0: APClass compatibility decides which APs can do ring fusion
1355 //
1356 SmilesParser parser = new SmilesParser(builder);
1357 IAtomContainer mol = parser.parseSmiles("c1ccccc1");
1359 StructureDiagramGenerator sdg = new StructureDiagramGenerator();
1360 sdg.generateCoordinates(mol);
1361 Fragment frag = new Fragment(mol, BBType.FRAGMENT);
1362 replaceHatomWithAP(frag, 2, apcNotFusable);
1363 replaceHatomWithAP(frag, 3, apcNotFusable);
1364 replaceHatomWithAP(frag, 4, apcA);
1365 replaceHatomWithAP(frag, 5, apcA);
1366 DGraph graph = new DGraph();
1367 graph.addVertex(frag);
1368
1369 List<List<RelatedAPPair>> combinations = EAUtils.searchRingFusionSites(
1370 graph, fragSpace, rcParams, false, logger, rng);
1371
1372 assertEquals(1, combinations.size());
1373 assertEquals(1, combinations.get(0).size());
1374 assertEquals(2, combinations.get(0).get(0).apA.getIndexInOwner());
1375 assertEquals(3, combinations.get(0).get(0).apB.getIndexInOwner());
1376
1377
1378 //
1379 // Case 1: one benzene fragment with 6 APs all in same symmetric set,
1380 // but NO request to project on symmetric APs
1381 //
1382 parser = new SmilesParser(builder);
1383 mol = parser.parseSmiles("c1ccccc1");
1385 sdg.generateCoordinates(mol);
1386 frag = new Fragment(mol, BBType.FRAGMENT);
1387 for (int i= 0; i<6; i++)
1388 {
1389 replaceHatomWithAP(frag, i, apcA);
1390 }
1391 graph = new DGraph();
1392 graph.addVertex(frag);
1393
1394 combinations = EAUtils.searchRingFusionSites(
1395 graph, fragSpace, rcParams, false, logger, rng);
1396
1397 assertEquals(6, combinations.size());
1398 Set<AttachmentPoint> involvedAPs = new HashSet<AttachmentPoint>();
1399 for (List<RelatedAPPair> comb : combinations)
1400 {
1401 assertEquals(1, comb.size());
1402 RelatedAPPair pair = comb.get(0);
1403 assertTrue(frag.getAttachmentPoints().contains(pair.apA));
1404 assertTrue(frag.getAttachmentPoints().contains(pair.apB));
1405 assertTrue(graph.getAttachmentPoints().contains(pair.apA));
1406 assertTrue(graph.getAttachmentPoints().contains(pair.apB));
1407 involvedAPs.add(pair.apA);
1408 involvedAPs.add(pair.apB);
1409 }
1410 assertEquals(6, involvedAPs.size());
1411
1412
1413 //
1414 // Case 2: one benzene fragment with 6 APs all in same symmetric set,
1415 // and we do request projection on symmetric APs
1416 //
1417 combinations = EAUtils.searchRingFusionSites(graph, fragSpace, rcParams, true, logger, rng);
1418
1419 // we aim at the maximum symmetry, so we find two combinations that
1420 // each accounts for 3 ring-fusion sites (i.e., pairs of APs that can
1421 // be used simultaneously to create each a fused ring)
1422 assertEquals(2, combinations.size());
1423 involvedAPs = new HashSet<AttachmentPoint>();
1424 for (List<RelatedAPPair> comb : combinations)
1425 {
1426 assertEquals(3, comb.size());
1427 involvedAPs = new HashSet<AttachmentPoint>();
1428 for (RelatedAPPair pair : comb)
1429 {
1430 involvedAPs.add(pair.apA);
1431 involvedAPs.add(pair.apB);
1432 }
1433 // both combination must involve all APs due to symmetry
1434 assertEquals(6, involvedAPs.size());
1435 }
1436
1437
1438 //
1439 // Case 3: Test handling of intra-fragment symmetry (i.e., symmetric APs)
1440 // but NO request to project on symmetric APs
1441 //
1442// This is the vertex we work with (NB: A, B, C are APClasses)
1443//
1444// B A H C
1445// 3--4 11--10
1446// / \ / \
1447// A 2 5---6 9 C
1448// \ / \ /
1449// 1--0 7--8
1450// B A H C
1451//
1452 mol = parser.parseSmiles("c1ccccc1c1ccccc1");
1454 sdg.generateCoordinates(mol);
1455 frag = new Fragment(mol, BBType.FRAGMENT);
1456 replaceHatomWithAP(frag, 0, apcA);
1457 replaceHatomWithAP(frag, 1, apcB);
1458 replaceHatomWithAP(frag, 2, apcA);
1459 replaceHatomWithAP(frag, 3, apcB);
1460 replaceHatomWithAP(frag, 4, apcA);
1461 replaceHatomWithAP(frag, 8, apcC);
1462 replaceHatomWithAP(frag, 9, apcC);
1463 replaceHatomWithAP(frag, 10, apcC);
1464 frag.setVertexId(321);
1465 graph = new DGraph();
1466 graph.addVertex(frag);
1467
1468 combinations = EAUtils.searchRingFusionSites(graph, fragSpace, rcParams, false, logger, rng);
1469
1470 assertEquals(6, combinations.size());
1471 int[] apUsageCounts = new int[8];
1472 for (List<RelatedAPPair> comb : combinations)
1473 {
1474 assertEquals(1, comb.size());
1475 for (RelatedAPPair pair : comb)
1476 {
1477 apUsageCounts[pair.apA.getIndexInOwner()] =
1478 apUsageCounts[pair.apA.getIndexInOwner()] + 1;
1479 apUsageCounts[pair.apB.getIndexInOwner()] =
1480 apUsageCounts[pair.apB.getIndexInOwner()] + 1;
1481 }
1482 }
1483 assertEquals(1, apUsageCounts[0]);
1484 assertEquals(2, apUsageCounts[1]);
1485 assertEquals(2, apUsageCounts[2]);
1486 assertEquals(2, apUsageCounts[3]);
1487 assertEquals(1, apUsageCounts[4]);
1488 assertEquals(1, apUsageCounts[5]);
1489 assertEquals(2, apUsageCounts[6]);
1490 assertEquals(1, apUsageCounts[7]);
1491
1492
1493 //
1494 // Case 4: as above but we do request to project on symmetric APs
1495 //
1496// This is the vertex we work with (NB: A, B, C are APClasses)
1497//
1498// B A H C
1499// 3--4 11--10
1500// / \ / \
1501// A 2 5---6 9 C
1502// \ / \ /
1503// 1--0 7--8
1504// B A H C
1505//
1506 combinations = EAUtils.searchRingFusionSites(graph, fragSpace, rcParams, true, logger, rng);
1507
1508 assertEquals(5, combinations.size());
1509 apUsageCounts = new int[8];
1510 int[] sizesCount = new int[4];
1511 for (List<RelatedAPPair> comb : combinations)
1512 {
1513 sizesCount[comb.size()] = sizesCount[comb.size()] +1;
1514 for (RelatedAPPair pair : comb)
1515 {
1516 apUsageCounts[pair.apA.getIndexInOwner()] =
1517 apUsageCounts[pair.apA.getIndexInOwner()] + 1;
1518 apUsageCounts[pair.apB.getIndexInOwner()] =
1519 apUsageCounts[pair.apB.getIndexInOwner()] + 1;
1520 }
1521 }
1522 assertEquals(2, apUsageCounts[0]);
1523 assertEquals(3, apUsageCounts[1]);
1524 assertEquals(2, apUsageCounts[2]);
1525 assertEquals(3, apUsageCounts[3]);
1526 assertEquals(2, apUsageCounts[4]);
1527 assertEquals(1, apUsageCounts[5]);
1528 assertEquals(2, apUsageCounts[6]);
1529 assertEquals(1, apUsageCounts[7]);
1530 assertEquals(0, sizesCount[0]);
1531 assertEquals(2, sizesCount[1]);
1532 assertEquals(3, sizesCount[2]);
1533 assertEquals(0, sizesCount[3]);
1534
1535
1536 //
1537 // Case 5: mix symmetric and asymmetric and do request to project on symmetric APs
1538 //
1539// This is the vertex we work with (NB: A, B, C are APClasses)
1540//
1541// B A C D
1542// 3--4 12--11
1543// / \ / \
1544// A 2 5--6--7 10 E
1545// \ / \ /
1546// 1--0 8--9
1547// B A G F
1548//
1549 mol = parser.parseSmiles("c1ccccc1Oc1ccccc1");
1551 sdg.generateCoordinates(mol);
1552 frag = new Fragment(mol, BBType.FRAGMENT);
1553 replaceHatomWithAP(frag, 0, apcA);
1554 replaceHatomWithAP(frag, 1, apcB);
1555 replaceHatomWithAP(frag, 2, apcA);
1556 replaceHatomWithAP(frag, 3, apcB);
1557 replaceHatomWithAP(frag, 4, apcA);
1558 replaceHatomWithAP(frag, 8, apcG);
1559 replaceHatomWithAP(frag, 9, apcF);
1560 replaceHatomWithAP(frag, 10, apcE);
1561 replaceHatomWithAP(frag, 11, apcD);
1562 replaceHatomWithAP(frag, 12, apcC);
1563 frag.setVertexId(321);
1564 graph = new DGraph();
1565 graph.addVertex(frag);
1566 combinations = EAUtils.searchRingFusionSites(graph, fragSpace, rcParams, true, logger, rng);
1567
1568 assertEquals(7, combinations.size());
1569 apUsageCounts = new int[11];
1570 sizesCount = new int[4];
1571 for (List<RelatedAPPair> comb : combinations)
1572 {
1573 sizesCount[comb.size()] = sizesCount[comb.size()] +1;
1574 for (RelatedAPPair pair : comb)
1575 {
1576 apUsageCounts[pair.apA.getIndexInOwner()] =
1577 apUsageCounts[pair.apA.getIndexInOwner()] + 1;
1578 apUsageCounts[pair.apB.getIndexInOwner()] =
1579 apUsageCounts[pair.apB.getIndexInOwner()] + 1;
1580 }
1581 }
1582 assertEquals(2, apUsageCounts[0]);
1583 assertEquals(3, apUsageCounts[1]);
1584 assertEquals(2, apUsageCounts[2]);
1585 assertEquals(3, apUsageCounts[3]);
1586 assertEquals(2, apUsageCounts[4]);
1587 assertEquals(1, apUsageCounts[5]);
1588 assertEquals(2, apUsageCounts[6]);
1589 assertEquals(2, apUsageCounts[7]);
1590 assertEquals(2, apUsageCounts[8]);
1591 assertEquals(1, apUsageCounts[9]);
1592 assertEquals(0, apUsageCounts[10]);
1593 assertEquals(0, sizesCount[0]);
1594 assertEquals(4, sizesCount[1]);
1595 assertEquals(3, sizesCount[2]);
1596 assertEquals(0, sizesCount[3]);
1597
1598
1599 //
1600 // Case 6: mix different types of ring fusion sites, some 4el, other 2el
1601 // NO request to project on symmetric APs
1602 //
1603// This is the vertex we work with (NB: A, B, C are APClasses)
1604//
1605// B A C C
1606// 3--4 11--10
1607// / \ / \
1608// A 2 5---6 9 C
1609// \ / \ /
1610// 1--0 7--8
1611// B A C C
1612//
1613 mol = parser.parseSmiles("c1ccccc1c1ccccc1");
1615 sdg.generateCoordinates(mol);
1616 frag = new Fragment(mol, BBType.FRAGMENT);
1617 replaceHatomWithAP(frag, 0, apcA);
1618 replaceHatomWithAP(frag, 1, apcB);
1619 replaceHatomWithAP(frag, 2, apcA);
1620 replaceHatomWithAP(frag, 3, apcB);
1621 replaceHatomWithAP(frag, 4, apcA);
1622 replaceHatomWithAP(frag, 7, apcC);
1623 replaceHatomWithAP(frag, 8, apcC);
1624 replaceHatomWithAP(frag, 9, apcC);
1625 replaceHatomWithAP(frag, 10, apcC);
1626 replaceHatomWithAP(frag, 11, apcC);
1627 frag.setVertexId(321);
1628 graph = new DGraph();
1629 graph.addVertex(frag);
1630 combinations = EAUtils.searchRingFusionSites(graph, fragSpace, rcParams, false, logger, rng);
1631
1632 assertEquals(12, combinations.size());
1633 apUsageCounts = new int[10];
1634 sizesCount = new int[4];
1635 for (List<RelatedAPPair> comb : combinations)
1636 {
1637 sizesCount[comb.size()] = sizesCount[comb.size()] +1;
1638 for (RelatedAPPair pair : comb)
1639 {
1640 apUsageCounts[pair.apA.getIndexInOwner()] =
1641 apUsageCounts[pair.apA.getIndexInOwner()] + 1;
1642 apUsageCounts[pair.apB.getIndexInOwner()] =
1643 apUsageCounts[pair.apB.getIndexInOwner()] + 1;
1644 }
1645 }
1646 assertEquals(3, apUsageCounts[0]);
1647 assertEquals(2, apUsageCounts[1]);
1648 assertEquals(2, apUsageCounts[2]);
1649 assertEquals(2, apUsageCounts[3]);
1650 assertEquals(3, apUsageCounts[4]);
1651 assertEquals(3, apUsageCounts[5]); // AP on atm 7
1652 assertEquals(2, apUsageCounts[6]); // AP on atm 8
1653 assertEquals(2, apUsageCounts[7]); // AP on atm 9
1654 assertEquals(2, apUsageCounts[8]); // AP on atm 10
1655 assertEquals(3, apUsageCounts[9]); // AP on atm 11
1656 assertEquals(0, sizesCount[0]);
1657 assertEquals(12, sizesCount[1]);
1658 assertEquals(0, sizesCount[2]);
1659 assertEquals(0, sizesCount[3]);
1660
1661
1662 //
1663 // Case 7: mix different types of ring fusion sites, some 4el, other 2el
1664 // With request of exploiting symmetry
1665 //
1666 combinations = EAUtils.searchRingFusionSites(
1667 graph, fragSpace, rcParams, true, logger, rng);
1668
1669 assertEquals(8, combinations.size());
1670 apUsageCounts = new int[10];
1671 sizesCount = new int[4];
1672 for (List<RelatedAPPair> comb : combinations)
1673 {
1674 sizesCount[comb.size()] = sizesCount[comb.size()] +1;
1675 for (RelatedAPPair pair : comb)
1676 {
1677 apUsageCounts[pair.apA.getIndexInOwner()] =
1678 apUsageCounts[pair.apA.getIndexInOwner()] + 1;
1679 apUsageCounts[pair.apB.getIndexInOwner()] =
1680 apUsageCounts[pair.apB.getIndexInOwner()] + 1;
1681 }
1682 }
1683 assertEquals(4, apUsageCounts[0]);
1684 assertEquals(3, apUsageCounts[1]);
1685 assertEquals(2, apUsageCounts[2]);
1686 assertEquals(3, apUsageCounts[3]);
1687 assertEquals(4, apUsageCounts[4]);
1688 assertEquals(4, apUsageCounts[5]); // AP on atm 7
1689 assertEquals(3, apUsageCounts[6]); // AP on atm 8
1690 assertEquals(2, apUsageCounts[7]); // AP on atm 9
1691 assertEquals(3, apUsageCounts[8]); // AP on atm 10
1692 assertEquals(4, apUsageCounts[9]); // AP on atm 11
1693 assertEquals(0, sizesCount[0]);
1694 assertEquals(0, sizesCount[1]);
1695 assertEquals(8, sizesCount[2]);
1696 assertEquals(0, sizesCount[3]);
1697
1698
1699 //
1700 // Case 8: detect different types of ring fusion sites
1701 //
1702// This is the vertex we work with (NB: A, B, C are APClasses)
1703//
1704// [1,2] is a 2el2atm site
1705// [2,3] is a 2el2atm site
1706// [9,10] is a 2el2atm site
1707// [3,10] is a 4el4atm site
1708//
1709// A A A A
1710// 2--3 10--9 [9,11] is a 3el3atm site
1711// | \ / \ A
1712// | 4---5 8--11 [11,17] is 4el3atm site
1713// | / \ / \ A
1714// 1--0(O) 6--7 12[N+]--17 A A A A
1715// A A \ / | 20-21 26-27 33--34 38--39
1716// 14--13 | / \ / \ / | / |
1717// A \ | _18--19 22-25 28--31--32 35--37 40
1718// (N)15--16 \ / \ / \ / \ /
1719// A 24-23 30--29 36 41
1720// [6,14] is a 4el3atm site A A A A
1721//
1722//
1723 mol = parser.parseSmiles("o1cccc1c1cc2c(cc1)c[n+]3c(c2)Nc(c3)[Ru]c1ccc(cc1)c1ccc(cc1)[Ru]c1ccc(N1)c1cnN(c1)");
1725 sdg.generateCoordinates(mol);
1726 frag = new Fragment(mol, BBType.FRAGMENT);
1727 replaceHatomWithAP(frag, 1, apcA);
1728 replaceHatomWithAP(frag, 2, apcA);
1729 replaceHatomWithAP(frag, 3, apcA);
1730 replaceHatomWithAP(frag, 6, apcA);
1731 replaceHatomWithAP(frag, 9, apcA);
1732 replaceHatomWithAP(frag, 10, apcA);
1733 replaceHatomWithAP(frag, 11, apcA);
1734 replaceHatomWithAP(frag, 14, apcA);
1735 replaceHatomWithAP(frag, 15, apcA);
1736 replaceHatomWithAP(frag, 17, apcA);
1737 replaceHatomWithAP(frag, 21, apcA);
1738 replaceHatomWithAP(frag, 23, apcA);
1739 replaceHatomWithAP(frag, 26, apcA);
1740 replaceHatomWithAP(frag, 30, apcA);
1741 replaceHatomWithAP(frag, 34, apcA);
1742 replaceHatomWithAP(frag, 36, apcA);
1743 replaceHatomWithAP(frag, 38, apcA);
1744 replaceHatomWithAP(frag, 41, apcA);
1745 frag.setVertexId(321);
1746 graph = new DGraph();
1747 graph.addVertex(frag);
1748
1749 //Just in case you need to look at the mol/fragment/graph
1750 //DenoptimIO.writeSDFFile("/tmp/mol.sdf", mol);
1751 //DenoptimIO.writeVertexToSDF("/tmp/frag.sdf", frag);
1752 //DenoptimIO.writeGraphToSDF(new File("/tmp/graph.sdf"), graph, true, true, logger, rng);
1753
1754 combinations = EAUtils.searchRingFusionSites(
1755 graph, fragSpace, rcParams, false, logger, rng);
1756
1757 assertEquals(17, combinations.size());
1758 apUsageCounts = new int[18];
1759 sizesCount = new int[4];
1760 Map<String,Integer> countTypes = new HashMap<String,Integer>();
1761 for (List<RelatedAPPair> comb : combinations)
1762 {
1763 sizesCount[comb.size()] = sizesCount[comb.size()] +1;
1764 for (RelatedAPPair pair : comb)
1765 {
1766 apUsageCounts[pair.apA.getIndexInOwner()] =
1767 apUsageCounts[pair.apA.getIndexInOwner()] + 1;
1768 apUsageCounts[pair.apB.getIndexInOwner()] =
1769 apUsageCounts[pair.apB.getIndexInOwner()] + 1;
1770 if (countTypes.containsKey(pair.propID))
1771 countTypes.put(pair.propID, countTypes.get(pair.propID)+1);
1772 else
1773 countTypes.put(pair.propID, 1);
1774 }
1775 }
1776 assertEquals(1, apUsageCounts[0]); // AP on atm 1
1777 assertEquals(2, apUsageCounts[1]); // AP on atm 2
1778 assertEquals(3, apUsageCounts[2]); // AP on atm 3
1779 assertEquals(2, apUsageCounts[3]); // AP on atm 6
1780 assertEquals(2, apUsageCounts[4]); // AP on atm 9
1781 assertEquals(2, apUsageCounts[5]); // AP on atm 10
1782 assertEquals(2, apUsageCounts[6]); // AP on atm 11
1783 assertEquals(2, apUsageCounts[7]); // AP on atm 14
1784 assertEquals(1, apUsageCounts[8]); // AP on atm 15
1785 assertEquals(1, apUsageCounts[9]); // AP on atm 17
1786 assertEquals(2, apUsageCounts[10]); // AP on atm 21
1787 assertEquals(2, apUsageCounts[11]); // AP on atm 23
1788 assertEquals(2, apUsageCounts[12]); // AP on atm 26
1789 assertEquals(2, apUsageCounts[13]); // AP on atm 29
1790 assertEquals(2, apUsageCounts[14]); // AP on atm 34
1791 assertEquals(2, apUsageCounts[15]); // AP on atm 36
1792 assertEquals(2, apUsageCounts[16]); // AP on atm 38
1793 assertEquals(2, apUsageCounts[17]); // AP on atm 41
1794 assertEquals(0, sizesCount[0]);
1795 assertEquals(17, sizesCount[1]);
1796 assertEquals(0, sizesCount[2]);
1797 assertEquals(0, sizesCount[3]);
1798 assertEquals(3, countTypes.get("2el2atm")); //WARNING: hard code type name!
1799 assertEquals(2, countTypes.get("3el3atm_6+5")); //WARNING: hard code type name!
1800 assertEquals(2, countTypes.get("3el3atm_6+6")); //WARNING: hard code type name!
1801 assertEquals(4, countTypes.get("4el4atm_6+6")); //WARNING: hard code type name!
1802 assertEquals(2, countTypes.get("4el4atm_6+5")); //WARNING: hard code type name!
1803 assertEquals(4, countTypes.get("4el4atm_5+5")); //WARNING: hard code type name!
1804
1805
1806 //
1807 // Case 9: fusion involves APs located on different vertexes. In this
1808 // example each F# is a vertex.
1809 //
1810 // \-3---2
1811 // A A A / |
1812 // 1--2 1---2 F3 1
1813 // / \ / F1 \ /
1814 // 0 F0 3-|-0 3-|-0
1815 // \ / \ F2 / A
1816 // 5--4 /-0-\
1817 // A
1818 //
1819 parser = new SmilesParser(builder);
1820 IAtomContainer molF0 = parser.parseSmiles("c1ccccc1");
1822 sdg.generateCoordinates(molF0);
1823 Fragment fragF0 = new Fragment(molF0, BBType.FRAGMENT);
1824 replaceHatomWithAP(fragF0, 3, apcA);
1825 replaceHatomWithAP(fragF0, 1, apcA);
1826 replaceHatomWithAP(fragF0, 2, apcA);
1827 fragF0.setVertexId(0);
1828
1829 // NB: conformation will be ignored
1830 IAtomContainer molF1 = parser.parseSmiles("C=CC=C");
1832 sdg.generateCoordinates(molF1);
1833 Fragment fragF1 = new Fragment(molF1, BBType.FRAGMENT);
1834 replaceHatomWithAP(fragF1, 0, apcA);
1835 replaceHatomWithAP(fragF1, 0, apcA);
1836 replaceHatomWithAP(fragF1, 1, apcA);
1837 replaceHatomWithAP(fragF1, 2, apcA);
1838 replaceHatomWithAP(fragF1, 3, apcA); // 4
1839 replaceHatomWithAP(fragF1, 3, apcA);
1840 fragF1.setVertexId(1);
1841
1842 IAtomContainer molF2 = parser.parseSmiles("N");
1844 sdg.generateCoordinates(molF2);
1845 Fragment fragF2 = new Fragment(molF2, BBType.FRAGMENT);
1846 replaceHatomWithAP(fragF2, 0, apcA);
1847 replaceHatomWithAP(fragF2, 0, apcA);
1848 replaceHatomWithAP(fragF2, 0, apcA);
1849 fragF2.setVertexId(2);
1850
1851 IAtomContainer molF3 = parser.parseSmiles("C=CC=C");
1853 sdg.generateCoordinates(molF3);
1854 Fragment fragF3 = new Fragment(molF1, BBType.FRAGMENT);
1855 replaceHatomWithAP(fragF3, 0, apcA);
1856 replaceHatomWithAP(fragF3, 0, apcA);
1857 replaceHatomWithAP(fragF3, 3, apcA);
1858 fragF3.setVertexId(3);
1859
1860 Vertex rcvOnF1a = FragmentSpace.getPolarizedRCV(true);
1861 Vertex rcvOnF2 = FragmentSpace.getPolarizedRCV(false);
1862 Vertex rcvOnF1b = FragmentSpace.getPolarizedRCV(true);
1863 Vertex rcvOnF3 = FragmentSpace.getPolarizedRCV(false);
1864
1865 DGraph graphManyFrags = new DGraph();
1866 graphManyFrags.addVertex(fragF0);
1867 graphManyFrags.appendVertexOnAP(fragF0.getAP(0), fragF1.getAP(0));
1868 graphManyFrags.appendVertexOnAP(fragF1.getAP(4), fragF2.getAP(0));
1869 graphManyFrags.appendVertexOnAP(fragF1.getAP(1), rcvOnF1a.getAP(0));
1870 graphManyFrags.appendVertexOnAP(fragF2.getAP(1), rcvOnF2.getAP(0));
1871 graphManyFrags.appendVertexOnAP(fragF1.getAP(5), fragF3.getAP(0));
1872 graphManyFrags.appendVertexOnAP(fragF1.getAP(3), rcvOnF1b.getAP(0));
1873 graphManyFrags.appendVertexOnAP(fragF3.getAP(2), rcvOnF3.getAP(0));
1874 graphManyFrags.addRing(rcvOnF1a, rcvOnF2);
1875 graphManyFrags.addRing(rcvOnF1b, rcvOnF3);
1876
1877 combinations = EAUtils.searchRingFusionSites(
1878 graphManyFrags, fragSpace, rcParams, false, logger, rng);
1879
1880 assertEquals(4, combinations.size());
1881
1882 Map<Long,Integer> vertexUsageCounts = new HashMap<Long,Integer>();
1883 for (List<RelatedAPPair> comb : combinations)
1884 {
1885 for (RelatedAPPair pair : comb)
1886 {
1887 long vIdA = pair.apA.getOwner().getVertexId();
1888 if (vertexUsageCounts.containsKey(vIdA))
1889 {
1890 vertexUsageCounts.put(vIdA, vertexUsageCounts.get(vIdA)+1);
1891 } else {
1892 vertexUsageCounts.put(vIdA,1);
1893 }
1894 long vIdB = pair.apB.getOwner().getVertexId();
1895 if (vertexUsageCounts.containsKey(vIdB))
1896 {
1897 vertexUsageCounts.put(vIdB, vertexUsageCounts.get(vIdB)+1);
1898 } else {
1899 vertexUsageCounts.put(vIdB,1);
1900 }
1901 }
1902 }
1903 assertTrue(vertexUsageCounts.containsKey(fragF0.getVertexId()));
1904 // NB: the [1,2] counts double because both APs belong to fragF0
1905 assertEquals(4, vertexUsageCounts.get(fragF0.getVertexId()));
1906 assertTrue(vertexUsageCounts.containsKey(fragF1.getVertexId()));
1907 assertEquals(1, vertexUsageCounts.get(fragF1.getVertexId()));
1908 assertTrue(vertexUsageCounts.containsKey(fragF2.getVertexId()));
1909 assertEquals(2, vertexUsageCounts.get(fragF2.getVertexId()));
1910 assertTrue(vertexUsageCounts.containsKey(fragF3.getVertexId()));
1911 assertEquals(1, vertexUsageCounts.get(fragF3.getVertexId()));
1912
1913
1914 //
1915 // Case 10: aliphatic ring fusion sites
1916 //
1917//
1918// A A A A 25
1919// \ / \ / / \
1920// (O)3--4 11-10 13==14(N) 18--19(O) 24
1921// / \ / \ / \ / | |
1922// 2 5---6 9--12 15--17 20 23
1923// \ / \ / \ / \ / \ /
1924// 1--0(S) (N)7--8 16 (N)21 22
1925// / / \ / \ / / \
1926// A A A A A A A A
1928// A A
1929// 41 44 46-47
1930// A A A A 25 / \ / \ / \
1931// \ / \ / / \ 39-40-42-43-45 48 52
1932// (O)3--4 11-10 13==14(N) 18--19(O) 24 / \ / / \
1933// / \ / \ / \ / | |/ 49---50-51-53-54
1934// 2 5---6 9--12 15--17 20 23-26-27 A A | |
1935// \ / \ / \ / \ / \ / | | 56-55
1936// 1--0(S) (N)7--8 16 (N)21 22 29-28-30-31 35-36 A
1937// / / \ / \ / / \ A | | / \
1938// A A A A A A A A 33-32-34 37
1939// A \ /
1940// 38
1941// A
1942//
1943
1944 mol = parser.parseSmiles("S1CCOCC1C1NCC(CC1)C1C=NC(C1)C1CC2C(N1)CC(CC2)"
1945 + "(C1CC(C1)C1CC(C1)C1CCCC1)" // branch with two 4-member rings
1946 + "C1C(C1)C1C(C1)C1CCCC1C1C(C1)C1CCC1"); // branch with 3-member rings
1948 sdg.generateCoordinates(mol);
1949 frag = new Fragment(mol, BBType.FRAGMENT);
1950 replaceHatomWithAP(frag, 4, apcA);
1951 replaceHatomWithAP(frag, 4, apcA);
1952 replaceHatomWithAP(frag, 7, apcA);
1953 replaceHatomWithAP(frag, 8, apcA);
1954 replaceHatomWithAP(frag, 8, apcA);
1955 replaceHatomWithAP(frag, 11, apcA);
1956 replaceHatomWithAP(frag, 11, apcA);
1957 replaceHatomWithAP(frag, 16, apcA);
1958 replaceHatomWithAP(frag, 16, apcA);
1959 replaceHatomWithAP(frag, 21, apcA);
1960 replaceHatomWithAP(frag, 22, apcA);
1961 replaceHatomWithAP(frag, 22, apcA);
1962 replaceHatomWithAP(frag, 29, apcA);
1963 replaceHatomWithAP(frag, 33, apcA);
1964 replaceHatomWithAP(frag, 38, apcA);
1965 replaceHatomWithAP(frag, 41, apcA);
1966 replaceHatomWithAP(frag, 44, apcA);
1967 replaceHatomWithAP(frag, 49, apcA);
1968 replaceHatomWithAP(frag, 50, apcA);
1969 replaceHatomWithAP(frag, 56, apcA);
1970 frag.setVertexId(321);
1971 graph = new DGraph();
1972 graph.addVertex(frag);
1973
1974 combinations = EAUtils.searchRingFusionSites(
1975 graph, fragSpace, rcParams, false, logger, rng);
1976
1977 assertEquals(27, combinations.size());
1978 apUsageCounts = new int[20];
1979 countTypes = new HashMap<String,Integer>();
1980 for (List<RelatedAPPair> comb : combinations)
1981 {
1982 for (RelatedAPPair pair : comb)
1983 {
1984 apUsageCounts[pair.apA.getIndexInOwner()] =
1985 apUsageCounts[pair.apA.getIndexInOwner()] + 1;
1986 apUsageCounts[pair.apB.getIndexInOwner()] =
1987 apUsageCounts[pair.apB.getIndexInOwner()] + 1;
1988 if (countTypes.containsKey(pair.propID))
1989 countTypes.put(pair.propID, countTypes.get(pair.propID)+1);
1990 else
1991 countTypes.put(pair.propID, 1);
1992 }
1993 }
1994
1995 assertEquals(3, apUsageCounts[0]); // AP on atm 4
1996 assertEquals(3, apUsageCounts[1]); // AP on atm 4
1997 assertEquals(6, apUsageCounts[2]); // AP on atm 7
1998 assertEquals(3, apUsageCounts[3]); // AP on atm 8
1999 assertEquals(3, apUsageCounts[4]); // AP on atm 8
2000 assertEquals(3, apUsageCounts[5]); // AP on atm 11
2001 assertEquals(3, apUsageCounts[6]); // AP on atm 11
2002 assertEquals(3, apUsageCounts[7]); // AP on atm 16
2003 assertEquals(3, apUsageCounts[8]); // AP on atm 16
2004 assertEquals(4, apUsageCounts[9]); // AP on atm 21
2005 assertEquals(3, apUsageCounts[10]); // AP on atm 22
2006 assertEquals(3, apUsageCounts[11]); // AP on atm 22
2007 assertEquals(3, apUsageCounts[12]); // AP on atm 29
2008 assertEquals(2, apUsageCounts[13]); // AP on atm 33
2009 assertEquals(1, apUsageCounts[14]); // AP on atm 38
2010 assertEquals(3, apUsageCounts[15]); // AP on atm 41
2011 assertEquals(2, apUsageCounts[16]); // AP on atm 44
2012 assertEquals(1, apUsageCounts[17]); // AP on atm 49 [49,50] is not a match because it is not -@
2013 assertEquals(1, apUsageCounts[18]); // AP on atm 50
2014 assertEquals(1, apUsageCounts[19]); // AP on atm 56
2015 assertEquals(2, countTypes.get("aliph2atm")); //WARNING: hard code type name!
2016 assertEquals(4, countTypes.get("aliph3atm")); //WARNING: hard code type name!
2017 assertEquals(6, countTypes.get("aliph4atm_6+6")); //WARNING: hard code type name!
2018 assertEquals(4, countTypes.get("aliph4atm_6+5")); //WARNING: hard code type name!
2019 assertEquals(2, countTypes.get("aliph4atm_6+4")); //WARNING: hard code type name!
2020 assertEquals(2, countTypes.get("aliph4atm_6+3")); //WARNING: hard code type name!
2021 assertEquals(2, countTypes.get("aliph4atm_5+5")); //WARNING: hard code type name!
2022 assertEquals(1, countTypes.get("aliph4atm_5+4")); //WARNING: hard code type name!
2023 assertEquals(1, countTypes.get("aliph4atm_5+3")); //WARNING: hard code type name!
2024 assertEquals(1, countTypes.get("aliph4atm_4+4")); //WARNING: hard code type name!
2025 assertEquals(1, countTypes.get("aliph4atm_4+3")); //WARNING: hard code type name!
2026 assertEquals(1, countTypes.get("aliph4atm_3+3")); //WARNING: hard code type name!
2027 assertFalse(countTypes.containsKey("2el2atm")); //WARNING: hard code type name!
2028 assertFalse(countTypes.containsKey("3el3atm_6+5")); //WARNING: hard code type name!
2029 assertFalse(countTypes.containsKey("4el4atm_6+6")); //WARNING: hard code type name!
2030 assertFalse(countTypes.containsKey("4el4atm_6+5")); //WARNING: hard code type name!
2031 assertFalse(countTypes.containsKey("4el4atm_5+5")); //WARNING: hard code type name!
2032
2033
2034 //
2035 // Case 11: avoid combinatorial explosion
2036 // We trigger combinatorial explosion by enabling symmetry in a system
2037 // with many symmetric APs.
2038 //
2039 mol = parser.parseSmiles("C1CCCCCCCCC1");
2041 sdg.generateCoordinates(mol);
2042 frag = new Fragment(mol, BBType.FRAGMENT);
2043 replaceHatomWithAP(frag, 0, apcA);
2044 replaceHatomWithAP(frag, 1, apcA);
2045 replaceHatomWithAP(frag, 2, apcA);
2046 replaceHatomWithAP(frag, 3, apcA);
2047 replaceHatomWithAP(frag, 4, apcA);
2048 replaceHatomWithAP(frag, 5, apcA);
2049 replaceHatomWithAP(frag, 6, apcA);
2050 replaceHatomWithAP(frag, 7, apcA);
2051 replaceHatomWithAP(frag, 8, apcA);
2052 replaceHatomWithAP(frag, 9, apcA);
2053 replaceHatomWithAP(frag, 0, apcA);
2054 replaceHatomWithAP(frag, 1, apcA);
2055 replaceHatomWithAP(frag, 2, apcA);
2056 replaceHatomWithAP(frag, 3, apcA);
2057 replaceHatomWithAP(frag, 4, apcA);
2058 replaceHatomWithAP(frag, 5, apcA);
2059 replaceHatomWithAP(frag, 6, apcA);
2060 replaceHatomWithAP(frag, 7, apcA);
2061 replaceHatomWithAP(frag, 8, apcA);
2062 replaceHatomWithAP(frag, 9, apcA);
2063 frag.setVertexId(321);
2064 graph = new DGraph();
2065 graph.addVertex(frag);
2066
2067 combinations = EAUtils.searchRingFusionSites(
2068 graph, fragSpace, rcParams, true, logger, rng);
2069
2070 // NB: given by the hard-coded limit to the number of combinations
2071 assertEquals(136, combinations.size());
2072 // NB: given by the hard-coded limit to the max number of ring
2073 // fusions on a single vertex.
2074 assertEquals(6, combinations.get(0).size());
2075
2076
2077 //
2078 // Case 12: detect 5el sites
2079 //
2080 //
2081 // 15--v16
2082 // | |
2083 // 14 11
2084 // \ / \
2085 // 10 12
2086 // | |
2087 // 0 9 13
2088 // / \ / \ /
2089 // 5 1 8
2090 // | | |
2091 // 4 2 7
2092 // \ / \ /
2093 // 3 6
2094 //
2095 //
2096 // 0 5 9 13
2097 mol = parser.parseSmiles("c1c2c(ccc1)ccc3c2c(c1cc3)cNc1");
2099 sdg.generateCoordinates(mol);
2100 frag = new Fragment(mol, BBType.FRAGMENT);
2101 replaceHatomWithAP(frag, 0, apcA);
2102 replaceHatomWithAP(frag, 3, apcA);
2103 replaceHatomWithAP(frag, 6, apcA);
2104 replaceHatomWithAP(frag, 13, apcA);
2105 replaceHatomWithAP(frag, 14, apcA);
2106 replaceHatomWithAP(frag, 16, apcA);
2107 frag.setVertexId(321);
2108 graph = new DGraph();
2109 graph.addVertex(frag);
2110
2111 combinations = EAUtils.searchRingFusionSites(
2112 graph, fragSpace, rcParams, false, logger, rng);
2113
2114 assertEquals(2, combinations.size());
2115 apUsageCounts = new int[6];
2116 sizesCount = new int[3];
2117 countTypes = new HashMap<String,Integer>();
2118 for (List<RelatedAPPair> comb : combinations)
2119 {
2120 sizesCount[comb.size()] = sizesCount[comb.size()] +1;
2121 for (RelatedAPPair pair : comb)
2122 {
2123 apUsageCounts[pair.apA.getIndexInOwner()] =
2124 apUsageCounts[pair.apA.getIndexInOwner()] + 1;
2125 apUsageCounts[pair.apB.getIndexInOwner()] =
2126 apUsageCounts[pair.apB.getIndexInOwner()] + 1;
2127 if (countTypes.containsKey(pair.propID))
2128 countTypes.put(pair.propID, countTypes.get(pair.propID)+1);
2129 else
2130 countTypes.put(pair.propID, 1);
2131 }
2132 }
2133 assertEquals(1, apUsageCounts[0]); // AP on atm 1
2134 assertEquals(1, apUsageCounts[1]); // AP on atm 3
2135 assertEquals(1, apUsageCounts[2]); // AP on atm 6
2136 assertEquals(0, apUsageCounts[3]); // AP on atm 13
2137 assertEquals(1, apUsageCounts[4]); // AP on atm 14
2138 assertEquals(0, apUsageCounts[5]); // AP on atm 16
2139 assertEquals(0, sizesCount[0]);
2140 assertEquals(2, sizesCount[1]);
2141 assertEquals(0, sizesCount[2]);
2142 assertEquals(1, countTypes.get("3el3atm_6+6")); //WARNING: hard code type name!
2143 assertEquals(1, countTypes.get("5el5atm_6+6+6")); //WARNING: hard code type name!
2144
2145
2146 //
2147 // Case 13: ignore constrained 5el sites
2148 //
2149 // 15
2150 // / \
2151 // 14 16
2152 // | |
2153 // 13 11
2154 // A \ / \
2155 // 10 12
2156 // A | /
2157 // 0 9 /
2158 // / \ / \ /
2159 // 5 1 8
2160 // | | |
2161 // 4 2 7
2162 // \ / \ /
2163 // 3 6
2164 //
2165 // 0 5 9 12
2166 mol = parser.parseSmiles("c1c2c(ccc1)ccc3c2c(c1N3)cccc1");
2168 sdg.generateCoordinates(mol);
2169 frag = new Fragment(mol, BBType.FRAGMENT);
2170 replaceHatomWithAP(frag, 0, apcA);
2171 replaceHatomWithAP(frag, 3, apcA);
2172 replaceHatomWithAP(frag, 6, apcA);
2173 replaceHatomWithAP(frag, 12, apcA);
2174 replaceHatomWithAP(frag, 13, apcA);
2175 replaceHatomWithAP(frag, 15, apcA);
2176 frag.setVertexId(321);
2177 graph = new DGraph();
2178 graph.addVertex(frag);
2179
2180 combinations = EAUtils.searchRingFusionSites(
2181 graph, fragSpace, rcParams, false, logger, rng);
2182
2183 assertEquals(1, combinations.size());
2184 assertEquals(1, combinations.get(0).size());
2185 //WARNING: hard code type name!
2186 assertEquals("3el3atm_6+6", combinations.get(0).get(0).propID);
2187
2188
2189 //
2190 // Case 12: detect 5el sites
2191 //
2192 // A
2193 // 13---14
2194 // | |
2195 // 12 10
2196 // A \ / \
2197 // 11 9
2198 // A | |
2199 // 0 6 8 A
2200 // / \ / \ /
2201 // 5 1 7
2202 // | |
2203 // 4 2
2204 // \ /
2205 // 3
2206 //
2207 //
2208 // 0 5
2209 mol = parser.parseSmiles("c1c(cccc1)c1cccc2c1cNc2");
2211 sdg.generateCoordinates(mol);
2212 frag = new Fragment(mol, BBType.FRAGMENT);
2213 replaceHatomWithAP(frag, 0, apcA);
2214 replaceHatomWithAP(frag, 8, apcA);
2215 replaceHatomWithAP(frag, 12, apcA);
2216 replaceHatomWithAP(frag, 14, apcA);
2217 frag.setVertexId(321);
2218 graph = new DGraph();
2219 graph.addVertex(frag);
2220
2221 combinations = EAUtils.searchRingFusionSites(
2222 graph, fragSpace, rcParams, false, logger, rng);
2223
2224 assertEquals(1, combinations.size());
2225 assertEquals(1, combinations.get(0).size());
2226 //WARNING: hard code type name!
2227 assertEquals("5el5atm_6-6*", combinations.get(0).get(0).propID);
2228
2229
2230 //
2231 // Case 13: detect 5el sites
2232 //
2233 //
2234 // 13---12
2235 // | |
2236 // 14 11
2237 // A \ /
2238 // 10
2239 // A |
2240 // 0 9
2241 // / \ / \ A
2242 // 5 1 8
2243 // | | |
2244 // 4 2 7
2245 // \ / \ /
2246 // 3 6
2247 //
2248 //
2249 // 0 5 9
2250 mol = parser.parseSmiles("c1c2c(ccc1)cccc2c1cNcc1");
2252 sdg.generateCoordinates(mol);
2253 frag = new Fragment(mol, BBType.FRAGMENT);
2254 replaceHatomWithAP(frag, 0, apcA);
2255 replaceHatomWithAP(frag, 8, apcA);
2256 replaceHatomWithAP(frag, 11, apcA);
2257 frag.setVertexId(321);
2258 graph = new DGraph();
2259 graph.addVertex(frag);
2260
2261 //Just in case you need to look at the mol/fragment/graph
2262 //DenoptimIO.writeSDFFile("/tmp/mol.sdf", mol);
2263 //DenoptimIO.writeVertexToSDF("/tmp/frag.sdf", frag);
2264 //DenoptimIO.writeGraphToSDF(new File("/tmp/graph.sdf"), graph, true, true, logger, rng);
2265
2266 combinations = EAUtils.searchRingFusionSites(
2267 graph, fragSpace, rcParams, false, logger, rng);
2268
2269 assertEquals(2, combinations.size());
2270 boolean found4el = false;
2271 boolean found5el = false;
2272 for (List<RelatedAPPair> comb : combinations)
2273 {
2274 assertEquals(1, combinations.get(0).size());
2275 RelatedAPPair pair = comb.get(0);
2276 if ("4el4atm_6+5".equals(pair.propID))
2277 found4el = true;
2278 if ("5el5atm_66-*".equals(pair.propID))
2279 found5el = true;
2280 }
2281 assertTrue(found4el);
2282 assertTrue(found5el);
2283 }
2284
2285//------------------------------------------------------------------------------
2286
2287 @Test
2288 public void testFusionSiteDetection_ImposeSymmetry() throws Exception
2289 {
2290 APClass apcSymImposed = APClass.make("apcA:1");
2291 APClass apcFree = APClass.make("apcB:1");
2292 APClass apcFusedBridge = APClass.make("apcFusedBridge:0");
2293 APClass hyd = APClass.make("hyd:1");
2294
2295 // Utilities
2296 Logger logger = Logger.getLogger("DummyLogger");
2297 Randomizer rng = new Randomizer();
2298
2299 // Make a fragment space that saturates all valences
2300 HashMap<APClass,APClass> capMap = new HashMap<APClass,APClass>();
2301 capMap.put(apcSymImposed, hyd);
2302 capMap.put(apcFree, hyd);
2303
2304 ArrayList<Vertex> cappingGroups = new ArrayList<Vertex>();
2305 Fragment capH = new Fragment();
2306 capH.addAtom(new Atom("H", new Point3d()));
2307 capH.addAP(0, new Point3d(1.0, 0, 0), hyd);
2308 cappingGroups.add(capH);
2309
2310 // Allows some ring closures via APClass compatibility
2311 HashMap<APClass,ArrayList<APClass>> rcCMap =
2312 new HashMap<APClass,ArrayList<APClass>>();
2313 rcCMap.put(apcSymImposed, new ArrayList<APClass>(Arrays.asList(apcFusedBridge)));
2314 // NB: apcNotFusable is intentionally not added to RC-CPMap!
2315
2317 FragmentSpace fragSpace = new FragmentSpace(fsp,
2318 new ArrayList<Vertex>(), //no scaffolds
2319 new ArrayList<Vertex>(), //no fragments
2320 cappingGroups, //H as capping
2321 new HashMap<APClass,ArrayList<APClass>>(),
2322 capMap, new HashSet<APClass>(),
2323 rcCMap);
2324 fragSpace.setAPclassBasedApproach(true);
2325
2326 /*
2327 HashMap<APClass, Double> symmetryConstraints =
2328 new HashMap<APClass, Double>();
2329 symmetryConstraints.put(apcSymImposed, 1.0);
2330 fragSpace.setSymmConstraints(symmetryConstraints);
2331 */
2332
2334
2335 SmilesParser parser = new SmilesParser(builder);
2336 IAtomContainer mol = parser.parseSmiles("c1ccccc1");
2338 StructureDiagramGenerator sdg = new StructureDiagramGenerator();
2339 sdg.generateCoordinates(mol);
2340 Fragment frag = new Fragment(mol, BBType.FRAGMENT);
2341 replaceHatomWithAP(frag, 0, apcSymImposed);
2342 replaceHatomWithAP(frag, 1, apcSymImposed);
2343 replaceHatomWithAP(frag, 2, apcFree);
2344 replaceHatomWithAP(frag, 3, apcSymImposed);
2345 replaceHatomWithAP(frag, 4, apcSymImposed);
2346 replaceHatomWithAP(frag, 5, apcFree);
2347 DGraph graph = new DGraph();
2348 graph.addVertex(frag);
2349
2350 List<List<RelatedAPPair>> combinations = EAUtils.searchRingFusionSites(
2351 graph, fragSpace, rcParams, false, logger, rng);
2352
2353 // 0:1 and 3:4 taken independently
2354 assertEquals(2, combinations.size());
2355
2356 // Now apply symmetry constraint and do it again
2357
2358 HashMap<APClass, Double> symmetryConstraints =
2359 new HashMap<APClass, Double>();
2360 symmetryConstraints.put(apcSymImposed, 1.0);
2361 fragSpace.setSymmConstraints(symmetryConstraints);
2362
2363 combinations = EAUtils.searchRingFusionSites(
2364 graph, fragSpace, rcParams, false, logger, rng);
2365
2366 // 0:1 and 3:4 are part of the same combination of rings
2367 assertEquals(1, combinations.size());
2368 assertEquals(2, combinations.get(0).size());
2369 }
2370
2371//------------------------------------------------------------------------------
2372
2373 public static void replaceHatomWithAP(Fragment frag, int srcId, APClass apc)
2374 {
2375 boolean done = false;
2376 for (IAtom atm : frag.getConnectedAtomsList(frag.getAtom(srcId)))
2377 {
2378 if ("H".equals(MoleculeUtils.getSymbolOrLabel(atm)))
2379 {
2380 frag.addAP(srcId, MoleculeUtils.getPoint3d(atm), apc);
2381 frag.removeAtom(atm);
2382 done = true;
2383 break;
2384 }
2385 }
2386 if (!done)
2387 throw new IllegalStateException("No H found that could be changed "
2388 + "into an AP.");
2389 }
2390
2391//------------------------------------------------------------------------------
2392
2393 @Test
2394 public void testGetUsableAromaticBridges() throws Exception
2395 {
2396 ArrayList<Vertex> libFrags = new ArrayList<Vertex>();
2397
2398 APClass apcA = APClass.make("apcA:1");
2399 APClass APC2EL = APClass.make("2el:0");
2400 APClass APC4EL = APClass.make("4el:0");
2401
2402 Fragment bridge4elA = new Fragment(4);
2403 IAtom a4elA_0 = new Atom("C", new Point3d());
2404 IAtom a4elA_1 = new Atom("C", new Point3d());
2405 IAtom a4elA_2 = new Atom("C", new Point3d());
2406 IAtom a4elA_3 = new Atom("C", new Point3d());
2407 bridge4elA.addAtom(a4elA_0);
2408 bridge4elA.addAtom(a4elA_1);
2409 bridge4elA.addAtom(a4elA_2);
2410 bridge4elA.addAtom(a4elA_3);
2411 bridge4elA.addBond(new Bond(a4elA_0, a4elA_1, IBond.Order.DOUBLE));
2412 bridge4elA.addBond(new Bond(a4elA_1, a4elA_2, IBond.Order.SINGLE));
2413 bridge4elA.addBond(new Bond(a4elA_2, a4elA_3, IBond.Order.DOUBLE));
2414 bridge4elA.addAP(0, new Point3d(), APC4EL);
2415 bridge4elA.addAP(3, new Point3d(), APC4EL);
2416 bridge4elA.addAP(0, new Point3d(), apcA);
2417 bridge4elA.addAP(1, new Point3d(), apcA);
2418 bridge4elA.addAP(2, new Point3d(), apcA);
2419 bridge4elA.addAP(3, new Point3d(), apcA);
2420 libFrags.add(bridge4elA);
2421
2422 Fragment bridge4elB = new Fragment(5);
2423 IAtom a4elB_0 = new Atom("Si", new Point3d());
2424 IAtom a4elB_1 = new Atom("Si", new Point3d());
2425 IAtom a4elB_2 = new Atom("Si", new Point3d());
2426 IAtom a4elB_3 = new Atom("Si", new Point3d());
2427 bridge4elB.addAtom(a4elB_0);
2428 bridge4elB.addAtom(a4elB_1);
2429 bridge4elB.addAtom(a4elB_2);
2430 bridge4elB.addAtom(a4elB_3);
2431 bridge4elB.addBond(new Bond(a4elB_0, a4elB_1, IBond.Order.DOUBLE));
2432 bridge4elB.addBond(new Bond(a4elB_1, a4elB_2, IBond.Order.SINGLE));
2433 bridge4elB.addBond(new Bond(a4elB_2, a4elB_3, IBond.Order.DOUBLE));
2434 bridge4elB.addAP(0, new Point3d(), APC4EL);
2435 bridge4elB.addAP(3, new Point3d(), APC4EL);
2436 libFrags.add(bridge4elB);
2437
2438 Fragment bridge2elA = new Fragment(6);
2439 IAtom a2elA_0 = new Atom("O", new Point3d());
2440 bridge2elA.addAtom(a2elA_0);
2441 bridge2elA.addAP(0, new Point3d(), APC2EL);
2442 bridge2elA.addAP(0, new Point3d(), APC2EL);
2443 libFrags.add(bridge2elA);
2444
2445 Fragment bridge2elB = new Fragment(7);
2446 IAtom a2elB_0 = new Atom("C", new Point3d());
2447 IAtom a2elB_1 = new Atom("C", new Point3d());
2448 bridge2elB.addAtom(a2elB_0);
2449 bridge2elB.addAtom(a2elB_1);
2450 bridge2elB.addBond(new Bond(a2elB_0, a2elB_1, IBond.Order.DOUBLE));
2451 bridge2elB.addAP(0, new Point3d(), APC2EL);
2452 bridge2elB.addAP(1, new Point3d(), APC2EL);
2453 bridge2elB.addAP(0, new Point3d(), apcA);
2454 bridge2elB.addAP(1, new Point3d(), apcA);
2455 libFrags.add(bridge2elB);
2456
2457 // Only to trigger class-based approach
2458 HashMap<APClass,ArrayList<APClass>> cpMap =
2459 new HashMap<APClass,ArrayList<APClass>>();
2460 cpMap.put(apcA, new ArrayList<APClass>());
2461
2463 FragmentSpace fs = new FragmentSpace(fsp,
2464 new ArrayList<Vertex>(),
2465 libFrags,
2466 new ArrayList<Vertex>(),
2467 cpMap,
2468 new HashMap<APClass,APClass>(),
2469 new HashSet<APClass>(),
2470 new HashMap<APClass,ArrayList<APClass>>());
2471
2472 // Wrong size is enough to find no match
2473 List<Vertex> lst = EAUtils.getUsableAromaticBridges("4el", new int[]{5},
2474 fs);
2475 assertEquals(0, lst.size());
2476
2477 // Wrong number of electrons is enough to find no match
2478 lst = EAUtils.getUsableAromaticBridges("19el", new int[]{4}, fs);
2479 assertEquals(0, lst.size());
2480
2481 // both #el and size need to be good
2482 lst = EAUtils.getUsableAromaticBridges("4el", new int[]{4}, fs);
2483 assertEquals(2, lst.size());
2484
2485 lst = EAUtils.getUsableAromaticBridges("2el", new int[]{1}, fs);
2486 assertEquals(1, lst.size());
2487
2488 lst = EAUtils.getUsableAromaticBridges("2el", new int[]{2}, fs);
2489 assertEquals(1, lst.size());
2490 }
2491
2492//------------------------------------------------------------------------------
2493
2494 @Test
2495 public void testGetUsableAliphaticBridges() throws Exception
2496 {
2497 ArrayList<Vertex> libFrags = new ArrayList<Vertex>();
2498
2499 APClass apcA = APClass.make("A:1");
2500 APClass apcB = APClass.make("B:0");
2501 APClass apcC = APClass.make("C:2");
2502 APClass apcD = APClass.make("D:2");
2503
2504 SmilesParser parser = new SmilesParser(builder);
2505 StructureDiagramGenerator sdg = new StructureDiagramGenerator();
2506
2507 IAtomContainer mol = parser.parseSmiles("CC");
2509 sdg.generateCoordinates(mol);
2510 Fragment frag = new Fragment(mol, BBType.FRAGMENT);
2511 replaceHatomWithAP(frag, 0, apcA);
2512 replaceHatomWithAP(frag, 0, apcB);
2513 replaceHatomWithAP(frag, 1, apcA);
2514 replaceHatomWithAP(frag, 1, apcD);
2515 frag.setBuildingBlockId(0);
2516 libFrags.add(frag);
2517
2518 IAtomContainer mol1 = parser.parseSmiles("CCC");
2520 sdg.generateCoordinates(mol1);
2521 Fragment frag1 = new Fragment(mol1, BBType.FRAGMENT);
2522 replaceHatomWithAP(frag1, 0, apcA);
2523 replaceHatomWithAP(frag1, 2, apcA);
2524 frag1.setBuildingBlockId(1);
2525 libFrags.add(frag1);
2526
2527 IAtomContainer mol2 = parser.parseSmiles("CCCC");
2529 sdg.generateCoordinates(mol2);
2530 Fragment frag2 = new Fragment(mol2, BBType.FRAGMENT);
2531 replaceHatomWithAP(frag2, 0, apcA);
2532 replaceHatomWithAP(frag2, 3, apcA);
2533 frag2.setBuildingBlockId(2);
2534 libFrags.add(frag2);
2535
2536 IAtomContainer mol3 = parser.parseSmiles("CCCCC");
2538 sdg.generateCoordinates(mol3);
2539 Fragment frag3 = new Fragment(mol3, BBType.FRAGMENT);
2540 replaceHatomWithAP(frag3, 0, apcA);
2541 replaceHatomWithAP(frag3, 1, apcA);
2542 replaceHatomWithAP(frag3, 4, apcA);
2543 frag3.setBuildingBlockId(3);
2544 libFrags.add(frag3);
2545
2546 // Only to trigger class-based approach
2547 HashMap<APClass,ArrayList<APClass>> cpMap =
2548 new HashMap<APClass,ArrayList<APClass>>();
2549 cpMap.put(apcB, new ArrayList<APClass>(Arrays.asList(apcA)));
2550 cpMap.put(apcC, new ArrayList<APClass>(Arrays.asList(apcD)));
2551
2553 FragmentSpace fs = new FragmentSpace(fsp,
2554 new ArrayList<Vertex>(),
2555 libFrags,
2556 new ArrayList<Vertex>(),
2557 cpMap,
2558 new HashMap<APClass,APClass>(),
2559 new HashSet<APClass>(),
2560 new HashMap<APClass,ArrayList<APClass>>());
2561
2562 // Same class on both ends
2563 List<Vertex> lst = EAUtils.getUsableAliphaticBridges(apcB, apcB,
2564 new int[]{2}, fs);
2565 assertEquals(4, lst.size());
2566
2567 // Multiple lengths
2568 lst = EAUtils.getUsableAliphaticBridges(apcB, apcB, new int[]{2,4}, fs);
2569 assertEquals(8, lst.size());
2570
2571 // APClass compatibility
2572 lst = EAUtils.getUsableAliphaticBridges(apcB, apcC, new int[]{2,4}, fs);
2573 assertEquals(1, lst.size());
2574 }
2575
2576//------------------------------------------------------------------------------
2577
2578}
General set of constants used in DENOPTIM.
static final String DUMMYATMSYMBOL
Symbol of dummy atom.
Class defining a space of building blocks.
void appendVertexToLibrary(Vertex v, Vertex.BBType bbt, ArrayList< Vertex > library)
Takes a vertex and add it to a given library.
void setAPclassBasedApproach(boolean useAPC)
Set the fragment space to behave according to APClass-based approach.
static Vertex getPolarizedRCV(boolean polarity)
Returns a newly-built vertex that can play the role of a ring-closing vertex even when working with 3...
void setSymmConstraints(HashMap< APClass, Double > map)
ArrayList< Vertex > getScaffoldLibrary()
ArrayList< Vertex > getFragmentLibrary()
Parameters defining the fragment space.
Helper methods for the genetic algorithm.
Definition: EAUtils.java:107
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:263
static int chooseNumberOfSitesToMutate(double[] multiSiteMutationProb, double hit)
Takes a decision on how many sites to mutate on a candidate.
Definition: EAUtils.java:224
static Candidate buildCandidateByXOver(List< Candidate > eligibleParents, Population population, Monitor mnt, GAParameters settings)
Generates a new offspring by performing a crossover operation.
Definition: EAUtils.java:313
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:1044
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:3038
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:2254
static List< List< RelatedAPPair > > searchRingFusionSites(DGraph graph, GAParameters gaParams)
Definition: EAUtils.java:2471
static DGraph buildGraph(GAParameters settings)
Graph construction starts with selecting a random core/scaffold.
Definition: EAUtils.java:1803
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:2994
static Vertex selectNonScaffoldNonCapVertex(DGraph g, Randomizer randomizer)
Chose randomly a vertex that is neither scaffold or capping group.
Definition: EAUtils.java:1490
void testMakeGraphFromFragmentationOfMol()
void testCandidateGenerationMethodReproducibility()
FragmentSpaceParameters prepare()
static final String NL
void testSearchForApPairsSuitableToRingFusion()
static void replaceHatomWithAP(Fragment frag, int srcId, APClass apc)
void testFusionSiteDetection_ImposeSymmetry()
void testSelectNonScaffoldNonCapVertex()
void testMakeGraphFromFragmentationOfMol_symmetry()
Test the detection of "some" symmetry.
void testMakeGraphFromFragmentationOfMol_linearities()
void testMakeGraphFromFragmentationOfMol_Symmetry()
IChemObjectBuilder builder
Private builder of atom containers.
void testChooseNumberOfSitesToMutate()
void testBuildGraphFromTemplateScaffold()
void testMakeGraphFromFragmentationOfMol_cappingGroups()
void testMakeGraphFromFragmentationOfMol_ScaffoldingPolicy()
void testBuildByXOver_Embedded_Free()
NB: the graphs from methods getPairOfTestGraphsB() and getPairOfTestGraphsBxo() and getPairOfTestGr...
static final String SEP
void testBuildByXOver_Embedded_FixedStructure()
void testBuildByXOver_Embedded_FreeBackwards()
NB: the graphs from methods getPairOfTestGraphsB() and getPairOfTestGraphsBxo() and getPairOfTestGr...
A collection of candidates.
Definition: Population.java:48
boolean add(Candidate c)
Definition: Population.java:87
static GAParameters prepare()
static DGraph[] getPairOfTestGraphsBxoxo()
Builds a pair of graphs that contain templates with ContractLevel#FREE contract.
static DGraph makeGraphE()
Produced a graph like this:
static DGraph[] getPairOfTestGraphsB()
Builds a pair of graphs that contain templates with ContractLevel#FREE contract.
static DGraph[] getPairOfTestGraphsBxo()
Builds a pair of graphs that contain templates with ContractLevel#FREE contract.
static DGraph makeGraphA()
Produced a graph like this:
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....
A candidate is the combination of a denoptim graph with molecular representation and may include also...
Definition: Candidate.java:40
void setFitness(double fitness)
Definition: Candidate.java:480
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:102
Vertex getVertexWithId(long vid)
Searches for a vertex with the given identifier.
Definition: DGraph.java:2811
int getSymmetricSetCount()
Returns the number of symmetric sets of vertices.
Definition: DGraph.java:321
ArrayList< AttachmentPoint > getAttachmentPoints()
Returns the list of all attachment points contained in this graph.
Definition: DGraph.java:4199
boolean isIsomorphicTo(DGraph other)
Checks if this graph is "DENOPTIM-isomorphic" to the other one given.
Definition: DGraph.java:3682
void addVertex(Vertex vertex)
Appends a vertex to this graph without creating any edge.
Definition: DGraph.java:1325
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:4845
void getChildrenTree(Vertex vertex, List< Vertex > children)
Gets all the children of the current vertex recursively.
Definition: DGraph.java:3000
Iterator< SymmetricVertexes > getSymSetsIterator()
Get an iterator for the sets of symmetrically related vertices.
Definition: DGraph.java:332
Vertex getVertexAtPosition(int pos)
Returns the vertex that is in the given position of the list of vertices belonging to this graph.
Definition: DGraph.java:2743
void appendVertexOnAP(AttachmentPoint srcAP, AttachmentPoint trgAP)
Append a vertex to this graph: adds the new vertex to the list of vertices belonging to the graph,...
Definition: DGraph.java:6005
List< Vertex > getVertexList()
Definition: DGraph.java:947
DGraph clone()
Returns almost "deep-copy" of this graph.
Definition: DGraph.java:3415
void removeCappingGroups(List< Vertex > lstVerts)
Remove capping groups that belong to this graph and are in the given list.
Definition: DGraph.java:4343
boolean sameAs(DGraph other, StringBuilder reason)
Compare this and another graph ignoring the vertex IDs.
Definition: DGraph.java:3894
SymmetricVertexes getSymSetForVertex(Vertex v)
Returns the set of vertexes symmetric to the given one.
Definition: DGraph.java:861
void addRing(Ring ring)
Definition: DGraph.java:1258
boolean isIsostructuralTo(DGraph other)
Checks if this graph is "DENOPTIM-isostructural" to the other one given.
Definition: DGraph.java:3809
Unit test for DENOPTIMGraph.
Definition: DGraphTest.java:73
static DGraph makeTestGraphA()
Build a graph meant to be used in unit tests.
An empty vertex has the behaviors of a vertex, but has no molecular structure.
void addAP()
Adds an attachment point with no APClass or other attribute.
Class representing a continuously connected portion of chemical object holding attachment points.
Definition: Fragment.java:61
List< IAtom > getConnectedAtomsList(IAtom atom)
Definition: Fragment.java:943
void addAP(int atomPositionNumber)
Adds an attachment point with a dummy APClass.
Definition: Fragment.java:343
void addBond(IBond bond)
Definition: Fragment.java:871
List< AttachmentPoint > getAttachmentPoints()
Definition: Fragment.java:1141
void addAtom(IAtom atom)
Definition: Fragment.java:836
IAtom getAtom(int number)
Definition: Fragment.java:843
void removeAtom(IAtom atom)
Definition: Fragment.java:899
A collection of Vertexs that are related by a relation that we call "symmetry", even though this clas...
ContractLevel getContractLevel()
Returns the contract level of this template, i.e., to what extent the content of this template can be...
Definition: Template.java:203
List< Vertex > getMutationSites(List< MutationType > ignoredTypes)
A list of mutation sites from within this vertex.
Definition: Template.java:886
void setContractLevel(ContractLevel contract)
Imposes the given contract to this template.
Definition: Template.java:214
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:62
void setVertexId(long vertexId2)
Definition: Vertex.java:282
Vertex.BBType getBuildingBlockType()
Definition: Vertex.java:319
void setAsRCV(boolean isRCV)
Definition: Vertex.java:275
void setBuildingBlockId(int buildingBlockId)
Definition: Vertex.java:312
void setBuildingBlockType(Vertex.BBType buildingBlockType)
Definition: Vertex.java:326
abstract IAtomContainer getIAtomContainer()
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
Definition: Vertex.java:1008
static Vertex newVertexFromLibrary(int bbId, Vertex.BBType bbt, FragmentSpace fragSpace)
Builds a new molecular fragment kind of vertex.
Definition: Vertex.java:215
Parameters and setting related to handling ring closures.
Utility methods for input/output.
static ArrayList< IAtomContainer > readSDFFile(String fileName)
Reads a file containing multiple molecules (multiple SD format))
static void writeData(String fileName, String data, boolean append)
Write text-like data file.
A collection of counters user to count actions taken by the evolutionary algorithm.
Definition: Monitor.java:37
void setParameters(RunTimeParameters otherParams)
Logger getLogger()
Get the name of the program specific logger.
Parameters for genetic algorithm.
A cutting rule with three SMARTS queries (atom 1, bond, atom2) and options.
Utilities for molecule conversion.
static String getSymbolOrLabel(IAtom atm)
Gets either the elemental symbol (for standard atoms) of the label (for pseudo-atoms).
static void explicitHydrogens(IAtomContainer mol)
Converts all the implicit hydrogens to explicit.
static Point3d getPoint3d(IAtom atm)
Return the 3D coordinates, if present.
Tool to generate random numbers and random decisions.
Definition: Randomizer.java:35
Defines how to define the scaffold vertex of a graph.
A chosen method for generation of new Candidates.
Definition: EAUtils.java:133
Possible chemical bond types an edge can represent.
Definition: Edge.java:303
Enum specifying to what extent the template's inner graph can be changed.
Definition: Template.java:104
FREE
Inner graphs are free to change within the confines of the required AttachmentPoints.
Definition: Template.java:109
FIXED
Inner graphs are effectively equivalent to the Fragment class, as no change in the inner structure is...
Definition: Template.java:116
FIXED_STRUCT
Inner graph keep the same structure, but the identify of vertices can change.
Definition: Template.java:124
The type of building block.
Definition: Vertex.java:87