$darkmode
DENOPTIM
RingSizeManager.java
Go to the documentation of this file.
1package denoptim.graph.rings;
2
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.List;
6import java.util.Map;
7import java.util.logging.Level;
8import java.util.logging.Logger;
9
10import org.openscience.cdk.Bond;
11import org.openscience.cdk.graph.matrix.TopologicalMatrix;
12import org.openscience.cdk.interfaces.IAtom;
13import org.openscience.cdk.interfaces.IAtomContainer;
14import org.openscience.cdk.interfaces.IBond;
15
16import denoptim.constants.DENOPTIMConstants;
17import denoptim.exception.DENOPTIMException;
18import denoptim.fragspace.FragmentSpace;
19import denoptim.graph.APClass;
20import denoptim.graph.AttachmentPoint;
21import denoptim.graph.DGraph;
22import denoptim.graph.Edge;
23import denoptim.graph.EmptyVertex;
24import denoptim.graph.Fragment;
25import denoptim.graph.Ring;
26import denoptim.graph.Vertex;
27import denoptim.graph.Edge.BondType;
28import denoptim.utils.MoleculeUtils;
29
36{
40 private IAtomContainer mol;
41
46 private int[][] topoMat;
47
52 private ArrayList<Vertex> lstVert;
53
57 private int sz;
58
62 private boolean[][] compatibilityOfPairs;
63
68 private List<Double> weigths;
69
75 private List<Boolean> done;
76
80 private Map<Vertex,ArrayList<Integer>> vIdToAtmId;
81
85 private List<Integer> ringSizeBias;
86
90 private FragmentSpace fragSpace = null;
91
96
100 private Logger logger;
101
105 private static final String NL = DENOPTIMConstants.EOL;
106
107//-----------------------------------------------------------------------------
108
116 RingClosureParameters rcParams)
117 {
118 this.fragSpace = fragSpace;
119 this.settings = rcParams;
120 this.logger = rcParams.getLogger();
121 this.ringSizeBias = rcParams.getRingSizeBias();
122 }
123
124//-----------------------------------------------------------------------------
125
133 public void initialize(IAtomContainer origMol, DGraph graph)
134 {
135 try
136 {
137 mol = (IAtomContainer) origMol.clone();
138 } catch (Throwable t) {
139 throw new IllegalArgumentException(t);
140 }
141
142 // Get the list of available RCAs
143 lstVert = graph.getFreeRCVertices();
144 sz = lstVert.size();
145
146 // Define link between list of vertices and list of atoms
148
149 // Build topological matrix
151
152 // Define compatibility of RCA pairs and weight factors
154
155 // Initialize vector of flags
156 done = new ArrayList<Boolean>(Collections.nCopies(sz,false));
157 }
158
159//-----------------------------------------------------------------------------
160
161 // NOTE: we don't really need the whole topological matrix, so the
162 // calculation of the shortest paths between the RCAs could be more
163 // efficient
164
165//TODO evaluate use of ShortestPath to fill only certain entries of topoMat
166
168 {
169 long startTime = System.nanoTime();
170 topoMat = TopologicalMatrix.getMatrix(mol);
171 long endTime = System.nanoTime();
172 long duration = (- startTime + endTime) / (long) 1000.0;
173
174 if (logger.isLoggable(Level.FINE))
175 {
176 StringBuilder sb = new StringBuilder();
177 sb.append("TopoMat N: " + mol.getAtomCount() + " " + duration
178 + " microsec." + NL);
179 int n = mol.getAtomCount();
180 sb.append("Topological matrix (n=" + n + ")"+NL);
181 for (int i=0; i<n; i++)
182 {
183 String l = " ";
184 for (int j=0; j<n; j++)
185 {
186 l = l + " " + topoMat[i][j];
187 }
188 sb.append(l+NL);
189 }
190 logger.log(Level.FINE, sb.toString());
191 }
192 }
193
194//-----------------------------------------------------------------------------
195
196 // NOTE: this method considers the ring size bias and sets also
197 // the weight factors
198
200 {
201 weigths = new ArrayList<Double>(Collections.nCopies(sz, 0.0));
202 compatibilityOfPairs = new boolean[sz][sz];
203 for (int i=0; i<sz; i++)
204 {
205 Vertex vI = lstVert.get(i);
206 IAtom atmI = null;
207 RingClosingAttractor rcaI = null;
208 boolean isAtmI = vI instanceof Fragment;
209 if (isAtmI)
210 {
211 atmI = mol.getAtom(vIdToAtmId.get(vI).get(0));
212
213 // Dealing with the possibility that RCV is the scaffold
214 if (mol.getConnectedAtomsList(atmI).size()==0)
215 continue;
216
217 rcaI = new RingClosingAttractor(atmI,mol);
218 if (!rcaI.isAttractor())
219 {
220 String s = "Attempt to evaluate RCA pair compatibility "
221 + "with a non-RCA end (" + atmI + ").";
222 throw new IllegalStateException(s);
223 }
224 }
225
226 for (int j=i+1; j<sz; j++)
227 {
228 Vertex vJ = lstVert.get(j);
229 IAtom atmJ = null;
230 RingClosingAttractor rcaJ = null;
231 boolean isAtmJ = vJ instanceof Fragment;
232 if (isAtmJ)
233 {
234 atmJ = mol.getAtom(vIdToAtmId.get(vJ).get(0));
235
236 rcaJ = new RingClosingAttractor(atmJ,mol);
237 if (!rcaJ.isAttractor())
238 {
239 String s = "Attempt to evaluate RCA pair compatibility "
240 + "with a non-RCA end (" + atmJ + ").";
241 throw new IllegalStateException(s);
242 }
243 }
244
245 if ((isAtmI && !isAtmJ) || (!isAtmI && isAtmJ))
246 {
247 continue;
248 }
249 if (!isAtmI && !isAtmJ)
250 {
251 // Ring size is ignored when RCVs are empty vertexes
252 compatibilityOfPairs[i][j] = true;
253 compatibilityOfPairs[j][i] = true;
254 weigths.set(i, weigths.get(i) + 1.0);
255 weigths.set(j, weigths.get(j) + 1.0);
256 continue;
257 }
258
259 if (rcaI.isCompatible(rcaJ)
260 && evaluateRCVPair(vI,vJ,fragSpace))
261 {
262 //TODO: evaluate the use of ShortestPath instead of this
263 int ringSize = topoMat[vIdToAtmId.get(vI).get(0)]
264 [vIdToAtmId.get(vJ).get(0)] - 1;
265 int szFct = 0;
266 if (ringSize < settings.getMaxRingSize())
267 {
268 szFct = ringSizeBias.get(ringSize);
269 }
270 if (szFct > 0)
271 {
272 compatibilityOfPairs[i][j] = true;
273 compatibilityOfPairs[j][i] = true;
274 weigths.set(i, weigths.get(i) + szFct);
275 weigths.set(j, weigths.get(j) + szFct);
276 }
277
278 logger.log(Level.FINE, " i:" + i + " j:" + j + " size:"
279 + ringSize + " factors:" + weigths);
280 }
281 }
282 }
283
284 if (logger.isLoggable(Level.FINE))
285 {
286 StringBuilder sb = new StringBuilder();
287 sb.append("RCV pairs compatibility (ring size-biased):"+NL);
288 for (int i=0; i<sz;i++)
289 {
290 String l = " ";
291 for (int j=0; j<sz; j++)
292 {
293 String p = "0";
294 if (compatibilityOfPairs[i][j])
295 p = "1";
296 l = l + " " + p;
297 }
298 sb.append(l+NL);
299 }
300 logger.log(Level.FINE, sb.toString());
301 }
302 }
303
304//------------------------------------------------------------------------------
305
316 private boolean evaluateRCVPair(Vertex vI, Vertex vJ,
318 {
319 String s = "Evaluation of RCV pair " + vI + " " + vJ + ": ";
320
321 // Get details on the first vertex (head)
322 Edge edgeI = vI.getEdgeToParent();
323 int srcApIdI = edgeI.getSrcAPID();
324 Vertex pvI = vI.getParent();
325 AttachmentPoint srcApI = pvI.getAttachmentPoints().get(srcApIdI);
326 int srcAtmIdI = srcApI.getAtomPositionNumber();
327 APClass parentAPClsI = edgeI.getSrcAPClass();
328
329 // Get details on the second vertex (tail)
330 Edge edgeJ = vJ.getEdgeToParent();
331 int srcApIdJ = edgeJ.getSrcAPID();
332 Vertex pvJ = vJ.getParent();
333 AttachmentPoint srcApJ =pvJ.getAttachmentPoints().get(srcApIdJ);
334 int srcAtmIdJ = srcApJ.getAtomPositionNumber();
335 APClass parentAPClsJ = edgeJ.getSrcAPClass();
336
337 // exclude if no entry in RC-Compatibility map
338 if (!fragSpace.getRCCompatibilityMatrix().containsKey(parentAPClsI))
339 {
340 logger.log(Level.FINE, s + "RC-CPMap does not contain class (I) "
341 + parentAPClsI + " " + parentAPClsI.hashCode());
342 return false;
343 }
344 ArrayList<APClass> compatClassesI = fragSpace.getRCCompatibilityMatrix()
345 .get(parentAPClsI);
346
347 // exclude if no entry in RC-Compatibility map
348 if (!fragSpace.getRCCompatibilityMatrix().containsKey(parentAPClsJ))
349 {
350 logger.log(Level.FINE, s + "RC-CPMap does not contain class (J) "
351 + parentAPClsJ + " " + parentAPClsJ.hashCode());
352 return false;
353 }
354 ArrayList<APClass> compatClassesJ = fragSpace.getRCCompatibilityMatrix()
355 .get(parentAPClsJ);
356
357 // exclude loops included within a single vertex
358 if (vI == vJ)
359 {
360 logger.log(Level.FINE, s + "vI same as vJ: loop not allowed!");
361 return false;
362 }
363
364 // exclude pairs of RCA-vertices having same src atom
365 if (pvI == pvJ && srcAtmIdI == srcAtmIdJ)
366 {
367 logger.log(Level.FINE, s + "Same src: " + pvI + " " + pvJ
368 + " " + srcAtmIdI + " " + srcAtmIdJ);
369 return false;
370 }
371
372 // exclude paths that do not connect APClass compatible ends
373 // NOTE that in ring closures the CPMap is symmetric, this
374 // also implies that CPMap for ring closure may be different
375 // from standard CPMap
376 if (!(compatClassesI.contains(parentAPClsJ) ||
377 compatClassesJ.contains(parentAPClsI)))
378 {
379 logger.log(Level.FINE,s + "APClass not compatible "
380 + parentAPClsJ);
381 return false;
382 }
383
384 logger.log(Level.FINE, s + "all criteria satisfied.");
385
386 return true;
387 }
388
389//-----------------------------------------------------------------------------
390
391 public List<Vertex> getRSBiasedListOfCandidates()
392 {
393 List<Vertex> wLst = new ArrayList<Vertex>();
394 for (int i=0; i<sz; i++)
395 {
396 if (done.get(i))
397 {
398 continue;
399 }
400 Vertex v = lstVert.get(i);
401 for (int j=0; j<weigths.get(i); j++)
402 {
403 wLst.add(v);
404 }
405 }
406
407 logger.log(Level.FINE, "Ring size-biased list of RCVs:" + wLst);
408
409 return wLst;
410 }
411
412//-----------------------------------------------------------------------------
413
414 public List<Vertex> getRSBiasedListOfCandidates(Vertex vI)
415 {
416 int i = lstVert.indexOf(vI);
417 List<Vertex> wLst = new ArrayList<Vertex>();
418 for (int j=0; j<sz; j++)
419 {
420 if (done.get(j) || !compatibilityOfPairs[i][j])
421 {
422 continue;
423 }
424
425 Vertex vJ = lstVert.get(j);
426
427 if (vI instanceof EmptyVertex && vJ instanceof EmptyVertex)
428 {
429 wLst.add(vJ);
430 continue;
431 }
432
433 int ringSize = topoMat[vIdToAtmId.get(vI).get(0)]
434 [vIdToAtmId.get(vJ).get(0)] - 1;
435
436 // The likeliness of picking this RCV is given by the ring-size
437 // factor, which accounts for the requested bias towards specific
438 // ring sizes. The larger the bias, the higher the number of
439 // slots occupied by vJ in the list of possible partners, thus
440 // the larger the likeliness of picking it when randomly
441 // choosing the partner for vI.
442 int szFct = 0; //This is the ring-size factor
443 if (ringSize < settings.getMaxRingSize())
444 {
445 szFct = ringSizeBias.get(ringSize);
446 }
447
448 // TODO: here we could consider biasing against crowding, but
449 // the parameters defining what crowding is are defined in
450 // GAParameters, so we would loose generality of this class.
451
452 for (int z=0; z<szFct; z++)
453 {
454 wLst.add(vJ);
455 }
456 }
457
458 logger.log(Level.FINE, "Ring size-biased list of RCVs for " + vI
459 + ": " + wLst);
460
461 return wLst;
462 }
463
464//-----------------------------------------------------------------------------
465
466 public void addRingClosingBond(Vertex vI, Vertex vJ)
467 {
468 // Check validity of assumption: RCV contain only one IAtom
469 if (vIdToAtmId.get(vI).size()!=1 || vIdToAtmId.get(vJ).size()!=1)
470 {
471 String s = "Attempt to make ring closing bond between "
472 + "multi-atom Ring Closing Vertices (RCV). "
473 + "For now, only single-atom RCVs are expected in "
474 + "this implementation.";
475 throw new IllegalStateException(s);
476 }
477
478 // Identify atoms to be bound and make the ring closing bond
479 IAtom srcI = mol.getConnectedAtomsList(
480 mol.getAtom(vIdToAtmId.get(vI).get(0))).get(0);
481 IAtom srcJ = mol.getConnectedAtomsList(
482 mol.getAtom(vIdToAtmId.get(vJ).get(0))).get(0);
483
484 // Assuming that APClasses on both sides agree on bond order
485 // and that vI and vJ are proper RCVs
486
487 BondType bndTyp = vI.getEdgeToParent().getBondType();
488 if (bndTyp.hasCDKAnalogue())
489 {
490 IBond bnd = new Bond(srcI,srcJ);
491 bnd.setOrder(bndTyp.getCDKOrder());
492 mol.addBond(bnd);
493 } else {
494 logger.log(Level.FINE,"WARNING! Attempt to add ring closing bond "
495 + "did not add any actual chemical bond because the "
496 + "bond type of the chord is '" + bndTyp +"'.");
497 }
498
499 logger.log(Level.FINEST, " ==> UPDATING "
500 + this.getClass().getSimpleName() + " <==");
501
502 // Update this RingSizeManager
505 }
506
507//-----------------------------------------------------------------------------
508
509 public void setVertexAsDone(Vertex v)
510 {
511 done.set(lstVert.indexOf(v),true);
512 }
513
514//-----------------------------------------------------------------------------
515
516 public boolean getCompatibilityOfPair(Vertex vI, Vertex vJ)
517 {
518 int i = lstVert.indexOf(vI);
519 int j = lstVert.indexOf(vJ);
520 return compatibilityOfPairs[i][j];
521 }
522
523//---------------------------------------------------------------------
524}
General set of constants used in DENOPTIM.
static final String EOL
new line character
Class defining a space of building blocks.
HashMap< APClass, ArrayList< APClass > > getRCCompatibilityMatrix()
Returns the compatibility matrix for ring closing fragment-fragment connections or null if not provid...
An attachment point (AP) is a possibility to attach a Vertex onto the vertex holding the AP (i....
int getAtomPositionNumber()
The index of the source atom in the atom list of the fragment.
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:102
ArrayList< Vertex > getFreeRCVertices()
Search for unused ring closing vertices: vertices that contain only a RingClosingAttractor and are no...
Definition: DGraph.java:984
This class represents the edge between two vertices.
Definition: Edge.java:38
APClass getSrcAPClass()
Definition: Edge.java:150
BondType getBondType()
Definition: Edge.java:164
An empty vertex has the behaviors of a vertex, but has no molecular structure.
Class representing a continuously connected portion of chemical object holding attachment points.
Definition: Fragment.java:61
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
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
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
abstract List< AttachmentPoint > getAttachmentPoints()
The RingClosingAttractor represent the available valence/connection that allows to close a ring.
boolean isAttractor()
Checks whether the constructed RingClosingAttractor does corresponds to a RingClosingAttractor in the...
boolean isCompatible(RingClosingAttractor other)
Evaluate compatibility between this RingClosingAttractor and another one.
Parameters and setting related to handling ring closures.
Utility class to calculate and manage the alternative ring sizes achievable by formation of Rings.
RingClosureParameters settings
Parameters related to rings.
boolean getCompatibilityOfPair(Vertex vI, Vertex vJ)
boolean[][] compatibilityOfPairs
Compatibility matrix between pairs of RCAs in the current system.
boolean evaluateRCVPair(Vertex vI, Vertex vJ, FragmentSpace fragSpace)
Method to analyze a pair of vertices and evaluate whether they respect the criteria for being the two...
Logger logger
tool managing the logs
void addRingClosingBond(Vertex vI, Vertex vJ)
int[][] topoMat
Topological matrix: contains the number of bonds (shortest path) separating the two atoms having inde...
RingSizeManager(FragmentSpace fragSpace, RingClosureParameters rcParams)
Creates a tool that will work according to the given system-aspecific settings.
IAtomContainer mol
Molecular representation of the current system.
void initialize(IAtomContainer origMol, DGraph graph)
Makes this ring size manager work on a specific system that has a molecular representation and a DENO...
List< Integer > ringSizeBias
Parameters setting the bias for selecting rings of given size.
ArrayList< Vertex > lstVert
List of Ring Closing Vertices (RCV as DENOPTIMVerex) each containing an available Ring Closing Attrac...
List< Double > weigths
List of weight factors used to control the likeliness of choosing rings of a given size for the curre...
List< Boolean > done
List of flags defining if an RCA has been "used", i.e., not used to make an actual chord,...
static final String NL
New line character.
Map< Vertex, ArrayList< Integer > > vIdToAtmId
Map linking the list of vertices and atoms.
int sz
Size of the list of available RCAs.
FragmentSpace fragSpace
Definition of the fragment space.
List< Vertex > getRSBiasedListOfCandidates(Vertex vI)
Logger getLogger()
Get the name of the program specific logger.
Utilities for molecule conversion.
static Map< Vertex, ArrayList< Integer > > getVertexToAtomIdMap(ArrayList< Vertex > vertLst, IAtomContainer mol)
Method to generate the map making in relation DENOPTIMVertex ID and atom index in the IAtomContainer ...
Possible chemical bond types an edge can represent.
Definition: Edge.java:303
boolean hasCDKAnalogue()
Checks if it is possible to convert this edge type into a CDK bond.
Definition: Edge.java:328