Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2019 Jakub Rydzewski (jr@fizyka.umk.pl). All rights reserved.
3 :
4 : See http://www.maze-code.github.io for more information.
5 :
6 : This file is part of maze.
7 :
8 : maze is free software: you can redistribute it and/or modify it under the
9 : terms of the GNU Lesser General Public License as published by the Free
10 : Software Foundation, either version 3 of the License, or (at your option)
11 : any later version.
12 :
13 : maze is distributed in the hope that it will be useful, but WITHOUT ANY
14 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 : FOR A PARTICULAR PURPOSE.
16 :
17 : See the 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 maze. If not, see <https://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 :
23 : /**
24 : * @file Memetic.cpp
25 : * @author J. Rydzewski (jr@fizyka.umk.pl)
26 : */
27 :
28 : #include "Memetic.h"
29 :
30 : namespace PLMD {
31 : namespace maze {
32 :
33 : //+PLUMEDOC MAZE_OPTIMIZER MAZE_MEMETIC_SAMPLING
34 : /*
35 :
36 : Calculates the biasing direction along which the ligand unbinds by
37 : minimizing the \ref MAZE_LOSS function. The optimal biasing direction is
38 : determined by performing a population-based memetics search with local
39 : heuristics.
40 :
41 : \par Examples
42 :
43 : Every optimizer implemented in the maze module needs a loss function as
44 : an argument, and it should be passed using the \ref MAZE_LOSS keyword.
45 :
46 : \plumedfile
47 : MAZE_MEMETIC_SAMPLING ...
48 : LABEL=ma
49 :
50 : LOSS=l
51 :
52 : N_ITER=10
53 : OPTIMIZER_STRIDE=200
54 :
55 : CAPACITY=20
56 :
57 : LOCAL_SEARCH_ON
58 : N_LOCAL_ITER=10
59 : LOCAL_SEARCH_RATE=0.1
60 : LOCAL_SEARCH_TYPE=stochastic_hill_climbing
61 :
62 : MUTATION_RATE=0.1
63 : MATING_RATE=0.7
64 : CAUCHY_ALPHA=0
65 : CAUCHY_BETA=0.1
66 :
67 : LIGAND=2635-2646
68 : PROTEIN=1-2634
69 : ... MAZE_MEMETIC_SAMPLING
70 : \endplumedfile
71 :
72 : As shown above, each optimizer should be provided with the LIGAND and
73 : the PROTEIN keywords.
74 :
75 : The neighbor list can be turned on by providing the NLIST keyword.
76 :
77 : */
78 : //+ENDPLUMEDOC
79 :
80 : /**
81 : * Register MAZE_MEMETIC_SAMPLING.
82 : */
83 : PLUMED_REGISTER_ACTION(Memetic, "MAZE_MEMETIC_SAMPLING")
84 :
85 4 : void Memetic::registerKeywords(Keywords& keys) {
86 4 : Optimizer::registerKeywords(keys);
87 :
88 4 : keys.add(
89 : "compulsory",
90 : "CAPACITY",
91 : "Sampling set size."
92 : );
93 :
94 4 : keys.add(
95 : "compulsory",
96 : "MUTATION_RATE",
97 : "Probability of mutation."
98 : );
99 :
100 4 : keys.add(
101 : "compulsory",
102 : "MATING_RATE",
103 : "Probability of mating."
104 : );
105 :
106 4 : keys.add(
107 : "compulsory",
108 : "CAUCHY_ALPHA",
109 : "Mean of Cauchy distribution for sampling."
110 : );
111 :
112 4 : keys.add(
113 : "compulsory",
114 : "CAUCHY_BETA",
115 : "Spread of Cauchy distribution for sampling."
116 : );
117 :
118 4 : keys.addFlag(
119 : "LOCAL_SEARCH_ON",
120 : false,
121 : "Turn local search on."
122 : );
123 :
124 4 : keys.add(
125 : "optional",
126 : "N_LOCAL_ITER",
127 : "Number of local search iterations."
128 : );
129 :
130 4 : keys.add(
131 : "optional",
132 : "LOCAL_SEARCH_RATE",
133 : "Rate of mutation in local search."
134 : );
135 :
136 4 : keys.add(
137 : "optional",
138 : "LOCAL_SEARCH_TYPE",
139 : "Type of local search."
140 : );
141 4 : }
142 :
143 2 : Memetic::Memetic(const ActionOptions& ao)
144 : : PLUMED_OPT_INIT(ao),
145 2 : bound_(true),
146 2 : score_worst_(0),
147 2 : score_best_(0),
148 2 : adaptation_(true),
149 2 : coding_len_(3),
150 2 : local_search_on_(false) {
151 2 : log.printf("maze> Memetic sampling.\n");
152 :
153 2 : if (keywords.exists("CAPACITY")) {
154 2 : parse("CAPACITY", capacity_);
155 :
156 2 : plumed_massert(
157 : capacity_ > 0,
158 : "maze> CAPACITY should be explicitly specified and positive.\n"
159 : );
160 :
161 2 : log.printf(
162 : "maze> CAPACITY read: %u.\n",
163 : capacity_
164 : );
165 : }
166 :
167 2 : if (keywords.exists("MUTATION_RATE")) {
168 2 : parse("MUTATION_RATE", mutation_rate_);
169 :
170 2 : plumed_massert(
171 : mutation_rate_ > 0 && mutation_rate_ <= 1,
172 : "maze> MUTATION_RATE should be in [0, 1).\n"
173 : );
174 :
175 2 : log.printf(
176 : "maze> MUTATION_RATE read: %f.\n",
177 : mutation_rate_
178 : );
179 : }
180 :
181 2 : if (keywords.exists("MATING_RATE")) {
182 2 : parse("MATING_RATE", mating_rate_);
183 :
184 2 : plumed_massert(
185 : mating_rate_ > 0 && mating_rate_ <= 1,
186 : "maze> MATING_RATE should be in [0, 1).\n"
187 : );
188 :
189 2 : log.printf(
190 : "maze> MATING_RATE read: %f.\n",
191 : mating_rate_
192 : );
193 : }
194 :
195 2 : if (keywords.exists("CAUCHY_ALPHA")) {
196 2 : parse("CAUCHY_ALPHA", cauchy_mean_alpha_);
197 :
198 2 : log.printf(
199 : "maze> CAUCHY_ALPHA read: %f.\n",
200 : cauchy_mean_alpha_
201 : );
202 : }
203 :
204 2 : if (keywords.exists("CAUCHY_BETA")) {
205 2 : parse("CAUCHY_BETA", cauchy_mean_beta_);
206 :
207 2 : plumed_massert(
208 : cauchy_mean_beta_ > 0,
209 : "maze> CAUCHY_BETA should be explicitly specified and positive.\n"
210 : );
211 :
212 2 : log.printf(
213 : "maze> CAUCHY_BETA read: %f.\n",
214 : cauchy_mean_beta_
215 : );
216 : }
217 :
218 2 : if (keywords.exists("LOCAL_SEARCH_ON")) {
219 2 : parseFlag("LOCAL_SEARCH_ON", local_search_on_);
220 :
221 2 : log.printf("maze> LOCAL_SEARCH_ON enabled: %d.\n", local_search_on_);
222 : }
223 :
224 2 : if (local_search_on_) {
225 1 : parse("N_LOCAL_ITER", n_local_iterations_);
226 :
227 1 : plumed_massert(
228 : n_local_iterations_ > 0,
229 : "maze> N_LOCAL_ITER should be explicitly specified and positive.\n"
230 : );
231 :
232 1 : log.printf(
233 : "maze> N_LOCAL_ITER read: %u.\n",
234 : n_local_iterations_
235 : );
236 :
237 1 : parse("LOCAL_SEARCH_RATE", local_search_rate_);
238 :
239 1 : plumed_massert(
240 : local_search_rate_ > 0 && local_search_rate_ <= 1,
241 : "maze> LOCAL_SEARCH_RATE should be in [0, 1).\n"
242 : );
243 :
244 1 : log.printf(
245 : "maze> LOCAL_SEARCH_RATE read: %f.\n",
246 : local_search_rate_
247 : );
248 :
249 2 : parse("LOCAL_SEARCH_TYPE", local_search_type_);
250 :
251 1 : plumed_massert(
252 : local_search_type_ == "stochastic_hill_climbing" ||
253 : local_search_type_ == "adaptive_random_search",
254 : "maze> LOCAL_SEARCH_TYPE should be: "
255 : "stochastic_hill_climbing, or adaptive_random_search.\n"
256 : );
257 :
258 1 : log.printf(
259 : "maze> LOCAL_SEARCH_TYPE read: %s.\n",
260 : local_search_type_.c_str()
261 : );
262 : }
263 :
264 2 : set_n_global_iterations(n_iter_);
265 :
266 4 : set_label("MEMETIC_SAMPLING");
267 :
268 : start_step_0();
269 :
270 2 : checkRead();
271 2 : }
272 :
273 6 : void Memetic::optimize() {
274 6 : Vector t = solve();
275 :
276 : set_opt(t);
277 6 : set_opt_value(score());
278 6 : }
279 :
280 : } // namespace maze
281 : } // namespace PLMD
|