$darkmode
DENOPTIM
APClass.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2022 Marco Foscato <marco.foscato@uib.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.graph;
20
21import java.lang.reflect.Type;
22import java.util.ArrayList;
23import java.util.Arrays;
24import java.util.Collections;
25import java.util.HashSet;
26import java.util.List;
27import java.util.Set;
28
29import com.google.gson.JsonDeserializationContext;
30import com.google.gson.JsonDeserializer;
31import com.google.gson.JsonElement;
32import com.google.gson.JsonObject;
33import com.google.gson.JsonParseException;
34
35import denoptim.constants.DENOPTIMConstants;
36import denoptim.exception.DENOPTIMException;
37import denoptim.fragspace.FragmentSpace;
38import denoptim.graph.Edge.BondType;
39import denoptim.graph.rings.RingClosingAttractor;
40
41public class APClass implements Cloneable,Comparable<APClass>
42{
47 private String rule;
48
53 private int subClass;
54
58 public static Set<APClass> uniqueAPClasses = new HashSet<APClass>();
59
64 private final static Object uniqueAPClassesLock = new Object();
65
69 public static final String ATPLUS = "ATplus";
70
74 public static final String ATMINUS = "ATminus";
75
79 public static final String ATNEUTRAL = "ATneutral";
80
85 public static final APClass RCACLASSPLUS = getUnique(ATPLUS, 0,
87
92 public static final APClass RCACLASSMINUS = getUnique(ATMINUS, 0,
94
99 public static final APClass RCACLASSNEUTRAL = getUnique(ATNEUTRAL, 0,
100 BondType.ANY);
101
106 public static final APClass APCAROMBRIDGE2EL = getUnique("2elAromBridge", 0,
107 BondType.SINGLE); //TODO: one day we should introduce AROMATIC type
108
113 public static final APClass APCAROMBRIDGE3EL = getUnique("3elAromBridge", 0,
114 BondType.SINGLE); //TODO: one day we should introduce AROMATIC type
115
120 public static final APClass APCAROMBRIDGE4EL = getUnique("4elAromBridge", 0,
121 BondType.SINGLE); //TODO: one day we should introduce AROMATIC type
122
126 public static final Set<APClass> APCAROMBRIDGES = new HashSet<APClass>(
128
133
137 public static final BondType DEFAULTBT = BondType.SINGLE;
138
139//------------------------------------------------------------------------------
140
144 public APClass()
145 {}
146
147//------------------------------------------------------------------------------
148
164 public static APClass make(String ruleAndSubclass) throws DENOPTIMException
165 {
166 if (!isValidAPClassString(ruleAndSubclass))
167 {
168 throw new DENOPTIMException("Attempt to use APClass '"
169 + ruleAndSubclass
170 + "' that does not respect syntax <rule>"
171 + DENOPTIMConstants.SEPARATORAPPROPSCL + "<subClass>.");
172 }
173 String[] parts = ruleAndSubclass.split(
175 return make(parts[0], Integer.parseInt(parts[1]));
176 }
177
178//------------------------------------------------------------------------------
179
197 public static APClass make(String rule, int subClass)
198 throws DENOPTIMException
199 {
200 return make(rule, subClass, DEFAULTBT);
201 }
202
203//------------------------------------------------------------------------------
204
219 public static APClass make(String ruleAndSubclass, BondType bt)
220 throws DENOPTIMException
221 {
222 if (!isValidAPClassString(ruleAndSubclass))
223 {
224 throw new DENOPTIMException("Attempt to use APClass '"
225 + ruleAndSubclass
226 + "' that does not respect syntax <rule>"
227 + DENOPTIMConstants.SEPARATORAPPROPSCL + "<subClass>.");
228 }
229 String[] parts = ruleAndSubclass.split(
231 return make(parts[0], Integer.parseInt(parts[1]), bt);
232 }
233
234//------------------------------------------------------------------------------
235
249 public static APClass make(String rule, int subClass, BondType bt)
250 throws DENOPTIMException
251 {
253 return getUnique(rule, subClass, bt);
254 } else {
255 throw new DENOPTIMException("Invalid sttempt to make APClass out "
256 + "of '" + rule + "' and '" + subClass + "'.");
257 }
258 }
259
260//------------------------------------------------------------------------------
261
270 private static APClass getUnique(String rule, int subClass, BondType bt)
271 {
272 APClass newApc = new APClass();
273 synchronized (uniqueAPClassesLock)
274 {
275 boolean found = false;
276 for (APClass existingApc : uniqueAPClasses)
277 {
278 if (existingApc.getRule().equals(rule)
279 && existingApc.getSubClass()==subClass)
280 {
281 newApc = existingApc;
282 found = true;
283 break;
284 }
285 }
286 if (!found)
287 {
288 newApc.setRule(rule);
289 newApc.setSubClass(subClass);
290 newApc.setBondType(bt);
291 } else {
292 // NB: the default bond type for RCAs must not be changed, but
293 // For non-RCA APClasses we do update the bond type.
294 if (bt != newApc.bndTyp && !RingClosingAttractor.RCAAPCLASSSET.contains(newApc))
295 {
296 System.err.println("WARNING! Changing bond order of "
297 + "APClass " + newApc + ": " + newApc.bndTyp
298 + " -> " + bt);
299 newApc.setBondType(bt);
300 }
301 }
302 uniqueAPClasses.add(newApc);
303 }
304 return newApc;
305 }
306
307//------------------------------------------------------------------------------
308
309 private void setBondType(BondType bt) {
310 this.bndTyp = bt;
311 }
312
313//------------------------------------------------------------------------------
314
315 private void setRule(String rule) {
316 this.rule = rule;
317 }
318
319//------------------------------------------------------------------------------
320
321 private void setSubClass(int sumClass) {
322 this.subClass = sumClass;
323 }
324
325//------------------------------------------------------------------------------
326
331 public static List<String> getAllAPClassesAsString()
332 {
333 List<String> names = new ArrayList<String>();
334 for (APClass apc : uniqueAPClasses)
335 {
336 names.add(apc.toString());
337 }
338 Collections.sort(names);
339 return names;
340 }
341
342//------------------------------------------------------------------------------
343
349 public String getRule() {
350 return rule;
351 }
352
353//------------------------------------------------------------------------------
354
360 public int getSubClass() {
361 return subClass;
362 }
363
364//------------------------------------------------------------------------------
365
370 return bndTyp;
371 }
372
373//------------------------------------------------------------------------------
374
380 public String toString() {
381 return rule + DENOPTIMConstants.SEPARATORAPPROPSCL
382 + Integer.toString(subClass);
383 }
384
385//------------------------------------------------------------------------------
386
392 public String toSDFString() {
393 return rule + DENOPTIMConstants.SEPARATORAPPROPSCL
394 + Integer.toString(subClass)
395 + DENOPTIMConstants.SEPARATORAPPROPSCL
396 + bndTyp;
397 }
398
399//------------------------------------------------------------------------------
400
409 public static boolean isValidAPSubCLassString(String s)
410 {
411 return s.matches("^[0-9]*$");
412 }
413
414//------------------------------------------------------------------------------
415
424 public static boolean isValidAPRuleString(String s)
425 {
426 if (s == null)
427 return false;
428 return s.matches("^[a-zA-Z0-9_-]+$");
429 }
430
431//------------------------------------------------------------------------------
432
440 public static boolean isValidAPClassString(String s)
441 {
442 if (!s.matches("^[a-z,A-Z,0-9].*"))
443 return false;
444
445 if (!s.matches(".*[0-9]$"))
446 return false;
447
448 if (s.contains(" "))
449 return false;
450
451 if (!s.contains(DENOPTIMConstants.SEPARATORAPPROPSCL))
452 return false;
453
454 int numSep = 0;
455 for (int i=0; i<s.length(); i++)
456 {
457 if (s.charAt(i) == DENOPTIMConstants.SEPARATORAPPROPSCL.charAt(0))
458 {
459 numSep++;
460 }
461 }
462 if (numSep != 1)
463 return false;
464
465 String apRule = s.split(DENOPTIMConstants.SEPARATORAPPROPSCL)[0];
466 String sub = s.split(DENOPTIMConstants.SEPARATORAPPROPSCL)[1];
467
468 return APClass.isValidAPRuleString(apRule)
470 }
471
472//------------------------------------------------------------------------------
473
483 public boolean isCPMapCompatibleWith(APClass other, FragmentSpace fragSpace)
484 {
485 return fragSpace.getCompatibleAPClasses(this).contains(other);
486 }
487
488//------------------------------------------------------------------------------
489
490 @Override
491 public int compareTo(APClass o)
492 {
493 int ruleComparison = this.rule.compareTo(o.rule);
494 if (ruleComparison == 0) {
495 return Integer.compare(this.subClass, o.subClass);
496 } else {
497 return ruleComparison;
498 }
499 }
500
501//------------------------------------------------------------------------------
502
508 @Override
509 public APClass clone() {
510 return this;
511 }
512
513//------------------------------------------------------------------------------
514
515 @Override
516 public boolean equals(Object o) {
517 if (!(o instanceof APClass)) {
518 return false;
519 }
520 return this.hashCode() == o.hashCode();
521 }
522
523//------------------------------------------------------------------------------
524
525 public static class APClassDeserializer
526 implements JsonDeserializer<APClass>
527 {
528 @Override
529 public APClass deserialize(JsonElement json, Type typeOfT,
530 JsonDeserializationContext context) throws JsonParseException
531 {
532 JsonObject jo = json.getAsJsonObject();
533 APClass apc = null;
534 if (jo.has("bndTyp"))
535 {
536 apc = getUnique(jo.get("rule").getAsString(),
537 jo.get("subClass").getAsInt(),
538 context.deserialize(jo.get("bndTyp"),BondType.class));
539 } else {
540 //Only for conversion to V3
541 String rule = jo.get("rule").getAsString();
542 int subClass = jo.get("subClass").getAsInt();
543 boolean found = false;
544 for (APClass existingApc : uniqueAPClasses)
545 {
546 if (existingApc.getRule().equals(rule)
547 && existingApc.getSubClass()==subClass)
548 {
549 apc = existingApc;
550 found = true;
551 break;
552 }
553 }
554 if (!found)
555 {
556 System.out.println("WARNING! Setting " + DEFAULTBT
557 + " for "+rule+":"+subClass);
558 apc = getUnique(jo.get("rule").getAsString(),
559 jo.get("subClass").getAsInt(), DEFAULTBT);
560 }
561 }
562 return apc;
563 }
564 }
565
566//------------------------------------------------------------------------------
567
568}
569
General set of constants used in DENOPTIM.
static final String SEPARATORAPPROPSCL
Separator between APClass and APSubClass and coordinates.
Class defining a space of building blocks.
ArrayList< APClass > getCompatibleAPClasses(APClass apc)
Returns a list of APClasses compatible with the given APClass.
APClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
Definition: APClass.java:529
static List< String > getAllAPClassesAsString()
Returns the list of the names of all APClasses.
Definition: APClass.java:331
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:483
APClass clone()
WARNING: this method does NOT clone! It just returns the reference to this.
Definition: APClass.java:509
static final APClass RCACLASSPLUS
Conventional class of attachment points on ring-closing vertexes.
Definition: APClass.java:85
static APClass make(String rule, int subClass)
Constructor for an APClass with default bond type (i.e., BondType#DEFAULTBT).
Definition: APClass.java:197
static final String ATNEUTRAL
String defining a conventional APClass.
Definition: APClass.java:79
static APClass make(String ruleAndSubclass, BondType bt)
Constructor for a fully defined APClass.
Definition: APClass.java:219
static APClass make(String rule, int subClass, BondType bt)
Constructor for a fully defined APClass.
Definition: APClass.java:249
boolean equals(Object o)
Definition: APClass.java:516
static final Object uniqueAPClassesLock
Synchronization lock.
Definition: APClass.java:64
BondType bndTyp
Bond type to use when converting edge users into formal bonds.
Definition: APClass.java:132
static final APClass RCACLASSMINUS
Conventional class of attachment points on ring-closing vertexes.
Definition: APClass.java:92
int compareTo(APClass o)
Definition: APClass.java:491
static boolean isValidAPClassString(String s)
Evaluate is a candidate string can be used as APClass.
Definition: APClass.java:440
static boolean isValidAPRuleString(String s)
Evaluates the given string as a candidate attachment point rule, i.e., as name of a fragmentation rul...
Definition: APClass.java:424
static final String ATMINUS
String defining a conventional APClass.
Definition: APClass.java:74
String rule
The main feature of the APClass.
Definition: APClass.java:47
BondType getBondType()
Definition: APClass.java:369
static final BondType DEFAULTBT
Default bond type for all but APClasses of RCVs.
Definition: APClass.java:137
void setBondType(BondType bt)
Definition: APClass.java:309
static final String ATPLUS
String defining a conventional APClass.
Definition: APClass.java:69
APClass()
Constructor for an empty APClass.
Definition: APClass.java:144
void setSubClass(int sumClass)
Definition: APClass.java:321
static boolean isValidAPSubCLassString(String s)
Evaluate the given string as a candidate for attachment point subclass, i.e., the attachment point cl...
Definition: APClass.java:409
int subClass
The secondary feature of the APClass.
Definition: APClass.java:53
String toString()
Do not use this to make SDF representations.
Definition: APClass.java:380
static APClass make(String ruleAndSubclass)
Creates an APClass if it does not exist already, or returns the reference to the existing instance.
Definition: APClass.java:164
static final APClass RCACLASSNEUTRAL
Conventional class of attachment points on ring-closing vertexes.
Definition: APClass.java:99
void setRule(String rule)
Definition: APClass.java:315
static final APClass APCAROMBRIDGE4EL
Conventional class of attachment points on aromatic-bridge vertexes bringing 4 electrons to the aroma...
Definition: APClass.java:120
static Set< APClass > uniqueAPClasses
Set unique APClasses.
Definition: APClass.java:58
static final APClass APCAROMBRIDGE2EL
Conventional class of attachment points on aromatic-bridge vertexes bringing 2 electrons to the aroma...
Definition: APClass.java:106
static final APClass APCAROMBRIDGE3EL
Conventional class of attachment points on aromatic-bridge vertexes bringing 3 electrons to the aroma...
Definition: APClass.java:113
static final Set< APClass > APCAROMBRIDGES
Conventional classes for of attachment points on aromatic-bridge vertexes.
Definition: APClass.java:126
static APClass getUnique(String rule, int subClass, BondType bt)
Checks if there is already a instance with the given members, if not it created one.
Definition: APClass.java:270
The RingClosingAttractor represent the available valence/connection that allows to close a ring.
static final Set< APClass > RCAAPCLASSSET
Recognized APClass for RingClosingAttractor.
Possible chemical bond types an edge can represent.
Definition: Edge.java:303