~ubuntu-branches/ubuntu/trusty/cdk/trusty-proposed

« back to all changes in this revision

Viewing changes to src/org/openscience/cdk/structgen/RandomGenerator.java

  • Committer: Bazaar Package Importer
  • Author(s): Paul Cager
  • Date: 2008-04-09 21:17:53 UTC
  • Revision ID: james.westby@ubuntu.com-20080409211753-46lmjw5z8mx5pd8d
Tags: upstream-1.0.2
ImportĀ upstreamĀ versionĀ 1.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Revision: 7717 $ $Author: kaihartmann $ $Date: 2007-01-14 18:07:55 +0100 (Sun, 14 Jan 2007) $    
 
2
 * 
 
3
 * Copyright (C) 1997-2007  The Chemistry Development Kit (CDK) project
 
4
 * 
 
5
 * Contact: cdk-devel@lists.sourceforge.net
 
6
 * 
 
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.
 
15
 * 
 
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.
 
20
 * 
 
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.
 
24
 */
 
25
package org.openscience.cdk.structgen;
 
26
 
 
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;
 
32
 
 
33
/**
 
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}.
 
38
 *
 
39
 * <p>Unlike the VicinitySampler, this methods does not sample
 
40
 * the full Faulon vicinity.
 
41
 * 
 
42
 * @see         org.openscience.cdk.structgen.VicinitySampler
 
43
 * 
 
44
 * @cdk.keyword structure generator
 
45
 */
 
46
public class RandomGenerator {
 
47
        
 
48
        LoggingTool logger = new LoggingTool(RandomGenerator.class);
 
49
        
 
50
        private IMolecule proposedStructure = null;
 
51
        private IMolecule molecule = null;
 
52
        private IMolecule trial = null;
 
53
 
 
54
        /**
 
55
         * Constructs a RandomGenerator with a given starting structure.
 
56
         *
 
57
         * @param   molecule  The starting structure
 
58
         */
 
59
        public RandomGenerator(IMolecule molecule)
 
60
        {
 
61
                setMolecule(molecule);
 
62
        }
 
63
 
 
64
 
 
65
        /**
 
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.
 
69
         *
 
70
         * @return A proposed molecule    
 
71
         */
 
72
        public IMolecule proposeStructure()
 
73
        {
 
74
                logger.debug("RandomGenerator->proposeStructure() Start");
 
75
                do
 
76
                {
 
77
                        try {
 
78
                                trial = (IMolecule)molecule.clone();
 
79
                        } catch (CloneNotSupportedException e) {
 
80
                                logger.error("Could not clone IAtomContainer!" + e.getMessage());
 
81
                                trial = null;
 
82
                        }
 
83
                        mutate(trial);
 
84
                        if(logger.isDebugEnabled()) {
 
85
                                String s = "BondCounts:    ";
 
86
                                for (int f = 0; f < trial.getAtomCount(); f++) {
 
87
                                        s += trial.getConnectedBondsCount(trial.getAtom(f)) + " ";
 
88
                                }
 
89
                                logger.debug(s);
 
90
                                s = "BondOrderSums: ";
 
91
                                for (int f = 0; f < trial.getAtomCount(); f++) {
 
92
                                        s += trial.getBondOrderSum(trial.getAtom(f)) + " ";
 
93
                                }
 
94
                                logger.debug(s);
 
95
                        }
 
96
                }
 
97
                while(trial == null || !ConnectivityChecker.isConnected(trial));
 
98
                proposedStructure = trial;
 
99
                
 
100
                return proposedStructure;
 
101
        }
 
102
 
 
103
        /**
 
104
         * Tell the RandomGenerator to accept the last structure that had been proposed.
 
105
         */
 
106
        public void acceptStructure()
 
107
        {
 
108
                if (proposedStructure != null)
 
109
                {
 
110
                        molecule = proposedStructure;
 
111
                }
 
112
        }
 
113
        
 
114
        
 
115
        /**
 
116
         * Randomly chooses four atoms and alters the bonding
 
117
         * pattern between them according to rules described 
 
118
         * in "Faulon, JCICS 1996, 36, 731".
 
119
         */
 
120
        public void mutate(IAtomContainer ac)
 
121
        {
 
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;
 
127
 
 
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;
 
134
                do
 
135
                {
 
136
                        do
 
137
                        {
 
138
                                nonZeroBondsCounter = 0;
 
139
                                /* Randomly choose four distinct atoms */
 
140
                                do
 
141
                                {
 
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);
 
148
                                }
 
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 */
 
155
                                
 
156
                                b1 = ac.getBond(ax1, ay1);
 
157
                                if (b1 != null)
 
158
                                {
 
159
                                        a11 = b1.getOrder();
 
160
                                        nonZeroBondsCounter ++;                         
 
161
                                }
 
162
                                else
 
163
                                {
 
164
                                        a11 = 0;
 
165
                                }
 
166
                                
 
167
                                b2 = ac.getBond(ax1, ay2);
 
168
                                if (b2 != null)
 
169
                                {
 
170
                                        a12 = b2.getOrder();
 
171
                                        nonZeroBondsCounter ++;                         
 
172
                                }
 
173
                                else
 
174
                                {
 
175
                                        a12 = 0;
 
176
                                }
 
177
 
 
178
                                b3 = ac.getBond(ax2, ay1);
 
179
                                if (b3 != null)
 
180
                                {
 
181
                                        a21 = b3.getOrder();
 
182
                                        nonZeroBondsCounter ++;                         
 
183
                                }
 
184
                                else
 
185
                                {
 
186
                                        a21 = 0;
 
187
                                }
 
188
                                
 
189
                                b4 = ac.getBond(ax2, ay2);                                                                      
 
190
                                if (b4 != null)
 
191
                                {
 
192
                                        a22 = b4.getOrder();
 
193
                                        nonZeroBondsCounter ++;
 
194
                                }
 
195
                                else
 
196
                                {
 
197
                                        a22 = 0;
 
198
                                }
 
199
                                logger.debug("RandomGenerator->mutate()->The old bond orders: a11, a12, a21, a22: " +  + a11 + ", " + a12 + ", " + a21 + ", " + a22);
 
200
                        }while(nonZeroBondsCounter < 2);
 
201
                        
 
202
                                        
 
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);
 
213
                        choiceCounter = 0;
 
214
                        for (double f = lowerborder; f <= upperborder; f++)
 
215
                        {
 
216
                                if (f != a11)
 
217
                                {
 
218
                                        choices[choiceCounter] = (int)f;
 
219
                                        choiceCounter ++;
 
220
                                }
 
221
                        }
 
222
                        if (choiceCounter > 0)
 
223
                        {
 
224
                                b11 = choices[(int)(Math.random() * choiceCounter)];
 
225
                        }
 
226
 
 
227
                        logger.debug("b11 = " + b11);
 
228
                }
 
229
                while (!(b11 != a11 && (b11 >= lowerborder && b11 <= upperborder)));
 
230
 
 
231
                double b12 = a11 + a12 - b11;
 
232
                double b21 = a11 + a21 - b11;
 
233
                double b22 = a22 - a11 + b11;
 
234
                
 
235
                
 
236
                if (b11 > 0)
 
237
                {
 
238
                        if (b1 == null)
 
239
                        {
 
240
                                b1 = ac.getBuilder().newBond(ax1, ay1, b11);
 
241
                                ac.addBond(b1);
 
242
                        }
 
243
                        else
 
244
                        {
 
245
                                b1.setOrder(b11);
 
246
                        }
 
247
                }
 
248
                else if (b1 != null)
 
249
                {
 
250
                        ac.removeBond(b1);
 
251
                }
 
252
                
 
253
                if (b12 > 0) 
 
254
                {
 
255
                        if (b2 == null)
 
256
                        {
 
257
                                b2 = ac.getBuilder().newBond(ax1, ay2, b12);
 
258
                                ac.addBond(b2);
 
259
                        }
 
260
                        else
 
261
                        {
 
262
                                b2.setOrder(b12);
 
263
                        }
 
264
                }
 
265
                else if (b2 != null)
 
266
                {
 
267
                        ac.removeBond(b2);
 
268
                }
 
269
                
 
270
                if (b21 > 0) 
 
271
                {
 
272
                        if (b3 == null)
 
273
                        {
 
274
                                b3 = ac.getBuilder().newBond(ax2, ay1, b21);
 
275
                                ac.addBond(b3);
 
276
                        }
 
277
                        else
 
278
                        {
 
279
                                b3.setOrder(b21);
 
280
                        }
 
281
                }
 
282
                else if (b3 != null)
 
283
                {
 
284
                        ac.removeBond(b3);
 
285
                }
 
286
 
 
287
                if (b22 > 0) 
 
288
                {
 
289
                        if (b4 == null)
 
290
                        {
 
291
                                b4 = ac.getBuilder().newBond(ax2, ay2, b22);
 
292
                                ac.addBond(b4);
 
293
                        }
 
294
                        else
 
295
                        {
 
296
                                b4.setOrder(b22);
 
297
                        }
 
298
                }
 
299
                else if (b4 != null)
 
300
                {
 
301
                        ac.removeBond(b4);
 
302
                }
 
303
                
 
304
                logger.debug("a11 a12 a21 a22: " + a11 + " " + a12 + " " + a21 + " " + a22);
 
305
                logger.debug("b11 b12 b21 b22: " + b11 + " " + b12 + " " + b21 + " " + b22);
 
306
        }
 
307
 
 
308
        
 
309
        /**
 
310
         * Assigns a starting structure to this generator.
 
311
         *
 
312
         * @param   molecule  a starting structure for this generator
 
313
         */
 
314
        public void setMolecule(IMolecule molecule)
 
315
        {
 
316
                this.molecule = molecule;       
 
317
        }
 
318
 
 
319
 
 
320
        /**
 
321
         * Returns the molecule which reflects the current state of this
 
322
         * stochastic structure generator.
 
323
         *
 
324
         * @return The molecule    
 
325
         */
 
326
        public IMolecule getMolecule()
 
327
        {
 
328
                return this.molecule;
 
329
        }
 
330
        
 
331
}