$darkmode
DENOPTIM
GraphBuildingTask.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2019 Marco Foscato <marco.foscato@uib.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.combinatorial;
20
21import java.io.File;
22import java.util.ArrayList;
23import java.util.HashMap;
24import java.util.Map;
25import java.util.logging.Level;
26
27import org.openscience.cdk.CDKConstants;
28import org.openscience.cdk.interfaces.IAtomContainer;
29
30import denoptim.constants.DENOPTIMConstants;
31import denoptim.exception.DENOPTIMException;
32import denoptim.fitness.FitnessParameters;
33import denoptim.fragspace.FragmentSpace;
34import denoptim.fragspace.FragmentSpaceParameters;
35import denoptim.fragspace.FragsCombination;
36import denoptim.fragspace.IdFragmentAndAP;
37import denoptim.graph.Candidate;
38import denoptim.graph.DGraph;
39import denoptim.graph.SymmetricVertexes;
40import denoptim.graph.Vertex;
41import denoptim.molecularmodeling.ThreeDimTreeBuilder;
42import denoptim.programs.RunTimeParameters.ParametersType;
43import denoptim.programs.combinatorial.CEBLParameters;
44import denoptim.task.FitnessTask;
45import denoptim.utils.GeneralUtils;
46import denoptim.utils.GraphUtils;
47import denoptim.utils.MoleculeUtils;
48
49
57public class GraphBuildingTask extends FitnessTask
58{
62 private int rootId;
63
68 private int graphId;
69
73 private int level;
74
79
83 private int nSubTasks = 0;
84
89 private ArrayList<Integer> nextIds;
90
95
100
105
106//------------------------------------------------------------------------------
107
111 public GraphBuildingTask(CEBLParameters settings, DGraph molGraph,
113 int verbosity) throws DENOPTIMException
114 {
115 super((FitnessParameters) settings.getParameters(
117 new Candidate(molGraph.clone()));
118 this.ceblSettings = settings;
119 // NB: we also ensure the fragment space parameters are not null
121 if (settings.containsParameters(ParametersType.FS_PARAMS))
122 {
123 fsParams = (FragmentSpaceParameters)settings.getParameters(
125 }
126 this.fragSpace = fsParams.getFragmentSpace();
127
129 rootId = molGraph.getGraphId();
131 this.workDir = new File(workDir);
132 this.fragsToAdd = fragsToAdd;
133 this.level = level;
134 this.verbosity = verbosity;
135 }
136
137//------------------------------------------------------------------------------
138
144 {
145 return nSubTasks;
146 }
147
148//------------------------------------------------------------------------------
149
154 public int getLevel()
155 {
156 return level;
157 }
158
159//------------------------------------------------------------------------------
160
166 public ArrayList<Integer> getNextIds()
167 {
168 return nextIds;
169 }
170
171//------------------------------------------------------------------------------
172
178 public int getGraphId()
179 {
180 return graphId;
181 }
182
183//------------------------------------------------------------------------------
184
189 public int getRootId()
190 {
191 return rootId;
192 }
193
194//------------------------------------------------------------------------------
195
201 public void setNextIds(ArrayList<Integer> nextIds) throws DENOPTIMException
202 {
203 this.nextIds = new ArrayList<Integer>();
204 for (Integer i : nextIds)
205 this.nextIds.add(i);
206 }
207
208//------------------------------------------------------------------------------
209
214 @Override
215 public Object call() throws Exception
216 {
217 try
218 {
219 String msg = "Call GraphBuildingTask " + id
220 + " (Lev:" + level + ", comb:" + nextIds + ")"
221 + DENOPTIMConstants.EOL + " - Fragsments to add: ";
222 for (IdFragmentAndAP src : fragsToAdd.keySet())
223 {
224 msg = msg + DENOPTIMConstants.EOL
225 + " "+src+" - "+fragsToAdd.get(src);
226 }
227 msg = msg + DENOPTIMConstants.EOL + " - RootGraph: " + dGraph;
228 fitnessSettings.getLogger().log(Level.FINE, msg);
229
230 // Initialize the 3d model builder
234 {
235 tb3d.setAlignBBsIn3D(false);
236 }
237
238 // Extend graph as requested
239 Map<Integer, SymmetricVertexes> newSymSets =
240 new HashMap<Integer, SymmetricVertexes>();
241 for (IdFragmentAndAP srcAp : fragsToAdd.keySet())
242 {
243 long sVId = srcAp.getVertexId();
244 int sApId = srcAp.getApId();
245 Vertex srcVrtx = dGraph.getVertexWithId(sVId);
246
247 IdFragmentAndAP trgAp = fragsToAdd.get(srcAp);
248 long tVId = trgAp.getVertexId();
249 int tFId = trgAp.getVertexMolId();
250 Vertex.BBType tFTyp = trgAp.getVertexMolType();
251 int tApId = trgAp.getApId();
252
253 // type "NONE" is used to represent unused AP
254 if (tFTyp == Vertex.BBType.NONE
255 || tFTyp == Vertex.BBType.UNDEFINED)
256 {
257 continue;
258 }
259
261 tVId, tFId, tFTyp, fragSpace);
262
263 // record symmetric relations between vertices
264 int tSymSetID = trgAp.getVrtSymSetId();
265 if (newSymSets.containsKey(tSymSetID))
266 {
267 newSymSets.get(tSymSetID).add(trgVrtx);
268 } else {
270 ss.add(trgVrtx);
271 newSymSets.put(tSymSetID, ss);
272 }
273
274 dGraph.appendVertexOnAP(srcVrtx.getAP(sApId),
275 trgVrtx.getAP(tApId));
276 }
277
278 // Append new symmetric sets
279 for (Integer ssId : newSymSets.keySet())
280 {
281 SymmetricVertexes ss = newSymSets.get(ssId);
282 if (ss.size() > 1)
283 {
285 }
286 }
287
288 Object[] res = dGraph.checkConsistency(ceblSettings);
289 if (res == null) // null is used to indicate an unacceptable graph
290 {
291 nSubTasks = 1;
293 rootId, nextIds);
294 }
295 else
296 {
297 // We don't add capping groups as they are among the candidate
298 // fragments to be put in each AP.
299 // If a graph still holds unused APs that should be capped,
300 // then such graph is an unfinished molecular entity that
301 // will be further grown, so no need to perceive rings or
302 // submit any external task.
303 boolean needsCaps = false;
305 {
307 }
308
309 ArrayList<DGraph> altCyclicGraphs = new ArrayList<DGraph>();
310 if (!needsCaps)
311 {
314 }
315 int sz = altCyclicGraphs.size();
316
317 if (sz>0 && !needsCaps)
318 {
319 nSubTasks = sz;
320
321 if (verbosity > 0)
322 {
323 msg = "Graph " + dGraph.getGraphId() + " is replaced by "
324 + sz + " cyclic alternatives.";
325 fitnessSettings.getLogger().log(Level.INFO, msg);
326 }
327
328 // WARNING! If cyclic versions of dGraph are available,
329 // we IGNORE the acyclic original. This is because,
330 // if at all possible, the acyclic graph is built anyway
331 // using capping groups instead of ring closing attractors.
332
333 // prepare log message
334 String lst = "[";
335 for (int ig = 0; ig<sz-1; ig++)
336 {
337 lst = lst + altCyclicGraphs.get(ig).getGraphId()+", ";
338 }
339 lst = lst + altCyclicGraphs.get(sz-1).getGraphId() + "]";
340
341 // process all alternative graphs
342 for (int ig = 0; ig<altCyclicGraphs.size(); ig++)
343 {
344 DGraph g = altCyclicGraphs.get(ig);
345 int gId = g.getGraphId();
346
347 if (verbosity > 0)
348 {
349 msg = "Graph " + gId
350 + " is cyclic alternative "
351 + (ig+1) + "/" + altCyclicGraphs.size()
352 + " " + lst;
353 fitnessSettings.getLogger().log(Level.INFO, msg);
354 }
355
356 // Prepare vector of results
357 // NB: in FSE we add also the ID of the root graph in
358 // this array, and the level
359 Object[] altRes = new Object[5];
360 try
361 {
362 // Prepare molecular representation
363 DGraph gWithNoRCVs = g.clone();
365 IAtomContainer mol =
367 gWithNoRCVs,true);
368
369 // Level that generated this graph
370 altRes[4] = level;
371
372 // Parent graph
373 altRes[3] = rootId;
374
375 altRes[2] = mol;
376
377 // Prepare SMILES
378 String smiles = MoleculeUtils.getSMILESForMolecule(
379 mol, ceblSettings.getLogger());
380 if (smiles == null)
381 {
382 smiles = "FAIL: NO SMILES GENERATED";
383 }
384 altRes[1] = smiles;
385
386 // Prepare INCHI-Key
387 String inchiKey =
390 if (inchiKey == null)
391 {
392 inchiKey = "UNDEFINED_INCHI";
393 }
394 altRes[0] = inchiKey;
395
396 // Store graph
399 graphId = gId;
400
401 // Optionally perform external task
403 {
404 // We change the graph that was originally given
405 // to the FitnessTask superclass!
406 dGraph = g;
407 result.setGraph(g);
408 sendToFitnessProvider(altRes);
409 }
410 }
411 catch (Throwable t)
412 {
413 msg = "Exception while working on cyclic graph "+g;
414 throw new Throwable(msg,t);
415 }
416 }
417 }
418 else
419 {
420 nSubTasks = 1;
421
422 // Store graph
423 DGraph gClone = dGraph.clone();
425 nextIds);
426
427 // Optionally improve the molecular representation, which
428 // is otherwise only given by the collection of building
429 // blocks (not aligned, nor roto-translated)
431 {
433 IAtomContainer mol = tb3d.convertGraphTo3DAtomContainer(
434 gClone,true);
435 res[2] = mol;
436 }
437
438 // Optionally perform external task
439 if (ceblSettings.submitFitnessTask() && !needsCaps)
440 {
441 Object[] fseRes = new Object[5];
442 fseRes[0] = res[0];
443 fseRes[1] = res[1];
444 fseRes[2] = res[2];
445 fseRes[3] = rootId;
446 fseRes[4] = level;
447 sendToFitnessProvider(fseRes);
448 }
449 }
450 }
451 }
452 catch (Throwable t)
453 {
454 // This is a trick to transmit the exception to the parent thread
455 // and store it as a property of the present task
456 hasException = true;
457 thrownExc = t;
458 throw new Exception(t);
459 }
460
461 completed = true;
462 return "PASS";
463 }
464
465//------------------------------------------------------------------------------
466
472 private void sendToFitnessProvider(Object[] res) throws Throwable
473 {
474 String molinchi = res[0].toString().trim();
475
476 //TODO: consider adding this. However, a UID based only on chemical
477 // constitution, might fail to appreciate some difference between the
478 //generated graphs, in particular differences in free APs and APClasses.
479 /*
480 if (((FitnessParameters) ceblSettings.getParameters(
481 ParametersType.FIT_PARAMS)).checkPreFitnessUID())
482 {
483 try
484 {
485 if (!scs.addNewUniqueEntry(molinchi))
486 {
487 //TODO: one day we'll have a monitor for FSE
488 //mnt.increase(CounterID.DUPLICATEPREFITNESS);
489 return;
490 }
491 } catch (Exception e) {
492 e.printStackTrace();
493 //TODO: one day we'll have a monitor for FSE
494 //mnt.increase(CounterID.FAILEDDUPLICATEPREFITNESSDETECTION);
495
496 }
497 }
498 */
499
500 String molsmiles = res[1].toString().trim();
501 fitProvMol = (IAtomContainer) res[2];
502 String parentGraphId = res[3].toString().trim();
503 String level = res[4].toString().trim();
504 fitProvMol.setProperty(DENOPTIMConstants.INCHIKEYTAG, molinchi);
505 fitProvMol.setProperty(DENOPTIMConstants.UNIQUEIDTAG, molinchi);
506 fitProvMol.setProperty(DENOPTIMConstants.SMILESTAG, molsmiles);
507 fitProvMol.setProperty(DENOPTIMConstants.PARENTGRAPHTAG, parentGraphId);
509 String molName = DENOPTIMConstants.FITFILENAMEPREFIX
512 fitProvMol.setProperty(CDKConstants.TITLE, molName);
513
514
515 fitProvInputFile = workDir + SEP + molName
517 fitProvOutFile = workDir + SEP + molName
519 fitProvPNGFile = workDir + SEP + molName
522
523 result.setName(molName);
524 result.setSmiles(molsmiles);
525 result.setUID(molinchi);
526
528 }
529
530//------------------------------------------------------------------------------
531
532}
Helper methods for the exploration of the fragment space.
Definition: CEBLUtils.java:45
static void storeGraphOfLevel(CEBLParameters settings, DGraph graph, int level, int rootId, ArrayList< Integer > nextIds)
Serialize a DENOPTIMGraph to a file.
Definition: CEBLUtils.java:187
Task that builds a graph by appending a given combination of fragments onto a given list of attachmen...
ThreeDimTreeBuilder tb3d
Tool for generating 3D models assembling 3D building blocks.
GraphBuildingTask(CEBLParameters settings, DGraph molGraph, FragsCombination fragsToAdd, int level, String workDir, int verbosity)
Constructor.
FragsCombination fragsToAdd
Pointer defining the active combination for this task.
FragmentSpace fragSpace
The fragment space.
int rootId
The graph ID of the root graph.
ArrayList< Integer > getNextIds()
Returns the set of indeces that identify the position of the the (next) combination of fragment in th...
int graphId
GraphID: may be from the original graph or from its latest generated cyclic alternative.
ArrayList< Integer > nextIds
Vector of indexes identifying the next combination of fragments.
CEBLParameters ceblSettings
Collection of settings controlling the execution of the task.
int getRootId()
Returns the graphID of the root graph.
void setNextIds(ArrayList< Integer > nextIds)
Set the set of indexes that identify the position of the the (next) combination of fragment in the sp...
int getGraphId()
Returns the graphID of the original graph or of the latest cyclic alternative.
int level
The active level of modification.
General set of constants used in DENOPTIM.
static final String INCHIKEYTAG
SDF tag containing the unique identifier of a candidate.
static final String CANDIDATE2DEXTENSION
Extension of output file with 2D picture of candidate.
static final String PARENTGRAPHTAG
SDF tag defining the ID of a parent graph (used in FSE)
static final String GRAPHLEVELTAG
SDF tag defining the graph generating level in an FSE run.
static final String UNIQUEIDTAG
SDF tag containing the unique identifier of a candidate.
static final String SMILESTAG
SDF tag containing the SMILES of a candidate.
static final String FITFILENAMEEXTOUT
Ending and extension of output file of external fitness provider.
static final String FITFILENAMEEXTIN
Ending and extension of input file of external fitness provider.
Settings defining the calculation of fitness.
Class defining a space of building blocks.
boolean useAPclassBasedApproach()
Check usage of APClass-based approach, i.e., uses attachment points with annotated data (i....
Parameters defining the fragment space.
Data structure identifying a combination of one or more pairs of attachment points located on specifi...
Data structure containing information that identifies a single AP of a vertex/fragment.
A candidate is the combination of a denoptim graph with molecular representation and may include also...
Definition: Candidate.java:40
void setSmiles(String smiles)
Definition: Candidate.java:473
void setGraph(DGraph graph)
Definition: Candidate.java:459
void setUID(String uid)
Definition: Candidate.java:466
void setName(String name)
Definition: Candidate.java:495
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:102
Vertex getVertexWithId(long vid)
Searches for a vertex with the given identifier.
Definition: DGraph.java:2582
boolean graphNeedsCappingGroups(FragmentSpace fragSpace)
Checks the graph for unused APs that need to be capped.
Definition: DGraph.java:4064
void setGraphId(int id)
Definition: DGraph.java:258
Object[] checkConsistency(RunTimeParameters settings)
Peeks into this graph to derive a preliminary chemical representation with SMILES and InChIKey.
Definition: DGraph.java:5353
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
DGraph clone()
Returns almost "deep-copy" of this graph.
Definition: DGraph.java:3186
ArrayList< DGraph > makeAllGraphsWithDifferentRingSets(RunTimeParameters settings)
Evaluates the possibility of closing rings in this graph and generates all alternative graphs resulti...
Definition: DGraph.java:5589
void replaceUnusedRCVsWithCapps(FragmentSpace fragSpace)
Removes unused ring-closing vertices.
Definition: DGraph.java:1526
void addSymmetricSetOfVertices(SymmetricVertexes symSet)
Adds a symmetric set of vertices to this graph.
Definition: DGraph.java:661
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...
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
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
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.
RunTimeParameters getParameters(ParametersType type)
Logger getLogger()
Get the name of the program specific logger.
Randomizer getRandomizer()
Returns the current program-specific randomizer.
Parameters controlling execution of the combinatorial algorithm for exploration of a fragment space b...
Task that assesses the fitness of a given graph.
DGraph dGraph
The graph representation of the entity to evaluate.
String fitProvInputFile
The file where we store the input to the fitness provider.
void runFitnessProvider()
This method runs the actual evaluation of the fitness, whether that is run internally (i....
String fitProvUIDFile
The file where we store the list of unique identifiers or previously evaluated candidates.
FitnessParameters fitnessSettings
Settings for the calculation of the fitness.
Candidate result
The data structure holding the results of this task.
String fitProvOutFile
The file where we store the final output from the fitness provider.
IAtomContainer fitProvMol
The chemical representation of the entity to evaluate.
String fitProvPNGFile
The file where we store the graphical representation of the candidate (i.e., a picture).
File workDir
The file system location where we want to be placed when doing the work.
Definition: Task.java:78
boolean completed
Flag about completion.
Definition: Task.java:41
int verbosity
Verbosity level.
Definition: Task.java:83
boolean hasException
Flag about exception.
Definition: Task.java:46
final String SEP
System-dependent file separator.
Definition: Task.java:88
Throwable thrownExc
Exception thrown.
Definition: Task.java:61
static String getPaddedString(int count, int number)
returns the padded string with zeroes placed to the left of 'number' up to reach the desired number o...
Utilities for graphs.
Definition: GraphUtils.java:40
static synchronized int getUniqueMoleculeIndex()
Unique counter for the number of molecules generated.
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 String getSMILESForMolecule(IAtomContainer mol, Logger logger)
Returns the SMILES representation of the molecule.
The type of building block.
Definition: Vertex.java:86
FS_PARAMS
Parameters pertaining the definition of the fragment space.
FIT_PARAMS
Parameters pertaining the calculation of fitness (i.e., the fitness provider).