1
/* $Revision: 7717 $ $Author: kaihartmann $ $Date: 2007-01-14 18:07:55 +0100 (Sun, 14 Jan 2007) $
3
* Copyright (C) 1997-2007 The Chemistry Development Kit (CDK) project
5
* Contact: cdk-devel@lists.sourceforge.net
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public License
9
* as published by the Free Software Foundation; either version 2.1
10
* of the License, or (at your option) any later version.
11
* All we ask is that proper credit is given for our work, which includes
12
* - but is not limited to - adding the above copyright notice to the beginning
13
* of your source code files, and to any copyright notice that you may distribute
14
* with programs based on this work.
16
* This program is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU Lesser General Public License for more details.
21
* You should have received a copy of the GNU Lesser General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25
package org.openscience.cdk.structgen;
27
import org.openscience.cdk.graph.ConnectivityChecker;
28
import org.openscience.cdk.interfaces.IAtomContainer;
29
import org.openscience.cdk.interfaces.IMolecule;
30
import org.openscience.cdk.math.MathTools;
31
import org.openscience.cdk.tools.LoggingTool;
34
* RandomGenerator is a generator of Constitutional Isomers. It needs to be
35
* provided with a starting constitution and it makes random moves in
36
* constitutional space from there.
37
* This generator was first suggested by J.-L. Faulon {@cdk.cite FAU96}.
39
* <p>Unlike the VicinitySampler, this methods does not sample
40
* the full Faulon vicinity.
42
* @see org.openscience.cdk.structgen.VicinitySampler
44
* @cdk.keyword structure generator
46
public class RandomGenerator {
48
LoggingTool logger = new LoggingTool(RandomGenerator.class);
50
private IMolecule proposedStructure = null;
51
private IMolecule molecule = null;
52
private IMolecule trial = null;
55
* Constructs a RandomGenerator with a given starting structure.
57
* @param molecule The starting structure
59
public RandomGenerator(IMolecule molecule)
61
setMolecule(molecule);
66
* Proposes a structure which can be accepted or rejected by an external
67
* entity. If rejected, the structure is not used as a starting point
68
* for the next random move in structure space.
70
* @return A proposed molecule
72
public IMolecule proposeStructure()
74
logger.debug("RandomGenerator->proposeStructure() Start");
78
trial = (IMolecule)molecule.clone();
79
} catch (CloneNotSupportedException e) {
80
logger.error("Could not clone IAtomContainer!" + e.getMessage());
84
if(logger.isDebugEnabled()) {
85
String s = "BondCounts: ";
86
for (int f = 0; f < trial.getAtomCount(); f++) {
87
s += trial.getConnectedBondsCount(trial.getAtom(f)) + " ";
90
s = "BondOrderSums: ";
91
for (int f = 0; f < trial.getAtomCount(); f++) {
92
s += trial.getBondOrderSum(trial.getAtom(f)) + " ";
97
while(trial == null || !ConnectivityChecker.isConnected(trial));
98
proposedStructure = trial;
100
return proposedStructure;
104
* Tell the RandomGenerator to accept the last structure that had been proposed.
106
public void acceptStructure()
108
if (proposedStructure != null)
110
molecule = proposedStructure;
116
* Randomly chooses four atoms and alters the bonding
117
* pattern between them according to rules described
118
* in "Faulon, JCICS 1996, 36, 731".
120
public void mutate(IAtomContainer ac)
122
logger.debug("RandomGenerator->mutate() Start");
123
int nrOfAtoms = ac.getAtomCount();
124
int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
125
double a11 = 0, a12 = 0, a22 = 0, a21 = 0;
126
double b11 = 0, lowerborder = 0, upperborder = 0;
128
org.openscience.cdk.interfaces.IAtom ax1 = null, ax2 = null, ay1 = null, ay2 = null;
129
org.openscience.cdk.interfaces.IBond b1 = null, b2 = null, b3 = null, b4 = null;
130
int[] choices = new int[3];
131
int choiceCounter = 0;
132
/* We need at least two non-zero bonds in order to be successful */
133
int nonZeroBondsCounter = 0;
138
nonZeroBondsCounter = 0;
139
/* Randomly choose four distinct atoms */
142
// this yields numbers between 0 and (nrOfAtoms - 1)
143
x1 = (int)(Math.random() * nrOfAtoms);
144
x2 = (int)(Math.random() * nrOfAtoms);
145
y1 = (int)(Math.random() * nrOfAtoms);
146
y2 = (int)(Math.random() * nrOfAtoms);
147
logger.debug("RandomGenerator->mutate(): x1, x2, y1, y2: " + x1 + ", " + x2 + ", " + y1 + ", " + y2);
149
while (!(x1 != x2 && x1 != y1 && x1 != y2 && x2 != y1 && x2 != y2 && y1 != y2));
150
ax1 = ac.getAtom(x1);
151
ay1 = ac.getAtom(y1);
152
ax2 = ac.getAtom(x2);
153
ay2 = ac.getAtom(y2);
154
/* Get four bonds for these four atoms */
156
b1 = ac.getBond(ax1, ay1);
160
nonZeroBondsCounter ++;
167
b2 = ac.getBond(ax1, ay2);
171
nonZeroBondsCounter ++;
178
b3 = ac.getBond(ax2, ay1);
182
nonZeroBondsCounter ++;
189
b4 = ac.getBond(ax2, ay2);
193
nonZeroBondsCounter ++;
199
logger.debug("RandomGenerator->mutate()->The old bond orders: a11, a12, a21, a22: " + + a11 + ", " + a12 + ", " + a21 + ", " + a22);
200
}while(nonZeroBondsCounter < 2);
203
/* Compute the range for b11 (see Faulons formulae for details) */
204
double[] cmax = {0, a11 - a22, a11 + a12 - 3, a11 + a21 - 3};
205
double[] cmin = {3, a11 + a12, a11 + a21, a11 - a22 + 3};
206
lowerborder = MathTools.max(cmax);
207
upperborder = MathTools.min(cmin);
208
/* Randomly choose b11 != a11 in the range max > r > min */
209
logger.debug("*** New Try ***");
210
logger.debug("a11 = ", a11);
211
logger.debug("upperborder = ", upperborder);
212
logger.debug("lowerborder = ", lowerborder);
214
for (double f = lowerborder; f <= upperborder; f++)
218
choices[choiceCounter] = (int)f;
222
if (choiceCounter > 0)
224
b11 = choices[(int)(Math.random() * choiceCounter)];
227
logger.debug("b11 = " + b11);
229
while (!(b11 != a11 && (b11 >= lowerborder && b11 <= upperborder)));
231
double b12 = a11 + a12 - b11;
232
double b21 = a11 + a21 - b11;
233
double b22 = a22 - a11 + b11;
240
b1 = ac.getBuilder().newBond(ax1, ay1, b11);
257
b2 = ac.getBuilder().newBond(ax1, ay2, b12);
274
b3 = ac.getBuilder().newBond(ax2, ay1, b21);
291
b4 = ac.getBuilder().newBond(ax2, ay2, b22);
304
logger.debug("a11 a12 a21 a22: " + a11 + " " + a12 + " " + a21 + " " + a22);
305
logger.debug("b11 b12 b21 b22: " + b11 + " " + b12 + " " + b21 + " " + b22);
310
* Assigns a starting structure to this generator.
312
* @param molecule a starting structure for this generator
314
public void setMolecule(IMolecule molecule)
316
this.molecule = molecule;
321
* Returns the molecule which reflects the current state of this
322
* stochastic structure generator.
324
* @return The molecule
326
public IMolecule getMolecule()
328
return this.molecule;