$darkmode
DENOPTIM
DGraph.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2019 Vishwesh Venkatraman <vishwesh.venkatraman@ntnu.no> and
4 * Marco Foscato <marco.foscato@uib.no>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published
8 * by the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20package denoptim.graph;
21
22import java.io.File;
23import java.io.Reader;
24import java.lang.reflect.Type;
25import java.util.ArrayDeque;
26import java.util.ArrayList;
27import java.util.Collection;
28import java.util.Collections;
29import java.util.Comparator;
30import java.util.HashMap;
31import java.util.HashSet;
32import java.util.Iterator;
33import java.util.LinkedHashMap;
34import java.util.List;
35import java.util.Map;
36import java.util.Map.Entry;
37import java.util.Queue;
38import java.util.Set;
39import java.util.concurrent.atomic.AtomicInteger;
40import java.util.function.Function;
41import java.util.logging.Level;
42import java.util.logging.Logger;
43import java.util.stream.Collectors;
44
45import org.jgrapht.alg.isomorphism.VF2GraphIsomorphismInspector;
46import org.jgrapht.graph.DefaultUndirectedGraph;
47import org.openscience.cdk.graph.ConnectivityChecker;
48import org.openscience.cdk.interfaces.IAtom;
49import org.openscience.cdk.interfaces.IAtomContainer;
50
51import com.google.gson.Gson;
52import com.google.gson.GsonBuilder;
53import com.google.gson.JsonArray;
54import com.google.gson.JsonDeserializationContext;
55import com.google.gson.JsonDeserializer;
56import com.google.gson.JsonElement;
57import com.google.gson.JsonObject;
58import com.google.gson.JsonParseException;
59import com.google.gson.JsonSerializationContext;
60import com.google.gson.JsonSerializer;
61
62import denoptim.constants.DENOPTIMConstants;
63import denoptim.exception.DENOPTIMException;
64import denoptim.fragspace.FragmentSpace;
65import denoptim.fragspace.FragmentSpaceParameters;
66import denoptim.graph.APClass.APClassDeserializer;
67import denoptim.graph.Edge.BondType;
68import denoptim.graph.Template.ContractLevel;
69import denoptim.graph.Vertex.BBType;
70import denoptim.graph.Vertex.DENOPTIMVertexDeserializer;
71import denoptim.graph.Vertex.VertexType;
72import denoptim.graph.rings.ClosableChain;
73import denoptim.graph.rings.CyclicGraphHandler;
74import denoptim.graph.rings.PathSubGraph;
75import denoptim.graph.rings.RingClosingAttractor;
76import denoptim.graph.rings.RingClosureParameters;
77import denoptim.graph.simplified.Node;
78import denoptim.graph.simplified.NodeConnection;
79import denoptim.graph.simplified.UndirectedEdge;
80import denoptim.io.DenoptimIO;
81import denoptim.json.DENOPTIMgson;
82import denoptim.json.DENOPTIMgson.DENOPTIMExclusionStrategyNoAPMap;
83import denoptim.molecularmodeling.ThreeDimTreeBuilder;
84import denoptim.programs.RunTimeParameters;
85import denoptim.programs.RunTimeParameters.ParametersType;
86import denoptim.utils.GeneralUtils;
87import denoptim.utils.GraphConversionTool;
88import denoptim.utils.GraphEdit;
89import denoptim.utils.GraphUtils;
90import denoptim.utils.MoleculeUtils;
91import denoptim.utils.MutationType;
92import denoptim.utils.ObjectPair;
93import denoptim.utils.RotationalSpaceUtils;
94
95
101public class DGraph implements Cloneable
102{
106 List<Vertex> gVertices;
107
111 List<Edge> gEdges;
112
116 List<Ring> gRings;
117
121 List<ClosableChain> closableChains;
122
123 /*
124 * Unique graph id
125 */
127
128 /*
129 * store the set of symmetric vertex ids at each level. This is only
130 * applicable for symmetric graphs
131 */
132 private List<SymmetricVertexes> symVertices;
133
139 String localMsg;
140
145
150
154 private DefaultUndirectedGraph<Vertex, UndirectedEdge>
155 jGraph = null;
156
160 private DefaultUndirectedGraph<Node, NodeConnection>
162
166 public enum StringFormat {JSON, GRAPHENC}
167
171 private AtomicInteger apCounter = new AtomicInteger(1);
172
173
174//------------------------------------------------------------------------------
175
176 public DGraph(List<Vertex> gVertices, List<Edge> gEdges)
177 {
178 this.gVertices = gVertices;
179 for (Vertex v : this.gVertices)
180 v.setGraphOwner(this);
181 this.gEdges = gEdges;
182 gRings = new ArrayList<>();
183 closableChains = new ArrayList<>();
184 symVertices = new ArrayList<>();
185 localMsg = "";
186 }
187
188//------------------------------------------------------------------------------
189
190 public DGraph(List<Vertex> gVertices, List<Edge> gEdges, List<Ring> gRings)
191 {
192 this(gVertices, gEdges);
193 this.gRings = gRings;
194 closableChains = new ArrayList<>();
195 symVertices = new ArrayList<>();
196 localMsg = "";
197 }
198
199//------------------------------------------------------------------------------
200
201 public DGraph(List<Vertex> gVertices, List<Edge> gEdges, List<Ring> gRings,
202 List<SymmetricVertexes> symSets)
203 {
204 this(gVertices, gEdges, gRings);
205 closableChains = new ArrayList<>();
206 this.symVertices = symSets;
207 localMsg = "";
208 }
209
210//------------------------------------------------------------------------------
211
212 public DGraph(List<Vertex> gVertices, List<Edge> gEdges, List<Ring> gRings,
213 List<ClosableChain> closableChains,
214 List<SymmetricVertexes> symVertices)
215 {
217 this.closableChains = closableChains;
218 localMsg = "";
219 }
220
221//------------------------------------------------------------------------------
222
223 public DGraph()
224 {
225 gVertices = new ArrayList<>();
226 gEdges = new ArrayList<>();
227 gRings = new ArrayList<>();
228 closableChains = new ArrayList<>();
229 symVertices = new ArrayList<>();
230 localMsg = "";
231 }
232
233//------------------------------------------------------------------------------
234
240 {
241 this.candidate = candidate;
242 }
243
244//------------------------------------------------------------------------------
245
252 {
253 return candidate;
254 }
255
256//------------------------------------------------------------------------------
257
258 public void setGraphId(int id)
259 {
260 graphId = id;
261 }
262
263//------------------------------------------------------------------------------
264
265 public int getGraphId()
266 {
267 return graphId;
268 }
269
270//------------------------------------------------------------------------------
271
272 public void setLocalMsg(String msg)
273 {
274 localMsg = msg;
275 }
276
277//------------------------------------------------------------------------------
278
279 public String getLocalMsg()
280 {
281 return localMsg;
282 }
283
284//------------------------------------------------------------------------------
285
286 public boolean hasSymmetricAP()
287 {
288 return (!symVertices.isEmpty());
289 }
290
291//------------------------------------------------------------------------------
292
294 {
295 boolean res = false;
297 {
298 if (ss.contains(v))
299 {
300 res = true;
301 break;
302 }
303 }
304 return res;
305 }
306
307//------------------------------------------------------------------------------
308
314 {
315 return symVertices.size();
316 }
317
318//------------------------------------------------------------------------------
319
324 public Iterator<SymmetricVertexes> getSymSetsIterator()
325 {
326 return symVertices.iterator();
327 }
328
329//------------------------------------------------------------------------------
330
335 public List<Vertex> getSymVerticesForVertex(Vertex v)
336 {
337 List<Vertex> lst = new ArrayList<Vertex>();
339 {
340 if (ss.contains(v))
341 {
342 ss.stream().forEach(i -> lst.add((Vertex) i));
343 }
344 }
345 return lst;
346 }
347
348//------------------------------------------------------------------------------
349
373 {
374 int initialSize = symVertices.size();
375
376 // This is do hold vertexes in a staging area (symVrtxsFromAnyBranch)
377 // without adding them to a SymmetricVertexes right away.
378 Set<Vertex> alreadyAssignedVrtxs = new HashSet<Vertex>();
379
380 // The sym vertexes on vrtx can have sym counterpart
381 // that are attached to vertexes sym to vrtx. Prepare a storage to
382 // collect all sym counterparts from any of vertexes sym to vrtx
383 Map<SymmetricAPs,List<Vertex>> symVrtxsFromAnyBranch =
384 new HashMap<SymmetricAPs,List<Vertex>>();
385 for (Vertex vrtx : getVertexList())
386 {
387 // NB: if there is a symmetric relation involving vrtx, then
388 // vrtx is in the set returned by the following lines
389 List<Vertex> vrtxsSymToVrtx = new ArrayList<Vertex>();
390 for (List<Vertex> tmpSymSets : symVrtxsFromAnyBranch.values())
391 {
392 if (tmpSymSets.contains(vrtx))
393 {
394 vrtxsSymToVrtx.addAll(tmpSymSets);
395 }
396 }
397 if (vrtxsSymToVrtx.size()==0)
398 vrtxsSymToVrtx.add(vrtx);
399
400 for (Vertex symToVrtx : vrtxsSymToVrtx)
401 {
402 Map<SymmetricAPs,List<Vertex>> symChildenSetsOnSymToVrtxs =
404 alreadyAssignedVrtxs);
405
406 for (SymmetricAPs key : symChildenSetsOnSymToVrtxs.keySet())
407 {
408 // Find any mapping with previously recorded SymmetricAPs
409 boolean foundSymmetricBranch = false;
410 for (SymmetricAPs keyOnMaster : key.getAllSameAs(
411 symVrtxsFromAnyBranch.keySet()))
412 {
413 foundSymmetricBranch = true;
414
415 // Here we must NOT consider the already assigned ones!
416 if (areApsUsedBySymmetricUsers(key.get(0),
417 keyOnMaster.get(0), new HashSet<Vertex>()))
418 {
419 // the previously recorded branch and
420 // this one are consistent
421 symVrtxsFromAnyBranch.get(keyOnMaster).addAll(
422 symChildenSetsOnSymToVrtxs.get(key));
423 } else {
424 // branches correspond to two different sets of
425 // symmetric vertexes. So, we treat the new branch
426 // independently
427 foundSymmetricBranch = false;
428 }
429 }
430 if (!foundSymmetricBranch)
431 {
432 // Effectively, in the first iteration of the loop
433 // we will always end up here
434 List<Vertex> lst = new ArrayList<Vertex>();
435 lst.addAll(symChildenSetsOnSymToVrtxs.get(key));
436 symVrtxsFromAnyBranch.put(key, lst);
437 }
438 }
439 }
440 }
441
442 for (List<Vertex> symVertexes : symVrtxsFromAnyBranch.values())
443 {
444 if (symVertexes.size()<2)
445 {
446 // We get rid of placeholders for vertexes that use APs that
447 // are not part of a symmetriAPs, but could have been part
448 // of symmetric subgraphs
449 continue;
450 }
451 alreadyAssignedVrtxs.addAll(symVertexes);
453 }
454
455 return (symVertices.size()-initialSize)>0;
456 }
457
458//------------------------------------------------------------------------------
459
460 Map<SymmetricAPs, List<Vertex>> findSymmetrySetsOfChildVertexes(
461 Vertex vrtx, Set<Vertex> alreadyAssignedVrtxs)
462 {
463 Map<SymmetricAPs,List<Vertex>> symSetsOfChildVrtxs =
464 new HashMap<SymmetricAPs,List<Vertex>>();
465
466 Set<AttachmentPoint> doneAPs = new HashSet<AttachmentPoint>();
467 for (SymmetricAPs symAPs : vrtx.getSymmetricAPSets())
468 {
469 // First condition: all symmetric APs must be in use
470 boolean addSymAPsAreUsed = true;
471 for (AttachmentPoint ap : symAPs)
472 {
473 if (ap.isAvailableThroughout())
474 {
475 addSymAPsAreUsed = false;
476 break;
477 }
478 }
479 if (!addSymAPsAreUsed)
480 continue;
481
482 // Now consider what vertex is attached to the symmetric APs
483 AttachmentPoint firstAp = symAPs.get(0);
484
485 boolean setSymmetryRelation = true;
486 List<Vertex> symVertexes = new ArrayList<Vertex>();
487 symVertexes.add(firstAp.getLinkedAPThroughout().getOwner());
488 for (AttachmentPoint ap : symAPs)
489 {
490 doneAPs.add(ap);
491
492 if (firstAp==ap)
493 continue;
494
495 setSymmetryRelation = areApsUsedBySymmetricUsers(firstAp, ap,
496 alreadyAssignedVrtxs);
497 if (!setSymmetryRelation)
498 break;
499
500 // OK: this user of AP is symmetric to the user on firstAP
501 symVertexes.add(ap.getLinkedAPThroughout().getOwner());
502 }
503
504 if (setSymmetryRelation)
505 {
506 symSetsOfChildVrtxs.put(symAPs,symVertexes);
507 alreadyAssignedVrtxs.addAll(symVertexes);
508 }
509 }
510
511 // Here we account for the possibility that vertex without sym APs
512 // is part of a subgraph the is symmetrically reproduced elsewhere.
513 // This is a common pattern in chemistry.
514 // To this end we create dummy symmetric sets of APs that contain
515 // only one APs, and use them as placeholder in case the same AP-user
516 // is found on symmetric branches.
517 for (AttachmentPoint ap : vrtx.getAttachmentPoints())
518 {
519 if (doneAPs.contains(ap) || ap.isAvailableThroughout())
520 continue;
521
522 Vertex user = ap.getLinkedAPThroughout().getOwner();
523 if (alreadyAssignedVrtxs.contains(user))
524 continue;
525
526 // Create an artifact of SymmetricAPs that contains one entry
527 SymmetricAPs soloSymAps = new SymmetricAPs();
528 soloSymAps.add(ap);
529
530 // Well, this contains only one entry, but for consistency we still
531 // use a list.
532 List<Vertex> symVertexes = new ArrayList<Vertex>();
533 symVertexes.add(user);
534
535 symSetsOfChildVrtxs.put(soloSymAps,symVertexes);
536 alreadyAssignedVrtxs.addAll(symVertexes);
537 }
538 return symSetsOfChildVrtxs;
539 }
540
541//------------------------------------------------------------------------------
542
566 AttachmentPoint apB, Set<Vertex> alreadyAssignedVrtxs)
567 {
568 AttachmentPoint apUserOfApA = apA.getLinkedAPThroughout();
569 Vertex userOfApA = apUserOfApA.getOwner();
570 boolean userOfApAIsFragment = Fragment.class.isInstance(userOfApA);
571
572 // 1st condition: (fast failing) the linked AP must have
573 // the same features. This is faster than checking vertex
574 // isomorphism.
575 AttachmentPoint apUserOfApB = apB.getLinkedAPThroughout();
576 if (!apUserOfApA.sameAs(apUserOfApB))
577 {
578 return false;
579 }
580
581 // 2nd condition: (fast-failing) the linked vertexes
582 // must be unassigned
583 Vertex userOfApB = apUserOfApB.getOwner();
584 if (alreadyAssignedVrtxs.contains(userOfApB))
585 {
586 return false;
587 }
588
589 // 3rd condition: (not fast, not too slow) the linked
590 // vertexes must be have same features
591 if (!userOfApB.sameAs(userOfApA))
592 {
593 return false;
594 }
595
596 // 4th condition: (slow) the linked vertexes
597 // are fragments that have been generated on the fly, so
598 // they do not have an assigned building block ID. We must
599 // therefore compare their internal structure.
600 if (userOfApAIsFragment)
601 {
602 // At this point we know the two vertexes are instances
603 // of the same class.
604 Fragment frgUserOfApA = (Fragment) userOfApA;
605 Fragment frgUserOfApB = (Fragment) userOfApB;
606 if (!frgUserOfApA.isIsomorphicTo(frgUserOfApB))
607 {
608 return false;
609 }
610 }
611 return true;
612 }
613
614//------------------------------------------------------------------------------
615
621 {
622 symVertices.remove(ss);
623 }
624
625//------------------------------------------------------------------------------
626
634 {
636 {
637 if (ss.contains(v))
638 {
639 return ss;
640 }
641 }
642 return new SymmetricVertexes();
643 }
644
645//------------------------------------------------------------------------------
646
647 public void setSymmetricVertexSets(List<SymmetricVertexes> symVertices)
648 {
649 this.symVertices.clear();
650 this.symVertices.addAll(symVertices);
651 }
652
653//------------------------------------------------------------------------------
654
662 throws DENOPTIMException
663 {
664 for (SymmetricVertexes oldSS : symVertices)
665 {
666 if (!Collections.disjoint(oldSS, symSet))
667 {
668 throw new DENOPTIMException("Adding " + symSet + " while "
669 + "there is already one that contains some of the same "
670 + "items");
671 }
672 }
673 symVertices.add(symSet);
674 }
675
676//------------------------------------------------------------------------------
677
678 public void setVertexList(ArrayList<Vertex> vertices)
679 {
680 gVertices = vertices;
681 jGraph = null;
682 jGraphKernel = null;
683 }
684
685//------------------------------------------------------------------------------
686
687 public void setEdgeList(ArrayList<Edge> edges)
688 {
689 gEdges = edges;
690 jGraph = null;
691 jGraphKernel = null;
692 }
693
694//------------------------------------------------------------------------------
695
696 public void setRings(ArrayList<Ring> rings)
697 {
698 gRings = rings;
699 jGraph = null;
700 jGraphKernel = null;
701 }
702
703//------------------------------------------------------------------------------
704
705 public void setCandidateClosableChains(ArrayList<ClosableChain> closableChains)
706 {
707 this.closableChains = closableChains;
708 }
709
710//------------------------------------------------------------------------------
711
712 public List<ClosableChain> getClosableChains()
713 {
714 return closableChains;
715 }
716
717//------------------------------------------------------------------------------
718
719 public List<Vertex> getVertexList()
720 {
721 return gVertices;
722 }
723
724//------------------------------------------------------------------------------
725
741 {
742 switch (gVertices.size())
743 {
744 case 0:
745 return null;
746 case 1:
747 return getVertexAtPosition(0);
748 }
750 for (Edge e : this.getEdgeList())
751 {
752 if (e.getTrgAP().getOwner() == v0)
753 {
754 ArrayList<Vertex> parentTree = new ArrayList<>();
755 getParentTree(v0,parentTree);
756 return parentTree.get(parentTree.size()-1);
757 }
758 }
759 return v0;
760 }
761
762//------------------------------------------------------------------------------
763
764 public List<Edge> getEdgeList()
765 {
766 return gEdges;
767 }
768
769//------------------------------------------------------------------------------
770
771 public List<Ring> getRings()
772 {
773 return gRings;
774 }
775
776//------------------------------------------------------------------------------
777
784 public List<Edge> getEdgesWithSrc(Vertex v)
785 {
786 List<Edge> edges = new ArrayList<Edge>();
787 for (Edge e : this.getEdgeList())
788 {
789 if (e.getSrcAP().getOwner() == v)
790 {
791 edges.add(e);
792 }
793 }
794 return edges;
795 }
796
797//------------------------------------------------------------------------------
798
805 public List<Edge> getEdgesWithTrg(Vertex v)
806 {
807 List<Edge> edges = new ArrayList<Edge>();
808 for (Edge e : this.getEdgeList())
809 {
810 if (e.getTrgAP().getOwner() == v)
811 {
812 edges.add(e);
813 }
814 }
815 return edges;
816 }
817
818//------------------------------------------------------------------------------
819
826 public ArrayList<Ring> getRingsInvolvingVertex(Vertex v)
827 {
828 ArrayList<Ring> rings = new ArrayList<Ring>();
829 for (Ring r : gRings)
830 {
831 if (r.contains(v))
832 {
833 rings.add(r);
834 }
835 }
836 return rings;
837 }
838
839//------------------------------------------------------------------------------
840
847 public ArrayList<Ring> getRingsInvolvingVertex(Vertex[] vs)
848 {
849 ArrayList<Ring> rings = new ArrayList<Ring>();
850 for (Ring r : gRings)
851 {
852 boolean matchesAll = true;
853 for (int i=0; i<vs.length; i++)
854 {
855 if (!r.contains(vs[i]))
856 {
857 matchesAll = false;
858 break;
859 }
860 }
861 if (matchesAll)
862 {
863 rings.add(r);
864 }
865 }
866 return rings;
867 }
868
869//------------------------------------------------------------------------------
870
871 public ArrayList<Ring> getRingsInvolvingVertexID(int vid)
872 {
873 ArrayList<Ring> rings = new ArrayList<Ring>();
874 for (Ring r : gRings)
875 {
876 if (r.containsID(vid))
877 {
878 rings.add(r);
879 }
880 }
881 return rings;
882 }
883
884//------------------------------------------------------------------------------
885
892 public boolean hasRings()
893 {
894 return gRings.size() > 0;
895 }
896
897//------------------------------------------------------------------------------
898
906 public boolean hasOrEmbedsRings()
907 {
908 if (gRings.size() > 0)
909 return true;
910 for (Vertex v : gVertices)
911 {
912 if (!(v instanceof Template))
913 continue;
914
915 Template t = (Template) v;
917 return true;
918 }
919 return false;
920 }
921
922//------------------------------------------------------------------------------
923
924 public boolean isVertexIDInRing(int vid)
925 {
926 boolean result = false;
927 for (Ring r : gRings)
928 {
929 if (r.containsID(vid))
930 {
931 result = true;
932 break;
933 }
934 }
935 return result;
936 }
937
938//------------------------------------------------------------------------------
939
940 public boolean isVertexInRing(Vertex v)
941 {
942 boolean result = false;
943 for (Ring r : gRings)
944 {
945 if (r.contains(v))
946 {
947 result = true;
948 break;
949 }
950 }
951 return result;
952 }
953
954//------------------------------------------------------------------------------
955
962 public ArrayList<Vertex> getRCVertices()
963 {
964 ArrayList<Vertex> rcvLst = new ArrayList<Vertex>();
965 for (Vertex v : gVertices)
966 {
967 if (v.isRCV())
968 {
969 rcvLst.add(v);
970 }
971 }
972 return rcvLst;
973 }
974
975//------------------------------------------------------------------------------
976
984 public ArrayList<Vertex> getFreeRCVertices()
985 {
986 ArrayList<Vertex> rcvLst = getRCVertices();
987 ArrayList<Vertex> free = new ArrayList<Vertex>();
988 for (Vertex v : rcvLst)
989 {
990 if (!isVertexInRing(v))
991 {
992 free.add(v);
993 }
994 }
995 return free;
996 }
997
998//------------------------------------------------------------------------------
999
1007 public ArrayList<Vertex> getUsedRCVertices()
1008 {
1009 ArrayList<Vertex> used = new ArrayList<Vertex>();
1010 used.addAll(getRCVertices());
1011 used.removeAll(getFreeRCVertices());
1012 return used;
1013 }
1014
1015//------------------------------------------------------------------------------
1016
1021 public void addEdge(Edge edge)
1022 {
1023 gEdges.add(edge);
1024 jGraph = null;
1025 jGraphKernel = null;
1026 }
1027
1028//------------------------------------------------------------------------------
1029
1030 public void addRing(Ring ring)
1031 {
1032 gRings.add(ring);
1033 jGraph = null;
1034 jGraphKernel = null;
1035 }
1036
1037//------------------------------------------------------------------------------
1038
1047 public void addRing(Vertex vI, Vertex vJ)
1048 throws DENOPTIMException
1049 {
1050 BondType bndTypI = vI.getEdgeToParent().getBondType();
1051 BondType bndTypJ = vJ.getEdgeToParent().getBondType();
1052 if (bndTypI != bndTypJ)
1053 {
1054 String s = "Attempt to close rings is not compatible "
1055 + "to the different bond type specified by the "
1056 + "head and tail APs: (" + bndTypI + "!="
1057 + bndTypJ + " for vertices " + vI + " "
1058 + vJ + ")";
1059 throw new DENOPTIMException(s);
1060 }
1061 addRing(vI,vJ,bndTypI);
1062 jGraph = null;
1063 jGraphKernel = null;
1064 }
1065
1066//------------------------------------------------------------------------------
1067
1075 public void addRing(Vertex vI, Vertex vJ, BondType bndTyp)
1076 {
1077 PathSubGraph path = new PathSubGraph(vI,vJ,this);
1078 ArrayList<Vertex> arrLst = new ArrayList<Vertex>();
1079 arrLst.addAll(path.getVertecesPath());
1080 Ring ring = new Ring(arrLst);
1081 ring.setBondType(bndTyp);
1082 this.addRing(ring);
1083 jGraph = null;
1084 jGraphKernel = null;
1085 }
1086
1087//------------------------------------------------------------------------------
1088
1097 public void addVertex(Vertex vertex) throws DENOPTIMException
1098 {
1099 if (containsVertexID(vertex.getVertexId()))
1100 throw new DENOPTIMException("Vertex must have a VertexID that is "
1101 + "unique within the graph. VertexID '"
1102 + vertex.getVertexId()+ "' already present in graph "
1103 + getGraphId());
1104 vertex.setGraphOwner(this);
1105 gVertices.add(vertex);
1106 jGraph = null;
1107 jGraphKernel = null;
1108 }
1109
1110//------------------------------------------------------------------------------
1111
1119 public void removeVertex(Vertex vertex)
1120 {
1121 if (!gVertices.contains(vertex))
1122 {
1123 return;
1124 }
1125
1126 vertex.resetGraphOwner();
1127 long vid = vertex.getVertexId();
1128
1129 // delete also any ring involving the removed vertex
1130 if (isVertexInRing(vertex))
1131 {
1132 ArrayList<Ring> rToRm = getRingsInvolvingVertex(vertex);
1133 for (Ring r : rToRm)
1134 {
1135 removeRing(r);
1136 }
1137 }
1138
1139 // remove edges involving the removed vertex
1140 ArrayList<Edge> eToDel = new ArrayList<>();
1141 for (int i=0; i<gEdges.size(); i++)
1142 {
1143 Edge edge = gEdges.get(i);
1144 if (vid == edge.getTrgVertex())
1145 {
1146 eToDel.add(edge);
1147 }
1148 // NB: the following allows to break the spanning tree
1149 if (vid == edge.getSrcVertex())
1150 {
1151 eToDel.add(edge);
1152 }
1153 }
1154 for (Edge e : eToDel)
1155 {
1156 this.removeEdge(e);
1157 }
1158
1159 //delete the removed vertex from symmetric sets, but leave other vertices
1160 List<SymmetricVertexes> ssToRemove = new ArrayList<SymmetricVertexes>();
1162 {
1163 if (ss.contains(vertex))
1164 {
1165 if (ss.size() < 3)
1166 {
1167 ssToRemove.add(ss);
1168 }
1169 else
1170 {
1171 ss.remove(vertex);
1172 }
1173 }
1174 }
1175 symVertices.removeAll(ssToRemove);
1176
1177 // remove the vertex from the graph
1178 gVertices.remove(vertex);
1179
1180 jGraph = null;
1181 jGraphKernel = null;
1182 }
1183
1184//------------------------------------------------------------------------------
1185
1195 public boolean removeVertexAndWeld(Vertex vertex,
1196 FragmentSpace fragSpace) throws DENOPTIMException
1197 {
1198 if (!gVertices.contains(vertex))
1199 {
1200 return false;
1201 }
1202
1203 List<Vertex> symSites = getSymVerticesForVertex(vertex);
1204 if (symSites.size() == 0)
1205 {
1206 symSites.add(vertex);
1207 } else {
1208 //TODO-V3 flip coin to decide if this should be a symmetric operation or not
1209 }
1210 for (Vertex oldLink : symSites)
1211 {
1213 if (!removeSingleVertexAndWeld(oldLink, fragSpace))
1214 {
1215 return false;
1216 }
1217 }
1218 // Reject deletions that cause the collapse of a 3-atom ring into a
1219 // loop (i.e., 1-atom ring) or multiple connection (i.e., a 3-atom ring)
1220 for (Ring r : gRings)
1221 {
1222 // 3 = 1 actual vertex + 2 RCVs
1223 if (r.getSize()!=3)
1224 continue;
1225
1226 AttachmentPoint apH = r.getHeadVertex().getEdgeToParent()
1227 .getSrcAPThroughout();
1228 AttachmentPoint apT = r.getTailVertex().getEdgeToParent()
1229 .getSrcAPThroughout();
1230
1231 if (apH.hasSameSrcAtom(apT) || apH.hasConnectedSrcAtom(apT))
1232 return false;
1233 }
1234 return true;
1235 }
1236
1237//------------------------------------------------------------------------------
1238
1247 public boolean removeSingleVertexAndWeld(Vertex vertex,
1248 FragmentSpace fragSpace) throws DENOPTIMException
1249 {
1250 if (!gVertices.contains(vertex))
1251 {
1252 return false;
1253 }
1254 if (vertex == getSourceVertex())
1255 {
1256 // Make sure there is something to weld, or give up. This to avoid
1257 // trying to remove the scaffold vertex (i.e., a vertex that has no
1258 // parents in this graph and the APs of which are only user as
1259 // source APs)
1260 boolean foundLinkToParent = false;
1261 for (AttachmentPoint ap : vertex.getAttachmentPoints())
1262 {
1263 if (ap.isAvailable() && !ap.isAvailableThroughout())
1264 {
1265 if (!ap.isSrcInUserThroughout())
1266 foundLinkToParent = true;
1267 }
1268 }
1269 if (!foundLinkToParent)
1270 return false;
1271
1272 // When we try to remove the only vertex inside a template, we
1273 // are removing the template itself
1274 if (gVertices.size()==1 && templateJacket!=null)
1275 {
1277 templateJacket, fragSpace);
1278 }
1279 }
1280
1281 // Get all APs that we'll try to weld into the parent
1282 ArrayList<AttachmentPoint> needyAPsOnChildren =
1283 new ArrayList<AttachmentPoint>();
1284 // And all APs where we could weld onto
1285 ArrayList<AttachmentPoint> freeAPsOnParent =
1286 new ArrayList<AttachmentPoint>();
1287 // vertex.getAPsFromChilddren(); //No, because it enter templates
1288 Map<AttachmentPoint,AttachmentPoint> apOnOldToNeedyAP =
1289 new HashMap<AttachmentPoint,AttachmentPoint>();
1290 for (AttachmentPoint apOnOld : vertex.getAttachmentPoints())
1291 {
1292 if (!apOnOld.isAvailableThroughout())
1293 {
1294 if (apOnOld.isSrcInUserThroughout())
1295 {
1296 // Links that depart from vertex
1297 AttachmentPoint needyAP =
1298 apOnOld.getLinkedAPThroughout();
1299 // NB: here do not use getSrcThroughout because it would
1300 // enter trg templates rather than staying on their surface.
1301 needyAPsOnChildren.add(needyAP);
1302 apOnOldToNeedyAP.put(apOnOld, needyAP);
1303 } else {
1304 AttachmentPoint apOnParent =
1305 apOnOld.getLinkedAPThroughout();
1306 // NB: here do not use getSrcThroughout because it would
1307 // enter src templates rather than staying on their surface.
1308 freeAPsOnParent.add(apOnParent);
1309 freeAPsOnParent.addAll(apOnParent.getOwner()
1311 }
1312 }
1313 }
1314
1315 // Get all possible parentAPs-childAPs mappings
1316 List<APMapping> mappings = fragSpace.mapAPClassCompatibilities(
1317 freeAPsOnParent, needyAPsOnChildren, 500);
1318 if (mappings.size() == 0)
1319 {
1320 // No APClass-compatible possibility of removing the link.
1321 return false;
1322 }
1323
1324 // Score mapping to prioritise those that preserve rings.
1325 // This to differentiate from the combination of DELETE+EXTEND operation
1326 // which cannot preserve rings.
1327 List<Integer> preferences = new ArrayList<Integer>();
1328 // Score rings in this level's graph
1329 for (int i=0; i<needyAPsOnChildren.size(); i++)
1330 {
1331 AttachmentPoint needyAP = needyAPsOnChildren.get(i);
1332 preferences.add(0);
1333
1334 Vertex ownerOfNeedy = needyAP.getOwner();
1335 for (Ring r : ownerOfNeedy.getGraphOwner()
1336 .getRingsInvolvingVertex(ownerOfNeedy))
1337 {
1338 // NB: here we stay at the level of the graph owning ownerOfNeedy
1339 Vertex lastBeforeOwnerOfNeedy =
1340 needyAP.getLinkedAP().getOwner();
1341 if (r.contains(lastBeforeOwnerOfNeedy))
1342 {
1343 preferences.set(i, preferences.get(i) + 1);
1344 }
1345 }
1346 }
1347
1348 // Choose best scoring mapping
1349 int maxScore = Integer.MIN_VALUE;
1350 APMapping bestScoringMapping = null;
1351 for (APMapping apm : mappings)
1352 {
1353 int score = 0;
1354 for (AttachmentPoint ap : apm.values())
1355 {
1356 score = score + preferences.get(needyAPsOnChildren.indexOf(ap));
1357 }
1358 if (score > maxScore)
1359 {
1360 maxScore = score;
1361 bestScoringMapping = apm;
1362 }
1363 }
1364
1365 APMapping bestScoringMappingReverse = new APMapping();
1366 for (Entry<AttachmentPoint, AttachmentPoint> e :
1367 bestScoringMapping.entrySet())
1368 {
1369 bestScoringMappingReverse.put(e.getValue(), e.getKey());
1370 }
1371
1372 // Update rings involving vertex directly (i.e., in this graph)
1373 ArrayList<Ring> rToEdit = getRingsInvolvingVertex(vertex);
1374 ArrayList<Ring> ringsToRemove = new ArrayList<Ring>();
1375 for (Ring r : rToEdit)
1376 {
1377 r.removeVertex(vertex);
1378 if (r.getSize() < 3)
1379 ringsToRemove.add(r);
1380 }
1381 for (Ring r : ringsToRemove)
1382 {
1383 removeRing(r);
1384 }
1385
1386 // Remove edges to/from old vertex, while keeping track of edits to do
1387 // in a hypothetical jacket template (if such template exists)
1388 LinkedHashMap<AttachmentPoint,AttachmentPoint> newInReplaceOldInInTmpl =
1389 new LinkedHashMap<AttachmentPoint,AttachmentPoint>();
1390 List<AttachmentPoint> oldAPToRemoveFromTmpl =
1391 new ArrayList<AttachmentPoint>();
1392 for (AttachmentPoint oldAP : vertex.getAttachmentPoints())
1393 {
1394 if (oldAP.isAvailable())
1395 {
1396 // NB: if this graph is embedded in a template, free/available
1397 // APs at this level (and sources at the vertex we are removing)
1398 // are mapped on the jacket templates' surface, and must be
1399 // removed.
1400 if (templateJacket!=null)
1401 {
1402 if (!oldAP.isAvailableThroughout())
1403 {
1404 AttachmentPoint lAP =
1405 oldAP.getLinkedAPThroughout();
1406 if (bestScoringMapping.keySet().contains(lAP))
1407 {
1408 newInReplaceOldInInTmpl.put(
1409 bestScoringMapping.get(lAP), oldAP);
1410 } else if (bestScoringMapping.values().contains(lAP))
1411 {
1412 newInReplaceOldInInTmpl.put(
1413 bestScoringMappingReverse.get(lAP), oldAP);
1414 } else {
1415 oldAPToRemoveFromTmpl.add(oldAP);
1416 }
1417 } else {
1418 oldAPToRemoveFromTmpl.add(oldAP);
1419 }
1420 }
1421 } else {
1422 removeEdge(oldAP.getEdgeUser());
1423 }
1424 }
1425
1426 // Update pointers in symmetric sets in this graph level
1427 // NB: this deals only with the symmetric relations of the removed vertex
1428 // The symm. relations of other removed child vertices are dealt with
1429 // when removing those vertices.
1430 List<SymmetricVertexes> ssToRemove = new ArrayList<SymmetricVertexes>();
1431 Iterator<SymmetricVertexes> ssIter = getSymSetsIterator();
1432 while (ssIter.hasNext())
1433 {
1434 SymmetricVertexes ss = ssIter.next();
1435 if (ss.contains(vertex))
1436 {
1437 ss.remove(vertex);
1438 }
1439 if (ss.size() < 2)
1440 ssToRemove.add(ss);
1441 }
1442 symVertices.removeAll(ssToRemove);
1443
1444 // Remove the vertex
1445 getVertexList().remove(vertex);
1446 vertex.resetGraphOwner();
1447
1448 // Add new edges (within the graph owning the removed vertex)
1449 List<AttachmentPoint> reconnettedApsOnChilds =
1450 new ArrayList<AttachmentPoint>();
1451 for (Entry<AttachmentPoint,AttachmentPoint> e :
1452 bestScoringMapping.entrySet())
1453 {
1454 AttachmentPoint apOnParent = e.getKey();
1455 AttachmentPoint apOnChild = e.getValue();
1456 if (containsVertex(apOnChild.getOwner())
1457 && containsVertex(apOnParent.getOwner()))
1458 {
1459 Edge edge = new Edge(apOnParent,apOnChild,
1460 apOnParent.getAPClass().getBondType());
1461 addEdge(edge);
1462 reconnettedApsOnChilds.add(apOnChild);
1463 } else {
1464 if (templateJacket!=null)
1465 {
1466 if (containsVertex(apOnParent.getOwner()))
1467 {
1469 newInReplaceOldInInTmpl.get(apOnParent), //AP on old vertex
1470 apOnParent);
1471 reconnettedApsOnChilds.add(apOnChild);
1472 }
1473 if (containsVertex(apOnChild.getOwner()))
1474 {
1476 newInReplaceOldInInTmpl.get(apOnChild), //AP on old vertex
1477 apOnChild);
1478 reconnettedApsOnChilds.add(apOnChild);
1479 }
1480 // The case where neither is contained in 'this' cannot
1481 // occur because of the initial checks that identify
1482 // attempts to remove the only vertex inside a template.
1483 } else {
1484 DENOPTIMException de = new DENOPTIMException("AP '"
1485 + apOnChild + "' seems connected to a template, "
1486 + "no template was found. Possible bug!");
1487 throw de;
1488 }
1489 }
1490 }
1491
1492 // update the mapping of this vertex's APs in the jacket template
1493 if (templateJacket!=null)
1494 {
1495 // Remove all APs that existed only in the old vertex
1496 for (AttachmentPoint apOnOld : oldAPToRemoveFromTmpl)
1497 {
1499 }
1500 }
1501
1502 // Remove branches of child-APs that were not mapped/done
1503 for (AttachmentPoint apOnChild : needyAPsOnChildren)
1504 {
1505 if (!reconnettedApsOnChilds.contains(apOnChild))
1506 {
1507 removeOrphanBranchStartingAt(apOnChild.getOwner());
1508 }
1509 }
1510
1511 jGraph = null;
1512 jGraphKernel = null;
1513
1514 return !this.containsVertex(vertex);
1515 }
1516
1517//------------------------------------------------------------------------------
1518
1527 throws DENOPTIMException
1528 {
1529 List<Vertex> rcvToReplace = new ArrayList<Vertex>();
1530 List<AttachmentPoint> apToCap = new ArrayList<AttachmentPoint>();
1531 for (Vertex v : getRCVertices())
1532 {
1533 if (getRingsInvolvingVertex(v).size()==0
1534 && v.getEdgeToParent()!=null)
1535 {
1536 rcvToReplace.add(v);
1537 apToCap.add(v.getEdgeToParent().getSrcAP());
1538 }
1539 }
1540 for (int i=0; i<rcvToReplace.size(); i++)
1541 {
1542 Vertex v = rcvToReplace.get(i);
1543 removeVertex(v);
1544
1545 AttachmentPoint apOnParent = apToCap.get(i);
1546 APClass cappAPClass = fragSpace.getAPClassOfCappingVertex(
1547 apOnParent.getAPClass());
1548
1549 if (cappAPClass != null)
1550 {
1551 Vertex capVrt = fragSpace.getCappingVertexWithAPClass(
1552 cappAPClass);
1553 capVrt.setVertexId(v.getVertexId());
1554 appendVertexOnAP(apOnParent, capVrt.getAP(0));
1555 }
1556 }
1557 }
1558
1559//------------------------------------------------------------------------------
1560
1569 {
1570 //Remove previous labeling
1571 for (Vertex v : gVertices)
1572 v.removeProperty(DENOPTIMConstants.VRTSYMMSETID);
1573
1574 Iterator<SymmetricVertexes> ssIter = getSymSetsIterator();
1575 int i = 0;
1576 while (ssIter.hasNext())
1577 {
1578 SymmetricVertexes ss = ssIter.next();
1579 String symmLabel = ss.hashCode() + "-" + i;
1580 for (Vertex v : ss)
1581 {
1582 v.setProperty(DENOPTIMConstants.VRTSYMMSETID, symmLabel);
1583 }
1584 i++;
1585 }
1586 for (Vertex v : gVertices)
1587 {
1588 i++;
1589 if (!v.hasProperty(DENOPTIMConstants.VRTSYMMSETID))
1590 v.setProperty(DENOPTIMConstants.VRTSYMMSETID, v.hashCode()+"-"+i);
1591 }
1592 }
1593
1594//------------------------------------------------------------------------------
1595
1601 {
1602 Map<String,List<Vertex>> collectedLabels = new HashMap<>();
1603 for (Vertex v : gVertices)
1604 {
1605 if (v.hasProperty(DENOPTIMConstants.VRTSYMMSETID))
1606 {
1607 String label = v.getProperty(
1608 DENOPTIMConstants.VRTSYMMSETID).toString();
1609 if (collectedLabels.containsKey(label))
1610 {
1611 collectedLabels.get(label).add(v);
1612 } else {
1613 List<Vertex> lst = new ArrayList<Vertex>();
1614 lst.add(v);
1615 collectedLabels.put(label, lst);
1616 }
1617 v.removeProperty(DENOPTIMConstants.VRTSYMMSETID);
1618 }
1619 }
1620
1621 for (String label : collectedLabels.keySet())
1622 {
1623 List<Vertex> symmvertices = collectedLabels.get(label);
1624
1625 if (symmvertices.size()>1)
1626 {
1627 SymmetricVertexes ss = null;
1628 for (Vertex v : symmvertices)
1629 {
1631 {
1632 ss = getSymSetForVertex(v);
1633 break;
1634 }
1635 }
1636
1637 if (ss != null)
1638 {
1639 for (Vertex v : symmvertices)
1640 ss.add(v);
1641
1642 } else {
1643 ss = new SymmetricVertexes();
1644 for (Vertex v : symmvertices)
1645 ss.add(v);
1646 try
1647 {
1649 } catch (DENOPTIMException e)
1650 {
1651 //this can never happen because we are testing for
1652 // preliminary existence of an id in the existing sets.
1653 }
1654 }
1655 }
1656 }
1657 }
1658
1659//------------------------------------------------------------------------------
1660
1680 public boolean replaceSubGraph(List<Vertex> subGrpVrtxs,
1681 DGraph incomingGraph,
1682 LinkedHashMap<AttachmentPoint,AttachmentPoint> apMap,
1683 FragmentSpace fragSpace) throws DENOPTIMException
1684 {
1685 for (Vertex vToRemove : subGrpVrtxs)
1686 {
1687 if (!gVertices.contains(vToRemove))
1688 {
1689 return false;
1690 }
1691 }
1692
1693 // Capping groups are removed and, if needed, re-added back
1694 subGrpVrtxs.stream().filter(v -> v.getBuildingBlockType()==BBType.CAP)
1695 .forEach(v -> this.removeVertex(v));
1696 subGrpVrtxs.removeIf(v -> v.getBuildingBlockType()==BBType.CAP);
1697 if (subGrpVrtxs.size() == 0)
1698 {
1699 throw new DENOPTIMException("Capping groups cannot be the only "
1700 + "vertex in a subgraph to replace.");
1701 }
1702
1703 // Refresh the symmetry set labels so that clones of the branch inherit
1704 // the same symmetry set labels.
1705 incomingGraph.reassignSymmetricLabels();
1706
1708
1709 // Verify that also the surrounding of vertices in the lists is
1710 // consistent between subGrpVrtxs and verticesToRemove. Even if the
1711 // two are consistent, there can still be differences in the childs.
1712 List<List<Vertex>> compatibleSymSubGrps = new ArrayList<List<Vertex>>();
1713 for (List<Vertex> symmetricSubGrpVrtx : getSymmetricSubGraphs(subGrpVrtxs))
1714 {
1715 boolean skip = false;
1716 for (int iv=0; iv<subGrpVrtxs.size(); iv++)
1717 {
1718 if (skip)
1719 break;
1720 Vertex oriVs = subGrpVrtxs.get(iv);
1721 Vertex symVs = symmetricSubGrpVrtx.get(iv);
1722 List<Vertex> oriVsChildren = oriVs.getChilddren();
1723 List<Vertex> symVsChildren = symVs.getChilddren();
1724
1725 // NB: oriVsChildren does not include CAPs from the
1726 // initial subgraph, while symVsChildren does include the
1727 // corresponding CAPs.
1728 oriVsChildren.removeIf(v -> v.getBuildingBlockType()==BBType.CAP);
1729 symVsChildren.removeIf(v -> v.getBuildingBlockType()==BBType.CAP);
1730 if (oriVsChildren.size()!=symVsChildren.size())
1731 {
1732 // we continue in the outer loop
1733 skip = true;
1734 continue;
1735 }
1736 for (int ic=0; ic<oriVsChildren.size(); ic++)
1737 {
1738 if (skip)
1739 break;
1740 // We have already checked those in the subgraph
1741 if (subGrpVrtxs.contains(oriVsChildren.get(ic)))
1742 continue;
1743 // We do allow the two child to be different vertices, but
1744 // we avoid having one CAP and one not. this because it will
1745 // lead to having free APs on the parent of the first and
1746 // busy APs on the parent of the second. This prevents
1747 // finding a mapping of the free APs.
1748 if (oriVsChildren.get(ic).getBuildingBlockType()
1749 != symVsChildren.get(ic).getBuildingBlockType())
1750 {
1751 skip = true;
1752 continue;
1753 }
1754 }
1755 }
1756 if (!skip)
1757 compatibleSymSubGrps.add(symmetricSubGrpVrtx);
1758 }
1759 if (compatibleSymSubGrps.size()==0)
1760 throw new DENOPTIMException("Failed to detect autosymmetry.");
1761
1762 for (List<Vertex> verticesToRemove : compatibleSymSubGrps)
1763 {
1764 // Prepare incoming graph
1765 DGraph graphToAdd = incomingGraph.clone();
1766 graphToAdd.renumberGraphVertices();
1767 List<Vertex> vertexAddedToThis = new ArrayList<Vertex>(
1768 graphToAdd.gVertices);
1769
1770 // Prepare subgraph (it already does not contain caps)
1771 removeCappingGroupsFromChilds(verticesToRemove);
1772
1773 // Prepare AP mapping projecting the one for subGrpVrtxs
1774 LinkedHashMap<AttachmentPoint,AttachmentPoint> localApMap =
1775 new LinkedHashMap<AttachmentPoint,AttachmentPoint>();
1776 for (Map.Entry<AttachmentPoint,AttachmentPoint> e : apMap.entrySet())
1777 {
1778 // WARNING! Assumption that subGrpVrtxs and verticesToRemove
1779 // are sorted accordingly to symmetry, which should be the case.
1780 int vrtPosOnOld = subGrpVrtxs.indexOf(e.getKey().getOwner());
1781 int apPosOnOld = e.getKey().getIndexInOwner();
1782 AttachmentPoint apOnOld = verticesToRemove.get(
1783 vrtPosOnOld).getAP(apPosOnOld);
1784
1785 int vrtPosOnNew = incomingGraph.indexOf(e.getValue().getOwner());
1786 int apPosOnNew = e.getValue().getIndexInOwner();
1787 AttachmentPoint apOnNew = graphToAdd.getVertexAtPosition(
1788 vrtPosOnNew).getAP(apPosOnNew);
1789 localApMap.put(apOnOld,apOnNew);
1790 }
1791
1792 if (!replaceSingleSubGraph(verticesToRemove, graphToAdd, localApMap))
1793 {
1794 return false;
1795 }
1796 addCappingGroups(vertexAddedToThis, fragSpace);
1797 }
1799 return true;
1800 }
1801
1802//------------------------------------------------------------------------------
1803
1816 public List<List<Vertex>> getSymmetricSubGraphs(
1817 List<Vertex> subGrpVrtxs) throws DENOPTIMException
1818 {
1819 if (subGrpVrtxs.stream().anyMatch(v -> v.getBuildingBlockType()==BBType.CAP))
1820 throw new DENOPTIMException("Capping groups must not be part of "
1821 + "symmetric subgraphs");
1822
1823 List<List<Vertex>> symSites = new ArrayList<List<Vertex>>();
1824
1825 if (subGrpVrtxs.size()==1)
1826 {
1827 for (Vertex sv : getSymVerticesForVertex(subGrpVrtxs.get(0)))
1828 {
1829 ArrayList<Vertex> lst = new ArrayList<Vertex>();
1830 lst.add(sv);
1831 symSites.add(lst);
1832 }
1833 if (symSites.size()==0)
1834 {
1835 symSites.add(subGrpVrtxs);
1836 }
1837 return symSites;
1838 }
1839
1840 // Identify the (sole) grand parent.
1841 List<Vertex> thoseWithoutParent = new ArrayList<Vertex>();
1842 for (Vertex v : subGrpVrtxs)
1843 {
1844 if (!subGrpVrtxs.contains(v.getParent()))
1845 thoseWithoutParent.add(v);
1846 }
1847 if (thoseWithoutParent.size()!=1)
1848 {
1849 throw new DENOPTIMException("SubGraph has more than one grand "
1850 + "parent.");
1851 }
1852 Vertex sourceOfSubGraph = thoseWithoutParent.get(0);
1853 int numSymmetricSubGraphs = getSymVerticesForVertex(sourceOfSubGraph).size();
1854 if (numSymmetricSubGraphs==0)
1855 {
1856 symSites.add(subGrpVrtxs);
1857 return symSites;
1858 }
1859
1860 // Identify the ends of the subgraph's spanning tree
1861 List<Vertex> thoseWithoutChildren = new ArrayList<Vertex>();
1862 for (Vertex v : subGrpVrtxs)
1863 {
1864 if (Collections.disjoint(v.getChilddren(),subGrpVrtxs))
1865 thoseWithoutChildren.add(v);
1866 }
1867
1868 // We want to verify that all the ends of the subgraph's spanning tree
1869 // have the same number of symmetric partners. This, while collecting
1870 // all ends that are outside the subgraph and are symmetric to any of
1871 // the ends belonging to the subgraph. The first, in fact, are the ends
1872 // of the symmetric subgraphs.
1873 Set<Vertex> upperLimits = new HashSet<Vertex>();
1874 Set<Vertex> doneBySymmetry = new HashSet<Vertex>();
1875 for (Vertex upperLimit : thoseWithoutChildren)
1876 {
1877 // We need to understand how many symmetric vertices are already
1878 // within the subgraph
1879 int numInSubGraphReplicas = 1;
1880
1881 if (doneBySymmetry.contains(upperLimit))
1882 continue;
1883
1884 // These are symmetric vertices that do belong to the subgraph
1885 Set<Vertex> symmSitesOnBranch = new HashSet<Vertex>(
1886 getSymVerticesForVertex(upperLimit));
1887 symmSitesOnBranch.retainAll(subGrpVrtxs);
1888 if (symmSitesOnBranch.size()>0)
1889 {
1890 numInSubGraphReplicas = symmSitesOnBranch.size();
1891 doneBySymmetry.addAll(symmSitesOnBranch);
1892 }
1893
1894 List<Vertex> lst = getSymVerticesForVertex(upperLimit);
1895 if (lst.size() != numInSubGraphReplicas*numSymmetricSubGraphs)
1896 {
1897 // The subgraph is not symmetrically reproduced.
1898 symSites.add(subGrpVrtxs);
1899 return symSites;
1900 }
1901 upperLimits.addAll(lst);
1902 }
1903
1904 for (Vertex symSources : getSymVerticesForVertex(sourceOfSubGraph))
1905 {
1906 List<Vertex> symSubGraph = new ArrayList<Vertex>();
1907 // The source of the symmetric subgraph is always the first!
1908 symSubGraph.add(symSources);
1909 getChildTreeLimited(symSources, symSubGraph, upperLimits);
1910 //NB: Capping groups are not supposed to be in the list.
1911 symSubGraph.removeIf(v -> v.getBuildingBlockType()==BBType.CAP);
1912 if (symSubGraph.size()!=subGrpVrtxs.size())
1913 {
1914 symSites = new ArrayList<List<Vertex>>();
1915 symSites.add(subGrpVrtxs);
1916 return symSites;
1917 }
1918 symSites.add(symSubGraph);
1919 }
1920
1921 return symSites;
1922 }
1923
1924//------------------------------------------------------------------------------
1925
1954 public boolean replaceSingleSubGraph(List<Vertex> subGrpVrtxs,
1955 DGraph newSubGraph,
1956 LinkedHashMap<AttachmentPoint,AttachmentPoint> apMap)
1957 throws DENOPTIMException
1958 {
1959 if (!gVertices.containsAll(subGrpVrtxs)
1960 || gVertices.contains(newSubGraph.getVertexAtPosition(0)))
1961 {
1962 return false;
1963 }
1964
1965 // Identify vertex that will be added
1966 ArrayList<Vertex> newvertices = new ArrayList<Vertex>();
1967 newvertices.addAll(newSubGraph.getVertexList());
1968
1969 // Collect APs from the vertices that will be removed, and that might
1970 // be reflected onto the jacket template or used to make links to the
1971 // rest of the graph.
1972 List<AttachmentPoint> interfaceApsOnOldBranch =
1973 new ArrayList<AttachmentPoint>();
1974 for (Vertex vToDel : subGrpVrtxs)
1975 {
1976 for (AttachmentPoint ap : vToDel.getAttachmentPoints())
1977 {
1978 if (ap.isAvailable())
1979 {
1980 // being available, this AP might be reflected onto
1981 // jacket template
1982 interfaceApsOnOldBranch.add(ap);
1983 } else {
1984 Vertex user = ap.getLinkedAP().getOwner();
1985 if (!subGrpVrtxs.contains(user))
1986 {
1987 interfaceApsOnOldBranch.add(ap);
1988 }
1989 }
1990 }
1991 }
1992
1993 List<AttachmentPoint> interfaceApsOnNewBranch =
1994 new ArrayList<AttachmentPoint>();
1995 for (Vertex v : newSubGraph.getVertexList())
1996 {
1997 for (AttachmentPoint ap : v.getAttachmentPoints())
1998 {
1999 if (ap.isAvailable())
2000 {
2001 // being available, this AP will have to be reflected onto
2002 // jacket template
2003 interfaceApsOnNewBranch.add(ap);
2004 }
2005 }
2006 }
2007
2008 // Keep track of the links that will be broken and re-created,
2009 // and also of the relation free APs may have with a possible template
2010 // that embeds this graph.
2011 LinkedHashMap<AttachmentPoint,AttachmentPoint>
2012 linksToRecreate = new LinkedHashMap<>();
2013 LinkedHashMap<AttachmentPoint,BondType>
2014 linkTypesToRecreate = new LinkedHashMap<>();
2015 LinkedHashMap<AttachmentPoint,AttachmentPoint>
2016 inToOutAPForTemplate = new LinkedHashMap<>();
2017 List<AttachmentPoint> oldAPToRemoveFromTmpl = new ArrayList<>();
2018 AttachmentPoint trgAPOnNewLink = null;
2019 for (AttachmentPoint oldAP : interfaceApsOnOldBranch)
2020 {
2021 if (oldAP.isAvailable())
2022 {
2023 // NB: if this graph is embedded in a template, free/available
2024 // APs at this level (and from the old link)
2025 // are mapped on the templates' surface
2026 if (templateJacket!=null)
2027 {
2028 if (oldAP.isAvailableThroughout())
2029 {
2030 if (!apMap.containsKey(oldAP))
2031 {
2032 // An AP of the old link is going to be removed from the
2033 // template-jacket's list of APs
2034 oldAPToRemoveFromTmpl.add(oldAP);
2035 } else {
2036 // This AP is not used, not even outside of the template
2037 // but for some reason the apMapping wants to keep it
2038 inToOutAPForTemplate.put(apMap.get(oldAP),oldAP);
2039 }
2040 } else {
2041 if (!apMap.containsKey(oldAP))
2042 {
2043 throw new DENOPTIMException("Cannot replace subgraph "
2044 + "if a used AP has no mapping.");
2045 } else {
2046 // This AP is not used, not even outside of the template
2047 // but for some reason the apMapping wants to keep it
2048 inToOutAPForTemplate.put(apMap.get(oldAP),oldAP);
2049 }
2050 }
2051 }
2052 continue;
2053 }
2054
2055 if (!apMap.containsKey(oldAP))
2056 {
2057 throw new DENOPTIMException("Cannot replace subgraph if a used "
2058 + "AP has no mapping. Missing mapping for AP "
2059 + oldAP.getIndexInOwner() + " in "
2060 + oldAP.getOwner().getVertexId());
2061 }
2062 AttachmentPoint newAP = apMap.get(oldAP);
2063 linksToRecreate.put(newAP, oldAP.getLinkedAP());
2064 linkTypesToRecreate.put(newAP, oldAP.getEdgeUser().getBondType());
2065
2066 // This is were we identify the edge/ap to the parent of the oldLink
2067 if (!oldAP.isSrcInUser())
2068 {
2069 trgAPOnNewLink = newAP;
2070 }
2071 }
2072
2073 // Identify rings that are affected by the change of vertices
2074 Map<Ring,List<Vertex>> ringsOverSubGraph =
2075 new HashMap<Ring,List<Vertex>>();
2076 for (int iA=0; iA<interfaceApsOnOldBranch.size(); iA++)
2077 {
2078 AttachmentPoint apA = interfaceApsOnOldBranch.get(iA);
2079
2080 if (apA.isAvailable())
2081 continue;
2082
2083 for (int iB=(iA+1); iB<interfaceApsOnOldBranch.size(); iB++)
2084 {
2085 AttachmentPoint apB = interfaceApsOnOldBranch.get(iB);
2086
2087 if (apB.isAvailable())
2088 continue;
2089
2090 Vertex vLinkedOnA = apA.getLinkedAP().getOwner();
2091 Vertex vLinkedOnB = apB.getLinkedAP().getOwner();
2093 new Vertex[] {
2094 apA.getOwner(), vLinkedOnA,
2095 apB.getOwner(), vLinkedOnB}))
2096 {
2097 List<Vertex> vPair = new ArrayList<Vertex>();
2098 vPair.add(r.getCloserToHead(vLinkedOnA, vLinkedOnB));
2099 vPair.add(r.getCloserToTail(vLinkedOnA, vLinkedOnB));
2100 ringsOverSubGraph.put(r, vPair);
2101 }
2102 }
2103 }
2104
2105 // remove the vertex-to-delete from the rings where they participate
2106 for (Ring r : ringsOverSubGraph.keySet())
2107 {
2108 List<Vertex> vPair = ringsOverSubGraph.get(r);
2109 PathSubGraph path = new PathSubGraph(vPair.get(0),vPair.get(1),this);
2110 List<Vertex> verticesInPath = path.getVertecesPath();
2111 for (int i=1; i<(verticesInPath.size()-1); i++)
2112 {
2113 r.removeVertex(verticesInPath.get(i));
2114 }
2115 }
2116
2117 // remove edges with old vertex
2118 for (AttachmentPoint oldAP : interfaceApsOnOldBranch)
2119 {
2120 if (!oldAP.isAvailable())
2121 removeEdge(oldAP.getEdgeUser());
2122 }
2123
2124 // remove the vertex from the graph
2125 for (Vertex vToDel : subGrpVrtxs)
2126 {
2127 // WARNING! This removes rings involving these vertices.
2128 removeVertex(vToDel);
2129 }
2130
2131 // finally introduce the new vertices from incoming graph into this graph
2132 for (Vertex incomingVrtx : newSubGraph.getVertexList())
2133 {
2134 addVertex(incomingVrtx);
2135 }
2136
2137 // import edges from incoming graph
2138 for (Edge incomingEdge : newSubGraph.getEdgeList())
2139 {
2140 addEdge(incomingEdge);
2141 }
2142
2143 // import rings from incoming graph
2144 for (Ring incomingRing : newSubGraph.getRings())
2145 {
2146 addRing(incomingRing);
2147 }
2148
2149 // import symmetric sets from incoming graph? No, this method doesn't do
2150 // it because we want to use it in situations where we have to perform
2151 // multiple replaceSubGraph operations and, afterwards, use the
2152 // symmetric labels to create symmetric sets that might span across
2153 // more than one of the subgraphs that were added.
2154
2155 // We keep track of the APs on the new link that have been dealt with
2156 List<AttachmentPoint> doneApsOnNew =
2157 new ArrayList<AttachmentPoint>();
2158
2159 // Connect the incoming subgraph to the rest of the graph
2160 if (trgAPOnNewLink != null)
2161 {
2162 // the incoming graph has a parent vertex, and the edge should be
2163 // directed accordingly
2164 Edge edge = new Edge(
2165 linksToRecreate.get(trgAPOnNewLink),
2166 trgAPOnNewLink,
2167 linkTypesToRecreate.get(trgAPOnNewLink));
2168 addEdge(edge);
2169 doneApsOnNew.add(trgAPOnNewLink);
2170 } else {
2171 // newLink does NOT have a parent vertex, so all the
2172 // edges see newLink as target vertex. Such links are dealt with
2173 // in the loop below. So, there is nothing special to do, here.
2174 }
2175 for (AttachmentPoint apOnNew : linksToRecreate.keySet())
2176 {
2177 if (apOnNew == trgAPOnNewLink)
2178 {
2179 continue; //done just before this loop
2180 }
2181 AttachmentPoint trgOnChild = linksToRecreate.get(apOnNew);
2182 Edge edge = new Edge(apOnNew,trgOnChild,
2183 linkTypesToRecreate.get(apOnNew));
2184 addEdge(edge);
2185 doneApsOnNew.add(apOnNew);
2186 }
2187
2188 // redefine rings that spanned over the removed subgraph
2189 for (Ring r : ringsOverSubGraph.keySet())
2190 {
2191 List<Vertex> vPair = ringsOverSubGraph.get(r);
2192 PathSubGraph path = new PathSubGraph(vPair.get(0),vPair.get(1),this);
2193 int initialInsertPoint = r.getPositionOf(vPair.get(0));
2194 List<Vertex> verticesInPath = path.getVertecesPath();
2195 for (int i=1; i<(verticesInPath.size()-1); i++)
2196 {
2197 r.insertVertex(initialInsertPoint+i, verticesInPath.get(i));
2198 }
2199 }
2200
2201 // update the mapping of this vertices' APs in the jacket template
2202 if (templateJacket != null)
2203 {
2205 for (AttachmentPoint apOnNew : inToOutAPForTemplate.keySet())
2206 {
2208 inToOutAPForTemplate.get(apOnNew),apOnNew);
2209 doneApsOnNew.add(apOnNew);
2210 }
2211
2212 // Project all remaining APs of new branch on the surface of template
2213 for (AttachmentPoint apOnNew : interfaceApsOnNewBranch)
2214 {
2215 if (!doneApsOnNew.contains(apOnNew))
2216 {
2218 }
2219 }
2220
2221 // Remove all APs that existed only in the old branch
2222 for (AttachmentPoint apOnOld : oldAPToRemoveFromTmpl)
2223 {
2225 }
2226 }
2227
2228 jGraph = null;
2229 jGraphKernel = null;
2230
2231 for (Vertex vOld : subGrpVrtxs)
2232 if (this.containsVertex(vOld))
2233 return false;
2234 for (Vertex vNew : newvertices)
2235 if (!this.containsVertex(vNew))
2236 return false;
2237 return true;
2238 }
2239
2240//------------------------------------------------------------------------------
2241
2258 public boolean replaceVertex(Vertex vertex, int bbId, BBType bbt,
2259 LinkedHashMap<Integer, Integer> apIdMap, FragmentSpace fragSpace)
2260 throws DENOPTIMException
2261 {
2262 return replaceVertex(vertex, bbId, bbt, apIdMap, true, fragSpace);
2263 }
2264
2265//------------------------------------------------------------------------------
2266
2282 public boolean replaceVertex(Vertex vertex, int bbId, BBType bbt,
2283 LinkedHashMap<Integer, Integer> apIdMap, boolean symmetry,
2284 FragmentSpace fragSpace)
2285 throws DENOPTIMException
2286 {
2287 if (!gVertices.contains(vertex))
2288 {
2289 return false;
2290 }
2291
2292 List<Vertex> symSites = new ArrayList<Vertex>();
2293 if (symmetry)
2294 {
2295 symSites = getSymVerticesForVertex(vertex);
2296 }
2297 if (symSites.size() == 0)
2298 {
2299 symSites.add(vertex);
2300 }
2301
2304 GraphUtils.getUniqueVertexIndex(), bbId, bbt, fragSpace);
2305 DGraph incomingGraph = new DGraph();
2306 incomingGraph.addVertex(newLink);
2307 incomingGraph.reassignSymmetricLabels();
2308
2309 for (Vertex oldLink : symSites)
2310 {
2311 DGraph graphAdded = incomingGraph.clone();
2313 oldLink.getUnfilteredMutationTypes());
2314 graphAdded.renumberGraphVertices();
2315
2316 ArrayList<Vertex> oldVertex = new ArrayList<Vertex>();
2317 oldVertex.add(oldLink);
2318 LinkedHashMap<AttachmentPoint,AttachmentPoint> apMap =
2319 new LinkedHashMap<AttachmentPoint,AttachmentPoint>();
2320 for (Map.Entry<Integer,Integer> e : apIdMap.entrySet())
2321 {
2322 apMap.put(oldLink.getAP(e.getKey()),
2323 graphAdded.getVertexAtPosition(0).getAP(e.getValue()));
2324 }
2325
2326 if (!replaceSingleSubGraph(oldVertex, graphAdded, apMap))
2327 {
2328 return false;
2329 }
2330 }
2332 return true;
2333 }
2334
2335//------------------------------------------------------------------------------
2336
2358 //NB: LinkedHashMap is used to retain reproducibility between runs.
2359
2360 public boolean insertVertex(Edge edge, int bbId, BBType bbt,
2361 LinkedHashMap<AttachmentPoint,Integer> apMap,
2362 FragmentSpace fragSpace)
2363 throws DENOPTIMException
2364 {
2365 if (!gEdges.contains(edge))
2366 {
2367 return false;
2368 }
2369
2370 List<Edge> symSites = new ArrayList<Edge> ();
2371 List<LinkedHashMap<AttachmentPoint,Integer>> symApMaps =
2372 new ArrayList<LinkedHashMap<AttachmentPoint,Integer>>();
2373 List<Vertex> symTrgvertices = getSymVerticesForVertex(
2374 edge.getTrgAP().getOwner());
2375 if (symTrgvertices.size() == 0)
2376 {
2377 symSites.add(edge);
2378 symApMaps.add(apMap);
2379 } else {
2380 for (Vertex trgVrtx : symTrgvertices)
2381 {
2382 Edge symEdge = trgVrtx.getEdgeToParent();
2383 symSites.add(symEdge);
2384
2385 LinkedHashMap<AttachmentPoint,Integer> locApMap = new
2386 LinkedHashMap<AttachmentPoint,Integer>();
2387 locApMap.put(symEdge.getSrcAP(), apMap.get(edge.getSrcAP()));
2388 locApMap.put(symEdge.getTrgAP(), apMap.get(edge.getTrgAP()));
2389 symApMaps.add(locApMap);
2390 }
2391 }
2392
2394 for (int i=0; i<symSites.size(); i++)
2395 {
2396 Edge symEdge = symSites.get(i);
2397 LinkedHashMap<AttachmentPoint,Integer> locApMap = symApMaps.get(i);
2398
2401 GraphUtils.getUniqueVertexIndex(), bbId, bbt, fragSpace);
2402 newSS.add(newLink);
2403 LinkedHashMap<AttachmentPoint,AttachmentPoint> apToApMap =
2404 new LinkedHashMap<AttachmentPoint,AttachmentPoint>();
2405 for (AttachmentPoint apOnGraph : locApMap.keySet())
2406 {
2407 apToApMap.put(apOnGraph, newLink.getAP(locApMap.get(apOnGraph)));
2408 }
2409 if (!insertSingleVertex(symEdge, newLink, apToApMap))
2410 {
2411 return false;
2412 }
2413 }
2414 if (newSS.size()>1)
2415 {
2417 }
2418 return true;
2419 }
2420
2421//------------------------------------------------------------------------------
2422
2440 public boolean insertSingleVertex(Edge edge, Vertex newLink,
2441 LinkedHashMap<AttachmentPoint,AttachmentPoint> apMap)
2442 throws DENOPTIMException
2443 {
2444 //TODO: for reproducibility the AP mapping should become an optional
2445 // parameter: if given we try to use it, if not given we GraphLinkFinder
2446 // will try to find a suitable mapping.
2447
2448 if (!gEdges.contains(edge) || gVertices.contains(newLink))
2449 {
2450 return false;
2451 }
2452
2453 // First keep track of the links that will be broken and re-created,
2454 // and also of the relation free APs may have with a possible template
2455 // that embeds this graph.
2456 AttachmentPoint orisEdgeSrc = edge.getSrcAP();
2457 AttachmentPoint orisEdgeTrg = edge.getTrgAP();
2458 Vertex srcVrtx = orisEdgeSrc.getOwner();
2459 Vertex trgVrtx = orisEdgeTrg.getOwner();
2460
2461 removeEdge(edge);
2462
2463 // Introduce the new vertex in the graph
2464 addVertex(newLink);
2465
2466 // Connect the new vertex to the graph
2467 Edge eSrcToLink = new Edge(orisEdgeSrc,
2468 apMap.get(orisEdgeSrc), edge.getBondType());
2469 addEdge(eSrcToLink);
2470 Edge eLinkToTrg = new Edge(apMap.get(orisEdgeTrg),
2471 orisEdgeTrg, edge.getBondType());
2472 addEdge(eLinkToTrg);
2473
2474 // update any affected ring
2475 if (isVertexInRing(srcVrtx) && isVertexInRing(trgVrtx))
2476 {
2477 ArrayList<Ring> rToEdit = new ArrayList<Ring>();
2478 rToEdit.addAll(getRingsInvolvingVertex(srcVrtx));
2479 rToEdit.retainAll(getRingsInvolvingVertex(trgVrtx));
2480 for (Ring r : rToEdit)
2481 {
2482 r.insertVertex(newLink,srcVrtx,trgVrtx);
2483 }
2484 }
2485
2486 // NB: if this graph is embedded in a template, new free/available
2487 // APs introduced with the new link need to be mapped on the surface of
2488 // the template
2489 if (templateJacket != null)
2490 {
2491 for (AttachmentPoint ap : newLink.getAttachmentPoints())
2492 {
2493 if (ap.isAvailable())
2494 {
2496 }
2497 }
2498 }
2499
2500 jGraph = null;
2501 jGraphKernel = null;
2502
2503 return !gEdges.contains(edge) && this.containsVertex(newLink);
2504 }
2505
2506//------------------------------------------------------------------------------
2507
2515 {
2516 return ((pos >= gVertices.size()) || pos < 0) ? null :
2517 gVertices.get(pos);
2518 }
2519
2520//------------------------------------------------------------------------------
2521
2531 {
2532 if (gVertices.contains(v))
2533 return true;
2534
2535 for (Vertex vrt : gVertices)
2536 {
2537 if (vrt instanceof Template)
2538 {
2539 Template t = (Template) vrt;
2541 return true;
2542 }
2543 }
2544 return false;
2545 }
2546
2547
2548//------------------------------------------------------------------------------
2549
2557 public boolean containsVertex(Vertex v)
2558 {
2559 return gVertices.contains(v);
2560 }
2561
2562//------------------------------------------------------------------------------
2563
2569 public int indexOf(Vertex v)
2570 {
2571 return gVertices.indexOf(v);
2572 }
2573
2574//------------------------------------------------------------------------------
2575
2582 public Vertex getVertexWithId(long vid)
2583 {
2584 Vertex v = null;
2585 int idx = indexOfVertexWithID(vid);
2586 if (idx != -1)
2587 v = gVertices.get(idx);
2588 return v;
2589 }
2590
2591//------------------------------------------------------------------------------
2592
2598 public int indexOfVertexWithID(long vid)
2599 {
2600 int idx = -1;
2601 for (int i=0; i<gVertices.size(); i++)
2602 {
2603 Vertex v = gVertices.get(i);
2604 if (v.getVertexId() == vid)
2605 {
2606 idx = i;
2607 break;
2608 }
2609 }
2610 return idx;
2611 }
2612
2613//------------------------------------------------------------------------------
2614
2620 public void removeEdge(Edge edge)
2621 {
2622 if (gEdges.contains(edge))
2623 {
2624 AttachmentPoint srcAP = edge.getSrcAP();
2625 AttachmentPoint trgAP = edge.getTrgAP();
2626 srcAP.setUser(null);
2627 trgAP.setUser(null);
2628
2629 gEdges.remove(edge);
2630 }
2631 jGraph = null;
2632 jGraphKernel = null;
2633 }
2634
2635//------------------------------------------------------------------------------
2636
2637 public void removeRing(Ring ring)
2638 {
2639 if (gRings.contains(ring))
2640 {
2641 gRings.remove(ring);
2642 }
2643 jGraph = null;
2644 jGraphKernel = null;
2645 }
2646
2647//------------------------------------------------------------------------------
2648
2649 public Edge getEdgeAtPosition(int pos)
2650 {
2651 if ((pos >= gEdges.size()) || pos < 0)
2652 return null;
2653 return gEdges.get(pos);
2654 }
2655
2656//------------------------------------------------------------------------------
2657
2658 public int getEdgeCount()
2659 {
2660 return gEdges.size();
2661 }
2662
2663//------------------------------------------------------------------------------
2664
2665 public int getRingCount()
2666 {
2667 return gRings.size();
2668 }
2669
2670//------------------------------------------------------------------------------
2671
2672 public int getVertexCount()
2673 {
2674 return gVertices.size();
2675 }
2676
2677//------------------------------------------------------------------------------
2678
2679 @Override
2680 public String toString()
2681 {
2682 StringBuilder sb = new StringBuilder(512);
2683
2684 sb.append(graphId).append(" ");
2685
2686 for (int i=0; i<gVertices.size(); i++)
2687 {
2688 sb.append(gVertices.get(i).toString()).append(",");
2689 }
2690
2691 sb.append(" ");
2692
2693 for (int i=0; i<gEdges.size(); i++)
2694 {
2695 sb.append(gEdges.get(i).toString()).append(",");
2696 }
2697
2698 sb.append(" ");
2699
2700 for (int i=0; i<gRings.size(); i++)
2701 {
2702 sb.append(gRings.get(i).toString()).append(" ");
2703 }
2704
2705 for (int i=0; i<symVertices.size(); i++)
2706 {
2707 sb.append(symVertices.get(i).toString()).append(" ");
2708 }
2709
2710 return sb.toString();
2711 }
2712
2713//------------------------------------------------------------------------------
2714
2724 @Deprecated
2725 public int getBondingAPIndex(Vertex srcVert, int dapidx,
2726 Vertex dstVert)
2727 {
2728 int n = getEdgeCount();
2729 for (int i = 0; i < n; i++)
2730 {
2731 Edge edge = getEdgeList().get(i);
2732
2733 // get the vertex ids
2734 long v1_id = edge.getSrcVertex();
2735 long v2_id = edge.getTrgVertex();
2736
2737 int dap_idx_v1 = edge.getSrcAPID();
2738
2739 if (srcVert.getVertexId() == v1_id && v2_id == dstVert.getVertexId()
2740 && dap_idx_v1 == dapidx)
2741 {
2742 return edge.getTrgAPID();
2743 }
2744 }
2745
2746 return -1;
2747 }
2748
2749//------------------------------------------------------------------------------
2750
2757 public ArrayList<Vertex> getChildVertices(Vertex vertex)
2758 {
2759 return vertex.getChilddren();
2760 }
2761
2762//------------------------------------------------------------------------------
2763
2771 public void getChildrenTree(Vertex vertex, List<Vertex> children)
2772 {
2773 List<Vertex> lst = getChildVertices(vertex);
2774 if (lst.isEmpty())
2775 {
2776 return;
2777 }
2778 for (Vertex child : lst)
2779 {
2780 if (!children.contains(child))
2781 {
2782 children.add(child);
2783 getChildrenTree(child, children);
2784 }
2785 }
2786 }
2787
2788//------------------------------------------------------------------------------
2789
2804 public void getChildrenTree(Vertex vertex, List<Vertex> children,
2805 boolean markBranches)
2806 {
2807 if (!markBranches)
2808 {
2809 getChildrenTree(vertex, children);
2810 return;
2811 }
2812
2813 AtomicInteger branchIdGenerator = new AtomicInteger(0);
2814 List<Integer> thisBranchId = new ArrayList<Integer>();
2815 thisBranchId.add(branchIdGenerator.getAndIncrement());
2816
2817 vertex.setProperty(DENOPTIMConstants.GRAPHBRANCHID, thisBranchId);
2818
2819 List<Vertex> lst = getChildVertices(vertex);
2820 if (lst.isEmpty())
2821 {
2822 return;
2823 }
2824 for (Vertex child : lst)
2825 {
2826 if (!children.contains(child))
2827 {
2828 children.add(child);
2829 if (lst.size()==1)
2830 {
2831 child.setProperty(DENOPTIMConstants.GRAPHBRANCHID,
2832 thisBranchId);
2833 getChildrenTree(child, children, branchIdGenerator,
2834 thisBranchId);
2835 } else {
2836 List<Integer> newBranchId = new ArrayList<>(thisBranchId);
2837 newBranchId.add(branchIdGenerator.getAndIncrement());
2838 child.setProperty(DENOPTIMConstants.GRAPHBRANCHID,
2839 newBranchId);
2840 getChildrenTree(child, children, branchIdGenerator,
2841 newBranchId);
2842 }
2843 }
2844 }
2845 }
2846
2847//------------------------------------------------------------------------------
2848
2861 public void getChildrenTree(Vertex vertex, List<Vertex> children,
2862 AtomicInteger branchIdGenerator, List<Integer> prevBranchId)
2863 {
2864 List<Vertex> lst = getChildVertices(vertex);
2865 if (lst.isEmpty())
2866 {
2867 return;
2868 }
2869 for (Vertex child : lst)
2870 {
2871 if (!children.contains(child))
2872 {
2873 children.add(child);
2874 if (lst.size()==1)
2875 {
2876 child.setProperty(DENOPTIMConstants.GRAPHBRANCHID,
2877 prevBranchId);
2878 getChildrenTree(child, children, branchIdGenerator,
2879 prevBranchId);
2880 } else {
2881 List<Integer> newBranchId = new ArrayList<>(prevBranchId);
2882 newBranchId.add(branchIdGenerator.getAndIncrement());
2883 child.setProperty(DENOPTIMConstants.GRAPHBRANCHID,
2884 newBranchId);
2885 getChildrenTree(child, children, branchIdGenerator,
2886 newBranchId);
2887 }
2888 }
2889 }
2890 }
2891
2892//------------------------------------------------------------------------------
2893
2906 public void getChildrenTree(Vertex vertex,
2907 List<Vertex> children, int numLayers, boolean stopBeforeRCVs)
2908 {
2909 if (numLayers==0)
2910 {
2911 return;
2912 }
2913 List<Vertex> lst = getChildVertices(vertex);
2914 if (lst.isEmpty())
2915 {
2916 return;
2917 }
2918 for (Vertex child : lst)
2919 {
2920 if (children.contains(child))
2921 continue;
2922
2923 if (stopBeforeRCVs && child.isRCV())
2924 continue;
2925
2926 children.add(child);
2927 getChildrenTree(child, children, numLayers-1, stopBeforeRCVs);
2928 }
2929 }
2930
2931//------------------------------------------------------------------------------
2932
2941 public List<Integer> getBranchIdOfVertexAtPosition(int i)
2942 {
2944 }
2945
2946//------------------------------------------------------------------------------
2947
2957 @SuppressWarnings("unchecked")
2958 public List<Integer> getBranchIdOfVertex(Vertex v)
2959 {
2960 if (!gVertices.contains(v))
2961 return null;
2962
2963 return (List<Integer>) v.getProperty(DENOPTIMConstants.GRAPHBRANCHID);
2964 }
2965
2966//------------------------------------------------------------------------------
2967
2979 {
2980 List<Integer> lst = getBranchIdOfVertex(v);
2981 String s = "";
2982 for (Integer i : lst)
2983 s = s + i + "_";
2984 return s;
2985 }
2986
2987//------------------------------------------------------------------------------
2988
3000 public boolean directedPathExists(Vertex src, Vertex trg)
3001 {
3002 List<Integer> bIdSrc = getBranchIdOfVertex(src);
3003 List<Integer> bIdTrg = getBranchIdOfVertex(trg);
3004 if (bIdSrc==null || bIdTrg==null)
3005 return false;
3006 if (bIdSrc.size()>bIdTrg.size())
3007 return false;
3008 int sharedSubBranches = 0;
3009 for (int i=0; i<bIdSrc.size(); i++)
3010 {
3011 if (bIdSrc.get(i)==bIdTrg.get(i))
3012 sharedSubBranches++;
3013 }
3014 return sharedSubBranches==bIdSrc.size();
3015 }
3016
3017//------------------------------------------------------------------------------
3018
3028 public void getChildTreeLimited(Vertex vertex,
3029 List<Vertex> children, boolean stopBeforeRCVs)
3030 {
3031 List<Vertex> lst = getChildVertices(vertex);
3032 if (lst.isEmpty())
3033 {
3034 return;
3035 }
3036 for (Vertex child : lst)
3037 {
3038 if (children.contains(child))
3039 continue;
3040
3041 if (stopBeforeRCVs && child.isRCV())
3042 continue;
3043
3044 children.add(child);
3045 getChildTreeLimited(child, children, stopBeforeRCVs);
3046 }
3047 }
3048
3049//------------------------------------------------------------------------------
3050
3060 public void getChildTreeLimited(Vertex vertex,
3061 List<Vertex> children, Set<Vertex> limits)
3062 {
3063 List<Vertex> lst = getChildVertices(vertex);
3064 if (lst.isEmpty())
3065 {
3066 return;
3067 }
3068 for (Vertex child : lst)
3069 {
3070 if (!children.contains(child))
3071 {
3072 children.add(child);
3073 if (!limits.contains(child))
3074 getChildTreeLimited(child, children, limits);
3075 }
3076 }
3077 }
3078
3079//------------------------------------------------------------------------------
3080
3092 public void getChildTreeLimited(Vertex vertex,
3093 List<Vertex> children, List<Vertex> limitsInClone,
3094 boolean stopBeforeRCVs)
3095 {
3096 List<Vertex> lst = getChildVertices(vertex);
3097 if (lst.isEmpty())
3098 {
3099 return;
3100 }
3101 for (Vertex child : lst)
3102 {
3103 if (children.contains(child))
3104 continue;
3105
3106 if (stopBeforeRCVs && child.isRCV())
3107 continue;
3108
3109 children.add(child);
3110 if (!limitsInClone.contains(child))
3111 getChildTreeLimited(child, children, limitsInClone, stopBeforeRCVs);
3112 }
3113 }
3114
3115//------------------------------------------------------------------------------
3116
3123 public Vertex getDeepestAmongThese(List<Vertex> list)
3124 {
3125 Vertex deepest = null;
3126 int shortest = Integer.MAX_VALUE;
3127 for (Vertex vertex : list)
3128 {
3129 List<Vertex> parentTree = new ArrayList<Vertex>();
3130 getParentTree(vertex, parentTree);
3131 if (parentTree.size()<shortest)
3132 {
3133 shortest = parentTree.size();
3134 deepest = vertex;
3135 }
3136 }
3137 return deepest;
3138 }
3139
3140//------------------------------------------------------------------------------
3141
3149 public void getParentTree(Vertex vertex,
3150 List<Vertex> parentTree)
3151 {
3152 Vertex parent = getParent(vertex);
3153 if (parent == null)
3154 {
3155 return;
3156 }
3157 if (parentTree.contains(parent))
3158 {
3159 // Cyclic graphs are not allowed!
3160 throw new IllegalArgumentException();
3161 }
3162 parentTree.add(parent);
3163 getParentTree(parent, parentTree);
3164 }
3165
3166//------------------------------------------------------------------------------
3167
3169 {
3170 Edge edge = v.getEdgeToParent();
3171 if (edge != null)
3172 {
3173 return edge.getSrcAP().getOwner();
3174 }
3175 return null;
3176 }
3177
3178//------------------------------------------------------------------------------
3179
3185 @Override
3186 public DGraph clone()
3187 {
3188 // When cloning, the VertexID remains the same so we'll have two
3189 // deep-copies of the same vertex having the same VertexID
3190 ArrayList<Vertex> cListVrtx = new ArrayList<>();
3191 Map<Long, Vertex> vidsInClone = new HashMap<Long, Vertex>();
3192 for (Vertex vOrig : gVertices)
3193 {
3194 Vertex vClone = vOrig.clone();
3195 cListVrtx.add(vClone);
3196 vidsInClone.put(vClone.getVertexId(), vClone);
3197 }
3198
3199 ArrayList<Edge> cListEdges = new ArrayList<>();
3200 for (Edge e : gEdges)
3201 {
3202 long srcVrtxId = e.getSrcVertex();
3203 int srcApId = this.getVertexWithId(srcVrtxId).getIndexOfAP(
3204 e.getSrcAP());
3205
3206 long trgVrtxId = e.getTrgVertex();
3207 int trgApId = this.getVertexWithId(trgVrtxId).getIndexOfAP(
3208 e.getTrgAP());
3209
3210 AttachmentPoint srcAPClone = vidsInClone.get(
3211 srcVrtxId).getAP(srcApId);
3212 AttachmentPoint trgAPClone = vidsInClone.get(
3213 trgVrtxId).getAP(trgApId);
3214
3215 cListEdges.add(new Edge(srcAPClone, trgAPClone,
3216 e.getBondType()));
3217 }
3218
3219 DGraph clone = new DGraph(cListVrtx, cListEdges);
3220
3221 // Copy the list but using the references to the cloned vertices
3222 ArrayList<Ring> cListRings = new ArrayList<>();
3223 for (Ring ring : gRings)
3224 {
3225 Ring cRing = new Ring();
3226 for (int iv=0; iv<ring.getSize(); iv++)
3227 {
3228 Vertex origVrtx = ring.getVertexAtPosition(iv);
3229 cRing.addVertex(
3230 clone.getVertexWithId(origVrtx.getVertexId()));
3231 }
3232 cRing.setBondType(ring.getBondType());
3233 cListRings.add(cRing);
3234 }
3235 clone.setRings(cListRings);
3236
3237 // The chainLinks are made of primitives, so it's just fine
3238 ArrayList<ClosableChain> cListClosableChains =
3239 new ArrayList<>();
3240 for (ClosableChain cc : closableChains)
3241 {
3242 cListClosableChains.add(cc.clone());
3243 }
3244 clone.setCandidateClosableChains(cListClosableChains);
3245
3246
3247 List<SymmetricVertexes> cSymVertices = new ArrayList<>();
3249 {
3250 SymmetricVertexes clonedSS = new SymmetricVertexes();
3251 for (Vertex origVrt : ss)
3252 {
3253 clonedSS.add(clone.gVertices.get(gVertices.indexOf(origVrt)));
3254 }
3255 cSymVertices.add(clonedSS);
3256 }
3257 clone.setSymmetricVertexSets(cSymVertices);
3258
3261
3262 return clone;
3263 }
3264
3265//------------------------------------------------------------------------------
3266
3274 {
3275 Vertex v = getVertexWithId(l);
3276 if (v == null)
3277 {
3278 return null;
3279 }
3280 return v.getEdgeToParent();
3281 }
3282
3283//------------------------------------------------------------------------------
3284
3291 public ArrayList<Integer> getIndexOfEdgesWithChild(int vid)
3292 {
3293 ArrayList<Integer> lstEdges = new ArrayList<>();
3294 for (int j=0; j<getEdgeCount(); j++)
3295 {
3296 Edge edge = getEdgeAtPosition(j);
3297
3298 if (edge.getSrcVertex() == vid)
3299 {
3300 lstEdges.add(j);
3301 }
3302 }
3303 return lstEdges;
3304 }
3305
3306//------------------------------------------------------------------------------
3307
3314 public ArrayList<Edge> getEdgesWithChild(int vid)
3315 {
3316 ArrayList<Edge> lstEdges = new ArrayList<>();
3317 for (int j=0; j<getEdgeCount(); j++)
3318 {
3319 Edge edge = getEdgeAtPosition(j);
3320
3321 if (edge.getSrcVertex() == vid)
3322 {
3323 lstEdges.add(edge);
3324 }
3325 }
3326 return lstEdges;
3327 }
3328
3329//------------------------------------------------------------------------------
3330
3334 public long getMaxVertexId()
3335 {
3336 long mval = Long.MIN_VALUE;
3337 for (Vertex v : gVertices) {
3338 mval = Math.max(mval, v.getVertexId());
3339 }
3340 return mval;
3341 }
3342
3343//------------------------------------------------------------------------------
3344
3349 public boolean containsVertexID(long l)
3350 {
3351 boolean result = false;
3352 for (Vertex v : gVertices)
3353 {
3354 if (l == v.getVertexId())
3355 {
3356 result = true;
3357 break;
3358 }
3359 }
3360 return result;
3361 }
3362
3363//------------------------------------------------------------------------------
3364
3368 public void cleanup()
3369 {
3370 if (gVertices != null)
3371 {
3372 gVertices.clear();
3373 }
3374 if (gEdges != null)
3375 {
3376 gEdges.clear();
3377 }
3378 if (gRings != null)
3379 {
3380 gRings.clear();
3381 }
3382 if (symVertices != null)
3383 {
3384 symVertices.clear();
3385 }
3386 if (closableChains != null)
3387 {
3388 closableChains.clear();
3389 }
3390 jGraph = null;
3391 jGraphKernel = null;
3392 }
3393
3394//------------------------------------------------------------------------------
3395
3396 /*
3397 * NB: this javadoc string is reproduced in the user manual HTML file.
3398 * In case of modifications, please keep the two sources compatible by
3399 * reproducing the modification on both sites.
3400 */
3401
3453 public boolean isIsomorphicTo(DGraph other) {
3454 if (this.jGraph == null)
3455 {
3456 this.jGraph = GraphConversionTool.getJGraphFromGraph(this);
3457 }
3458 if (other.jGraph == null)
3459 {
3460 other.jGraph = GraphConversionTool.getJGraphFromGraph(other);
3461 }
3462
3463 // Simple but slow because it ignores symmetry
3464 /*
3465 Comparator<DENOPTIMVertex> vComp = (v1, v2) -> {
3466 // Vertex.sameAs returns boolean, so we need to produce
3467 // an int to allow comparison.
3468 StringBuilder sb = new StringBuilder();
3469 boolean areSame = v1.sameAs(v2, sb);
3470
3471 if (areSame) {
3472 return 0;
3473 } else {
3474 return Integer.compare(v1.getBuildingBlockId(),
3475 v2.getBuildingBlockId());
3476 }
3477 };
3478 */
3479
3480 Comparator<Vertex> vComp = new Comparator<Vertex>() {
3481
3482 Map<Vertex,Set<Vertex>> symmetryShortCuts =
3483 new HashMap<Vertex,Set<Vertex>>();
3484
3485 @Override
3486 public int compare(Vertex v1, Vertex v2) {
3487
3488 // exploit symmetric relations between vertices
3489 if (symmetryShortCuts.containsKey(v1)
3490 && symmetryShortCuts.get(v1).contains(v2))
3491 {
3492 return 0;
3493 }
3494
3495 // Vertex.sameAs returns boolean, so we need to produce
3496 // an int to allow comparison.
3497 StringBuilder sb = new StringBuilder();
3498 if (v1.sameAs(v2, sb))
3499 {
3500 Set<Vertex> symToV2 = new HashSet<Vertex>();
3501 symToV2.addAll(v2.getGraphOwner().getSymSetForVertex(v2));
3502 Set<Vertex> symToV1 = new HashSet<Vertex>();
3503 symToV1.addAll(v1.getGraphOwner().getSymSetForVertex(v1));
3504 for (Vertex v1s : symToV1)
3505 {
3506 if (symmetryShortCuts.containsKey(v1s))
3507 {
3508 symmetryShortCuts.get(v1s).addAll(symToV2);
3509 } else {
3510 symmetryShortCuts.put(v1s,symToV2);
3511 }
3512 }
3513 return 0;
3514 } else {
3515 // We must return something different than zero
3516 if (Integer.compare(v1.getBuildingBlockId(),
3517 v2.getBuildingBlockId())!=0)
3518 return Integer.compare(v1.getBuildingBlockId(),
3519 v2.getBuildingBlockId());
3520 if (Integer.compare(v1.hashCode(),
3521 v2.hashCode())!=0)
3522 return Integer.compare(v1.hashCode(),
3523 v2.hashCode());
3524 return Integer.compare(v1.getBuildingBlockId()+v1.hashCode(),
3525 v2.getBuildingBlockId()+v2.hashCode());
3526 }
3527 }
3528 };
3529
3530 Comparator<UndirectedEdge> eComp =
3532
3533 // NB: these two were created to evaluate the simplest and fasted
3534 // possible scenario. It turns out that for a graph like the following
3535 // one the time spent to do automorphism (i.e., isomorphism with itself)
3536 // can only be improved by 20% when using these two simplest and
3537 // useless (i.e., inaccurate) comparators. Instead the above, and useful
3538 // comparators do introduce some computational demands, but are less
3539 // detrimental than having to address a wide multitude of possible
3540 // mappings: this seems to be the liming factor, rather than the
3541 // implementation of the comparators.
3542
3543 // Example of challenging, yet simple graph:
3544 //29 853_1_0_-1,855_2_1_0,857_1_1_0,858_1_1_0,859_1_1_0,861_2_1_1,862_2_1_1,863_2_1_1,864_2_1_1,865_2_1_1,866_2_1_1,867_2_1_1,868_2_1_1,869_2_1_1, 853_1_855_0_1_c:0_ATneutral:0,853_0_857_1_1_c:0_c:0,853_2_858_1_1_c:0_c:0,853_3_859_1_1_c:0_c:0,857_0_861_0_1_c:0_ATneutral:0,857_2_862_0_1_c:0_ATneutral:0,857_3_863_0_1_c:0_ATneutral:0,858_0_864_0_1_c:0_ATneutral:0,858_2_865_0_1_c:0_ATneutral:0,858_3_866_0_1_c:0_ATneutral:0,859_0_867_0_1_c:0_ATneutral:0,859_2_868_0_1_c:0_ATneutral:0,859_3_869_0_1_c:0_ATneutral:0, SymmetricSet [symIds=[857, 858, 859]] SymmetricSet [symIds=[861, 862, 863, 864, 865, 866, 867, 868, 869]]
3545
3546 /*
3547 Comparator<UndirectedEdgeRelation> eCompDummy = (e1, e2) -> {
3548 return Integer.compare(e1.hashCode(),e2.hashCode());
3549 };
3550 Comparator<DENOPTIMVertex> vCompDummy = (v1, v2) -> {
3551 return Integer.compare(v1.getBuildingBlockId(),
3552 v2.getBuildingBlockId());
3553 };
3554 */
3555
3556 VF2GraphIsomorphismInspector<Vertex, UndirectedEdge> vf2 =
3557 new VF2GraphIsomorphismInspector<>(this.jGraph, other.jGraph,
3558 vComp, eComp);
3559
3560 return vf2.isomorphismExists();
3561 }
3562
3563//------------------------------------------------------------------------------
3564
3580 public boolean isIsostructuralTo(DGraph other) {
3581 if (this.jGraphKernel == null)
3582 {
3583 this.jGraphKernel = GraphConversionTool.getJGraphKernelFromGraph(this);
3584 }
3585 if (other.jGraphKernel == null)
3586 {
3587 other.jGraphKernel = GraphConversionTool.getJGraphKernelFromGraph(other);
3588 }
3589
3590 Comparator<Node> vComp = new Comparator<Node>() {
3591
3592 Map<Node,Set<Node>> symmetryShortCuts =
3593 new HashMap<Node,Set<Node>>();
3594
3595 @Override
3596 public int compare(Node v1, Node v2) {
3597
3598 // exploit symmetric relations between vertices
3599 if (symmetryShortCuts.containsKey(v1)
3600 && symmetryShortCuts.get(v1).contains(v2))
3601 {
3602 return 0;
3603 }
3604
3605 int result = v1.compare(v2);
3606 if (result==0)
3607 {
3608 Vertex dv1 = v1.getDNPVertex();
3609 Vertex dv2 = v2.getDNPVertex();
3610 if (dv1==null && dv2==null)
3611 {
3612 return result;
3613 }
3614
3615 Set<Node> symToV2 = new HashSet<Node>();
3616 for (Vertex sv : dv2.getGraphOwner().getSymSetForVertex(dv2))
3617 {
3618 symToV2.add((Node) sv.getProperty(
3620 }
3621
3622 Set<Node> symToV1 = new HashSet<Node>();
3623 for (Vertex sv : dv1.getGraphOwner().getSymSetForVertex(dv1))
3624 {
3625 symToV1.add((Node) sv.getProperty(
3627 }
3628
3629 for (Node v1s : symToV1)
3630 {
3631 if (symmetryShortCuts.containsKey(v1s))
3632 {
3633 symmetryShortCuts.get(v1s).addAll(symToV2);
3634 } else {
3635 symmetryShortCuts.put(v1s,symToV2);
3636 }
3637 }
3638 return 0;
3639 }
3640 return result;
3641 }
3642 };
3643
3644 Comparator<NodeConnection> eComp = NodeConnection::compare;
3645
3646 VF2GraphIsomorphismInspector<Node, NodeConnection> vf2 =
3647 new VF2GraphIsomorphismInspector<>(this.jGraphKernel,
3648 other.jGraphKernel, vComp, eComp);
3649
3650 return vf2.isomorphismExists();
3651 }
3652
3653//------------------------------------------------------------------------------
3654
3665 public boolean sameAs(DGraph other, StringBuilder reason)
3666 {
3667 if (this.getEdgeCount() != other.getEdgeCount())
3668 {
3669 reason.append("Different number of edges ("+this.getEdgeCount()+":"
3670 +other.getEdgeCount()+")");
3671 return false;
3672 }
3673
3674 if (this.getVertexCount() != other.getVertexCount())
3675 {
3676 reason.append("Different number of vertices ("+this.getVertexCount()+":"
3677 +other.getVertexCount()+")");
3678 return false;
3679 }
3680
3681 if (this.getSymmetricSetCount() != other.getSymmetricSetCount())
3682 {
3683 reason.append("Different number of symmetric sets ("
3684 + this.getSymmetricSetCount() + ":"
3685 + other.getSymmetricSetCount() + ")");
3686 return false;
3687 }
3688
3689 if (this.getRingCount() != other.getRingCount())
3690 {
3691 reason.append("Different number of Rings ("+this.getRingCount()+":"
3692 +other.getRingCount()+")");
3693 return false;
3694 }
3695
3696 //Pairwise correspondence of vertices
3697 Map<Vertex,Vertex> vertexMap =
3698 new HashMap<Vertex,Vertex>();
3699
3700 vertexMap.put(this.getVertexAtPosition(0),other.getVertexAtPosition(0));
3701
3702 //WARNING: assuming that the first vertex in the vertex list is the root
3703 // and also that there are no disconnections. Both assumptions are
3704 // reasonable for graphs.
3705 try {
3706 if (!compareGraphNodes(this.getVertexAtPosition(0), this,
3707 other.getVertexAtPosition(0), other,
3708 vertexMap,reason))
3709 {
3710 return false;
3711 }
3712 } catch (DENOPTIMException e) {
3713 e.printStackTrace();
3714 reason.append("Exception");
3715 return false;
3716 }
3717
3718 //Check Symmetric sets
3719 Iterator<SymmetricVertexes> ssIter = this.getSymSetsIterator();
3720 while (ssIter.hasNext())
3721 {
3722 SymmetricVertexes ssT = ssIter.next();
3723
3725 vertexMap.get(ssT.get(0)));
3726 if (ssO.size() == 0)
3727 {
3728 // ssO is empty because no SymmetricSet was found that
3729 // contains the given vertex. This means the two graphs
3730 // are different
3731 reason.append("Symmetric set not found for vertex ("
3732 + ssT.get(0) + ")");
3733 return false;
3734 }
3735
3736 if (ssT.size() != ssO.size())
3737 {
3738 reason.append("Different number of symmetric sets on vertex "
3739 + ssT.get(0) + "("+ssT.size()+":"+ssO.size()+")");
3740 return false;
3741 }
3742
3743 Set<Vertex> mappedVrtxFromThis = new HashSet<>();
3744 ssT.stream().forEach(v -> mappedVrtxFromThis.add(vertexMap.get(v)));
3745
3746 Set<Vertex> vrtxFromOther = new HashSet<>();
3747 ssO.stream().forEach(v -> vrtxFromOther.add(v));
3748 if (!vrtxFromOther.equals(mappedVrtxFromThis))
3749 {
3750 reason.append("Difference in symmetric set " + ssT + " vs " + ssO);
3751 return false;
3752 }
3753 }
3754
3755 //Check Rings
3756 for (Ring rT : this.getRings())
3757 {
3758 Vertex vhT = rT.getHeadVertex();
3759 Vertex vtT = rT.getTailVertex();
3760 boolean hasRing = other
3761 .getRingsInvolvingVertex(vertexMap.get(vhT))
3762 .stream()
3763 .anyMatch(rO -> sameAsRings(reason, vertexMap, rT, vhT,
3764 vtT, rO));
3765 if (!hasRing) {
3766 return false;
3767 }
3768 }
3769
3770 return true;
3771 }
3772
3773//------------------------------------------------------------------------------
3774
3775 private boolean sameAsRings(StringBuilder reason, Map<Vertex,
3776 Vertex> vertexMap, Ring rT, Vertex vhT,
3777 Vertex vtT, Ring rO) {
3778 if (rT.getSize() != rO.getSize()) {
3779 reason.append("Different ring size (").append(rT.getSize())
3780 .append(":").append(rO.getSize()).append(")");
3781 return false;
3782 }
3783
3784 if (rO.getHeadVertex() == vertexMap.get(vhT)
3785 && rO.getTailVertex() == vertexMap.get(vtT)) {
3786 for (int i = 1; i < rT.getSize(); i++) {
3787 if (vertexMap.get(rT.getVertexAtPosition(i))
3788 != rO.getVertexAtPosition(i)) {
3789 reason.append("Rings differ (A) (").append(rT).append(":")
3790 .append(rO).append(")");
3791 return false;
3792 }
3793 }
3794 } else if (rO.getHeadVertex() == vertexMap.get(vtT)
3795 && rO.getTailVertex() == vertexMap.get(vhT)) {
3796 for (int i = 1; i < rT.getSize(); i++) {
3797 int j = rO.getSize() - i - 1;
3798 if (vertexMap.get(rT.getVertexAtPosition(i))
3799 != rO.getVertexAtPosition(j)) {
3800 reason.append("Rings differ (B) (").append(rT).append(":")
3801 .append(rO).append(")");
3802 return false;
3803 }
3804 }
3805 } else {
3806 reason.append("Rings differ (C) (").append(rT).append(":")
3807 .append(rO).append(")");
3808 return false;
3809 }
3810 return true;
3811 }
3812
3813//------------------------------------------------------------------------------
3814
3825 public static boolean compareGraphNodes(Vertex thisV,
3826 DGraph thisG,
3827 Vertex otherV,
3828 DGraph otherG) throws DENOPTIMException
3829 {
3830 Map<Vertex, Vertex> map = new HashMap<>();
3831 map.put(thisV, otherV);
3832 return compareGraphNodes(thisV, thisG, otherV, otherG, map,
3833 new StringBuilder());
3834 }
3835
3836//------------------------------------------------------------------------------
3837
3849 private static boolean compareGraphNodes(Vertex seedOnA,
3850 DGraph gA, Vertex seedOnB, DGraph gB,
3851 Map<Vertex,Vertex> vertexMap, StringBuilder reason)
3852 throws DENOPTIMException
3853 {
3854 if (!seedOnA.sameAs(seedOnB, reason))
3855 {
3856 reason.append("Different vertex ("+seedOnA+":"+seedOnB+")");
3857 return false;
3858 }
3859
3860 List<Edge> edgesFromThis = gA.getEdgesWithSrc(seedOnA);
3861 List<Edge> edgesFromOther = gB.getEdgesWithSrc(seedOnB);
3862 if (edgesFromThis.size() != edgesFromOther.size())
3863 {
3864 reason.append("Different number of edges from vertex "+seedOnA+" ("
3865 +edgesFromThis.size()+":"
3866 +edgesFromOther.size()+")");
3867 return false;
3868 }
3869
3870 // pairwise correspondence between child vertices
3871 ArrayList<Vertex[]> pairs = new ArrayList<Vertex[]>();
3872
3873 for (Edge et : edgesFromThis)
3874 {
3875 boolean found = false;
3876 Edge eo = null;
3877 StringBuilder innerSb = new StringBuilder();
3878 int otherEdgeI = 0;
3879 for (Edge e : edgesFromOther)
3880 {
3881 innerSb.append(" Edge"+otherEdgeI+":");
3882 if (et.sameAs(e,innerSb))
3883 {
3884 found = true;
3885 eo = e;
3886 break;
3887 }
3888 }
3889 if (!found)
3890 {
3891 reason.append("Edge not found in other("+et+"). "
3892 + "Edges in othes: "+innerSb.toString());
3893 return false;
3894 }
3895
3896 //Check: this should never be true
3897 if (vertexMap.keySet().contains(
3898 gA.getVertexWithId(et.getTrgVertex())))
3899 {
3900 throw new DENOPTIMException("More than one attempt to set vertex map.");
3901 }
3902 vertexMap.put(gA.getVertexWithId(et.getTrgVertex()),
3903 gB.getVertexWithId(eo.getTrgVertex()));
3904
3905 Vertex[] pair = new Vertex[]{
3906 gA.getVertexWithId(et.getTrgVertex()),
3907 gB.getVertexWithId(eo.getTrgVertex())};
3908 pairs.add(pair);
3909 }
3910
3911 //Recursion on child vertices
3912 for (Vertex[] pair : pairs)
3913 {
3914 Vertex v = pair[0];
3915 Vertex o = pair[1];
3916 boolean localRes = compareGraphNodes(v, gA, o, gB,vertexMap,
3917 reason);
3918 if (!localRes)
3919 {
3920 return false;
3921 }
3922 }
3923
3924 return true;
3925 }
3926
3927//------------------------------------------------------------------------------
3928
3935 public boolean containsAtoms()
3936 {
3937 for (Vertex v : getVertexList())
3938 {
3939 if (v.containsAtoms())
3940 {
3941 return true;
3942 }
3943 }
3944 return false;
3945 }
3946
3947//------------------------------------------------------------------------------
3948
3954 {
3955 int n = 0;
3956 for (Vertex v : getVertexList())
3957 {
3958 n += v.getHeavyAtomsCount();
3959 }
3960 return n;
3961 }
3962
3963//------------------------------------------------------------------------------
3964
3970 public ArrayList<AttachmentPoint> getAttachmentPoints()
3971 {
3972 ArrayList<AttachmentPoint> lstAPs =
3973 new ArrayList<AttachmentPoint>();
3974 for (Vertex v : gVertices)
3975 {
3976 lstAPs.addAll(v.getAttachmentPoints());
3977 }
3978 return lstAPs;
3979 }
3980
3981//------------------------------------------------------------------------------
3982
3988 public ArrayList<AttachmentPoint> getAvailableAPs()
3989 {
3990 ArrayList<AttachmentPoint> lstFreeAPs =
3991 new ArrayList<AttachmentPoint>();
3993 {
3994 if (ap.isAvailable())
3995 {
3996 lstFreeAPs.add(ap);
3997 }
3998 }
3999 return lstFreeAPs;
4000 }
4001
4002//------------------------------------------------------------------------------
4003
4011 public List<AttachmentPoint> getAvailableAPsThroughout()
4012 {
4013 ArrayList<AttachmentPoint> lstFreeAPs =
4014 new ArrayList<AttachmentPoint>();
4016 {
4017 if (ap.isAvailableThroughout())
4018 {
4019 lstFreeAPs.add(ap);
4020 }
4021 }
4022 return lstFreeAPs;
4023 }
4024
4025//------------------------------------------------------------------------------
4026
4036 {
4037 AttachmentPoint ap = null;
4038 for (AttachmentPoint apCand : getAttachmentPoints())
4039 {
4040 if (apCand.getID() == id)
4041 {
4042 ap = apCand;
4043 break;
4044 }
4045 }
4046 return ap;
4047 }
4048
4049//------------------------------------------------------------------------------
4050
4051 protected int getUniqueAPIndex()
4052 {
4053 return apCounter.getAndIncrement();
4054 }
4055
4056//------------------------------------------------------------------------------
4057
4064 public boolean graphNeedsCappingGroups(FragmentSpace fragSpace)
4065 {
4066 for (Vertex v : getVertexList()) {
4067 for (AttachmentPoint ap : v.getAttachmentPoints()) {
4068 if (ap.isAvailable() && fragSpace.getAPClassOfCappingVertex(
4069 ap.getAPClass()) !=null
4070 ) {
4071 return true;
4072 }
4073 }
4074 }
4075 return false;
4076 }
4077
4078//------------------------------------------------------------------------------
4079
4084 public void removeCappingGroupsOn(Vertex vertex)
4085 {
4086 ArrayList<Vertex> toDel = new ArrayList<Vertex>();
4087 for (Vertex vtx : this.getChildVertices(vertex))
4088 {
4089 if (vtx instanceof Fragment == false)
4090 {
4091 continue;
4092 }
4093 // capping groups have fragment type 2
4094 if (((Fragment) vtx).getBuildingBlockType() == BBType.CAP
4095 && !isVertexInRing(vtx))
4096 {
4097 toDel.add(vtx);
4098 }
4099 }
4100
4101 for (Vertex v : toDel)
4102 {
4103 removeVertex(v);
4104 }
4105 }
4106
4107//------------------------------------------------------------------------------
4108
4114 public void removeCappingGroups(List<Vertex> lstVerts)
4115 {
4116 List<Long> rvids = new ArrayList<>();
4117 for (int i=0; i<lstVerts.size(); i++)
4118 {
4119 Vertex vtx = lstVerts.get(i);
4120 if (vtx instanceof Fragment == false)
4121 {
4122 continue;
4123 }
4124
4125 if (((Fragment) vtx).getBuildingBlockType() == BBType.CAP
4126 && !isVertexInRing(vtx))
4127 {
4128 rvids.add(vtx.getVertexId());
4129 }
4130 }
4131
4132 // remove the vids from the vertex lst
4133 for (int i=0; i<rvids.size(); i++)
4134 {
4135 long vid = rvids.get(i);
4137 }
4138 }
4139
4140//------------------------------------------------------------------------------
4141
4142 public void removeCappingGroupsFromChilds(List<Vertex> lstVerts)
4143 {
4144 for (Vertex v : lstVerts)
4145 {
4147 }
4148 }
4149
4150//------------------------------------------------------------------------------
4151
4157 {
4158 removeCappingGroups(new ArrayList<Vertex>(gVertices));
4159 }
4160
4161//------------------------------------------------------------------------------
4162
4170 {
4171 if (!fragSpace.useAPclassBasedApproach())
4172 return;
4173 addCappingGroups(new ArrayList<Vertex>(gVertices), fragSpace);
4174 }
4175
4176//------------------------------------------------------------------------------
4177
4192 public void addCappingGroups(List<Vertex> vertexAddedToThis,
4193 FragmentSpace fragSpace) throws DENOPTIMException
4194 {
4195 if (!fragSpace.useAPclassBasedApproach())
4196 return;
4197
4198 for (Vertex curVertex : vertexAddedToThis)
4199 {
4200 // no capping of a capping group. Since capping groups are expected
4201 // to have only one AP, there should never be a capping group with
4202 // a free AP.
4203 if (curVertex.getBuildingBlockType() == Vertex.BBType.CAP)
4204 {
4205 continue;
4206 }
4207
4208 for (AttachmentPoint curDap : curVertex.getAttachmentPoints())
4209 {
4210 if (curDap.isAvailableThroughout())
4211 {
4212 APClass apcCap = fragSpace.getAPClassOfCappingVertex(
4213 curDap.getAPClass());
4214 if (apcCap != null)
4215 {
4216 int bbIdCap = fragSpace.getCappingFragment(apcCap);
4217
4218 if (bbIdCap != -1)
4219 {
4222 bbIdCap, BBType.CAP, fragSpace);
4223 DGraph molGraph = curDap.getOwner()
4224 .getGraphOwner();
4225 if (molGraph == null)
4226 throw new Error("Cannot add capping "
4227 + "groups to a vertex that does not "
4228 + "belong to a graph.");
4229 molGraph.appendVertexOnAP(curDap, capVrtx.getAP(0));
4230 }
4231 else
4232 {
4233 String msg = "Capping is required but no proper "
4234 + "capping fragment found with APCalss "
4235 + apcCap;
4236 throw new Error(msg);
4237 }
4238 }
4239 }
4240 }
4241 }
4242 }
4243
4244//------------------------------------------------------------------------------
4245
4258 public DGraph extractSubgraph(int index)
4259 throws DENOPTIMException
4260 {
4261 return extractSubgraph(this.getVertexAtPosition(index));
4262 }
4263
4264//------------------------------------------------------------------------------
4265
4278 throws DENOPTIMException
4279 {
4280 return extractSubgraph(seed, Integer.MAX_VALUE, false);
4281 }
4282
4283//------------------------------------------------------------------------------
4284
4303 public DGraph extractSubgraph(Vertex seed, int numLayers,
4304 boolean stopBeforeRCVs) throws DENOPTIMException
4305 {
4306 if (!this.gVertices.contains(seed))
4307 {
4308 throw new DENOPTIMException("Attempt to extract a subgraph giving "
4309 + "a seed vertex that is not contained in this graph.");
4310 }
4311 DGraph subGraph = this.clone();
4312 Vertex seedClone = subGraph.getVertexAtPosition(
4313 this.indexOf(seed));
4314
4315 ArrayList<Vertex> subGrpVrtxs = new ArrayList<Vertex>();
4316 subGrpVrtxs.add(seedClone);
4317 subGraph.getChildrenTree(seedClone, subGrpVrtxs, numLayers, stopBeforeRCVs);
4318 ArrayList<Vertex> toRemove = new ArrayList<Vertex>();
4319 for (Vertex v : subGraph.gVertices)
4320 {
4321 if (!subGrpVrtxs.contains(v))
4322 {
4323 toRemove.add(v);
4324 }
4325 }
4326
4327 for (Vertex v : toRemove)
4328 {
4329 subGraph.removeVertex(v);
4330 }
4331
4332 return subGraph;
4333 }
4334
4335//------------------------------------------------------------------------------
4336
4355 List<Vertex> limits, boolean stopBeforeRCVs)
4356 throws DENOPTIMException
4357 {
4358 if (!this.gVertices.contains(seed))
4359 {
4360 throw new DENOPTIMException("Attempt to extract a subgraph giving "
4361 + "a seed vertex that is not contained in this graph.");
4362 }
4363
4364 if (limits.size()==0)
4365 {
4366 return extractSubgraph(seed, stopBeforeRCVs);
4367 }
4368
4369 DGraph subGraph = this.clone();
4370 Vertex seedClone = subGraph.getVertexAtPosition(
4371 this.indexOf(seed));
4372
4373 List<Vertex> limitsInClone = new ArrayList<Vertex>();
4374 for (Vertex v : limits)
4375 limitsInClone.add(subGraph.getVertexAtPosition(this.indexOf(v)));
4376
4377 ArrayList<Vertex> subGrpVrtxs = new ArrayList<Vertex>();
4378 subGrpVrtxs.add(seedClone);
4379 subGraph.getChildTreeLimited(seedClone, subGrpVrtxs, limitsInClone,
4380 stopBeforeRCVs);
4381
4382 ArrayList<Vertex> toRemove = new ArrayList<Vertex>();
4383 for (Vertex v : subGraph.gVertices)
4384 {
4385 if (!subGrpVrtxs.contains(v))
4386 {
4387 toRemove.add(v);
4388 }
4389 }
4390 for (Vertex v : toRemove)
4391 {
4392 subGraph.removeVertex(v);
4393 }
4394
4395 return subGraph;
4396 }
4397
4398//------------------------------------------------------------------------------
4399
4414 public DGraph extractSubgraph(Vertex seed, boolean stopBeforeRCVs)
4415 throws DENOPTIMException
4416 {
4417 if (!this.gVertices.contains(seed))
4418 {
4419 throw new DENOPTIMException("Attempt to extract a subgraph giving "
4420 + "a seed vertex that is not contained in this graph.");
4421 }
4422
4423 DGraph subGraph = this.clone();
4424 Vertex seedClone = subGraph.getVertexAtPosition(
4425 this.indexOf(seed));
4426
4427 ArrayList<Vertex> subGrpVrtxs = new ArrayList<Vertex>();
4428 subGrpVrtxs.add(seedClone);
4429 subGraph.getChildTreeLimited(seedClone, subGrpVrtxs, stopBeforeRCVs);
4430
4431 ArrayList<Vertex> toRemove = new ArrayList<Vertex>();
4432 for (Vertex v : subGraph.gVertices)
4433 {
4434 if (!subGrpVrtxs.contains(v))
4435 {
4436 toRemove.add(v);
4437 }
4438 }
4439 for (Vertex v : toRemove)
4440 {
4441 subGraph.removeVertex(v);
4442 }
4443
4444 return subGraph;
4445 }
4446
4447//------------------------------------------------------------------------------
4448
4457 public List<DGraph> extractPattern(GraphPattern pattern)
4458 throws DENOPTIMException
4459 {
4460 return extractPattern(pattern, false).keySet().stream().collect(
4461 Collectors.toList());
4462 }
4463
4464//------------------------------------------------------------------------------
4465
4488 public Map<DGraph,ObjectPair> extractPattern(GraphPattern pattern,
4489 boolean recordConnectivity) throws DENOPTIMException
4490 {
4491 if (pattern != GraphPattern.RING) {
4492 throw new IllegalArgumentException("Graph pattern " + pattern +
4493 " not supported.");
4494 }
4495
4496 List<Set<Vertex>> disjointMultiCycleVertices = this
4497 .getRings()
4498 .stream()
4499 .map(Ring::getVertices)
4500 .map(HashSet::new)
4501 .collect(Collectors.toList());
4502
4503 GeneralUtils.unionOfIntersectingSets(disjointMultiCycleVertices);
4504
4505 Map<DGraph,ObjectPair> subGraphsAndConnections = new LinkedHashMap<>();
4506 for (Set<Vertex> fusedRing : disjointMultiCycleVertices) {
4507 if (recordConnectivity)
4508 {
4509 Set<Edge> connectionToSubgraph = new HashSet<Edge>();
4510 Set<Edge> connectionFromSubgraph = new HashSet<Edge>();
4511 DGraph subGraph = extractSubgraph(fusedRing, connectionToSubgraph,
4512 connectionFromSubgraph);
4513 ObjectPair connections = new ObjectPair(connectionToSubgraph,
4514 connectionFromSubgraph);
4515 subGraphsAndConnections.put(subGraph, connections);
4516 } else {
4517 DGraph subGraph = extractSubgraph(fusedRing);
4518 subGraphsAndConnections.put(subGraph, null);
4519 }
4520 }
4521
4522 for (DGraph g : subGraphsAndConnections.keySet()) {
4523 g.storeCurrentVertexIDs();
4524 g.renumberGraphVertices();
4526 }
4527
4528 return subGraphsAndConnections;
4529 }
4530
4531 //------------------------------------------------------------------------------
4532
4539 public DGraph extractSubgraph(Collection<Vertex> definedOn)
4540 {
4541 DGraph subgraph = extractSubgraph(definedOn, null, null);
4542 return subgraph;
4543 }
4544
4545//------------------------------------------------------------------------------
4546
4558 public DGraph extractSubgraph(Collection<Vertex> definedOn,
4559 Set<Edge> connectionToSubgraph,
4560 Set<Edge> connectionFromSubgraph)
4561 {
4562
4563 DGraph subgraph = this.clone();
4564
4565 Set<Vertex> complement = subgraph
4566 .getVertexList()
4567 .stream()
4568 .filter(u -> definedOn
4569 .stream()
4570 .allMatch(v -> v.getVertexId() != u.getVertexId())
4571 ).collect(Collectors.toSet());
4572
4573 Set<Long> vrtxIDsInComplement = complement.stream()
4574 .map(v -> v.getVertexId())
4575 .collect(Collectors.toSet());
4576
4577 if (connectionToSubgraph!=null && connectionFromSubgraph!=null)
4578 {
4579 for (Vertex v : definedOn)
4580 {
4581 for (Edge e : this.getEdgeList())
4582 {
4583 if (e.getSrcAP().getOwner() == v &&
4584 vrtxIDsInComplement.contains(e.getTrgVertex()))
4585 {
4586 connectionFromSubgraph.add(e);
4587 }
4588
4589 if (e.getTrgAP().getOwner() == v &&
4590 vrtxIDsInComplement.contains(e.getSrcVertex()))
4591 {
4592 connectionToSubgraph.add(e);
4593 }
4594 }
4595 }
4596 }
4597
4598 for (Vertex v : complement) {
4599 subgraph.removeVertex(v);
4600 }
4601
4602 return subgraph;
4603 }
4604
4605//------------------------------------------------------------------------------
4606
4617 FragmentSpace fragSpace) throws DENOPTIMException
4618 {
4619 return embedPatternsInTemplates(pattern, fragSpace, ContractLevel.FREE);
4620 }
4621
4622//------------------------------------------------------------------------------
4623
4638 FragmentSpace fragSpace, ContractLevel contract)
4639 throws DENOPTIMException
4640 {
4641 // We will return a modified clone of this graph
4642 DGraph graph = this.clone();
4643 // We use IDs to find the mapping of APs between cloned graphs. So, must
4644 // ensure the IDs of APs are unique within the graph.
4645 graph.ensureUniqueApIDs();
4646
4647 // Identify the subgraphs to be replaced by templates
4648 Map<DGraph,ObjectPair> subGraphsAndLinks = graph.extractPattern(
4649 pattern, true);
4650
4651 // Replace the subgraphs with the templates
4652 for (Map.Entry<DGraph,ObjectPair> entry : subGraphsAndLinks.entrySet())
4653 {
4654 // WARNING: while the subgraph is a clone of 'graph', the sets
4655 // contain referenced to the edges of 'graph'.
4656 DGraph subGraph = entry.getKey();
4657
4658 // Make template
4659 BBType tmplType = subGraph.hasScaffoldTypeVertex() ?
4660 BBType.SCAFFOLD :
4662 Template tmpl = new Template(tmplType);
4663 tmpl.setInnerGraph(subGraph);
4664 tmpl.setContractLevel(contract);
4665
4666 // Recover info on which APs of the original subgraph (i.e., APs in
4667 // 'graph') correspond to APs on the template.
4668 LinkedHashMap<AttachmentPoint, AttachmentPoint> apMapOrigToTmpl =
4669 new LinkedHashMap<AttachmentPoint, AttachmentPoint>();
4670 @SuppressWarnings("unchecked")
4671 Set<Edge> edsToSubgrph = (Set<Edge>) entry.getValue().getFirst();
4672 for (Edge e : edsToSubgrph)
4673 {
4674 AttachmentPoint apOnOrig = e.getTrgAP();
4675 AttachmentPoint apOnTmpl = tmpl.getOuterAPFromInnerAP(
4676 subGraph.getAPWithId(apOnOrig.getID()));
4677 apMapOrigToTmpl.put(apOnOrig, apOnTmpl);
4678 }
4679 @SuppressWarnings("unchecked")
4680 Set<Edge> edsFromSubGrph = (Set<Edge>) entry.getValue().getSecond();
4681 for (Edge e : edsFromSubGrph)
4682 {
4683 AttachmentPoint apOnOrig = e.getSrcAP();
4684 AttachmentPoint apOnTmpl = tmpl.getOuterAPFromInnerAP(
4685 subGraph.getAPWithId(apOnOrig.getID()));
4686 apMapOrigToTmpl.put(apOnOrig, apOnTmpl);
4687 }
4688
4689 // Identify the vertexes in the subgraph replaced by the template
4690 List<Vertex> toReplaceByTemplate = new ArrayList<>();
4691 for (Vertex embeddedVrtx : subGraph.gVertices)
4692 {
4693 long vIdInThis = (long) embeddedVrtx.getProperty(
4695 toReplaceByTemplate.add(graph.getVertexWithId(vIdInThis));
4696 }
4697
4698 // Do the actual replacement of original subgraph with the template
4699 DGraph singleVertedGraph = new DGraph();
4700 singleVertedGraph.addVertex(tmpl);
4701 graph.replaceSubGraph(toReplaceByTemplate, singleVertedGraph,
4702 apMapOrigToTmpl, fragSpace);
4703 }
4704
4705 return graph;
4706 }
4707
4708//------------------------------------------------------------------------------
4709
4717 private static void reorderVertexList(DGraph g)
4718 {
4719 Vertex newScaffold = g.getSourceVertex();
4720 if (newScaffold == null) {
4721 return;
4722 }
4723 DGraph.setScaffold(newScaffold);
4725 }
4726
4727//------------------------------------------------------------------------------
4728
4733 private static void fixEdgeDirections(DGraph graph)
4734 {
4735 Vertex src = graph.getSourceVertex();
4736 fixEdgeDirections(src, new HashSet<>());
4737 }
4738
4739//------------------------------------------------------------------------------
4740
4745 private static void fixEdgeDirections(Vertex v,
4746 Set<Long> visited)
4747 {
4748 visited.add(v.getVertexId());
4749 int visitedVertexEncounters = 0;
4750 for (int i = 0; i < v.getNumberOfAPs(); i++) {
4751 AttachmentPoint ap = v.getAP(i);
4752 Edge edge = ap.getEdgeUser();
4753 if (edge != null) {
4754 long srcVertex = edge.getSrcVertex();
4755 boolean srcIsVisited = srcVertex != v.getVertexId()
4756 && visited.contains(srcVertex);
4757
4758 visitedVertexEncounters += srcIsVisited ? 1 : 0;
4759 if (visitedVertexEncounters >= 2) {
4760 throw new IllegalArgumentException("Invalid graph. "
4761 + "Contains a cycle.");
4762 }
4763
4764 boolean edgeIsWrongWay = edge.getTrgVertex()
4765 == v.getVertexId() && !srcIsVisited;
4766 if (edgeIsWrongWay) {
4767 edge.flipEdge();
4768 }
4769 if (!srcIsVisited) {
4770 fixEdgeDirections(edge.getTrgAP().getOwner(), visited);
4771 }
4772 }
4773 }
4774 }
4775
4776//------------------------------------------------------------------------------
4777
4788 public boolean removeBranchStartingAt(Vertex v, boolean symmetry)
4789 throws DENOPTIMException
4790 {
4791 boolean res = true;
4792 if (hasSymmetryInvolvingVertex(v) && symmetry)
4793 {
4794 for (Vertex sv : getSymSetForVertex(v))
4795 {
4796 boolean res2 = removeBranchStartingAt(sv);
4797 if (!res2)
4798 {
4799 res = res2;
4800 }
4801 }
4802 }
4803 else
4804 {
4805 res = removeBranchStartingAt(v);
4806 }
4807 return res;
4808 }
4809
4810//------------------------------------------------------------------------------
4811
4822 throws DENOPTIMException
4823 {
4824 Edge edgeToParent = v.getEdgeToParent();
4825 if (edgeToParent != null)
4826 {
4827 removeEdge(edgeToParent);
4828 }
4830 }
4831
4832//------------------------------------------------------------------------------
4833
4848 throws DENOPTIMException
4849 {
4850 // now get the vertices attached to v
4851 ArrayList<Vertex> children = new ArrayList<Vertex>();
4852 getChildrenTree(v, children);
4853
4854 // delete the children vertices and associated edges
4855 for (Vertex c : children) {
4856 removeVertex(c);
4857 }
4858
4859 // finally delete the vertex and associated edges
4860 removeVertex(v);
4861
4862 return getVertexWithId(v.getVertexId()) == null;
4863 }
4864
4865//------------------------------------------------------------------------------
4866
4879 FragmentSpace fragSpace) throws DENOPTIMException
4880 {
4881 List<Ring> rings = getRingsInvolvingVertex(v);
4882 if (rings.isEmpty())
4883 {
4884 return false;
4885 }
4886
4887 // Identify the RCVs defining the chord that might become an edge
4888 // The corresponding ring is the "frame" we'll use throughout this
4889 // operation, and is the smallest ring that is closest to the appointed
4890 // vertex.
4891 Ring frame = null;
4892 Vertex[] replacedByEdge = new Vertex[2];
4893 int minDist = Integer.MAX_VALUE;
4894 BondType bt = null;
4895 for (Ring r : rings)
4896 {
4897 int dist = Math.min(r.getDistance(r.getHeadVertex(),v),
4898 r.getDistance(r.getTailVertex(),v));
4899 if (dist < minDist)
4900 {
4901 minDist = dist;
4902 frame = r;
4903 replacedByEdge[0] = r.getHeadVertex();
4904 replacedByEdge[1] = r.getTailVertex();
4905 bt = r.getBondType();
4906 }
4907 }
4908
4909 // Find out where branching vertices are along the frame ring
4910 boolean frameHasBranching = false;
4911 List<Integer> branchingPositions = new ArrayList<Integer>();
4912 int posOfFocusVrtInRing = frame.getPositionOf(v);
4913 for (int i=0; i<frame.getSize(); i++)
4914 {
4915 Vertex vi = frame.getVertexAtPosition(i);
4916 // We consider the scaffold as a branching point, i.e., it will never be removed
4918 {
4919 branchingPositions.add(i);
4920 continue;
4921 }
4922 long oNonCap = vi.getAttachmentPoints().size()
4925 if (oNonCap > 2)
4926 {
4927 branchingPositions.add(i);
4928 frameHasBranching = true;
4929 }
4930 }
4931
4932 // Make sure this ring is not all there is in this graph.
4933 if (rings.size()==1 && !frameHasBranching)
4934 {
4935 return false;
4936 }
4937
4938 // Identify the end points of chain that gets removed, i.e., the chain
4939 // containing V and is between branchingDownstreamId and
4940 // branchingUpstreamId gets removed.
4941 int branchingDownstreamId = -1;
4942 for (int i=0; i<frame.getSize(); i++)
4943 {
4944 int iTranslated = i + posOfFocusVrtInRing;
4945 if (iTranslated >= frame.getSize())
4946 iTranslated = iTranslated - frame.getSize();
4947 if (branchingPositions.contains(iTranslated))
4948 {
4949 branchingDownstreamId = iTranslated;
4950 break;
4951 }
4952 }
4953 int branchingUpstreamId = -1;
4954 for (int i=(frame.getSize()-1); i>-1; i--)
4955 {
4956 int iTranslated = i + posOfFocusVrtInRing;
4957 if (iTranslated >= frame.getSize())
4958 iTranslated = iTranslated - frame.getSize();
4959 if (branchingPositions.contains(iTranslated))
4960 {
4961 branchingUpstreamId = iTranslated;
4962 break;
4963 }
4964 }
4965
4966 // Now, collect the vertices along the ring based on whether they
4967 // will be removed or remain (possible with a change of edge direction
4968 // and replacement of an RCV pair by edge)
4969 List<Vertex> remainingChain = new ArrayList<Vertex>();
4970 for (int i=0; i<frame.getSize(); i++)
4971 {
4972 int iTranslated = i + branchingDownstreamId;
4973 if (iTranslated >= frame.getSize())
4974 iTranslated = iTranslated - frame.getSize();
4975 remainingChain.add(frame.getVertexAtPosition(iTranslated));
4976 if (iTranslated == branchingUpstreamId)
4977 {
4978 break;
4979 }
4980 }
4981 List<Vertex> toRemoveChain = new ArrayList<Vertex>();
4982 for (int i=0; i<frame.getSize(); i++)
4983 {
4984 int iTranslated = i + branchingUpstreamId + 1; //exclude branch point
4985 if (iTranslated >= frame.getSize())
4986 iTranslated = iTranslated - frame.getSize();
4987 toRemoveChain.add(frame.getVertexAtPosition(iTranslated));
4988 if (iTranslated == (branchingDownstreamId - 1)) //exclude branch point
4989 {
4990 break;
4991 }
4992 }
4993
4994 // Need to exclude the case where the chain to remove consists only of
4995 // the RCVs because it would lead to loss of the chord and creation of
4996 // cyclic graph. Also, proceeding without making the edge would simply
4997 // correspond to removing the chord.
4998 if (toRemoveChain.size() == 2)
4999 {
5000 int countOrRCVs = 0;
5001 for (Vertex vtr : toRemoveChain)
5002 {
5003 if (vtr.isRCV())
5004 countOrRCVs++;
5005 }
5006 if (countOrRCVs == 2)
5007 {
5008 return false;
5009 }
5010 }
5011
5012 // To understand if we need to reverse some edges, we identify the
5013 // deepest vertex level-wise. It may or may not be a scaffold!!!
5014 int deepestLevel = Integer.MAX_VALUE;
5015 Vertex deepestVrtRemainingChain = null;
5016 for (Vertex vint : remainingChain)
5017 {
5018 int lvl = getLevel(vint);
5019 if (lvl < deepestLevel)
5020 {
5021 deepestLevel = lvl;
5022 deepestVrtRemainingChain = vint;
5023 }
5024 }
5025
5026 // Check if we need to transform a pair of RCVs into an edge, and
5027 // identify APs used by the edge that replaces the to-be-removed RCVs.
5028 // I do not see how the chain can possibly contain only one of the
5029 // RCVs, so I assume that if one RCV is there, then the other is too.
5030 if (remainingChain.contains(replacedByEdge[0]))
5031 {
5032 AttachmentPoint apSrcOfNewEdge = replacedByEdge[0]
5034 AttachmentPoint apTrgOfNewEdge = replacedByEdge[1]
5036
5037 // Remove the RCVs that will be replaced by an edge
5038 removeVertex(replacedByEdge[0]);
5039 remainingChain.remove(replacedByEdge[0]);
5040 removeVertex(replacedByEdge[1]);
5041 remainingChain.remove(replacedByEdge[1]);
5042
5043 // And make the new edge. The direction can be anything. Later, we
5044 // decide if we need to reverse it.
5045 //NB: the compatibility between the APs should be granted by the
5046 // previous existence of the chord. so no need to check
5047 // apSrcOfNewEdge.getAPClass().isCPMapCompatibleWith(
5048 // apTrgOfNewEdge.getAPClass()))
5049 addEdge(new Edge(apSrcOfNewEdge, apTrgOfNewEdge, bt));
5050 } else {
5051 // We remove the frame already, otherwise we will try to recreate
5052 // such ring from RCVs and waste time with it.
5053 removeRing(frame);
5054 }
5055
5056 // Now, inspect the paths from the deepest vertex and outwards, to
5057 // find out where to start reversing edges.
5058 List<Vertex> chainToReverseA = new ArrayList<Vertex>();
5059 List<Vertex> chainToReverseB = new ArrayList<Vertex>();
5060 for (int i=(remainingChain.indexOf(deepestVrtRemainingChain)+1);
5061 i<remainingChain.size(); i++)
5062 {
5063 Vertex vPrev = remainingChain.get(i-1);
5064 Vertex vHere = remainingChain.get(i);
5065 if (!vPrev.getChilddren().contains(vHere))
5066 {
5067 // in an healthy spanning tree, once we find the first reversed
5068 // edge, all the following edges will also have to be reversed.
5069 if (chainToReverseA.size()==0)
5070 chainToReverseA.add(vPrev);
5071 chainToReverseA.add(vHere);
5072 }
5073 }
5074 for (int i=(remainingChain.indexOf(deepestVrtRemainingChain)-1);i>-1;i--)
5075 {
5076 Vertex vPrev = remainingChain.get(i+1);
5077 Vertex vHere = remainingChain.get(i);
5078 if (!vPrev.getChilddren().contains(vHere))
5079 {
5080 if (chainToReverseB.size()==0)
5081 chainToReverseB.add(vPrev);
5082 chainToReverseB.add(vHere);
5083 }
5084 }
5085
5086 // These are to remember all chords that will have to be recreated
5087 LinkedHashMap<Vertex,Vertex> chordsToRecreate =
5088 new LinkedHashMap<Vertex,Vertex>();
5089 LinkedHashMap<Vertex,BondType> chordsToRecreateBB =
5090 new LinkedHashMap<Vertex,BondType>();
5091
5092 // Change direction of those edges that have to be reversed as a
5093 // consequence of the change in the spanning tree.
5094 if (chainToReverseA.size()+chainToReverseB.size() > 1)
5095 {
5096 List<Vertex> chainToWorkOn = null;
5097 for (int ic=0; ic<2; ic++)
5098 {
5099 if (ic == 1)
5100 chainToWorkOn = chainToReverseA;
5101 else
5102 chainToWorkOn = chainToReverseB;
5103
5104 for (int i=1; i<chainToWorkOn.size(); i++)
5105 {
5106 Vertex vHere = chainToWorkOn.get(i);
5107 Vertex vPrev = chainToWorkOn.get(i-1);
5108 List<Ring> ringsToRecreate = new ArrayList<>();
5109 for (Ring r : getRingsInvolvingVertex(vHere))
5110 {
5111 ringsToRecreate.add(r);
5112 chordsToRecreate.put(r.getHeadVertex(),
5113 r.getTailVertex());
5114 chordsToRecreateBB.put(r.getHeadVertex(),
5115 r.getBondType());
5116 }
5117 for (Ring r : ringsToRecreate)
5118 {
5119 removeRing(r);
5120 }
5121
5122 Edge edgeToPrevious = vHere.getEdgeWith(vPrev);
5123 if (edgeToPrevious == null)
5124 {
5125 // Since we have already made the new edge this should
5126 // never happen.
5127 String debugFile = "debug_"+v.getVertexId()+".json";
5128 DenoptimIO.writeGraphToJSON(new File(debugFile), this);
5129 throw new DENOPTIMException("Unconnected vertices "
5130 + vHere.getVertexId() + " and "
5131 + vPrev.getVertexId() + ". Unable to deal with "
5132 + "removal of " + v + " from ring " + frame
5133 + " in graph " + this.getGraphId()
5134 + ". See graph in " + debugFile);
5135 } else {
5136 if (edgeToPrevious.getSrcAP().getOwner() == vHere)
5137 {
5138 // This is an edge that has to be reversed.
5139 AttachmentPoint newSrcAP =
5140 edgeToPrevious.getTrgAP();
5141 AttachmentPoint newTrgAP =
5142 edgeToPrevious.getSrcAP();
5143 if (newSrcAP.getAPClass().isCPMapCompatibleWith(
5144 newTrgAP.getAPClass(), fragSpace))
5145 {
5146 BondType oldBt = edgeToPrevious.getBondType();
5147 removeEdge(edgeToPrevious);
5148 addEdge(new Edge(newSrcAP, newTrgAP,
5149 oldBt));
5150 } else {
5151 // There is a non-reversible connection along
5152 // the way, therefore we cannot do this
5153 // specific mutation.
5154 return false;
5155 }
5156 }
5157 }
5158 }
5159 }
5160 }
5161
5162 // Delete the chain to be removed
5163 for (Vertex vtr : toRemoveChain)
5164 {
5165 // This works across template boundaries!
5166 for (Vertex child : vtr.getChildrenThroughout())
5167 {
5168 if (remainingChain.contains(child)
5169 || toRemoveChain.contains(child))
5170 continue;
5171 DGraph ownerOfChild = child.getGraphOwner();
5172 ownerOfChild.removeVertex(child);
5173 }
5174 if (templateJacket!= null)
5175 {
5176 List<AttachmentPoint> apProjectionsToRemove =
5177 new ArrayList<AttachmentPoint>();
5178 for (AttachmentPoint outerAP :
5180 {
5181 AttachmentPoint innerAP =
5183 if (innerAP.getOwner() == vtr)
5184 {
5185 apProjectionsToRemove.add(innerAP);
5186 }
5187 }
5188 for (AttachmentPoint apToRemove : apProjectionsToRemove)
5190 }
5191 removeVertex(vtr);
5192 }
5193
5194 // Regenerate the rings that have been affected
5195 for (Vertex h : chordsToRecreate.keySet())
5196 {
5197 addRing(h, chordsToRecreate.get(h), chordsToRecreateBB.get(h));
5198 }
5199
5200 // Symmetry relation need to be compared with the change of topology.
5201 // The worst that can happen is that two vertices that are
5202 // listed as symmetric are, instead, one the (grand)parent of
5203 // the other. This is inconsistent with the expectations when
5204 // dealing with any operation with symmetric vertices.
5205 // A different level does NOT imply a parent-child relation,
5206 // but is a sign that the topology has changed substantially,
5207 // and that the symmetric relation is, most likely, not sensible
5208 // anymore.
5209 List<SymmetricVertexes> ssToRemove = new ArrayList<SymmetricVertexes>();
5210 Iterator<SymmetricVertexes> ssIter = getSymSetsIterator();
5211 while (ssIter.hasNext())
5212 {
5213 SymmetricVertexes ss = ssIter.next();
5214 int level = -2;
5215 for (Vertex vrt : ss)
5216 {
5217 if (level==-2)
5218 {
5219 level = getLevel(vrt);
5220 } else {
5221 if (level != getLevel(vrt))
5222 {
5223 ssToRemove.add(ss);
5224 break;
5225 }
5226 }
5227 }
5228 }
5229 for (SymmetricVertexes ss : ssToRemove)
5231
5232 // The free-ed up APs need to be projected to template's surface
5233 if (templateJacket!= null)
5234 {
5235 for (AttachmentPoint innerAP : getAvailableAPs())
5236 {
5238 }
5239 }
5240
5241 return true;
5242 }
5243
5244//------------------------------------------------------------------------------
5245
5251 @Deprecated
5253 {
5254 HashMap<Long, Long> nmap = new HashMap<>();
5255 for (int i=0; i<getVertexCount(); i++)
5256 {
5257 long vid = getVertexList().get(i).getVertexId();
5258 long nvid = -vid;
5259 nmap.put(vid, nvid);
5260
5261 getVertexList().get(i).setVertexId(nvid);
5262
5263 for (int j=0; j<getEdgeCount(); j++)
5264 {
5265 Edge e = getEdgeList().get(j);
5266 if (e.getSrcVertex() == vid) {
5267 e.getSrcAP().getOwner().setVertexId(nvid);
5268 }
5269 if (e.getTrgVertex() == vid) {
5270 e.getTrgAP().getOwner().setVertexId(nvid);
5271 }
5272 }
5273 }
5274 }
5275
5276//------------------------------------------------------------------------------
5277
5284 {
5286 }
5287
5288//------------------------------------------------------------------------------
5289
5296 public Map<Long,Long> renumberVerticesGetMap()
5297 {
5298 Map<Long, Long> nmap = new HashMap<>();
5299
5300 // for the vertices in the graph, get new vertex ids
5301 for (int i=0; i<getVertexCount(); i++)
5302 {
5303 Vertex v = getVertexList().get(i);
5304 long vid = v.getVertexId();
5305 long nvid = GraphUtils.getUniqueVertexIndex();
5306
5307 nmap.put(vid, nvid);
5308
5309 v.setVertexId(nvid);
5311 }
5312
5313 return nmap;
5314 }
5315
5316//------------------------------------------------------------------------------
5317
5326 public int getLevel(Vertex v)
5327 {
5328 ArrayList<Vertex> parentTree = new ArrayList<>();
5329 getParentTree(v,parentTree);
5330 return parentTree.size() - 1;
5331 }
5332
5333//------------------------------------------------------------------------------
5334
5353 public Object[] checkConsistency(RunTimeParameters settings)
5354 throws DENOPTIMException
5355 {
5356 return checkConsistency(settings, false);
5357 }
5358
5359//------------------------------------------------------------------------------
5360
5384 public Object[] checkConsistency(RunTimeParameters settings, boolean permissive)
5385 throws DENOPTIMException
5386 {
5388 if (settings.containsParameters(ParametersType.RC_PARAMS))
5389 {
5390 rcSettings = (RingClosureParameters)settings.getParameters(
5392 }
5394 if (settings.containsParameters(ParametersType.FS_PARAMS))
5395 {
5396 fsSettings = (FragmentSpaceParameters)settings.getParameters(
5398 }
5399
5400 // calculate the molecule representation
5401 ThreeDimTreeBuilder t3d = new ThreeDimTreeBuilder(settings.getLogger(),
5402 settings.getRandomizer());
5403 t3d.setAlignBBsIn3D(false);
5404 IAtomContainer mol = t3d.convertGraphTo3DAtomContainer(this,true);
5405 if (mol == null)
5406 {
5407 String msg ="Evaluation of graph: graph-to-mol returned null!"
5408 + toString();
5409 settings.getLogger().log(Level.FINE, msg);
5410 return null;
5411 }
5412
5413 // check if the molecule is connected
5414 boolean isConnected = ConnectivityChecker.isConnected(mol);
5415 if (!isConnected)
5416 {
5417 String msg = "Evaluation of graph: Not all connected"
5418 + toString();
5419 settings.getLogger().log(Level.FINE, msg);
5420 return null;
5421 }
5422
5423 // SMILES
5424 String smiles = null;
5425 smiles = MoleculeUtils.getSMILESForMolecule(mol,settings.getLogger());
5426 if (smiles == null)
5427 {
5428 String msg = "Evaluation of graph: SMILES is null! "
5429 + toString();
5430 settings.getLogger().log(Level.FINE, msg);
5431 smiles = "FAIL: NO SMILES GENERATED";
5432 }
5433 // if by chance the smiles indicates a disconnected molecule
5434 if (smiles.contains(".") && !permissive)
5435 {
5436 String msg = "Evaluation of graph: SMILES contains \".\"" + smiles;
5437 settings.getLogger().log(Level.FINE, msg);
5438 return null;
5439 }
5440
5441 // criteria from definition of Fragment space
5442 // 1A) number of heavy atoms
5443 if (fsSettings.getMaxHeavyAtom()>0 && !permissive)
5444 {
5446 fsSettings.getMaxHeavyAtom())
5447 {
5448 String msg = "Evaluation of graph: Max atoms constraint "
5449 + " violated: " + smiles;
5450 settings.getLogger().log(Level.FINE, msg);
5451 return null;
5452 }
5453 }
5454
5455 // 1B) molecular weight
5456 double mw = MoleculeUtils.getMolecularWeight(mol);
5457 if (fsSettings.getMaxMW()>0 && !permissive)
5458 {
5459 if (mw > fsSettings.getMaxMW())
5460 {
5461 String msg = "Evaluation of graph: Molecular weight "
5462 + "constraint violated: " + smiles + " | MW: " + mw;
5463 settings.getLogger().log(Level.FINE, msg);
5464 return null;
5465 }
5466 }
5467 mol.setProperty("MOL_WT", mw);
5468
5469 // 1C) number of rotatable bonds
5471 if (fsSettings.getMaxRotatableBond()>0 && !permissive)
5472 {
5473 if (nrot > fsSettings.getMaxRotatableBond())
5474 {
5475 String msg = "Evaluation of graph: Max rotatable bonds "
5476 + "constraint violated: "+ smiles;
5477 settings.getLogger().log(Level.FINE, msg);
5478 return null;
5479 }
5480 }
5481 mol.setProperty("ROT_BND", nrot);
5482
5483 // 1D) unacceptable free APs
5484 if (fsSettings.getFragmentSpace().useAPclassBasedApproach())
5485 {
5486 if (hasForbiddenEnd(fsSettings))
5487 {
5488 String msg = "Evaluation of graph: forbidden end in graph!";
5489 settings.getLogger().log(Level.FINE, msg);
5490 return null;
5491 }
5492 }
5493
5494 // criteria from settings of ring closures
5495 if (rcSettings.allowRingClosures() && !permissive)
5496 {
5497 // Count rings and RCAs
5498 int nPossRings = 0;
5499 Set<String> doneType = new HashSet<>();
5500 Map<String,String> rcaTypes = RingClosingAttractor.RCATYPEMAP;
5501 for (String rcaTyp : rcaTypes.keySet())
5502 {
5503 if (doneType.contains(rcaTyp))
5504 {
5505 continue;
5506 }
5507
5508 int nThisType = 0;
5509 int nCompType = 0;
5510 for (Vertex v : getRCVertices())
5511 {
5512 if (v.containsAtoms())
5513 {
5514 IAtom atm = v.getIAtomContainer().getAtom(0);
5515 if (MoleculeUtils.getSymbolOrLabel(atm).equals(rcaTyp))
5516 {
5517 nThisType++;
5518 } else if (MoleculeUtils.getSymbolOrLabel(atm).equals(
5519 rcaTypes.get(rcaTyp)))
5520 {
5521 nCompType++;
5522 }
5523 if (rcaTyp.equals(rcaTypes.get(rcaTyp)))
5524 {
5525 nCompType++;
5526 }
5527 }
5528 }
5529
5530 // check number of rca per type
5531 if (nThisType > rcSettings.getMaxRcaPerType(rcaTyp) ||
5532 nCompType > rcSettings.getMaxRcaPerType(rcaTyp))
5533 {
5534 String msg = "Evaluation of graph: too many RCAs! "
5535 + rcaTyp + ":" + nThisType + " "
5536 + rcaTypes.get(rcaTyp) + ":" + nCompType;
5537 settings.getLogger().log(Level.FINE, msg);
5538 return null;
5539 }
5540 if (nThisType < rcSettings.getMinRcaPerType(rcaTyp) ||
5541 nCompType < rcSettings.getMinRcaPerType(rcaTyp))
5542 {
5543 String msg = "Evaluation of graph: too few RCAs! "
5544 + rcaTyp + ":" + nThisType + " "
5545 + rcaTypes.get(rcaTyp) + ":" + nCompType;
5546 settings.getLogger().log(Level.FINE, msg);
5547 return null;
5548 }
5549
5550 nPossRings = nPossRings + Math.min(nThisType, nCompType);
5551 doneType.add(rcaTyp);
5552 doneType.add(rcaTypes.get(rcaTyp));
5553 }
5554 if (nPossRings < rcSettings.getMinRingClosures())
5555 {
5556 String msg = "Evaluation of graph: too few ring candidates";
5557 settings.getLogger().log(Level.FINE, msg);
5558 return null;
5559 }
5560 }
5561
5562 // get the smiles/Inchi representation
5563 String inchiKey = MoleculeUtils.getInChIKeyForMolecule(mol,
5564 settings.getLogger());
5565 if (inchiKey == null)
5566 {
5567 String msg = "Evaluation of graph: InChI Key is null!";
5568 settings.getLogger().log(Level.WARNING, msg);
5569 inchiKey = "UNDEFINED_INCHI";
5570 }
5571
5572 Object[] res = new Object[3];
5573 res[0] = inchiKey;
5574 res[1] = smiles;
5575 res[2] = mol;
5576
5577 return res;
5578 }
5579
5580//------------------------------------------------------------------------------
5581
5589 public ArrayList<DGraph> makeAllGraphsWithDifferentRingSets(
5590 RunTimeParameters settings)
5591 throws DENOPTIMException
5592 {
5594 if (settings.containsParameters(ParametersType.RC_PARAMS))
5595 {
5596 rcSettings = (RingClosureParameters)settings.getParameters(
5598 }
5600 if (settings.containsParameters(ParametersType.FS_PARAMS))
5601 {
5602 fsSettings = (FragmentSpaceParameters)settings.getParameters(
5604 }
5605 ArrayList<DGraph> lstGraphs = new ArrayList<>();
5606
5607 boolean rcnEnabled = fsSettings.getFragmentSpace()
5609 if (!rcnEnabled)
5610 return lstGraphs;
5611
5612 boolean evaluateRings = rcSettings.allowRingClosures();
5613 if (!evaluateRings)
5614 return lstGraphs;
5615
5616 // get a atoms/bonds molecular representation (no 3D needed)
5617 ThreeDimTreeBuilder t3d = new ThreeDimTreeBuilder(settings.getLogger(),
5618 settings.getRandomizer());
5619 t3d.setAlignBBsIn3D(false);
5620 IAtomContainer mol = t3d.convertGraphTo3DAtomContainer(this,false);
5621
5622 // Set rotatable property as property of IBond
5624 fsSettings.getRotSpaceDefFile(), true, true,
5625 settings.getLogger());
5626
5627 // get the set of possible RCA combinations = ring closures
5628 CyclicGraphHandler cgh = new CyclicGraphHandler(rcSettings,
5629 fsSettings.getFragmentSpace());
5630 ArrayList<List<Ring>> allCombsOfRings =
5631 cgh.getPossibleCombinationOfRings(mol, this);
5632
5633 // Keep closable chains that are relevant for chelate formation
5634 if (rcSettings.buildChelatesMode())
5635 {
5636 ArrayList<List<Ring>> toRemove = new ArrayList<>();
5637 for (List<Ring> setRings : allCombsOfRings)
5638 {
5639 if (!cgh.checkChelatesGraph(this,setRings))
5640 {
5641 toRemove.add(setRings);
5642 }
5643 }
5644 allCombsOfRings.removeAll(toRemove);
5645 }
5646
5647 // prepare output graphs
5648 for (List<Ring> ringSet : allCombsOfRings)
5649 {
5650 // clone root graph
5651 DGraph newGraph = this.clone();
5652
5653 Map<Long,Long> vRenum = newGraph.renumberVerticesGetMap();
5655
5656 // add rings
5657 for (Ring oldRing : ringSet)
5658 {
5659 Ring newRing = new Ring();
5660 for (int i=0; i<oldRing.getSize(); i++)
5661 {
5662 long oldVId = oldRing.getVertexAtPosition(i).getVertexId();
5663 long newVId = vRenum.get(oldVId);
5664 newRing.addVertex(newGraph.getVertexWithId(newVId));
5665 }
5666 newRing.setBondType(oldRing.getBondType());
5667 newGraph.addRing(newRing);
5668 }
5669
5670 // store
5671 lstGraphs.add(newGraph);
5672 }
5673
5674 return lstGraphs;
5675 }
5676
5677//------------------------------------------------------------------------------
5678
5686 public boolean hasForbiddenEnd(FragmentSpaceParameters fsSettings)
5687 {
5688 List<Vertex> vertices = getVertexList();
5689 Set<APClass> classOfForbEnds =
5691 boolean found = false;
5692 for (Vertex vtx : vertices)
5693 {
5694 List<AttachmentPoint> daps = vtx.getAttachmentPoints();
5695 for (AttachmentPoint dp : daps)
5696 {
5697 if (dp.isAvailable())
5698 {
5699 APClass apClass = dp.getAPClass();
5700 if (classOfForbEnds.contains(apClass))
5701 {
5702 found = true;
5703 String msg = "Forbidden free AP for Vertex: "
5704 + vtx.getVertexId() + " "
5705 + vtx.toString()
5706 + "\n"+ this +" \n "
5707 + " AP class: " + apClass;
5708 fsSettings.getLogger().log(Level.WARNING, msg);
5709 break;
5710 }
5711 }
5712 }
5713 if (found)
5714 {
5715 break;
5716 }
5717 }
5718
5719 return found;
5720 }
5721
5722//------------------------------------------------------------------------------
5723
5743 public void appendGraphOnGraph(List<Vertex> parentVertices,
5744 List<Integer> parentAPIdx,
5745 DGraph subGraph,
5746 Vertex childVertex, int childAPIdx,
5747 BondType bndType, boolean onAllSymmAPs)
5748 throws DENOPTIMException
5749 {
5750 // Collector for symmetries created by appending copies of subGraph
5751 Map<Vertex, SymmetricVertexes> newSymSets = new HashMap<>();
5752
5753 // Repeat append for each parent vertex while collecting symmetries
5754 for (int i=0; i<parentVertices.size(); i++)
5755 {
5756 appendGraphOnGraph(parentVertices.get(i), parentAPIdx.get(i),
5757 subGraph, childVertex, childAPIdx, bndType,
5758 newSymSets, onAllSymmAPs);
5759 }
5760 }
5761
5762//------------------------------------------------------------------------------
5763
5777 AttachmentPoint trgAP) throws DENOPTIMException
5778 {
5779 if (!srcAP.isAvailable())
5780 {
5781 throw new DENOPTIMException("Attempt to use unavailable attachment "
5782 + "point " + srcAP + " on vertex "
5783 + srcAP.getOwner().getVertexId());
5784 }
5785 if ( !trgAP.isAvailable())
5786 {
5787 throw new DENOPTIMException("Attempt to use unavailable attachment "
5788 + "point " + trgAP + " on vertex "
5789 + trgAP.getOwner().getVertexId());
5790 }
5791
5792 BondType btSrc = srcAP.getBondType();
5793 BondType btTrg = trgAP.getBondType();
5794 BondType bndTyp = btSrc;
5795 if (btSrc != btTrg)
5796 {
5797 if (btSrc == BondType.ANY && btTrg != BondType.ANY)
5798 {
5799 bndTyp = btTrg;
5800 } else {
5801 if (btSrc != BondType.ANY && btTrg == BondType.ANY)
5802 {
5803 bndTyp = btSrc;
5804 } else {
5805 bndTyp = BondType.UNDEFINED;
5806 }
5807 }
5808 }
5809
5810 this.addVertex(trgAP.getOwner());
5811 Edge edge = new Edge(srcAP,trgAP, bndTyp);
5812 addEdge(edge);
5813 }
5814
5815//------------------------------------------------------------------------------
5816
5826 public void appendGraphOnAP(AttachmentPoint apOnThisGraph,
5827 AttachmentPoint apOnIncomingGraph, BondType bndType)
5828 throws DENOPTIMException
5829 {
5830 DGraph incomingGraph = apOnIncomingGraph.getOwner().getGraphOwner();
5831 incomingGraph.renumberGraphVertices();
5832
5833 Edge edge = new Edge(apOnThisGraph, apOnIncomingGraph,
5834 bndType);
5835 addEdge(edge);
5836
5837 //Import vertices
5838 for (Vertex incomingVrtx : incomingGraph.getVertexList())
5839 {
5840 addVertex(incomingVrtx);
5841 }
5842
5843 //Import edges
5844 for (Edge incomingEdge : incomingGraph.getEdgeList())
5845 {
5846 addEdge(incomingEdge);
5847 }
5848
5849 //Import rings
5850 for (Ring incomingRing : incomingGraph.getRings())
5851 {
5852 addRing(incomingRing);
5853 }
5854
5855 incomingGraph.cleanup();
5856 }
5857
5858//------------------------------------------------------------------------------
5859
5880 public void appendGraphOnAP(Vertex parentVertex, int parentAPIdx,
5881 DGraph subGraph,
5882 Vertex childVertex, int childAPIdx,
5883 BondType bndType,
5884 Map<Vertex, SymmetricVertexes> newSymSets)
5885 throws DENOPTIMException
5886 {
5887 // Clone and renumber the subgraph to ensure uniqueness
5888 DGraph sgClone = subGraph.clone();
5889 // The clones have the same vertex IDs before renumbering vertices
5890 Vertex cvClone = sgClone.getVertexWithId(
5891 childVertex.getVertexId());
5892 sgClone.renumberGraphVertices();
5893
5894 Edge edge = new Edge(parentVertex.getAP(parentAPIdx),
5895 cvClone.getAP(childAPIdx), bndType);
5896 addEdge(edge);
5897
5898 // Import all vertices from cloned subgraph, i.e., sgClone
5899 for (int i=0; i<sgClone.getVertexList().size(); i++)
5900 {
5901 Vertex clonV = sgClone.getVertexList().get(i);
5902 Vertex origV = subGraph.getVertexList().get(i);
5903
5904 addVertex(sgClone.getVertexList().get(i));
5905
5906 // also need to tmp store pointers to symmetric vertices
5907 // Why is this working on subGraph and not on sgClone?
5908 // Since we are only checking is there is symmetry, there should be
5909 // no difference between doing it on sgClone or subGraph.
5910 if (subGraph.hasSymmetryInvolvingVertex(origV))
5911 {
5912 if (newSymSets.containsKey(origV))
5913 {
5914 newSymSets.get(origV).add(clonV);
5915 }
5916 else
5917 {
5918 newSymSets.put(origV, sgClone.getSymSetForVertex(clonV));
5919 }
5920 }
5921 else
5922 {
5923 if (newSymSets.containsKey(origV))
5924 {
5925 newSymSets.get(origV).add(clonV);
5926 }
5927 else
5928 {
5930 ss.add(clonV);
5931 newSymSets.put(origV, ss);
5932 }
5933 }
5934 }
5935 // Import all edges from cloned subgraph
5936 for (int i=0; i<sgClone.getEdgeList().size(); i++)
5937 {
5938 addEdge(sgClone.getEdgeList().get(i));
5939 }
5940 // Import all rings from cloned subgraph
5941 for (int i=0; i<sgClone.getRings().size(); i++)
5942 {
5943 addRing(sgClone.getRings().get(i));
5944 }
5945
5946 // project tmp symmetric set into final symmetric sets
5947 Set<SymmetricVertexes> doneTmpSymSets = new HashSet<SymmetricVertexes>();
5948 for (Map.Entry<Vertex, SymmetricVertexes> e : newSymSets.entrySet())
5949 {
5950 SymmetricVertexes tmpSS = e.getValue();
5951 if (doneTmpSymSets.contains(tmpSS))
5952 {
5953 continue;
5954 }
5955 doneTmpSymSets.add(tmpSS);
5956 boolean done = false;
5957 // NB: no need to check all entries of tmpSS: the first is enough
5958 SymmetricVertexes oldSS;
5959 Iterator<SymmetricVertexes> iter = getSymSetsIterator();
5960 while (iter.hasNext())
5961 {
5962 oldSS = iter.next();
5963 if (oldSS.contains(tmpSS.get(0)))
5964 {
5965 oldSS.addAll(tmpSS);
5966 done = true;
5967 break;
5968 }
5969 }
5970 if (!done)
5971 {
5972 if (tmpSS.size() <= 1)
5973 {
5974 // tmpSS has always at least one entry: the initial vrtx
5975 continue;
5976 }
5977 //Move tmpSS into a new SS on molGraph
5979 newSS.addAll(tmpSS);
5981 }
5982 }
5983 }
5984
5985//------------------------------------------------------------------------------
5986
6005 public void appendGraphOnGraph(Vertex parentVertex,
6006 int parentAPIdx, DGraph subGraph,
6007 Vertex childVertex, int childAPIdx,
6008 BondType bndType,
6009 Map<Vertex, SymmetricVertexes> newSymSets,
6010 boolean onAllSymmAPs)
6011 throws DENOPTIMException
6012 {
6013 SymmetricAPs symAPs = parentVertex.getSymmetricAPs(
6014 parentVertex.getAP(parentAPIdx));
6015 if (symAPs.size()!=0 && onAllSymmAPs)
6016 {
6017 for (AttachmentPoint symAP : symAPs)
6018 {
6019 if (!symAP.isAvailable())
6020 {
6021 continue;
6022 }
6023 appendGraphOnAP(parentVertex, symAP.getIndexInOwner(),
6024 subGraph, childVertex,
6025 childAPIdx, bndType, newSymSets);
6026 }
6027 } else {
6028 appendGraphOnAP(parentVertex, parentAPIdx, subGraph, childVertex,
6029 childAPIdx, bndType, newSymSets);
6030 }
6031 }
6032
6033//-----------------------------------------------------------------------------
6034
6042 public List<Long> findVerticesIds(VertexQuery query, Logger logger)
6043 {
6044 List<Long> matches = new ArrayList<>();
6045 for (Vertex v : findVertices(query, logger))
6046 {
6047 matches.add(v.getVertexId());
6048 }
6049 return matches;
6050 }
6051
6052//-----------------------------------------------------------------------------
6053
6062 public ArrayList<Vertex> findVertices(VertexQuery vrtxQuery, Logger logger)
6063 {
6064 return findVertices(vrtxQuery, true,logger);
6065 }
6066
6067//-----------------------------------------------------------------------------
6068
6079 public ArrayList<Vertex> findVertices(VertexQuery vrtxQuery,
6080 boolean purgeSym, Logger logger)
6081 {
6082 ArrayList<Vertex> matches = new ArrayList<>(getVertexList());
6083
6084 logger.log(Level.FINE, "Candidates: " + matches);
6085
6086 //Check condition vertex ID
6087 Long vidQuery = vrtxQuery.getVertexIDQuery();
6088 if (vidQuery != null)
6089 {
6090 ArrayList<Vertex> newLst = new ArrayList<>();
6091 for (Vertex v : matches)
6092 {
6093 if (v.getVertexId() == vidQuery.intValue())
6094 {
6095 newLst.add(v);
6096 }
6097 }
6098 matches = newLst;
6099 }
6100 logger.log(Level.FINE," After filtering by vertex ID: " + matches);
6101
6102 //Check condition vertex type (NB: essentially the vertex implementation
6103 VertexType vtQuery = vrtxQuery.getVertexTypeQuery();
6104 if (vtQuery != null)
6105 {
6106 ArrayList<Vertex> newLst = new ArrayList<>();
6107 for (Vertex v : matches)
6108 {
6109 if (v.getVertexType() == vtQuery)
6110 {
6111 newLst.add(v);
6112 }
6113 }
6114 matches = newLst;
6115 logger.log(Level.FINER, " After filtering by vertex type: "
6116 + matches);
6117 }
6118
6119 //Check condition building block Type
6120 BBType bbtQuery = vrtxQuery.getVertexBBTypeQuery();
6121 if (bbtQuery != null)
6122 {
6123 ArrayList<Vertex> newLst = new ArrayList<>();
6124 for (Vertex v : matches)
6125 {
6126 if (v.getBuildingBlockType() == bbtQuery)
6127 {
6128 newLst.add(v);
6129 }
6130 }
6131 matches = newLst;
6132 logger.log(Level.FINER, " After filtering by building block "
6133 + "type: " + matches);
6134 }
6135
6136 //Check condition building block ID
6137 Integer bbID = vrtxQuery.getVertexBBIDQuery();
6138 if (bbID != null)
6139 {
6140 ArrayList<Vertex> newLst = new ArrayList<>();
6141 for (Vertex v : matches)
6142 {
6143 if (v.getBuildingBlockId() == bbID.intValue())
6144 {
6145 newLst.add(v);
6146 }
6147 }
6148 matches = newLst;
6149 logger.log(Level.FINER, " After filtering by building block ID: "
6150 + matches);
6151 }
6152
6153 //Check condition: level of vertex
6154 Integer levelQuery = vrtxQuery.getVertexLevelQuery();
6155 if (levelQuery != null)
6156 {
6157 ArrayList<Vertex> newLst = new ArrayList<Vertex>();
6158 for (Vertex v : matches)
6159 {
6160 if (getLevel(v) == levelQuery)
6161 {
6162 newLst.add(v);
6163 }
6164 }
6165 matches = newLst;
6166 logger.log(Level.FINER, " After filtering by level: " + matches);
6167 }
6168
6169 logger.log(Level.FINE, "After all vertex-based filters: " + matches);
6170
6171 List<EdgeQuery> inAndOutEdgeQueries = new ArrayList<>();
6172 inAndOutEdgeQueries.add(vrtxQuery.getInEdgeQuery());
6173 inAndOutEdgeQueries.add(vrtxQuery.getOutEdgeQuery());
6174 for (int i=0; i<2; i++)
6175 {
6176 String inOrOut = "";
6177 if (i==0)
6178 inOrOut = "incoming";
6179 else
6180 inOrOut = "ourgoing";
6181
6182 EdgeQuery edgeQuery = inAndOutEdgeQueries.get(i);
6183 if (edgeQuery == null)
6184 {
6185 continue;
6186 }
6187
6188 EdgeFinder edgeFinder = new EdgeFinder(i-1);
6189
6190 Integer eTrgApIDx = edgeQuery.getTargetAPIdx();
6191 if (eTrgApIDx != null)
6192 {
6193 ArrayList<Vertex> newLst = new ArrayList<>();
6194 for (Vertex v : matches)
6195 {
6196 for (Edge e : edgeFinder.apply(v))
6197 {
6198 if (e.getTrgAPID() == eTrgApIDx)
6199 {
6200 newLst.add(v);
6201 break;
6202 }
6203 }
6204 }
6205 matches = newLst;
6206 logger.log(Level.FINER, " After " + inOrOut
6207 + " edge trgAPID filter: " + matches);
6208 }
6209
6210 Integer eInSrcApIDx = edgeQuery.getSourceAPIdx();
6211 if (eInSrcApIDx != null)
6212 {
6213 ArrayList<Vertex> newLst = new ArrayList<>();
6214 for (Vertex v : matches)
6215 {
6216 for (Edge e : edgeFinder.apply(v))
6217 {
6218 if (e != null && e.getSrcAPID() == eInSrcApIDx)
6219 {
6220 newLst.add(v);
6221 break;
6222 }
6223 }
6224 }
6225 matches = newLst;
6226 logger.log(Level.FINER, " After " + inOrOut
6227 + " edge srcAPID filter: " + matches);
6228 }
6229
6230 if (i==0)
6231 {
6232 Long eSrcVrtID = edgeQuery.getSourceVertexId();
6233 if (eSrcVrtID != null)
6234 {
6235 ArrayList<Vertex> newLst = new ArrayList<>();
6236 for (Vertex v : matches)
6237 {
6238 for (Edge e : edgeFinder.apply(v))
6239 {
6240 if(e.getSrcAP().getOwner().getVertexId()==eSrcVrtID)
6241 {
6242 newLst.add(v);
6243 break;
6244 }
6245 }
6246 }
6247 matches = newLst;
6248 logger.log(Level.FINER, " After " + inOrOut
6249 + " edge src VertexID filter: " + matches);
6250 }
6251 } else if (i==1) {
6252 Long eTrgVrtID = edgeQuery.getTargetVertexId();
6253 if (eTrgVrtID != null)
6254 {
6255 ArrayList<Vertex> newLst = new ArrayList<>();
6256 for (Vertex v : matches)
6257 {
6258 for (Edge e : edgeFinder.apply(v))
6259 {
6260 if(e.getTrgAP().getOwner().getVertexId()==eTrgVrtID)
6261 {
6262 newLst.add(v);
6263 break;
6264 }
6265 }
6266 }
6267 matches = newLst;
6268 logger.log(Level.FINER, " After " + inOrOut
6269 + " edge trg VertexID filter: " + matches);
6270 }
6271 }
6272
6273 BondType btQuery = edgeQuery.getBondType();
6274 if (btQuery != null)
6275 {
6276 ArrayList<Vertex> newLst = new ArrayList<>();
6277 for (Vertex v : matches)
6278 {
6279 for (Edge e : edgeFinder.apply(v))
6280 {
6281 if (e.getBondType() == btQuery)
6282 {
6283 newLst.add(v);
6284 break;
6285 }
6286 }
6287 }
6288 matches = newLst;
6289 logger.log(Level.FINER, " After " + inOrOut
6290 + " edge bond type filter: " + matches);
6291 }
6292
6293 APClass srcAPC = edgeQuery.getSourceAPClass();
6294 if (srcAPC != null)
6295 {
6296 ArrayList<Vertex> newLst = new ArrayList<>();
6297 for (Vertex v : matches)
6298 {
6299 for (Edge e : edgeFinder.apply(v))
6300 {
6301 if (e.getSrcAPClass().equals(srcAPC))
6302 {
6303 newLst.add(v);
6304 break;
6305 }
6306 }
6307 }
6308 matches = newLst;
6309 }
6310
6311 APClass trgAPC = edgeQuery.getTargetAPClass();
6312 if (trgAPC != null)
6313 {
6314 ArrayList<Vertex> newLst = new ArrayList<>();
6315 for (Vertex v : matches)
6316 {
6317 for (Edge e : edgeFinder.apply(v))
6318 {
6319 if (e.getTrgAPClass().equals(trgAPC))
6320 {
6321 newLst.add(v);
6322 break;
6323 }
6324 }
6325 }
6326 matches = newLst;
6327 }
6328 logger.log(Level.FINER, "After all " + inOrOut
6329 + " edge-based filters: " + matches);
6330 }
6331
6332 // Identify symmetric sets and keep only one member
6333 if (purgeSym)
6334 removeSymmetryRedundance(matches);
6335
6336 logger.log(Level.FINE, "Final Matches (after symmetry): " + matches);
6337
6338 return matches;
6339 }
6340
6341//-----------------------------------------------------------------------------
6342
6349 private class EdgeFinder implements Function<Vertex,List<Edge>>
6350 {
6351 private int mode = 0;
6352
6357 public EdgeFinder(int i)
6358 {
6359 mode = i;
6360 }
6361
6362 @Override
6363 public List<Edge> apply(Vertex v)
6364 {
6365 List<Edge> edges = new ArrayList<Edge>();
6366 if (mode < 0)
6367 {
6368 Edge eToParent = v.getEdgeToParent();
6369 if (eToParent != null)
6370 edges.add(eToParent);
6371 } else {
6373 {
6374 if (!ap.isAvailable() && ap.isSrcInUser())
6375 {
6376 edges.add(ap.getEdgeUser());
6377 }
6378 }
6379 }
6380 return edges;
6381 }
6382 }
6383
6384//-----------------------------------------------------------------------------
6385
6392 public void removeSymmetryRedundance(List<Vertex> list)
6393 {
6394 List<Vertex> symRedundant = new ArrayList<>();
6395 Iterator<SymmetricVertexes> itSymm = getSymSetsIterator();
6396 while (itSymm.hasNext())
6397 {
6398 SymmetricVertexes ss = itSymm.next();
6399 for (Vertex v : list)
6400 {
6401 if (symRedundant.contains(v))
6402 {
6403 continue;
6404 }
6405 if (ss.contains(v))
6406 {
6407 symRedundant.addAll(ss);
6408 symRedundant.remove(v);
6409 }
6410 }
6411 }
6412 for (Vertex v : symRedundant)
6413 {
6414 list.remove(v);
6415 }
6416 }
6417
6418//-----------------------------------------------------------------------------
6419
6426 public void removeSymmetryRedundantIds(ArrayList<Long> list) {
6427 ArrayList<Vertex> vList = new ArrayList<>();
6428 for (long vid : list) {
6429 vList.add(getVertexWithId(vid));
6430 }
6432 list.clear();
6433 for (Vertex v : vList) {
6434 list.add(v.getVertexId());
6435 }
6436 }
6437
6438//------------------------------------------------------------------------------
6439
6453 public DGraph editGraph(ArrayList<GraphEdit> edits,
6454 boolean symmetry, FragmentSpace fragSpace, Logger logger)
6455 throws DENOPTIMException
6456 {
6457 DGraph modGraph = this.clone();
6458
6459 for (GraphEdit edit : edits)
6460 {
6461 logger.log(Level.FINE, "Graph edit task: " + edit.getType());
6462
6463 switch (edit.getType())
6464 {
6465 case REPLACECHILD:
6466 {
6467 DGraph inGraph = edit.getIncomingGraph();
6468 VertexQuery query = edit.getVertexQuery();
6469 int idAPOnInGraph = -1; // Initialization to invalid value
6470 Vertex rootOfInGraph = null;
6471 if (edit.getIncomingAPId() != null)
6472 {
6473 AttachmentPoint ap = inGraph.getAPWithId(
6474 edit.getIncomingAPId().intValue());
6475 if (ap == null)
6476 {
6477 String msg = "Skipping " + edit.getType() + " on "
6478 + "graph " + getGraphId() + ". The incoming"
6479 + " graph has no AP with ID = "
6480 + edit.getIncomingAPId() + ". The IDs of "
6481 + "free APs are:";
6482 for (AttachmentPoint freeAP : inGraph.getAvailableAPs())
6483 {
6484 msg = msg + " " + freeAP.getID();
6485 }
6486 msg = msg + ". "
6487 + "Please, use one of those values in "
6488 + "'idAPOnIncomingGraph'.";
6489 logger.log(Level.WARNING, msg);
6490 }
6491 idAPOnInGraph = ap.getIndexInOwner();
6492 rootOfInGraph = ap.getOwner();
6493 } else {
6494 ArrayList<AttachmentPoint> freeAPs =
6495 inGraph.getAvailableAPs();
6496 if (freeAPs.size()==1)
6497 {
6498 AttachmentPoint ap = freeAPs.get(0);
6499 idAPOnInGraph = ap.getIndexInOwner();
6500 rootOfInGraph = ap.getOwner();
6501 } else {
6502 String geClsName = GraphEdit.class.getSimpleName();
6503 String msg = "Skipping " + edit.getType() + " on "
6504 + "graph " + getGraphId() + ". The incoming"
6505 + " graph has more than one free AP ("
6506 + freeAPs.size() + ") and "
6507 + "the " + geClsName + " "
6508 + "does not provide sufficient information "
6509 + "to unambiguously choose one AP. "
6510 + "Please, add 'idAPOnIncomingGraph' in "
6511 + "the definition of " + geClsName + ".";
6512 logger.log(Level.WARNING, msg);
6513 }
6514 }
6515
6516 ArrayList<Vertex> matches = modGraph.findVertices(query,
6517 false, logger);
6518 for (Vertex vertexToReplace : matches)
6519 {
6520 Edge edgeToParent = vertexToReplace.getEdgeToParent();
6521 if (edgeToParent == null)
6522 {
6523 //The matched vertex has no parent, therefore
6524 // the change would correspond to changing the graph
6525 // completely. This is unlikely the desired effect,
6526 // so we do not do anything.
6527 continue;
6528 }
6529 Vertex parent = vertexToReplace.getParent();
6530 int srcApId = edgeToParent.getSrcAPID();
6531
6532 BondType bondType = edgeToParent.getBondType();
6533
6534 modGraph.removeBranchStartingAt(vertexToReplace,symmetry);
6535
6536 modGraph.appendGraphOnGraph(parent, srcApId, inGraph,
6537 rootOfInGraph, idAPOnInGraph, bondType,
6538 new HashMap<Vertex, SymmetricVertexes>(), symmetry);
6539 }
6540 break;
6541 }
6542 case CHANGEVERTEX:
6543 {
6544 // One of the ways to provide the incoming vertex/subgraph
6545 if (edit.getIncomingBBId() > -1
6546 && edit.getIncomingBBType() != null
6547 && edit.getIncomingGraph() == null)
6548 {
6549 ArrayList<Vertex> matches = modGraph.findVertices(
6550 edit.getVertexQuery(), false, logger);
6551 for (Vertex vertexToChange : matches)
6552 {
6553 if (modGraph.containsVertex(vertexToChange))
6554 {
6555 DGraph graph = vertexToChange.getGraphOwner();
6556 graph.replaceVertex(vertexToChange,
6557 edit.getIncomingBBId(),
6558 edit.getIncomingBBType(),
6559 edit.getAPMappig(),
6560 symmetry,
6561 fragSpace);
6562 }
6563 }
6564 }
6565 // Another of the ways to provide the incoming vertex/subgraph
6566 if (edit.getIncomingGraph() != null
6567 && edit.getIncomingBBType() == null)
6568 {
6569 // Since the replaceSingleSubGraph method below does not
6570 // deal with symmetry, we keep symmetrically-redundant
6571 // matches
6572 ArrayList<Vertex> matches = modGraph.findVertices(
6573 edit.getVertexQuery(), false, logger);
6574
6575 for (Vertex vertexToChange : matches)
6576 {
6577 DGraph graph = vertexToChange.getGraphOwner();
6578 DGraph newSubG = edit.getIncomingGraph().clone();
6579 newSubG.renumberGraphVertices();
6580
6581 LinkedHashMap<AttachmentPoint,AttachmentPoint> apMap =
6582 new LinkedHashMap<AttachmentPoint,AttachmentPoint>();
6583 for (Map.Entry<Integer,Integer> e :
6584 edit.getAPMappig().entrySet())
6585 {
6586 apMap.put(vertexToChange.getAP(e.getKey()),
6587 newSubG.getAvailableAPs().get(
6588 e.getValue()));
6589 }
6590
6591 List<Vertex> oldSubG = new ArrayList<Vertex>();
6592 oldSubG.add(vertexToChange);
6593 graph.replaceSingleSubGraph(oldSubG, newSubG, apMap);
6594 }
6595 }
6596
6597 break;
6598 }
6599 case DELETEVERTEX:
6600 {
6601 ArrayList<Vertex> matches = modGraph.findVertices(
6602 edit.getVertexQuery(), false, logger);
6603 for (Vertex vertexToRemove : matches)
6604 {
6605 if (modGraph.containsVertex(vertexToRemove))
6606 modGraph.removeBranchStartingAt(vertexToRemove,
6607 symmetry);
6608 }
6609 break;
6610 }
6611 }
6612 }
6613 return modGraph;
6614 }
6615
6616//------------------------------------------------------------------------------
6617
6622 public List<Vertex> getMutableSites()
6623 {
6624 List<Vertex> mutableSites = new ArrayList<Vertex>();
6625 for (Vertex v : gVertices)
6626 {
6627 mutableSites.addAll(v.getMutationSites(
6628 new ArrayList<MutationType>()));
6629 }
6630 return mutableSites;
6631 }
6632
6633//------------------------------------------------------------------------------
6634
6642 public List<Vertex> getMutableSites(List<MutationType> ignoredTypes)
6643 {
6644 List<Vertex> mutableSites = new ArrayList<Vertex>();
6645 for (Vertex v : gVertices)
6646 {
6647 mutableSites.addAll(v.getMutationSites(ignoredTypes));
6648 }
6649 return mutableSites;
6650 }
6651
6652//------------------------------------------------------------------------------
6653
6660 public String toJson()
6661 {
6662 Gson gson = DENOPTIMgson.getWriter();
6663 String jsonOutput = gson.toJson(this);
6664 return jsonOutput;
6665 }
6666
6667//------------------------------------------------------------------------------
6668
6669 protected void ensureUniqueApIDs()
6670 {
6672 {
6673 ap.setID(apCounter.getAndIncrement());
6674 }
6675 }
6676
6677//------------------------------------------------------------------------------
6678
6685 public static DGraph fromJson(String json)
6686 {
6687 Gson gson = DENOPTIMgson.getReader();
6688 DGraph graph = gson.fromJson(json, DGraph.class);
6689 return graph;
6690 }
6691
6692//------------------------------------------------------------------------------
6693
6700 public static DGraph fromJson(Reader reader)
6701 {
6702 Gson gson = DENOPTIMgson.getReader();
6703 DGraph graph = gson.fromJson(reader, DGraph.class);
6704 return graph;
6705 }
6706
6707//------------------------------------------------------------------------------
6708
6712 public static class DENOPTIMGraphSerializer
6713 implements JsonSerializer<DGraph>
6714 {
6715 @Override
6716 public JsonElement serialize(DGraph g, Type typeOfSrc,
6717 JsonSerializationContext context)
6718 {
6719 boolean regenerateVrtxID = false;
6720 boolean regenerateAP = false;
6721 Set<Long> unqVrtxIDs = new HashSet<Long>();
6722 Set<Integer> unqApIDs = new HashSet<Integer>();
6723 for (Vertex v : g.getVertexList())
6724 {
6725 if (!unqVrtxIDs.add(v.getVertexId()))
6726 {
6727 regenerateVrtxID = true;
6728 }
6729 for (AttachmentPoint ap : v.getAttachmentPoints())
6730 {
6731 if (!unqApIDs.add(ap.getID()))
6732 {
6733 regenerateAP = true;
6734 break;
6735 }
6736 }
6737 }
6738 if (regenerateVrtxID)
6739 {
6741 }
6742 if (regenerateAP)
6743 {
6745 }
6746
6747 JsonObject jsonObject = new JsonObject();
6748 jsonObject.addProperty("graphId", g.graphId);
6749 jsonObject.add("gVertices", context.serialize(g.gVertices));
6750 jsonObject.add("gEdges", context.serialize(g.gEdges));
6751 jsonObject.add("gRings", context.serialize(g.gRings));
6752 jsonObject.add("symVertices", context.serialize(g.symVertices));
6753 return jsonObject;
6754 }
6755 }
6756
6757 //--------------------------------------------------------------------------
6758
6759 public static class DENOPTIMGraphDeserializer
6760 implements JsonDeserializer<DGraph>
6761 {
6762 @Override
6763 public DGraph deserialize(JsonElement json, Type typeOfT,
6764 JsonDeserializationContext context) throws JsonParseException
6765 {
6766 JsonObject jsonObject = json.getAsJsonObject();
6767
6768 // First, build a graph with a graph ID and a list of vertices
6769 JsonObject partialJsonObj = new JsonObject();
6770 partialJsonObj.add("graphId", jsonObject.get("graphId"));
6771 partialJsonObj.add("gVertices", jsonObject.get("gVertices"));
6772
6773 Gson gson = new GsonBuilder()
6774 .setExclusionStrategies(new DENOPTIMExclusionStrategyNoAPMap())
6775 .registerTypeAdapter(Vertex.class,
6777 .registerTypeAdapter(APClass.class, new APClassDeserializer())
6778 .setPrettyPrinting()
6779 .create();
6780
6781 DGraph graph = gson.fromJson(partialJsonObj, DGraph.class);
6782
6783 // Refresh APs
6784 for (Vertex v : graph.getVertexList())
6785 {
6786 // Regenerate reference to fragment owner
6787 v.setGraphOwner(graph);
6788
6789 for (AttachmentPoint ap : v.getAttachmentPoints())
6790 {
6791 // Regenerate reference to AP owner
6792 ap.setOwner(v);
6793 }
6794 }
6795
6796 // Then, recover those members that are heavily based on references:
6797 // edges, rings.
6798 JsonArray edgeArr = jsonObject.get("gEdges").getAsJsonArray();
6799 for (JsonElement e : edgeArr)
6800 {
6801 JsonObject o = e.getAsJsonObject();
6802 AttachmentPoint srcAP = graph.getAPWithId(
6803 o.get("srcAPID").getAsInt());
6804 AttachmentPoint trgAP = graph.getAPWithId(
6805 o.get("trgAPID").getAsInt());
6806
6807 Edge edge = new Edge(srcAP, trgAP,
6808 context.deserialize(o.get("bondType"),BondType.class));
6809 graph.addEdge(edge);
6810 }
6811
6812 // Now, recover the rings
6813 JsonArray ringArr = jsonObject.get("gRings").getAsJsonArray();
6814 for (JsonElement e : ringArr)
6815 {
6816 JsonObject o = e.getAsJsonObject();
6817 Ring ring = new Ring();
6818 for (JsonElement re : o.get("vertices").getAsJsonArray())
6819 {
6820 ring.addVertex(graph.getVertexWithId(re.getAsInt()));
6821 }
6822 ring.setBondType(context.deserialize(o.get("bndTyp"),
6823 BondType.class));
6824 graph.addRing(ring);
6825 }
6826
6827 //and symmetry relations between vertexes
6828 if (jsonObject.has("symVertices"))
6829 {
6830 for (JsonElement elSet : jsonObject.get("symVertices").getAsJsonArray())
6831 {
6833 for (JsonElement elId : elSet.getAsJsonArray())
6834 {
6835 int id = context.deserialize(elId, Integer.class);
6836 ss.add(graph.getVertexWithId(id));
6837 }
6838 try
6839 {
6840 graph.addSymmetricSetOfVertices(ss);
6841 } catch (DENOPTIMException e1)
6842 {
6843 e1.printStackTrace();
6844 throw new Error("Vertex listed in multiple symmetric "
6845 + "sets. Check this: " + elSet);
6846 }
6847 }
6848 }
6849
6850 return graph;
6851 }
6852 }
6853
6854//------------------------------------------------------------------------------
6855
6863 public static void setScaffold(Vertex v) {
6864 ArrayList<Vertex> newVertexList = new ArrayList<>();
6865
6866 Set<Long> visited = new HashSet<>();
6867 Queue<Vertex> currLevel = new ArrayDeque<>();
6868 Queue<Vertex> nextLevel = new ArrayDeque<>();
6869 currLevel.add(v);
6870
6871 while (!currLevel.isEmpty()) {
6872 Vertex currVertex = currLevel.poll();
6873
6874 long currId = currVertex.getVertexId();
6875 if (!visited.contains(currId)) {
6876 visited.add(currId);
6877
6878 newVertexList.add(currVertex);
6879
6880 Iterable<Vertex> neighbors = currVertex
6882 .stream()
6884 .filter(e -> e != null)
6885 .map(e -> e.getSrcVertex() == currId ?
6886 e.getTrgAP() : e.getSrcAP())
6888 .collect(Collectors.toList());
6889 for (Vertex adj : neighbors) {
6890 nextLevel.add(adj);
6891 }
6892 }
6893
6894 if (currLevel.isEmpty()) {
6895 currLevel = nextLevel;
6896 nextLevel = new ArrayDeque<>();
6897 }
6898 }
6899
6900 v.getGraphOwner().setVertexList(newVertexList);
6901 }
6902
6903//------------------------------------------------------------------------------
6904
6909 public boolean hasScaffoldTypeVertex() {
6910 return getVertexList()
6911 .stream()
6912 .anyMatch(v -> v.getBuildingBlockType() == BBType.SCAFFOLD);
6913 }
6914
6915//------------------------------------------------------------------------------
6916
6922 public void setTemplateJacket(Template template)
6923 {
6924 this.templateJacket = template;
6925 }
6926
6927//------------------------------------------------------------------------------
6928
6933 {
6934 return templateJacket;
6935 }
6936
6937//------------------------------------------------------------------------------
6938
6944 {
6945 if (templateJacket == null)
6946 return this;
6947 else
6949 }
6950
6951//------------------------------------------------------------------------------
6952
6965 public List<Template> getEmbeddingPath()
6966 {
6967 List<Template> path = new ArrayList<Template>();
6968 if (templateJacket==null)
6969 return path;
6970 if (templateJacket.getGraphOwner()!=null)
6972 path.add(templateJacket);
6973 return path;
6974 }
6975
6976//------------------------------------------------------------------------------
6977
6983 {
6984 for (Vertex v : gVertices)
6985 {
6986 v.setProperty(DENOPTIMConstants.STOREDVID, v.getVertexId());
6987 }
6988 }
6989
6990//------------------------------------------------------------------------------
6991
7005 public AttachmentPoint getAPOnLeftVertexID(long nbrVid, long vid)
7006 {
7007 Vertex v1 = getVertexWithId(nbrVid);
7008 Vertex v2 = getVertexWithId(vid);
7009 if ( v1== null || v2 == null)
7010 return null;
7011
7012 if (getChildVertices(v1).contains(v2))
7013 {
7014 return v2.getEdgeToParent().getSrcAP();
7015 } else if (getChildVertices(v2).contains(v1))
7016 {
7017 return v1.getEdgeToParent().getTrgAP();
7018 }
7019
7020 // At this point the two vertices are not directly connected, but there
7021 // could still be a chord between them. Here, we check for chords:
7022 /*
7023 for (DENOPTIMRing r : getRingsInvolvingVertex(v1))
7024 {
7025 if (r.contains(v2))
7026 {
7027 int lstId = r.getSize()-1;
7028 // Position 0 and lstId are where the RCVs sit
7029 if (r.getPositionOf(v1)==1 && r.getPositionOf(v2)==lstId)
7030 {
7031 return r.getHeadVertex().getEdgeToParent().getSrcAP();
7032 }
7033 if (r.getPositionOf(v1)==lstId && r.getPositionOf(v2)==1)
7034 {
7035 return r.getTailVertex().getEdgeToParent().getSrcAP();
7036 }
7037 }
7038 }
7039 */
7040 return null;
7041 }
7042
7043//------------------------------------------------------------------------------
7044
7054 public boolean isReversible(FragmentSpace fragSpace)
7055 {
7056 for (Edge e : gEdges)
7057 {
7058 if (!e.getTrgAPClass().isCPMapCompatibleWith(e.getSrcAPClass(),
7059 fragSpace))
7060 {
7061 return false;
7062 }
7063 }
7064 return true;
7065 }
7066
7067//------------------------------------------------------------------------------
7068
7086 DGraph graphB, List<Template> path)
7087 {
7088 if (path.isEmpty())
7089 return graphY;
7090 Template currentLevelVertex = null;
7091 DGraph currentLevelGraphEmdInB = graphB;
7092 DGraph currentLevelGraphEmbInY = graphY;
7093 for (Template t : path)
7094 {
7095 currentLevelVertex = (Template) currentLevelGraphEmbInY
7096 .getVertexAtPosition(currentLevelGraphEmdInB.indexOf(t));
7097 currentLevelGraphEmdInB = t.getInnerGraph();
7098 currentLevelGraphEmbInY = currentLevelVertex.getInnerGraph();
7099 }
7100 return currentLevelVertex.getInnerGraph();
7101 }
7102
7103//------------------------------------------------------------------------------
7104
7113 public List<AttachmentPoint> getInterfaceAPs(List<Vertex> subGraphB)
7114 {
7115 List<AttachmentPoint> interfaceAPs = new ArrayList<AttachmentPoint>();
7116 for (Vertex v : subGraphB)
7117 {
7118 for (AttachmentPoint ap : v.getAttachmentPoints())
7119 {
7120 if (ap.isAvailableThroughout())
7121 continue;
7122 if (ap.isAvailable())
7123 {
7124 // This AP is used across the template boundary
7125 interfaceAPs.add(ap);
7126 } else {
7127 Vertex user = ap.getLinkedAP().getOwner();
7128 if (!subGraphB.contains(user))
7129 {
7130 // AP used to make a connection to outside subgraph
7131 interfaceAPs.add(ap);
7132 }
7133 }
7134 }
7135 }
7136 return interfaceAPs;
7137 }
7138
7139//------------------------------------------------------------------------------
7140
7148 public List<AttachmentPoint> getSubgraphAPs(
7149 List<Vertex> subGraphB)
7150 {
7151 List<AttachmentPoint> aps = new ArrayList<AttachmentPoint>();
7152 for (Vertex v : subGraphB)
7153 {
7154 for (AttachmentPoint ap : v.getAttachmentPoints())
7155 {
7156 if (ap.isAvailable())
7157 {
7158 aps.add(ap);
7159 continue;
7160 }
7161 Vertex user = ap.getLinkedAP().getOwner();
7162 if (!subGraphB.contains(user))
7163 {
7164 // AP used to make a connection to outside subgraph
7165 aps.add(ap);
7166 }
7167 }
7168 }
7169 return aps;
7170 }
7171
7172//------------------------------------------------------------------------------
7173
7174}
General set of constants used in DENOPTIM.
static final Object GRAPHBRANCHID
Property of Vertex used to record the identity of the graph branch holding that Vertex.
static final Object STOREDVID
Key of the property remembering vertex IDs.
static final Object VRTSYMMSETID
Property of Vertex used to keep mark symmetric vertexes during graph operations and before defining t...
Class defining a space of building blocks.
boolean useAPclassBasedApproach()
Check usage of APClass-based approach, i.e., uses attachment points with annotated data (i....
APClass getAPClassOfCappingVertex(APClass srcApClass)
Parameters defining the fragment space.
boolean isCPMapCompatibleWith(APClass other, FragmentSpace fragSpace)
Check compatibility as defined in the compatibility matrix considering this AP as source and the othe...
Definition: APClass.java:455
BondType getBondType()
Definition: APClass.java:341
String toString()
Do not use this to make SDF representations.
Definition: APClass.java:352
Class representing a mapping between attachment points (APs).
Definition: APMapping.java:42
An attachment point (AP) is a possibility to attach a Vertex onto the vertex holding the AP (i....
AttachmentPoint getLinkedAP()
Gets the attachment point (AP) that is connected to this AP via the edge user.
void setUser(Edge edge)
Sets the reference to the edge that is using this attachment point.
APClass getAPClass()
Returns the Attachment Point class.
int getID()
Returns a unique integer that is used to sort list of attachment points.
BondType getBondType()
Returns the bond type preferred by this attachment point as defined by the APClass,...
boolean isAvailable()
Check availability of this attachment point.
boolean hasConnectedSrcAtom(AttachmentPoint other)
Checks if this and another APs are rooted on atoms that are bonded in any way other than a possible c...
boolean sameAs(AttachmentPoint other)
Compares the features of this and another attachment point and decides if the two are same.
boolean hasSameSrcAtom(AttachmentPoint other)
AttachmentPoint getLinkedAPThroughout()
Gets the attachment point (AP) that is connected to this AP via the edge user or in any edge user tha...
Edge getEdgeUser()
Gets the edge that is using this AP, or null if no edge is using this AP.
A candidate is the combination of a denoptim graph with molecular representation and may include also...
Definition: Candidate.java:40
DGraph deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
Definition: DGraph.java:6763
We expect unique IDs for vertices.
Definition: DGraph.java:6714
JsonElement serialize(DGraph g, Type typeOfSrc, JsonSerializationContext context)
Definition: DGraph.java:6716
Utility to make selection of edges to a vertex tunable by a parameter.
Definition: DGraph.java:6350
List< Edge > apply(Vertex v)
Definition: DGraph.java:6363
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:102
boolean removeVertexAndWeld(Vertex vertex, FragmentSpace fragSpace)
Remove a given vertex belonging to this graph and re-connects the resulting graph branches as much as...
Definition: DGraph.java:1195
List< ClosableChain > getClosableChains()
Definition: DGraph.java:712
void getChildrenTree(Vertex vertex, List< Vertex > children, int numLayers, boolean stopBeforeRCVs)
Gets all the children of the current vertex recursively.
Definition: DGraph.java:2906
void setTemplateJacket(Template template)
Sets the reference to a template that embeds this graph, i.e., this graph's "jacket" template.
Definition: DGraph.java:6922
void setVertexList(ArrayList< Vertex > vertices)
Definition: DGraph.java:678
String toJson()
Produces a string that represents this graph and that adheres to the JSON format.
Definition: DGraph.java:6660
void getChildTreeLimited(Vertex vertex, List< Vertex > children, Set< Vertex > limits)
Gets all the children of the current vertex recursively until it finds one of the vertices listed as ...
Definition: DGraph.java:3060
ArrayList< Integer > getIndexOfEdgesWithChild(int vid)
Definition: DGraph.java:3291
Candidate candidate
Reference to the candidate entity owning this graph, or null.
Definition: DGraph.java:144
boolean replaceVertex(Vertex vertex, int bbId, BBType bbt, LinkedHashMap< Integer, Integer > apIdMap, FragmentSpace fragSpace)
Replaced a given vertex belonging to this graph with a new vertex generated specifically for this pur...
Definition: DGraph.java:2258
AttachmentPoint getAPOnLeftVertexID(long nbrVid, long vid)
Finds the AP that is on the first given parameter and that is used to make a connection to the second...
Definition: DGraph.java:7005
Vertex getVertexWithId(long vid)
Searches for a vertex with the given identifier.
Definition: DGraph.java:2582
int getSymmetricSetCount()
Returns the number of symmetric sets of vertices.
Definition: DGraph.java:313
Vertex getSourceVertex()
Identifies and return the vertex from which the spanning tree originates.
Definition: DGraph.java:740
List< Integer > getBranchIdOfVertex(Vertex v)
Returns the branch identifier.
Definition: DGraph.java:2958
Edge getEdgeAtPosition(int pos)
Definition: DGraph.java:2649
void getChildrenTree(Vertex vertex, List< Vertex > children, boolean markBranches)
Gets all the children of the current vertex recursively.
Definition: DGraph.java:2804
DGraph embedPatternsInTemplates(GraphPattern pattern, FragmentSpace fragSpace, ContractLevel contract)
Searches for the given pattern type and generated a new graph where each set of (clones of) vertexes ...
Definition: DGraph.java:4637
DGraph extractSubgraph(int index)
Creates a new graph that corresponds to the subgraph of this graph when exploring the spanning tree f...
Definition: DGraph.java:4258
void removeRing(Ring ring)
Definition: DGraph.java:2637
ArrayList< AttachmentPoint > getAttachmentPoints()
Returns the list of all attachment points contained in this graph.
Definition: DGraph.java:3970
boolean containsVertexID(long l)
Checks if a number is already used as VertexIDs within the graph.
Definition: DGraph.java:3349
boolean containsVertex(Vertex v)
Check if this graph contains the specified vertex.
Definition: DGraph.java:2557
boolean isIsomorphicTo(DGraph other)
Checks if this graph is "DENOPTIM-isomorphic" to the other one given.
Definition: DGraph.java:3453
ArrayList< AttachmentPoint > getAvailableAPs()
Returns the list of available attachment points contained in this graph.
Definition: DGraph.java:3988
void setCandidateClosableChains(ArrayList< ClosableChain > closableChains)
Definition: DGraph.java:705
ArrayList< Ring > getRingsInvolvingVertex(Vertex v)
Returns the list of rings that include the given vertex in their fundamental cycle.
Definition: DGraph.java:826
void addVertex(Vertex vertex)
Appends a vertex to this graph without creating any edge.
Definition: DGraph.java:1097
ArrayList< Ring > getRingsInvolvingVertexID(int vid)
Definition: DGraph.java:871
int indexOfVertexWithID(long vid)
Returns the position of the first vertex that has the given ID.
Definition: DGraph.java:2598
boolean removeSingleVertexAndWeld(Vertex vertex, FragmentSpace fragSpace)
Remove a given vertex belonging to this graph and re-connects the resulting graph branches as much as...
Definition: DGraph.java:1247
List< ClosableChain > closableChains
The potentially closable chains of vertices.
Definition: DGraph.java:121
DefaultUndirectedGraph< Vertex, UndirectedEdge > jGraph
JGraph representation used to detect DENOPTIM-isomorphism.
Definition: DGraph.java:155
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:4616
DGraph(List< Vertex > gVertices, List< Edge > gEdges)
Definition: DGraph.java:176
void getChildrenTree(Vertex vertex, List< Vertex > children)
Gets all the children of the current vertex recursively.
Definition: DGraph.java:2771
boolean graphNeedsCappingGroups(FragmentSpace fragSpace)
Checks the graph for unused APs that need to be capped.
Definition: DGraph.java:4064
String getLocalMsg()
Definition: DGraph.java:279
AttachmentPoint getAPWithId(int id)
Returns the attachment point with the given identifier, or null if no AP is found with the given iden...
Definition: DGraph.java:4035
void removeVertex(Vertex vertex)
Remove a vertex from this graph.
Definition: DGraph.java:1119
Iterator< SymmetricVertexes > getSymSetsIterator()
Get an iterator for the sets of symmetrically related vertices.
Definition: DGraph.java:324
void setGraphId(int id)
Definition: DGraph.java:258
void removeSymmetryRedundance(List< Vertex > list)
Remove all but one of the symmetry-related partners in a list of vertices.
Definition: DGraph.java:6392
static void reorderVertexList(DGraph g)
Sets the vertex at the lowest level as the scaffold, changes the directions of edges so that the sc...
Definition: DGraph.java:4717
DGraph extractSubgraph(Vertex seed)
Creates a new graph that corresponds to the subgraph of this graph when exploring the spanning tree f...
Definition: DGraph.java:4277
ArrayList< Vertex > getRCVertices()
Search for ring closing vertices: vertices that contain only a RingClosingAttractor
Definition: DGraph.java:962
ArrayList< Vertex > getFreeRCVertices()
Search for unused ring closing vertices: vertices that contain only a RingClosingAttractor and are no...
Definition: DGraph.java:984
void setCandidateOwner(Candidate candidate)
Sets the reference to the candidate item that is defined by this graph.
Definition: DGraph.java:239
List< List< Vertex > > getSymmetricSubGraphs(List< Vertex > subGrpVrtxs)
We assume that the subgraph is a continuously connected, directed graph.
Definition: DGraph.java:1816
DGraph extractSubgraph(Vertex seed, int numLayers, boolean stopBeforeRCVs)
Creates a new graph that corresponds to the subgraph of this graph when exploring the spanning tree f...
Definition: DGraph.java:4303
int indexOf(Vertex v)
Returns the index of a vertex in the list of vertices of this graph.
Definition: DGraph.java:2569
DGraph editGraph(ArrayList< GraphEdit > edits, boolean symmetry, FragmentSpace fragSpace, Logger logger)
Edit this graph according to a given list of edit tasks.
Definition: DGraph.java:6453
List< Vertex > gVertices
The vertices belonging to this graph.
Definition: DGraph.java:106
boolean hasScaffoldTypeVertex()
Checks if this graph contains a scaffold vertex.
Definition: DGraph.java:6909
void setRings(ArrayList< Ring > rings)
Definition: DGraph.java:696
Object[] checkConsistency(RunTimeParameters settings)
Peeks into this graph to derive a preliminary chemical representation with SMILES and InChIKey.
Definition: DGraph.java:5353
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:2514
boolean containsAtoms()
Returns true if this graph has any vertex that contains atoms.
Definition: DGraph.java:3935
List< Edge > getEdgesWithTrg(Vertex v)
Returns the list of edges that arrive from the given vertex, i.e., edges where the trgAP is owned by ...
Definition: DGraph.java:805
static DGraph getEmbeddedGraphInClone(DGraph graphY, DGraph graphB, List< Template > path)
Searches for a graphs (X) embedded at any level in a graph (Y) by knowing.
Definition: DGraph.java:7085
List< Ring > gRings
The rings defined in this graph.
Definition: DGraph.java:116
int getBondingAPIndex(Vertex srcVert, int dapidx, Vertex dstVert)
Definition: DGraph.java:2725
void setSymmetricVertexSets(List< SymmetricVertexes > symVertices)
Definition: DGraph.java:647
AtomicInteger apCounter
Generator of unique AP identifiers within this graph.
Definition: DGraph.java:171
Vertex getDeepestAmongThese(List< Vertex > list)
Identify the oldest ancestor (i.e., most great grandparent) in the given collection.
Definition: DGraph.java:3123
void appendGraphOnAP(AttachmentPoint apOnThisGraph, AttachmentPoint apOnIncomingGraph, BondType bndType)
Appends a graph onto this graph.
Definition: DGraph.java:5826
static void setScaffold(Vertex v)
Update the graph so that the vertex argument is at the scaffold level i.e.
Definition: DGraph.java:6863
Map< DGraph, ObjectPair > extractPattern(GraphPattern pattern, boolean recordConnectivity)
Extracts subgraphs that match the provided pattern.
Definition: DGraph.java:4488
boolean isReversible(FragmentSpace fragSpace)
Checks is the every edge in the graph can be defined in the opposite direction according to the APCla...
Definition: DGraph.java:7054
String getBranchIdOfVertexAsStr(Vertex v)
Returns the branch identifier as a literal string.
Definition: DGraph.java:2978
List< AttachmentPoint > getAvailableAPsThroughout()
Returns the list of attachment points contained in this graph that are available throughout the templ...
Definition: DGraph.java:4011
boolean directedPathExists(Vertex src, Vertex trg)
Uses branch identifiers to define is two vertices are in such a relation that allows the drawing of a...
Definition: DGraph.java:3000
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:5776
List< Vertex > getVertexList()
Definition: DGraph.java:719
boolean removeBranchStartingAt(Vertex v)
Deletes the branch, i.e., the specified vertex and its children.
Definition: DGraph.java:4821
static boolean compareGraphNodes(Vertex thisV, DGraph thisG, Vertex otherV, DGraph otherG)
Compares graphs by spanning vertices starting from the given vertex and following the direction of ed...
Definition: DGraph.java:3825
boolean hasSymmetricAP()
Definition: DGraph.java:286
void convertSymmetricLabelsToSymmetricSets()
Looks for any symmetric labels, creates symmetric sets that collect the same information,...
Definition: DGraph.java:1600
DGraph(List< Vertex > gVertices, List< Edge > gEdges, List< Ring > gRings, List< ClosableChain > closableChains, List< SymmetricVertexes > symVertices)
Definition: DGraph.java:212
List< AttachmentPoint > getInterfaceAPs(List< Vertex > subGraphB)
Searches for all AttachmentPoints that represent the interface between a subgraph,...
Definition: DGraph.java:7113
DGraph clone()
Returns almost "deep-copy" of this graph.
Definition: DGraph.java:3186
boolean hasForbiddenEnd(FragmentSpaceParameters fsSettings)
Check if there are forbidden ends: free attachment points that are not suitable for capping and not a...
Definition: DGraph.java:5686
List< DGraph > extractPattern(GraphPattern pattern)
Extracts subgraphs that match the provided pattern.
Definition: DGraph.java:4457
void removeCappingGroups(List< Vertex > lstVerts)
Remove capping groups that belong to this graph and are in the given list.
Definition: DGraph.java:4114
ArrayList< Vertex > getChildVertices(Vertex vertex)
Definition: DGraph.java:2757
boolean sameAsRings(StringBuilder reason, Map< Vertex, Vertex > vertexMap, Ring rT, Vertex vhT, Vertex vtT, Ring rO)
Definition: DGraph.java:3775
DGraph extractSubgraph(Vertex seed, boolean stopBeforeRCVs)
Creates a new graph that corresponds to the subgraph of this graph when exploring the spanning tree f...
Definition: DGraph.java:4414
void renumberGraphVertices()
Reassign vertex IDs to all vertices of this graph.
Definition: DGraph.java:5283
boolean containsOrEmbedsVertex(Vertex v)
Check if the specified vertex is contained in this graph as a node or in any inner graphs that may be...
Definition: DGraph.java:2530
ArrayList< DGraph > makeAllGraphsWithDifferentRingSets(RunTimeParameters settings)
Evaluates the possibility of closing rings in this graph and generates all alternative graphs resulti...
Definition: DGraph.java:5589
static DGraph fromJson(Reader reader)
Reads a JSON string and returns an instance of this class.
Definition: DGraph.java:6700
void addRing(Vertex vI, Vertex vJ, BondType bndTyp)
Adds a chord between the given vertices, thus adding a ring in this graph.
Definition: DGraph.java:1075
List< Vertex > getSymVerticesForVertex(Vertex v)
Definition: DGraph.java:335
boolean replaceSubGraph(List< Vertex > subGrpVrtxs, DGraph incomingGraph, LinkedHashMap< AttachmentPoint, AttachmentPoint > apMap, FragmentSpace fragSpace)
Replaced the subgraph represented by a given collection of vertices that belong to this graph.
Definition: DGraph.java:1680
void changeSignOfVertexID()
Change all vertex IDs to the corresponding negative value.
Definition: DGraph.java:5252
static boolean compareGraphNodes(Vertex seedOnA, DGraph gA, Vertex seedOnB, DGraph gB, Map< Vertex, Vertex > vertexMap, StringBuilder reason)
Compares graphs by spanning vertices starting from the given vertex and following the direction of ed...
Definition: DGraph.java:3849
boolean insertSingleVertex(Edge edge, Vertex newLink, LinkedHashMap< AttachmentPoint, AttachmentPoint > apMap)
Inserts a given vertex in between two vertices connected by the given edge.
Definition: DGraph.java:2440
void getChildTreeLimited(Vertex vertex, List< Vertex > children, List< Vertex > limitsInClone, boolean stopBeforeRCVs)
Gets all the children of the current vertex recursively until it finds one of the vertices listed as ...
Definition: DGraph.java:3092
void reassignSymmetricLabels()
Marks the vertices of this graph with a string that is consistent for all vertices that belong to sym...
Definition: DGraph.java:1568
List< Edge > gEdges
The edges belonging to this graph.
Definition: DGraph.java:111
void replaceUnusedRCVsWithCapps(FragmentSpace fragSpace)
Removes unused ring-closing vertices.
Definition: DGraph.java:1526
void appendGraphOnGraph(List< Vertex > parentVertices, List< Integer > parentAPIdx, DGraph subGraph, Vertex childVertex, int childAPIdx, BondType bndType, boolean onAllSymmAPs)
Append a graph (incoming=I) onto this (receiving=R).
Definition: DGraph.java:5743
void setEdgeList(ArrayList< Edge > edges)
Definition: DGraph.java:687
boolean sameAs(DGraph other, StringBuilder reason)
Compare this and another graph ignoring the vertex IDs.
Definition: DGraph.java:3665
int getLevel(Vertex v)
Calculates the level of a vertex in this graph.
Definition: DGraph.java:5326
Vertex getParent(Vertex v)
Definition: DGraph.java:3168
void removeSymmetryRedundantIds(ArrayList< Long > list)
Remove all but one of the symmetry-related partners in a given list of vertex IDs.
Definition: DGraph.java:6426
void removeSymmetrySet(SymmetricVertexes ss)
Removed the given symmetric set, if present.
Definition: DGraph.java:620
void storeCurrentVertexIDs()
Copies the current vertexID of each vertex into a property of the vertex itself.
Definition: DGraph.java:6982
void appendGraphOnAP(Vertex parentVertex, int parentAPIdx, DGraph subGraph, Vertex childVertex, int childAPIdx, BondType bndType, Map< Vertex, SymmetricVertexes > newSymSets)
Append a subgraph (I) to this graph (R) specifying which vertex and attachment point to use for the c...
Definition: DGraph.java:5880
static void fixEdgeDirections(DGraph graph)
Flips edges in the graph so that the scaffold is the only source vertex.
Definition: DGraph.java:4733
DGraph getOutermostGraphOwner()
Definition: DGraph.java:6943
void removeCappingGroupsOn(Vertex vertex)
Remove capping groups on the given vertex of this graph.
Definition: DGraph.java:4084
List< Long > findVerticesIds(VertexQuery query, Logger logger)
Search a graph for vertices that match the criteria defined in a query vertex.
Definition: DGraph.java:6042
Map< SymmetricAPs, List< Vertex > > findSymmetrySetsOfChildVertexes(Vertex vrtx, Set< Vertex > alreadyAssignedVrtxs)
Definition: DGraph.java:460
static DGraph fromJson(String json)
Reads a JSON string and returns an instance of this class.
Definition: DGraph.java:6685
List< Edge > getEdgesWithSrc(Vertex v)
Returns the list of edges that depart from the given vertex, i.e., edges where the srcAP is owned by ...
Definition: DGraph.java:784
void addRing(Vertex vI, Vertex vJ)
Adds a chord between the given vertices, thus adding a ring in this graph.
Definition: DGraph.java:1047
List< Ring > getRings()
Definition: DGraph.java:771
DGraph extractSubgraph(Collection< Vertex > definedOn, Set< Edge > connectionToSubgraph, Set< Edge > connectionFromSubgraph)
Returns a clone of the subgraph defined by the a collection of vertices belonging to this graph.
Definition: DGraph.java:4558
boolean isVertexIDInRing(int vid)
Definition: DGraph.java:924
void addSymmetricSetOfVertices(SymmetricVertexes symSet)
Adds a symmetric set of vertices to this graph.
Definition: DGraph.java:661
SymmetricVertexes getSymSetForVertex(Vertex v)
Returns the set of vertexes symmetric to the given one.
Definition: DGraph.java:633
void getParentTree(Vertex vertex, List< Vertex > parentTree)
Traverse the graph until it identifies the source of the directed path reachable from the given verte...
Definition: DGraph.java:3149
void addCappingGroups(FragmentSpace fragSpace)
Add a capping groups on free unused attachment points.
Definition: DGraph.java:4169
DGraph(List< Vertex > gVertices, List< Edge > gEdges, List< Ring > gRings)
Definition: DGraph.java:190
List< Edge > getEdgeList()
Definition: DGraph.java:764
DGraph(List< Vertex > gVertices, List< Edge > gEdges, List< Ring > gRings, List< SymmetricVertexes > symSets)
Definition: DGraph.java:201
void removeCappingGroups()
Remove all capping groups on this graph.
Definition: DGraph.java:4156
void cleanup()
Wipes the data in this graph.
Definition: DGraph.java:3368
boolean hasRings()
Check for rings in this graph.
Definition: DGraph.java:892
void removeCappingGroupsFromChilds(List< Vertex > lstVerts)
Definition: DGraph.java:4142
Object[] checkConsistency(RunTimeParameters settings, boolean permissive)
Peeks into this graph to derive a preliminary chemical representation with SMILES and InChIKey.
Definition: DGraph.java:5384
List< Vertex > getMutableSites(List< MutationType > ignoredTypes)
A list of mutation sites from within this graph.
Definition: DGraph.java:6642
DefaultUndirectedGraph< Node, NodeConnection > jGraphKernel
JGraph representation used to detect DENOPTIM-isostructural graphs.
Definition: DGraph.java:161
ArrayList< Edge > getEdgesWithChild(int vid)
Definition: DGraph.java:3314
ArrayList< Vertex > findVertices(VertexQuery vrtxQuery, boolean purgeSym, Logger logger)
Filters a list of vertices according to a query.
Definition: DGraph.java:6079
boolean isVertexInRing(Vertex v)
Definition: DGraph.java:940
List< AttachmentPoint > getSubgraphAPs(List< Vertex > subGraphB)
Searches for all AttachmentPoints that are owned by vertices in a subgraph but either available or us...
Definition: DGraph.java:7148
Candidate getCandidateOwner()
Returns the reference of the candidate item that is defined by this graph.
Definition: DGraph.java:251
List< SymmetricVertexes > symVertices
Definition: DGraph.java:132
void addRing(Ring ring)
Definition: DGraph.java:1030
ArrayList< Ring > getRingsInvolvingVertex(Vertex[] vs)
Returns the list of rings that include the given list of vertices in their fundamental cycle.
Definition: DGraph.java:847
Map< Long, Long > renumberVerticesGetMap()
Reassign vertex IDs to a graph.
Definition: DGraph.java:5296
static boolean areApsUsedBySymmetricUsers(AttachmentPoint apA, AttachmentPoint apB, Set< Vertex > alreadyAssignedVrtxs)
Checks if the Vertexs that are attached to two given AttachmentPoints apA and apB satisfy these condi...
Definition: DGraph.java:565
boolean hasSymmetryInvolvingVertex(Vertex v)
Definition: DGraph.java:293
static void fixEdgeDirections(Vertex v, Set< Long > visited)
Recursive utility method for fixEdgeDirections(graph).
Definition: DGraph.java:4745
boolean replaceVertex(Vertex vertex, int bbId, BBType bbt, LinkedHashMap< Integer, Integer > apIdMap, boolean symmetry, FragmentSpace fragSpace)
Replaced a given vertex belonging to this graph with a new vertex generated specifically for this pur...
Definition: DGraph.java:2282
ArrayList< Vertex > getUsedRCVertices()
Search for used ring closing vertices: vertices that contain only a RingClosingAttractor and are part...
Definition: DGraph.java:1007
boolean insertVertex(Edge edge, int bbId, BBType bbt, LinkedHashMap< AttachmentPoint, Integer > apMap, FragmentSpace fragSpace)
Inserts a given vertex in between two vertices connected by the given edge.
Definition: DGraph.java:2360
Edge getEdgeWithParent(long l)
Looks for an edge that points to a vertex with the given vertex id.
Definition: DGraph.java:3273
void getChildrenTree(Vertex vertex, List< Vertex > children, AtomicInteger branchIdGenerator, List< Integer > prevBranchId)
Gets all the children of the current vertex recursively.
Definition: DGraph.java:2861
void removeEdge(Edge edge)
Removes an edge and update the free valences of the attachment points that were originally involved i...
Definition: DGraph.java:2620
void getChildTreeLimited(Vertex vertex, List< Vertex > children, boolean stopBeforeRCVs)
Gets all the children of the current vertex recursively.
Definition: DGraph.java:3028
Template templateJacket
Reference to the Template embedding this graph.
Definition: DGraph.java:149
boolean removeBranchStartingAt(Vertex v, boolean symmetry)
Deletes the branch, i.e., the specified vertex and its children.
Definition: DGraph.java:4788
int getHeavyAtomsCount()
Calculate the number of atoms from the graph representation.
Definition: DGraph.java:3953
DGraph extractSubgraph(Collection< Vertex > definedOn)
Returns a clone of the subgraph defined by the a collection of vertices belonging to this graph.
Definition: DGraph.java:4539
boolean removeOrphanBranchStartingAt(Vertex v)
Deletes the branch, i.e., the specified vertex and its children.
Definition: DGraph.java:4847
List< Vertex > getMutableSites()
A list of mutation sites from within this graph.
Definition: DGraph.java:6622
String localMsg
A free-format string used to record simple properties in the graph.
Definition: DGraph.java:139
void addEdge(Edge edge)
Adds the edge to the list of edges belonging to this graph.
Definition: DGraph.java:1021
boolean replaceSingleSubGraph(List< Vertex > subGrpVrtxs, DGraph newSubGraph, LinkedHashMap< AttachmentPoint, AttachmentPoint > apMap)
Replaced the subgraph represented by a given collection of vertices that belong to this graph.
Definition: DGraph.java:1954
List< Template > getEmbeddingPath()
Find the path that one has to traverse to reach this graph from any template-embedding structure.
Definition: DGraph.java:6965
void addCappingGroups(List< Vertex > vertexAddedToThis, FragmentSpace fragSpace)
Add a capping group on the given vertices, if needed.
Definition: DGraph.java:4192
Template getTemplateJacket()
Definition: DGraph.java:6932
boolean removeChainUpToBranching(Vertex v, FragmentSpace fragSpace)
Mutates the graph by removing the chain where a given vertex is located up to the first branching (i....
Definition: DGraph.java:4878
List< Integer > getBranchIdOfVertexAtPosition(int i)
Returns the branch identifier.
Definition: DGraph.java:2941
void setLocalMsg(String msg)
Definition: DGraph.java:272
void appendGraphOnGraph(Vertex parentVertex, int parentAPIdx, DGraph subGraph, Vertex childVertex, int childAPIdx, BondType bndType, Map< Vertex, SymmetricVertexes > newSymSets, boolean onAllSymmAPs)
Append a graph (incoming=I) onto this graph (receiving=R).
Definition: DGraph.java:6005
boolean isIsostructuralTo(DGraph other)
Checks if this graph is "DENOPTIM-isostructural" to the other one given.
Definition: DGraph.java:3580
DGraph extractSubgraph(Vertex seed, List< Vertex > limits, boolean stopBeforeRCVs)
Creates a new graph that corresponds to the subgraph of this graph when exploring the spanning tree f...
Definition: DGraph.java:4354
boolean hasOrEmbedsRings()
Check for rings in this graph and in any graph that is embedded at any level in any vertex of this gr...
Definition: DGraph.java:906
boolean detectSymVertexSets()
Tries to determine the set of symmetric vertices in this graph based on finding compatible Vertexes t...
Definition: DGraph.java:372
ArrayList< Vertex > findVertices(VertexQuery vrtxQuery, Logger logger)
Filters a list of vertices according to a query.
Definition: DGraph.java:6062
This class represents the edge between two vertices.
Definition: Edge.java:38
AttachmentPoint getTrgAP()
Definition: Edge.java:115
void flipEdge()
Exchanges source and target vertices and respective APs of this edge.
Definition: Edge.java:292
long getSrcVertex()
Definition: Edge.java:122
AttachmentPoint getSrcAP()
Definition: Edge.java:94
long getTrgVertex()
Definition: Edge.java:143
BondType getBondType()
Definition: Edge.java:164
A query for edges: a list of properties that target edges should possess in order to match this query...
Definition: EdgeQuery.java:28
Class representing a continuously connected portion of chemical object holding attachment points.
Definition: Fragment.java:61
boolean isIsomorphicTo(Vertex other)
Checks for isomorphism of the graph representation of this and another fragment.
Definition: Fragment.java:1066
This class represents the closure of a ring in a spanning tree.
Definition: Ring.java:40
Vertex getTailVertex()
Definition: Ring.java:95
int getPositionOf(Vertex v)
Definition: Ring.java:415
void addVertex(Vertex v)
Append a DENOPTIMVertex to the list.
Definition: Ring.java:71
Vertex getVertexAtPosition(int i)
Definition: Ring.java:107
void setBondType(BondType bndType)
Set the bond type (i.e., bond order) of the chord connecting the head and the tail vertices.
Definition: Ring.java:158
List< Vertex > getVertices()
Definition: Ring.java:214
Vertex getHeadVertex()
Definition: Ring.java:83
A collection of AttachmentPoints that are related by a relation that we call "symmetry",...
Set< SymmetricAPs > getAllSameAs(Set< SymmetricAPs > others)
Identifies any set of symmetric APs that, although it contains references to different instances of A...
boolean add(T item)
Adds an item to this list, if not already present.
A collection of Vertexs that are related by a relation that we call "symmetry", even though this clas...
void removeProjectionOfInnerAP(AttachmentPoint oldInnerAP)
Removes the mapping of the given inner AP from this template's surface, if such mapping exists.
Definition: Template.java:399
void setInnerGraph(DGraph innerGraph)
Definition: Template.java:298
void updateInnerApID(AttachmentPoint oldInnerAP, AttachmentPoint newInnerAP)
Replaces a given link between APs on the surface of this template (i.e., outerAP) and the correspondi...
Definition: Template.java:377
void addInnerToOuterAPMapping(AttachmentPoint newInnerAP)
Adds the projection of an AP in the template's inner graph (i.e., innerAP) to the list of APs visible...
Definition: Template.java:348
ArrayList< AttachmentPoint > getAttachmentPoints()
Return the list of attachment points visible from outside the template, i.e., the so-called outer APs...
Definition: Template.java:458
void clearIAtomContainer()
Removes the molecular representation.
Definition: Template.java:600
void setContractLevel(ContractLevel contract)
Imposes the given contract to this template.
Definition: Template.java:214
AttachmentPoint getOuterAPFromInnerAP(AttachmentPoint innerAP)
Definition: Template.java:828
AttachmentPoint getInnerAPFromOuterAP(AttachmentPoint outerAP)
Definition: Template.java:808
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
ArrayList< Vertex > getChildrenThroughout()
Looks into the edges that use any of the APs that belong to this vertex and returns the list of verti...
Definition: Vertex.java:1057
abstract Vertex clone()
Returns a deep-copy of this vertex.
void setMutationTypes(List< MutationType > lst)
Definition: Vertex.java:809
int getBuildingBlockId()
Returns the index of the building block that should correspond to the position of the building block ...
Definition: Vertex.java:284
Edge getEdgeToParent()
Looks into the edges that use any of the APs that belong to this vertex and returns the edge that has...
Definition: Vertex.java:972
void setVertexId(long vertexId2)
Definition: Vertex.java:261
int getFreeAPCountThroughout()
Counts the number of attachment points that are availability throughout the graph level,...
Definition: Vertex.java:410
int getIndexOfAP(AttachmentPoint ap)
Returns the position of the given AP in the list of APs of this vertex.
Definition: Vertex.java:949
Vertex getParent()
Looks into the edges that use any of the APs that belong to this vertex and returns the vertex which ...
Definition: Vertex.java:996
Vertex.BBType getBuildingBlockType()
Definition: Vertex.java:298
DGraph getGraphOwner()
Returns the graph this vertex belongs to or null.
Definition: Vertex.java:779
ArrayList< Vertex > getChilddren()
Looks into the edges that use any of the APs that belong to this vertex and returns the list of verti...
Definition: Vertex.java:1085
abstract List< AttachmentPoint > getAttachmentPoints()
abstract List< SymmetricAPs > getSymmetricAPSets()
Object getProperty(Object property)
Definition: Vertex.java:1136
boolean sameAs(Vertex other)
Compares this and another vertex ignoring vertex IDs.
Definition: Vertex.java:597
int getCappedAPCountThroughout()
Counts the number of attachment points that are used by BBType#CAP vertex.
Definition: Vertex.java:493
void setProperty(Object key, Object property)
Definition: Vertex.java:1148
ArrayList< AttachmentPoint > getFreeAPThroughout()
Gets attachment points that are availability throughout the graph level, i.e., checks also across the...
Definition: Vertex.java:382
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
Definition: Vertex.java:920
static Vertex newVertexFromLibrary(int bbId, Vertex.BBType bbt, FragmentSpace fragSpace)
Builds a new molecular fragment kind of vertex.
Definition: Vertex.java:214
Edge getEdgeWith(Vertex other)
Finds the edge between this and the other vertex, if it exists.
Definition: Vertex.java:1419
Query for searching vertices.
ClosableChain represents a chain of fragments (chain links) that is closable (or candidate closable).
This is a tool to identify and manage vertices' connections not included in the DGraph,...
boolean checkChelatesGraph(DGraph molGraph, List< Ring > ringsSet)
Evaluates the combination of a DENOPTIMGraph and a set of DENOPTIMRings and decides whether it's a pr...
ArrayList< List< Ring > > getPossibleCombinationOfRings(IAtomContainer mol, DGraph molGraph)
Identifies all possible ring closing paths and returns them as list of DENOPTIMRings ready to be appe...
This object represents a path in a DGraph.
List< Vertex > getVertecesPath()
Returns the list of verteces involved.
The RingClosingAttractor represent the available valence/connection that allows to close a ring.
static final Map< String, String > RCATYPEMAP
Recognized types of RingClosingAttractor and compatible types.
Parameters and setting related to handling ring closures.
boolean buildChelatesMode
Flag activating procedures favoring formation of chelates.
This class represents a subgraph feature that defined the structure of a graph.
Definition: Node.java:32
int compare(Node other)
Definition: Node.java:76
static final String REFTOVERTEXKERNEL
Property if Vertex used to store the reference to the corresponding Node.
Definition: Node.java:47
Utility methods for input/output.
static void writeGraphToJSON(File file, DGraph graph)
Writes the graph to JSON file.
Class for de/serializing DENOPTIM graphs from/to JSON format.
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.
Collection of parameters controlling the behavior of the software.
RunTimeParameters getParameters(ParametersType type)
Logger getLogger()
Get the name of the program specific logger.
static< T > void unionOfIntersectingSets(List< Set< T > > list)
Takes the union of any two sets in this list that intersect.
Tool to convert string into graphs and into molecular representation.
static DefaultUndirectedGraph< Vertex, UndirectedEdge > getJGraphFromGraph(DGraph dg)
Converts a DGraph into a simplified JGraphT DefaultUndirectedGraph.
static DefaultUndirectedGraph< Node, NodeConnection > getJGraphKernelFromGraph(DGraph dg)
Converts a DGraph into a simplified JGraphT DefaultUndirectedGraph.
Definition of a graph editing task.
Definition: GraphEdit.java:38
Utilities for graphs.
Definition: GraphUtils.java:40
static synchronized void ensureVertexIDConsistency(long l)
Method used to ensure consistency between internal atomic integer and vertex id from imported graphs.
Definition: GraphUtils.java:55
static synchronized long getUniqueVertexIndex()
Unique counter for the number of graph vertices generated.
Definition: GraphUtils.java:97
static synchronized int getUniqueGraphIndex()
Unique counter for the number of graphs generated.
Utilities for molecule conversion.
static String getInChIKeyForMolecule(IAtomContainer mol, Logger logger)
Generates the InChI key for the given atom container.
static int getNumberOfRotatableBonds(IAtomContainer mol)
Count number of rotatable bonds.
static String getSMILESForMolecule(IAtomContainer mol, Logger logger)
Returns the SMILES representation of the molecule.
static double getMolecularWeight(IAtomContainer mol)
static String getSymbolOrLabel(IAtom atm)
Gets either the elemental symbol (for standard atoms) of the label (for pseudo-atoms).
static int getHeavyAtomCount(IAtomContainer mol)
The heavy atom count.
This class is the equivalent of the Pair data structure used in C++ Although AbstractMap....
Definition: ObjectPair.java:30
Tool box for definition and management of the rotational space, which is given by the list of rotatab...
static ArrayList< ObjectPair > defineRotatableBonds(IAtomContainer mol, String defRotBndsFile, boolean addIterfragBonds, boolean excludeRings, Logger logger)
Define the rotational space (also torsional space) for a given molecule.
Identifier for the format of string representations of a graph.
Definition: DGraph.java:166
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
The type of building block.
Definition: Vertex.java:86
Flag declaring the type of Vertex implementation.
Definition: Vertex.java:172
FS_PARAMS
Parameters pertaining the definition of the fragment space.
RC_PARAMS
Parameters pertaining to ring closures in graphs.