$darkmode
DENOPTIM
PathSubGraphTest.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.graph.rings;
20
21import static org.junit.jupiter.api.Assertions.assertEquals;
22import static org.junit.jupiter.api.Assertions.assertNotNull;
23import static org.junit.jupiter.api.Assertions.assertNull;
24import static org.junit.jupiter.api.Assertions.assertThrows;
25
26import java.util.ArrayList;
27import java.util.Arrays;
28import java.util.HashMap;
29import java.util.List;
30import java.util.Map;
31import java.util.logging.Logger;
32
33import javax.vecmath.Point3d;
34
35import org.junit.jupiter.api.Test;
36import org.openscience.cdk.Atom;
37import org.openscience.cdk.Bond;
38import org.openscience.cdk.PseudoAtom;
39import org.openscience.cdk.interfaces.IAtom;
40import org.openscience.cdk.interfaces.IAtomContainer;
41import org.openscience.cdk.interfaces.IBond;
42import org.openscience.cdk.interfaces.IChemObjectBuilder;
43import org.openscience.cdk.silent.SilentChemObjectBuilder;
44
45import denoptim.exception.DENOPTIMException;
46import denoptim.fragspace.FragmentSpace;
47import denoptim.graph.APClass;
48import denoptim.graph.DGraph;
49import denoptim.graph.DGraphTest;
50import denoptim.graph.Edge;
51import denoptim.graph.Edge.BondType;
52import denoptim.graph.EmptyVertex;
53import denoptim.graph.Fragment;
54import denoptim.graph.Vertex;
55import denoptim.graph.Vertex.BBType;
56import denoptim.molecularmodeling.ThreeDimTreeBuilder;
57import denoptim.utils.Randomizer;
58
65public class PathSubGraphTest {
66
67 //------------------------------------------------------------------------------
81 public static DGraph makeTestGraphA() throws DENOPTIMException
82 {
83 APClass apc = APClass.make("A",0);
84
85 DGraph graph = new DGraph();
86
87 IChemObjectBuilder builder = SilentChemObjectBuilder.getInstance();
88
89 IAtomContainer iacA = builder.newAtomContainer();
90 IAtom iaA1 = new Atom("O",new Point3d(0,0,0));
91 IAtom iaA2 = new Atom("O",new Point3d(1,0,0));
92 iacA.addAtom(iaA1);
93 iacA.addAtom(iaA2);
94 iacA.addBond(new Bond(iaA1, iaA2, IBond.Order.SINGLE));
95 Fragment vA = new Fragment(0,iacA,BBType.FRAGMENT);
96 vA.addAP(0,new Point3d(0,-1,0),apc);
97 vA.addAP(1,new Point3d(2,0,0),apc);
98
99 IAtomContainer iacB = builder.newAtomContainer();
100 IAtom iaB1 = new Atom("C",new Point3d(0,0,0));
101 IAtom iaB2 = new Atom("C",new Point3d(1,0,0));
102 IAtom iaB3 = new Atom("C",new Point3d(1,-0.33,0));
103 IAtom iaB4 = new Atom("C",new Point3d(1,-0.66,0));
104 IAtom iaB5 = new Atom("C",new Point3d(1,-1,0));
105 IAtom iaB6 = new Atom("C",new Point3d(0,-1,0));
106 IAtom iaB7 = new Atom("C",new Point3d(0,-0.5,0));
107 iacB.addAtom(iaB1);
108 iacB.addAtom(iaB2);
109 iacB.addAtom(iaB3);
110 iacB.addAtom(iaB4);
111 iacB.addAtom(iaB5);
112 iacB.addAtom(iaB6);
113 iacB.addAtom(iaB7);
114 iacB.addBond(new Bond(iaB1, iaB2, IBond.Order.SINGLE));
115 iacB.addBond(new Bond(iaB2, iaB3, IBond.Order.SINGLE));
116 iacB.addBond(new Bond(iaB3, iaB4, IBond.Order.SINGLE));
117 iacB.addBond(new Bond(iaB4, iaB5, IBond.Order.SINGLE));
118 iacB.addBond(new Bond(iaB5, iaB6, IBond.Order.SINGLE));
119 iacB.addBond(new Bond(iaB6, iaB7, IBond.Order.SINGLE));
120 iacB.addBond(new Bond(iaB1, iaB7, IBond.Order.SINGLE));
121 Fragment vB = new Fragment(1,iacB,BBType.FRAGMENT);
122 vB.addAP(0,new Point3d(-1,0,0),apc);
123 vB.addAP(5,new Point3d(-1,-1,0),apc);
124 vB.addAP(6,new Point3d(1,1,0),apc);
125
126 IAtomContainer iacC = builder.newAtomContainer();
127 IAtom iaC1 = new Atom("N",new Point3d(0,0,0));
128 IAtom iaC2 = new Atom("N",new Point3d(-1,0,0));
129 IAtom iaC3 = new Atom("N",new Point3d(0,-1,0));
130 iacC.addAtom(iaC1);
131 iacC.addAtom(iaC2);
132 iacC.addAtom(iaC3);
133 iacC.addBond(new Bond(iaC1, iaC2, IBond.Order.SINGLE));
134 iacC.addBond(new Bond(iaC2, iaC3, IBond.Order.SINGLE));
135 iacC.addBond(new Bond(iaC1, iaC3, IBond.Order.SINGLE));
136 Fragment vC = new Fragment(2,iacC,BBType.FRAGMENT);
137 vC.addAP(0,new Point3d(1,0,0),apc);
138 vC.addAP(1,new Point3d(-1,1,0),apc);
139 vC.addAP(2,new Point3d(-1,-1,0),apc);
140
141 IAtomContainer iacG = builder.newAtomContainer();
142 IAtom iaG1 = new Atom("P",new Point3d(0,0,0));
143 IAtom iaG2 = new Atom("P",new Point3d(0,0,1));
144 IAtom iaG3 = new Atom("P",new Point3d(0,0,2));
145 iacG.addAtom(iaG1);
146 iacG.addAtom(iaG2);
147 iacG.addAtom(iaG3);
148 iacG.addBond(new Bond(iaG1, iaG2, IBond.Order.SINGLE));
149 iacG.addBond(new Bond(iaG2, iaG3, IBond.Order.SINGLE));
150 Fragment vG = new Fragment(5,iacG,BBType.FRAGMENT);
151 vG.addAP(0,new Point3d(1,0,0),apc);
152
153 IAtomContainer iacD = builder.newAtomContainer();
154 iacD.addAtom(new PseudoAtom("ATN",new Point3d(0,0,0)));
155 Fragment vD = new Fragment(3,iacD,BBType.FRAGMENT);
156 vD.addAP(0,new Point3d(-1,0,0),APClass.make("ATneutral",0));
157 vD.setAsRCV(true);
158
159 IAtomContainer iacE = builder.newAtomContainer();
160 iacE.addAtom(new PseudoAtom("ATN",new Point3d(0,0,0)));
161 Fragment vE = new Fragment(4,iacE,BBType.FRAGMENT);
162 vE.addAP(0, new Point3d(-1,0,0),APClass.make("ATneutral",0));
163 vE.setAsRCV(true);
164
165 graph.addVertex(vA);
166 graph.addVertex(vD);
167 graph.addVertex(vB);
168 graph.addVertex(vC);
169 graph.addVertex(vG);
170 graph.addVertex(vE);
171 graph.addEdge(new Edge(vA.getAP(0), vD.getAP(0), BondType.SINGLE));
172 graph.addEdge(new Edge(vA.getAP(1), vB.getAP(0), BondType.SINGLE));
173 graph.addEdge(new Edge(vB.getAP(1), vC.getAP(0), BondType.SINGLE));
174 graph.addEdge(new Edge(vC.getAP(2), vG.getAP(0), BondType.SINGLE));
175 graph.addEdge(new Edge(vC.getAP(1), vE.getAP(0), BondType.SINGLE));
176
177 return graph;
178 }
179
180//------------------------------------------------------------------------------
181
194 {
195 APClass apc = APClass.make("A",0,BondType.SINGLE);
196
197 DGraph graph = new DGraph();
198
199 IChemObjectBuilder builder = SilentChemObjectBuilder.getInstance();
200
201 IAtomContainer iacA = builder.newAtomContainer();
202 IAtom iaA1 = new Atom("O",new Point3d(0,0,0));
203 iacA.addAtom(iaA1);
204 Fragment vA = new Fragment(0,iacA,BBType.FRAGMENT);
205 vA.addAP(0,new Point3d(0,-1,0),apc);
206 vA.addAP(0,new Point3d(1,-1,0),apc);
207
208 IAtomContainer iacB = builder.newAtomContainer();
209 IAtom iaB1 = new Atom("C",new Point3d(0,0,0));
210 iacB.addAtom(iaB1);
211 Fragment vB = new Fragment(1,iacB,BBType.FRAGMENT);
212 vB.addAP(0,new Point3d(-1,0,0),apc);
213 vB.addAP(0,new Point3d(-1,-1,0),apc);
214
215 IAtomContainer iacC = builder.newAtomContainer();
216 IAtom iaC1 = new Atom("N",new Point3d(0,0,0));
217 iacC.addAtom(iaC1);
218 Fragment vC = new Fragment(2,iacC,BBType.FRAGMENT);
219 vC.addAP(0,new Point3d(1,0,0),apc);
220 vC.addAP(0,new Point3d(1,1,0),apc);
221
222 IAtomContainer iacG = builder.newAtomContainer();
223 IAtom iaG1 = new Atom("P",new Point3d(0,0,0));
224 iacG.addAtom(iaG1);
225 Fragment vG = new Fragment(5,iacG,BBType.FRAGMENT);
226 vG.addAP(0,new Point3d(1,0,0),apc);
227 vG.addAP(0,new Point3d(-1,1,0),apc);
228
229 IAtomContainer iacD = builder.newAtomContainer();
230 iacD.addAtom(new PseudoAtom("ATN",new Point3d(0,0,0)));
231 Fragment vD = new Fragment(3,iacD,BBType.FRAGMENT);
232 vD.addAP(0,new Point3d(-1,0,0),APClass.make("ATneutral",0));
233 vD.setAsRCV(true);
234
235 IAtomContainer iacE = builder.newAtomContainer();
236 iacE.addAtom(new PseudoAtom("ATN",new Point3d(0,0,0)));
237 Fragment vE = new Fragment(4,iacE,BBType.FRAGMENT);
238 vE.addAP(0, new Point3d(-1,0,0),APClass.make("ATneutral",0));
239 vE.setAsRCV(true);
240
241 graph.addVertex(vA);
242 graph.addVertex(vD);
243 graph.addVertex(vB);
244 graph.addVertex(vC);
245 graph.addVertex(vG);
246 graph.addVertex(vE);
247 graph.addEdge(new Edge(vA.getAP(0), vD.getAP(0), BondType.SINGLE));
248 graph.addEdge(new Edge(vA.getAP(1), vB.getAP(0), BondType.SINGLE));
249 graph.addEdge(new Edge(vB.getAP(1), vC.getAP(0), BondType.SINGLE));
250 graph.addEdge(new Edge(vC.getAP(1), vG.getAP(0), BondType.SINGLE));
251 graph.addEdge(new Edge(vG.getAP(1), vE.getAP(0), BondType.SINGLE));
252
253 return graph;
254 }
255
256//------------------------------------------------------------------------------
257
258 @Test
259 public void testMakePathSubGraph_sameVrtx() throws Exception
260 {
262
265
266 assertEquals(1,path.getVertecesPath().size(),
267 "Number of vertices in the path");
268 assertEquals(g.getVertexAtPosition(5),path.getVertecesPath().get(0),
269 "First vertex in the path is the fifth vertex in the graph.");
270 }
271
272 //------------------------------------------------------------------------------
273
274 @Test
275 public void testMakePathSubGraph_sameBranch() throws Exception
276 {
278
281
282 assertEquals(2,path.getVertecesPath().size(),
283 "Number of vertices in the path");
284 assertEquals(1,path.getEdgesPath().size(),
285 "Number of edges in the path");
286 assertEquals(g.getVertexAtPosition(2),path.getVertecesPath().get(0),
287 "First vertex in the path");
288 assertEquals(g.getVertexAtPosition(3),path.getVertecesPath().get(1),
289 "Second vertex in the path");
290
291 path = new PathSubGraph(g.getVertexAtPosition(5),
293
294 assertEquals(3,path.getVertecesPath().size(),
295 "Number of vertices in the path");
296 assertEquals(2,path.getEdgesPath().size(),
297 "Number of edges in the path");
298 assertEquals(g.getVertexAtPosition(5),path.getVertecesPath().get(0),
299 "First vertex in the path");
300 assertEquals(g.getVertexAtPosition(3),path.getVertecesPath().get(1),
301 "Second vertex in the path");
302 assertEquals(g.getVertexAtPosition(2),path.getVertecesPath().get(2),
303 "Third vertex in the path");
304 }
305
306
307//------------------------------------------------------------------------------
308
309 @Test
310 public void testMakePathSubGraph_differentBranch() throws Exception
311 {
314
317
318 assertEquals(5,path.getVertecesPath().size(),
319 "Number of vertices in the path");
320 }
321
322//------------------------------------------------------------------------------
323
324 @Test
325 public void testMakePathSubGraph_givenAdjacency() throws Exception
326 {
327 DGraph g = new DGraph();
328 EmptyVertex v1 = new EmptyVertex(1);
329 v1.addAP(APClass.make("A",0));
330 v1.addAP(APClass.make("A",1));
331 EmptyVertex v2 = new EmptyVertex(2);
332 v2.addAP(APClass.make("B",0));
333 v2.addAP(APClass.make("B",1));
334 EmptyVertex v3 = new EmptyVertex(3);
335 v3.addAP(APClass.make("C",0));
336 v3.addAP(APClass.make("C",1));
337 EmptyVertex v6 = new EmptyVertex(6);
338 v6.addAP(APClass.make("Z",0));
339 v6.addAP(APClass.make("X",1));
340 g.addVertex(new EmptyVertex(0));
341 g.addVertex(v1);
342 g.addVertex(v2);
343 g.addVertex(v3);
344 g.addVertex(new EmptyVertex(4));
345 g.addVertex(new EmptyVertex(5));
346 g.addVertex(v6);
347
348 // Same vertex
351
352 assertEquals(1,path.getVertecesPath().size(),
353 "Number of vertices in the path");
354 assertEquals(0,path.getEdgesPath().size(),
355 "Number of edges in the path");
356 assertEquals(g.getVertexAtPosition(0),path.getVertecesPath().get(0),
357 "Vertex in path");
358
359 // Non-connected vertexes
360 assertThrows(DENOPTIMException.class, () -> new PathSubGraph(
362 assertThrows(DENOPTIMException.class, () -> new PathSubGraph(
364
365 // Non-connected with irrelevant jump rules
366 Map<Vertex, List<Vertex>> adjacency = new HashMap<>();
367 adjacency.put(g.getVertexAtPosition(3), Arrays.asList(
369
370 assertThrows(DENOPTIMException.class, () -> new PathSubGraph(
371 g.getVertexAtPosition(0), g.getVertexAtPosition(1),adjacency));
372 assertThrows(DENOPTIMException.class, () -> new PathSubGraph(
373 g.getVertexAtPosition(1), g.getVertexAtPosition(0),adjacency));
374
375 // Non-connected with adjacency rule
376 Map<Vertex, List<Vertex>> adjacency2 = new HashMap<>();
377 adjacency2.computeIfAbsent(g.getVertexAtPosition(0), k -> new ArrayList<Vertex>())
378 .add(g.getVertexAtPosition(1));
379 adjacency2.computeIfAbsent(g.getVertexAtPosition(1), k -> new ArrayList<Vertex>())
380 .add(g.getVertexAtPosition(0));
381 adjacency2.computeIfAbsent(g.getVertexAtPosition(1), k -> new ArrayList<Vertex>())
382 .add(g.getVertexAtPosition(4));
383 adjacency2.computeIfAbsent(g.getVertexAtPosition(4), k -> new ArrayList<Vertex>())
384 .add(g.getVertexAtPosition(1));
385
386 path = new PathSubGraph(g.getVertexAtPosition(0),
387 g.getVertexAtPosition(4), adjacency2);
388
389 assertEquals(3,path.getVertecesPath().size(),
390 "Number of vertices in the path");
391 assertEquals(2,path.getEdgesPath().size(),
392 "Number of edges in the path");
393 for (Edge e : path.getEdgesPath()) {
394 assertNull(e, "Edge is supposed to be null in path driven only by adjacency rule");
395 }
396
397 // Mixing adjacency and actual edges
398 g.addEdge(new Edge(v1.getAP(0), v2.getAP(1), BondType.SINGLE));
399 g.addEdge(new Edge(v2.getAP(0), v3.getAP(0), BondType.TRIPLE));
400 g.addEdge(new Edge(v1.getAP(1), v6.getAP(1), BondType.DOUBLE));
401
402 // edges are present, but we require not to use them
403 assertThrows(DENOPTIMException.class, () -> new PathSubGraph(
404 g.getVertexAtPosition(4), v3, adjacency2, false));
405
406 // now we do require to use them
407 path = new PathSubGraph(g.getVertexAtPosition(4), v3, adjacency2, true);
408
409 assertEquals(4,path.getVertecesPath().size(),
410 "Number of vertices in the path");
411 assertEquals(3,path.getEdgesPath().size(),
412 "Number of edges in the path");
413 List<Edge> edges = path.getEdgesPath();
414 assertNull(edges.get(0), "Edge is supposed to be null in path driven only by adjacency rule");
415 assertNotNull(edges.get(1), "Edge is supposed to be not null in path driven by adjacency and actual edges");
416 assertNotNull(edges.get(2), "Edge is supposed to be not null in path driven by adjacency and actual edges");
417 assertEquals(BondType.SINGLE, edges.get(1).getBondType(), "Bond type in the path");
418 assertEquals(BondType.TRIPLE, edges.get(2).getBondType(), "Bond type in the path");
419 }
420
421//------------------------------------------------------------------------------
422
423 @Test
424 public void testMakePathSubGraph_withIAC() throws Exception
425 {
426 DGraph gA = makeTestGraphA();
427 DGraph gB = makeTestGraphB();
428
429 Logger logger = Logger.getLogger("DummyLogger");
430 Randomizer rng = new Randomizer();
431
432 ThreeDimTreeBuilder t3d = new ThreeDimTreeBuilder(logger,rng);
433 t3d.setAlignBBsIn3D(false); //3D not needed
434 IAtomContainer molA = t3d.convertGraphTo3DAtomContainer(gA,true);
435 IAtomContainer molB = t3d.convertGraphTo3DAtomContainer(gB,true);
436
438 gA.getVertexAtPosition(5));
439 pA.makeMolecularRepresentation(molA, false, logger, rng);
441 gB.getVertexAtPosition(5));
442 pB.makeMolecularRepresentation(molB, false, logger, rng);
443
444 IAtomContainer iacA = pA.getMolecularRepresentation();
445 assertEquals(14,iacA.getAtomCount(), "Atom count in the path");
446
447 IAtomContainer iacB = pB.getMolecularRepresentation();
448 assertEquals(6,iacB.getAtomCount(), "Atom count in the path");
449 }
450
451//------------------------------------------------------------------------------
452
453}
Class defining a space of building blocks.
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
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:104
void addVertex(Vertex vertex)
Appends a vertex to this graph without creating any edge.
Definition: DGraph.java:1391
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:3163
void addEdge(Edge edge)
Adds the edge to the list of edges belonging to this graph.
Definition: DGraph.java:1295
Unit test for DENOPTIMGraph.
Definition: DGraphTest.java:72
static FragmentSpace prepare()
Definition: DGraphTest.java:79
static DGraph makeTestGraphO_B(FragmentSpace fs)
Creates a test graph that intentionally violates APClass compatibility and looks like this:
This class represents the edge between two vertices.
Definition: Edge.java:38
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
void addAP(int atomPositionNumber)
Adds an attachment point with a dummy APClass.
Definition: Fragment.java:343
void setAsRCV(boolean isRCV)
Definition: Vertex.java:274
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
Definition: Vertex.java:1007
This object represents a path in a DGraph.
void makeMolecularRepresentation(IAtomContainer mol, boolean make3D, Logger logger, Randomizer randomizer)
Creates the molecular representation, list of atoms and bonds involved in the path between the head a...
List< Vertex > getVertecesPath()
Returns the list of verteces involved.
IAtomContainer getMolecularRepresentation()
Returns the molecular representation.
List< Edge > getEdgesPath()
Returns the list of edges involved, if any.
static DGraph makeTestGraphB()
Build a graph meant to be used in unit tests.
static DGraph makeTestGraphA()
Build a graph meant to be used in unit tests.
Tool to build build three-dimensional (3D) tree-like molecular structures from DGraph.
void setAlignBBsIn3D(boolean align)
Sets the flag that controls whether building blocks have to be aligned according to the AP vectors or...
IAtomContainer convertGraphTo3DAtomContainer(DGraph graph)
Created a three-dimensional molecular representation from a given DGraph.
Tool to generate random numbers and random decisions.
Definition: Randomizer.java:35
Possible chemical bond types an edge can represent.
Definition: Edge.java:305
The type of building block.
Definition: Vertex.java:86