1 /* Copyright (C) 2009-2010 Syed Asad Rahman <asad@ebi.ac.uk>
2  *
3  * Contact: cdk-devel@lists.sourceforge.net
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1
8  * of the License, or (at your option) any later version.
9  * All we ask is that proper credit is given for our work, which includes
10  * - but is not limited to - adding the above copyright notice to the beginning
11  * of your container code files, and to any copyright notice that you may distribute
12  * with programs based on this work.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 package org.openscience.cdk.smsd.algorithm.mcgregor;
24 
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Map;
29 import org.openscience.cdk.interfaces.IAtom;
30 import org.openscience.cdk.interfaces.IAtomContainer;
31 import org.openscience.cdk.interfaces.IBond;
32 import org.openscience.cdk.isomorphism.matchers.IQueryAtom;
33 import org.openscience.cdk.isomorphism.matchers.IQueryAtomContainer;
34 import org.openscience.cdk.isomorphism.matchers.IQueryBond;
35 import org.openscience.cdk.smsd.algorithm.matchers.AtomMatcher;
36 import org.openscience.cdk.smsd.algorithm.matchers.BondMatcher;
37 import org.openscience.cdk.smsd.algorithm.matchers.DefaultBondMatcher;
38 import org.openscience.cdk.smsd.algorithm.matchers.DefaultMCSPlusAtomMatcher;
39 import org.openscience.cdk.smsd.algorithm.matchers.DefaultMatcher;
40 import org.openscience.cdk.smsd.helper.BinaryTree;
41 
42 /**
43  * Class to perform check/methods for McGregor class.
44  * @cdk.module smsd
45  * @cdk.githash
46  * @author Syed Asad Rahman &lt;asad@ebi.ac.uk&gt;
47  * @deprecated SMSD has been deprecated from the CDK with a newer, more recent
48  *             version of SMSD is available at <a href="http://github.com/asad/smsd">http://github.com/asad/smsd</a>.
49  */
50 @Deprecated
51 public class McGregorChecks {
52 
53     /**
54      *
55      * @param source
56      * @param target
57      * @param neighborBondNumA
58      * @param neighborBondNumB
59      * @param iBondNeighborAtomsA
60      * @param iBondNeighborAtomsB
61      * @param cBondNeighborsA
62      * @param cBondNeighborsB
63      * @param shouldMatchBonds
64      * @return
65      */
isFurtherMappingPossible(IAtomContainer source, IAtomContainer target, int neighborBondNumA, int neighborBondNumB, List<Integer> iBondNeighborAtomsA, List<Integer> iBondNeighborAtomsB, List<String> cBondNeighborsA, List<String> cBondNeighborsB, boolean shouldMatchBonds)66     protected static boolean isFurtherMappingPossible(IAtomContainer source, IAtomContainer target,
67             int neighborBondNumA, int neighborBondNumB, List<Integer> iBondNeighborAtomsA,
68             List<Integer> iBondNeighborAtomsB, List<String> cBondNeighborsA, List<String> cBondNeighborsB,
69             boolean shouldMatchBonds) {
70 
71         for (int row = 0; row < neighborBondNumA; row++) {
72             //            System.out.println("i " + row);
73             String g1A = cBondNeighborsA.get(row * 4 + 0);
74             String g2a = cBondNeighborsA.get(row * 4 + 1);
75 
76             for (int column = 0; column < neighborBondNumB; column++) {
77 
78                 String g1B = cBondNeighborsB.get(column * 4 + 0);
79                 String g2B = cBondNeighborsB.get(column * 4 + 1);
80 
81                 if (isAtomMatch(g1A, g2a, g1B, g2B)) {
82                     try {
83 
84                         int indexI = iBondNeighborAtomsA.get(row * 3 + 0);
85                         int indexIPlus1 = iBondNeighborAtomsA.get(row * 3 + 1);
86 
87                         int indexJ = iBondNeighborAtomsB.get(column * 3 + 0);
88                         int indexJPlus1 = iBondNeighborAtomsB.get(column * 3 + 1);
89 
90                         IAtom r1A = source.getAtom(indexI);
91                         IAtom r2A = source.getAtom(indexIPlus1);
92                         IBond reactantBond = source.getBond(r1A, r2A);
93 
94                         IAtom p1B = target.getAtom(indexJ);
95                         IAtom p2B = target.getAtom(indexJPlus1);
96                         IBond productBond = target.getBond(p1B, p2B);
97 
98                         if (isMatchFeasible(source, reactantBond, target, productBond, shouldMatchBonds)) {
99                             return true;
100                         }
101                     } catch (Exception e) {
102                         e.printStackTrace();
103                     }
104                 }
105             }
106         }
107 
108         return false;
109     }
110 
isMatchFeasible(IAtomContainer ac1, IBond bondA1, IAtomContainer ac2, IBond bondA2, boolean shouldMatchBonds)111     protected static boolean isMatchFeasible(IAtomContainer ac1, IBond bondA1, IAtomContainer ac2, IBond bondA2,
112             boolean shouldMatchBonds) {
113 
114         if (ac1 instanceof IQueryAtomContainer) {
115             if (((IQueryBond) bondA1).matches(bondA2)) {
116                 IQueryAtom atom1 = (IQueryAtom) (bondA1.getBegin());
117                 IQueryAtom atom2 = (IQueryAtom) (bondA1.getEnd());
118                 // ok, bonds match
119                 if (atom1.matches(bondA2.getBegin()) && atom2.matches(bondA2.getEnd())
120                         || atom1.matches(bondA2.getEnd()) && atom2.matches(bondA2.getBegin())) {
121                     // ok, atoms match in either order
122                     return true;
123                 }
124                 return false;
125             }
126             return false;
127         } else {
128 
129             //Bond Matcher
130             BondMatcher bondMatcher = new DefaultBondMatcher(ac1, bondA1, shouldMatchBonds);
131             //Atom Matcher
132             AtomMatcher atomMatcher1 = new DefaultMCSPlusAtomMatcher(ac1, bondA1.getBegin(), shouldMatchBonds);
133             //Atom Matcher
134             AtomMatcher atomMatcher2 = new DefaultMCSPlusAtomMatcher(ac1, bondA1.getEnd(), shouldMatchBonds);
135 
136             if (DefaultMatcher.isBondMatch(bondMatcher, ac2, bondA2, shouldMatchBonds)
137                     && DefaultMatcher.isAtomMatch(atomMatcher1, atomMatcher2, ac2, bondA2, shouldMatchBonds)) {
138                 return true;
139             }
140             return false;
141         }
142     }
143 
144     /**
145      *
146      * @param mappedAtomsSize
147      * @param atomFromOtherMolecule
148      * @param molecule
149      * @param mappedAtomsOrg
150      * @return
151      */
searchCorrespondingAtom(int mappedAtomsSize, int atomFromOtherMolecule, int molecule, List<Integer> mappedAtomsOrg)152     protected static int searchCorrespondingAtom(int mappedAtomsSize, int atomFromOtherMolecule, int molecule,
153             List<Integer> mappedAtomsOrg) {
154 
155         List<Integer> mappedAtoms = new ArrayList<Integer>(mappedAtomsOrg);
156 
157         int correspondingAtom = 0;
158         for (int a = 0; a < mappedAtomsSize; a++) {
159             if ((molecule == 1) && (mappedAtoms.get(a * 2 + 0).intValue() == atomFromOtherMolecule)) {
160                 correspondingAtom = mappedAtoms.get(a * 2 + 1);
161             }
162             if ((molecule == 2) && (mappedAtoms.get(a * 2 + 1).intValue() == atomFromOtherMolecule)) {
163                 correspondingAtom = mappedAtoms.get(a * 2 + 0);
164             }
165         }
166         return correspondingAtom;
167     }
168 
169     /**
170      *
171      * @param g1A
172      * @param g2A
173      * @param g1B
174      * @param g2B
175      * @return
176      */
isAtomMatch(String g1A, String g2A, String g1B, String g2B)177     protected static boolean isAtomMatch(String g1A, String g2A, String g1B, String g2B) {
178         if ((g1A.compareToIgnoreCase(g1B) == 0 && g2A.compareToIgnoreCase(g2B) == 0)
179                 || (g1A.compareToIgnoreCase(g2B) == 0 && g2A.compareToIgnoreCase(g1B) == 0)) {
180             return true;
181         }
182         return false;
183     }
184 
185     /*
186      * Modified function call by ASAD in Java have to check
187      */
removeTreeStructure(BinaryTree curStruc)188     protected static int removeTreeStructure(BinaryTree curStruc) {
189 
190         BinaryTree equalStruc = curStruc.getEqual();
191         BinaryTree notEqualStruc = curStruc.getNotEqual();
192         curStruc = null;
193 
194         if (equalStruc != null) {
195             removeTreeStructure(equalStruc);
196         }
197 
198         if (notEqualStruc != null) {
199             removeTreeStructure(notEqualStruc);
200         }
201 
202         return 0;
203     }
204 
205     //Function compaires a structure array with itself. Sometimes a mapping occurs several times within the array.
206     //The function eliminates these recurring mappings. Function is called in function best_solution.
207     //The function is called by itself as long as the last list element is processed.
208     /**
209      *
210      * @param atomMapping
211      * @return
212      */
removeRecurringMappings(List<Integer> atomMapping)213     protected static List<Integer> removeRecurringMappings(List<Integer> atomMapping) {
214 
215         boolean exist = true;
216         List<Integer> tempMap = new ArrayList<Integer>();
217         int tempCounter = 0;
218         int atomMappingSize = atomMapping.size();
219         for (int x = 0; x < atomMappingSize; x += 2) {
220             int atom = atomMapping.get(x);
221             for (int y = x + 2; y < atomMappingSize; y += 2) {
222                 if (atom == atomMapping.get(y)) {
223                     exist = false;
224                 }
225             }
226             if (exist == true) {
227                 tempMap.add(atomMapping.get(x + 0));
228                 tempMap.add(atomMapping.get(x + 1));
229                 tempCounter += 2;
230             }
231 
232             exist = true;
233         }
234 
235         return tempMap;
236     }
237 
238     /**
239      * The function is called in function partsearch. The function is given a temporary matrix and a position (row/column)
240      * within this matrix. First the function sets all entries to zero, which can be exlcuded in respect to the current
241      * atom by atom matching. After this the function replaces all entries in the same row and column of the current
242      * position by zeros. Only the entry of the current position is set to one.
243      * Return value "count_arcsleft" counts the number of arcs, which are still in the matrix.
244      * @param row
245      * @param column
246      * @param marcs
247      * @param mcGregorHelper
248      */
removeRedundantArcs(int row, int column, List<Integer> marcs, McgregorHelper mcGregorHelper)249     protected static void removeRedundantArcs(int row, int column, List<Integer> marcs, McgregorHelper mcGregorHelper) {
250         int neighborBondNumA = mcGregorHelper.getNeighborBondNumA();
251         int neighborBondNumB = mcGregorHelper.getNeighborBondNumB();
252         List<Integer> iBondNeighborAtomsA = mcGregorHelper.getiBondNeighborAtomsA();
253         List<Integer> iBondNeighborAtomsB = mcGregorHelper.getiBondNeighborAtomsB();
254         int g1Atom = iBondNeighborAtomsA.get(row * 3 + 0);
255         int g2Atom = iBondNeighborAtomsA.get(row * 3 + 1);
256         int g3Atom = iBondNeighborAtomsB.get(column * 3 + 0);
257         int g4Atom = iBondNeighborAtomsB.get(column * 3 + 1);
258 
259         for (int x = 0; x < neighborBondNumA; x++) {
260             int rowAtom1 = iBondNeighborAtomsA.get(x * 3 + 0);
261             int rowAtom2 = iBondNeighborAtomsA.get(x * 3 + 1);
262 
263             for (int y = 0; y < neighborBondNumB; y++) {
264                 int columnAtom3 = iBondNeighborAtomsB.get(y * 3 + 0);
265                 int columnAtom4 = iBondNeighborAtomsB.get(y * 3 + 1);
266 
267                 if (McGregorChecks.cases(g1Atom, g2Atom, g3Atom, g4Atom, rowAtom1, rowAtom2, columnAtom3,
268                         columnAtom4)) {
269                     marcs.set(x * neighborBondNumB + y, 0);
270                 }
271 
272             }
273         }
274 
275         for (int v = 0; v < neighborBondNumA; v++) {
276             marcs.set(v * neighborBondNumB + column, 0);
277         }
278 
279         for (int w = 0; w < neighborBondNumB; w++) {
280             marcs.set(row * neighborBondNumB + w, 0);
281         }
282 
283         marcs.set(row * neighborBondNumB + column, 1);
284     }
285 
286     /**
287      *
288      * @param bondNumber
289      * @param cSet
290      * @return
291      */
generateCSetCopy(int bondNumber, List<String> cSet)292     protected static List<String> generateCSetCopy(int bondNumber, List<String> cSet) {
293         List<String> cTabCopy = new ArrayList<String>();
294         for (int a = 0; a < bondNumber; a++) {
295             cTabCopy.add(cSet.get(a * 4 + 0));
296             cTabCopy.add(cSet.get(a * 4 + 1));
297             cTabCopy.add("X");
298             cTabCopy.add("X");
299         }
300         return cTabCopy;
301     }
302 
303     /**
304      *
305      * @param atomContainer
306      * @return
307      * @throws IOException
308      */
generateCTabCopy(IAtomContainer atomContainer)309     protected static List<String> generateCTabCopy(IAtomContainer atomContainer) throws IOException {
310         List<String> cTabCopy = new ArrayList<String>();
311         for (int a = 0; a < atomContainer.getBondCount(); a++) {
312             String atomI = atomContainer.getBond(a).getBegin().getSymbol();
313             String atomJ = atomContainer.getBond(a).getEnd().getSymbol();
314             cTabCopy.add(atomI);
315             cTabCopy.add(atomJ);
316             cTabCopy.add("X");
317             cTabCopy.add("X");
318         }
319         return cTabCopy;
320     }
321 
322     /**
323      *
324      * @param g1Atom
325      * @param g3Atom
326      * @param g4Atom
327      * @param rowAtom1
328      * @param rowAtom2
329      * @param columnAtom3
330      * @param columnAtom4
331      * @return
332      */
case1(int g1Atom, int g3Atom, int g4Atom, int rowAtom1, int rowAtom2, int columnAtom3, int columnAtom4)333     protected static boolean case1(int g1Atom, int g3Atom, int g4Atom, int rowAtom1, int rowAtom2,
334             int columnAtom3, int columnAtom4) {
335         if (((g1Atom == rowAtom1) || (g1Atom == rowAtom2))
336                 && (!(((columnAtom3 == g3Atom) || (columnAtom4 == g3Atom)) || ((columnAtom3 == g4Atom) || (columnAtom4 == g4Atom))))) {
337             return true;
338         }
339         return false;
340     }
341 
342     /**
343      *
344      * @param g2Atom
345      * @param g3Atom
346      * @param g4Atom
347      * @param rowAtom1
348      * @param rowAtom2
349      * @param columnAtom3
350      * @param columnAtom4
351      * @return
352      */
case2(int g2Atom, int g3Atom, int g4Atom, int rowAtom1, int rowAtom2, int columnAtom3, int columnAtom4)353     protected static boolean case2(int g2Atom, int g3Atom, int g4Atom, int rowAtom1, int rowAtom2,
354             int columnAtom3, int columnAtom4) {
355         if (((g2Atom == rowAtom1) || (g2Atom == rowAtom2))
356                 && (!(((columnAtom3 == g3Atom) || (columnAtom4 == g3Atom)) || ((columnAtom3 == g4Atom) || (columnAtom4 == g4Atom))))) {
357             return true;
358         }
359         return false;
360     }
361 
362     /**
363      *
364      * @param g1Atom
365      * @param g3Atom
366      * @param g2Atom
367      * @param rowAtom1
368      * @param rowAtom2
369      * @param columnAtom3
370      * @param columnAtom4
371      * @return
372      */
case3(int g1Atom, int g3Atom, int g2Atom, int rowAtom1, int rowAtom2, int columnAtom3, int columnAtom4)373     protected static boolean case3(int g1Atom, int g3Atom, int g2Atom, int rowAtom1, int rowAtom2,
374             int columnAtom3, int columnAtom4) {
375         if (((g3Atom == columnAtom3) || (g3Atom == columnAtom4))
376                 && (!(((rowAtom1 == g1Atom) || (rowAtom2 == g1Atom)) || ((rowAtom1 == g2Atom) || (rowAtom2 == g2Atom))))) {
377             return true;
378         }
379         return false;
380     }
381 
382     /**
383      *
384      * @param g1Atom
385      * @param g2Atom
386      * @param g4Atom
387      * @param rowAtom1
388      * @param rowAtom2
389      * @param columnAtom3
390      * @param columnAtom4
391      * @return
392      */
case4(int g1Atom, int g2Atom, int g4Atom, int rowAtom1, int rowAtom2, int columnAtom3, int columnAtom4)393     protected static boolean case4(int g1Atom, int g2Atom, int g4Atom, int rowAtom1, int rowAtom2,
394             int columnAtom3, int columnAtom4) {
395         if (((g4Atom == columnAtom3) || (g4Atom == columnAtom4))
396                 && (!(((rowAtom1 == g1Atom) || (rowAtom2 == g1Atom)) || ((rowAtom1 == g2Atom) || (rowAtom2 == g2Atom))))) {
397             return true;
398         }
399         return false;
400     }
401 
402     /**
403      *
404      * @param g1Atom
405      * @param g2Atom
406      * @param g3Atom
407      * @param g4Atom
408      * @param rowAtom1
409      * @param rowAtom2
410      * @param columnAtom3
411      * @param columnAtom4
412      * @return
413      */
cases(int g1Atom, int g2Atom, int g3Atom, int g4Atom, int rowAtom1, int rowAtom2, int columnAtom3, int columnAtom4)414     protected static boolean cases(int g1Atom, int g2Atom, int g3Atom, int g4Atom, int rowAtom1, int rowAtom2,
415             int columnAtom3, int columnAtom4) {
416         if (case1(g1Atom, g3Atom, g4Atom, rowAtom1, rowAtom2, columnAtom3, columnAtom4)
417                 || case2(g2Atom, g3Atom, g4Atom, rowAtom1, rowAtom2, columnAtom3, columnAtom4)
418                 || case3(g1Atom, g3Atom, g2Atom, rowAtom1, rowAtom2, columnAtom3, columnAtom4)
419                 || case4(g1Atom, g2Atom, g4Atom, rowAtom1, rowAtom2, columnAtom3, columnAtom4)) {
420             return true;
421         }
422         return false;
423     }
424 
425     /**
426      *
427      * @param source
428      * @param target
429      * @param neighborBondNumA
430      * @param neighborBondNumB
431      * @param iBondNeighborAtomsA
432      * @param iBondNeighborAtomsB
433      * @param cBondNeighborsA
434      * @param cBondNeighborsB
435      * @param modifiedARCS
436      * @param shouldMatchBonds
437      * @return
438      */
setArcs(IAtomContainer source, IAtomContainer target, int neighborBondNumA, int neighborBondNumB, List<Integer> iBondNeighborAtomsA, List<Integer> iBondNeighborAtomsB, List<String> cBondNeighborsA, List<String> cBondNeighborsB, List<Integer> modifiedARCS, boolean shouldMatchBonds)439     protected static List<Integer> setArcs(IAtomContainer source, IAtomContainer target, int neighborBondNumA,
440             int neighborBondNumB, List<Integer> iBondNeighborAtomsA, List<Integer> iBondNeighborAtomsB,
441             List<String> cBondNeighborsA, List<String> cBondNeighborsB, List<Integer> modifiedARCS,
442             boolean shouldMatchBonds) {
443 
444         for (int row = 0; row < neighborBondNumA; row++) {
445             for (int column = 0; column < neighborBondNumB; column++) {
446 
447                 String g1A = cBondNeighborsA.get(row * 4 + 0);
448                 String g2A = cBondNeighborsA.get(row * 4 + 1);
449                 String g1B = cBondNeighborsB.get(column * 4 + 0);
450                 String g2B = cBondNeighborsB.get(column * 4 + 1);
451 
452                 if (McGregorChecks.isAtomMatch(g1A, g2A, g1B, g2B)) {
453 
454                     int indexI = iBondNeighborAtomsA.get(row * 3 + 0);
455                     int indexIPlus1 = iBondNeighborAtomsA.get(row * 3 + 1);
456 
457                     IAtom r1A = source.getAtom(indexI);
458                     IAtom r2A = source.getAtom(indexIPlus1);
459                     IBond reactantBond = source.getBond(r1A, r2A);
460 
461                     int indexJ = iBondNeighborAtomsB.get(column * 3 + 0);
462                     int indexJPlus1 = iBondNeighborAtomsB.get(column * 3 + 1);
463 
464                     IAtom p1B = target.getAtom(indexJ);
465                     IAtom p2B = target.getAtom(indexJPlus1);
466                     IBond productBond = target.getBond(p1B, p2B);
467                     if (isMatchFeasible(source, reactantBond, target, productBond, shouldMatchBonds)) {
468                         modifiedARCS.set(row * neighborBondNumB + column, 1);
469                     }
470                 }
471             }
472         }
473         return modifiedARCS;
474     }
475 
476     /**
477      *
478      * @param tempmarcs
479      * @param neighborBondNumA
480      * @param neighborBondNumB
481      * @return
482      */
countArcsLeft(List<Integer> tempmarcs, int neighborBondNumA, int neighborBondNumB)483     protected static int countArcsLeft(List<Integer> tempmarcs, int neighborBondNumA, int neighborBondNumB) {
484         int arcsleft = 0;
485 
486         for (int a = 0; a < neighborBondNumA; a++) {
487             for (int b = 0; b < neighborBondNumB; b++) {
488 
489                 if (tempmarcs.get(a * neighborBondNumB + b) == (1)) {
490                     arcsleft++;
491                 }
492             }
493         }
494         return arcsleft;
495     }
496 
497     /**
498      *
499      * @param correspondingAtom
500      * @param newSymbol
501      * @param neighborBondNum
502      * @param atomContainer
503      * @param cBondNeighbors
504      * @return
505      */
changeCharBonds(int correspondingAtom, String newSymbol, int neighborBondNum, IAtomContainer atomContainer, List<String> cBondNeighbors)506     protected static int changeCharBonds(int correspondingAtom, String newSymbol, int neighborBondNum,
507             IAtomContainer atomContainer, List<String> cBondNeighbors) {
508         for (int atomIndex = 0; atomIndex < neighborBondNum; atomIndex++) {
509             IBond bond = atomContainer.getBond(atomIndex);
510             if ((atomContainer.indexOf(bond.getBegin()) == correspondingAtom)
511                     && (cBondNeighbors.get(atomIndex * 4 + 2).compareToIgnoreCase("X") == 0)) {
512                 cBondNeighbors.set(atomIndex * 4 + 2, cBondNeighbors.get(atomIndex * 4 + 0));
513                 cBondNeighbors.set(atomIndex * 4 + 0, newSymbol);
514             }
515 
516             if ((atomContainer.indexOf(bond.getEnd()) == correspondingAtom)
517                     && (cBondNeighbors.get(atomIndex * 4 + 3).compareToIgnoreCase("X") == 0)) {
518                 cBondNeighbors.set(atomIndex * 4 + 3, cBondNeighbors.get(atomIndex * 4 + 1));
519                 cBondNeighbors.set(atomIndex * 4 + 1, newSymbol);
520             }
521 
522         }
523 
524         return 0;
525     }
526 
527     /**
528      *
529      * @param correspondingAtom
530      * @param newSymbol
531      * @param neighborBondNum
532      * @param iBondNeighbors
533      * @param cBondNeighbors
534      * @return
535      */
changeCharBonds(int correspondingAtom, String newSymbol, int neighborBondNum, List<Integer> iBondNeighbors, List<String> cBondNeighbors)536     protected static int changeCharBonds(int correspondingAtom, String newSymbol, int neighborBondNum,
537             List<Integer> iBondNeighbors, List<String> cBondNeighbors) {
538 
539         for (int atomIndex = 0; atomIndex < neighborBondNum; atomIndex++) {
540             if ((iBondNeighbors.get(atomIndex * 3 + 0) == (correspondingAtom))
541                     && (cBondNeighbors.get(atomIndex * 4 + 2).compareToIgnoreCase("X") == 0)) {
542                 cBondNeighbors.set(atomIndex * 4 + 2, cBondNeighbors.get(atomIndex * 4 + 0));
543                 cBondNeighbors.set(atomIndex * 4 + 0, newSymbol);
544             }
545 
546             if ((iBondNeighbors.get(atomIndex * 3 + 1) == (correspondingAtom))
547                     && (cBondNeighbors.get(atomIndex * 4 + 3).compareToIgnoreCase("X") == 0)) {
548                 cBondNeighbors.set(atomIndex * 4 + 3, cBondNeighbors.get(atomIndex * 4 + 1));
549                 cBondNeighbors.set(atomIndex * 4 + 1, newSymbol);
550             }
551 
552         }
553 
554         return 0;
555     }
556 
isFurtherMappingPossible(IAtomContainer source, IAtomContainer target, McgregorHelper mcGregorHelper, boolean shouldMatchBonds)557     static boolean isFurtherMappingPossible(IAtomContainer source, IAtomContainer target,
558             McgregorHelper mcGregorHelper, boolean shouldMatchBonds) {
559 
560         int neighborBondNumA = mcGregorHelper.getNeighborBondNumA();
561         int neighborBondNumB = mcGregorHelper.getNeighborBondNumB();
562         List<Integer> iBondNeighborAtomsA = mcGregorHelper.getiBondNeighborAtomsA();
563         List<Integer> iBondNeighborAtomsB = mcGregorHelper.getiBondNeighborAtomsB();
564         List<String> cBondNeighborsA = mcGregorHelper.getcBondNeighborsA();
565         List<String> cBondNeighborsB = mcGregorHelper.getcBondNeighborsB();
566 
567         for (int row = 0; row < neighborBondNumA; row++) {
568             //            System.out.println("i " + row);
569             String g1A = cBondNeighborsA.get(row * 4 + 0);
570             String g2A = cBondNeighborsA.get(row * 4 + 1);
571 
572             for (int column = 0; column < neighborBondNumB; column++) {
573 
574                 String g1B = cBondNeighborsB.get(column * 4 + 0);
575                 String g2B = cBondNeighborsB.get(column * 4 + 1);
576 
577                 if (isAtomMatch(g1A, g2A, g1B, g2B)) {
578                     try {
579 
580                         int indexI = iBondNeighborAtomsA.get(row * 3 + 0);
581                         int indexIPlus1 = iBondNeighborAtomsA.get(row * 3 + 1);
582 
583                         int indexJ = iBondNeighborAtomsB.get(column * 3 + 0);
584                         int indexJPlus1 = iBondNeighborAtomsB.get(column * 3 + 1);
585 
586                         IAtom r1A = source.getAtom(indexI);
587                         IAtom r2A = source.getAtom(indexIPlus1);
588                         IBond reactantBond = source.getBond(r1A, r2A);
589 
590                         IAtom p1B = target.getAtom(indexJ);
591                         IAtom p2B = target.getAtom(indexJPlus1);
592                         IBond productBond = target.getBond(p1B, p2B);
593 
594                         if (isMatchFeasible(source, reactantBond, target, productBond, shouldMatchBonds)) {
595                             return true;
596                         }
597                     } catch (Exception e) {
598                         e.printStackTrace();
599                     }
600                 }
601             }
602         }
603 
604         return false;
605     }
606 
markUnMappedAtoms(boolean flag, IAtomContainer container, Map<Integer, Integer> presentMapping)607     static List<Integer> markUnMappedAtoms(boolean flag, IAtomContainer container, Map<Integer, Integer> presentMapping) {
608         List<Integer> unmappedMolAtoms = new ArrayList<Integer>();
609 
610         int unmappedNum = 0;
611         boolean atomIsUnmapped = true;
612 
613         for (int a = 0; a < container.getAtomCount(); a++) {
614             //Atomic list are only numbers from 1 to atom_number1
615             if (flag && presentMapping.containsKey(a)) {
616                 atomIsUnmapped = false;
617             } else if (!flag && presentMapping.containsValue(a)) {
618                 atomIsUnmapped = false;
619             }
620             if (atomIsUnmapped) {
621                 unmappedMolAtoms.add(unmappedNum++, a);
622             }
623             atomIsUnmapped = true;
624         }
625         return unmappedMolAtoms;
626     }
627 
markUnMappedAtoms(boolean flag, IAtomContainer container, List<Integer> mappedAtoms, int cliqueSize)628     static List<Integer> markUnMappedAtoms(boolean flag, IAtomContainer container, List<Integer> mappedAtoms,
629             int cliqueSize) {
630         List<Integer> unmappedMolAtoms = new ArrayList<Integer>();
631         int unmappedNum = 0;
632         boolean atomIsUnmapped = true;
633         for (int a = 0; a < container.getAtomCount(); a++) {
634             //Atomic list are only numbers from 1 to atom_number1
635             for (int b = 0; b < cliqueSize; b += 2) {
636                 if (flag && mappedAtoms.get(b) == a) {
637                     atomIsUnmapped = false;
638                 } else if (!flag && mappedAtoms.get(b + 1) == a) {
639                     atomIsUnmapped = false;
640                 }
641             }
642             if (atomIsUnmapped) {
643                 unmappedMolAtoms.add(unmappedNum++, a);
644             }
645             atomIsUnmapped = true;
646         }
647         return unmappedMolAtoms;
648     }
649 }
650