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 [MAZE_LOSS](MAZE_LOSS.md) function. The optimal biasing direction is
38 : determined by performing a population-based memetics search with local
39 : heuristics.
40 :
41 : ## 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 [MAZE_LOSS](MAZE_LOSS.md) keyword.
45 :
46 : ```plumed
47 : l: MAZE_LOSS PARAMS=1,1,1
48 :
49 : MAZE_MEMETIC_SAMPLING ...
50 : LABEL=ma
51 :
52 : LOSS=l
53 :
54 : N_ITER=10
55 : OPTIMIZER_STRIDE=200
56 :
57 : CAPACITY=20
58 :
59 : LOCAL_SEARCH_ON
60 : N_LOCAL_ITER=10
61 : LOCAL_SEARCH_RATE=0.1
62 : LOCAL_SEARCH_TYPE=stochastic_hill_climbing
63 :
64 : MUTATION_RATE=0.1
65 : MATING_RATE=0.7
66 : CAUCHY_ALPHA=0
67 : CAUCHY_BETA=0.1
68 :
69 : LIGAND=2635-2646
70 : PROTEIN=1-2634
71 : ... MAZE_MEMETIC_SAMPLING
72 : ```
73 :
74 : As shown above, each optimizer should be provided with the LIGAND and
75 : the PROTEIN keywords.
76 :
77 : The neighbor list can be turned on by providing the NLIST keyword.
78 :
79 : */
80 : //+ENDPLUMEDOC
81 :
82 : /**
83 : * Register MAZE_MEMETIC_SAMPLING.
84 : */
85 : PLUMED_REGISTER_ACTION(Memetic, "MAZE_MEMETIC_SAMPLING")
86 :
87 6 : void Memetic::registerKeywords(Keywords& keys) {
88 6 : Optimizer::registerKeywords(keys);
89 :
90 6 : keys.add(
91 : "compulsory",
92 : "CAPACITY",
93 : "Sampling set size."
94 : );
95 :
96 6 : keys.add(
97 : "compulsory",
98 : "MUTATION_RATE",
99 : "Probability of mutation."
100 : );
101 :
102 6 : keys.add(
103 : "compulsory",
104 : "MATING_RATE",
105 : "Probability of mating."
106 : );
107 :
108 6 : keys.add(
109 : "compulsory",
110 : "CAUCHY_ALPHA",
111 : "Mean of Cauchy distribution for sampling."
112 : );
113 :
114 6 : keys.add(
115 : "compulsory",
116 : "CAUCHY_BETA",
117 : "Spread of Cauchy distribution for sampling."
118 : );
119 :
120 6 : keys.addFlag(
121 : "LOCAL_SEARCH_ON",
122 : false,
123 : "Turn local search on."
124 : );
125 :
126 6 : keys.add(
127 : "optional",
128 : "N_LOCAL_ITER",
129 : "Number of local search iterations."
130 : );
131 :
132 6 : keys.add(
133 : "optional",
134 : "LOCAL_SEARCH_RATE",
135 : "Rate of mutation in local search."
136 : );
137 :
138 6 : keys.add(
139 : "optional",
140 : "LOCAL_SEARCH_TYPE",
141 : "Type of local search."
142 : );
143 6 : }
144 :
145 2 : Memetic::Memetic(const ActionOptions& ao)
146 : : PLUMED_OPT_INIT(ao),
147 2 : bound_(true),
148 2 : score_worst_(0),
149 2 : score_best_(0),
150 2 : adaptation_(true),
151 2 : coding_len_(3),
152 2 : local_search_on_(false) {
153 2 : log.printf("maze> Memetic sampling.\n");
154 :
155 2 : if (keywords.exists("CAPACITY")) {
156 2 : parse("CAPACITY", capacity_);
157 :
158 2 : plumed_massert(
159 : capacity_ > 0,
160 : "maze> CAPACITY should be explicitly specified and positive.\n"
161 : );
162 :
163 2 : log.printf(
164 : "maze> CAPACITY read: %u.\n",
165 : capacity_
166 : );
167 : }
168 :
169 2 : if (keywords.exists("MUTATION_RATE")) {
170 2 : parse("MUTATION_RATE", mutation_rate_);
171 :
172 2 : plumed_massert(
173 : mutation_rate_ > 0 && mutation_rate_ <= 1,
174 : "maze> MUTATION_RATE should be in [0, 1).\n"
175 : );
176 :
177 2 : log.printf(
178 : "maze> MUTATION_RATE read: %f.\n",
179 : mutation_rate_
180 : );
181 : }
182 :
183 2 : if (keywords.exists("MATING_RATE")) {
184 2 : parse("MATING_RATE", mating_rate_);
185 :
186 2 : plumed_massert(
187 : mating_rate_ > 0 && mating_rate_ <= 1,
188 : "maze> MATING_RATE should be in [0, 1).\n"
189 : );
190 :
191 2 : log.printf(
192 : "maze> MATING_RATE read: %f.\n",
193 : mating_rate_
194 : );
195 : }
196 :
197 2 : if (keywords.exists("CAUCHY_ALPHA")) {
198 2 : parse("CAUCHY_ALPHA", cauchy_mean_alpha_);
199 :
200 2 : log.printf(
201 : "maze> CAUCHY_ALPHA read: %f.\n",
202 : cauchy_mean_alpha_
203 : );
204 : }
205 :
206 2 : if (keywords.exists("CAUCHY_BETA")) {
207 2 : parse("CAUCHY_BETA", cauchy_mean_beta_);
208 :
209 2 : plumed_massert(
210 : cauchy_mean_beta_ > 0,
211 : "maze> CAUCHY_BETA should be explicitly specified and positive.\n"
212 : );
213 :
214 2 : log.printf(
215 : "maze> CAUCHY_BETA read: %f.\n",
216 : cauchy_mean_beta_
217 : );
218 : }
219 :
220 2 : if (keywords.exists("LOCAL_SEARCH_ON")) {
221 2 : parseFlag("LOCAL_SEARCH_ON", local_search_on_);
222 :
223 2 : log.printf("maze> LOCAL_SEARCH_ON enabled: %d.\n", local_search_on_);
224 : }
225 :
226 2 : if (local_search_on_) {
227 1 : parse("N_LOCAL_ITER", n_local_iterations_);
228 :
229 1 : plumed_massert(
230 : n_local_iterations_ > 0,
231 : "maze> N_LOCAL_ITER should be explicitly specified and positive.\n"
232 : );
233 :
234 1 : log.printf(
235 : "maze> N_LOCAL_ITER read: %u.\n",
236 : n_local_iterations_
237 : );
238 :
239 1 : parse("LOCAL_SEARCH_RATE", local_search_rate_);
240 :
241 1 : plumed_massert(
242 : local_search_rate_ > 0 && local_search_rate_ <= 1,
243 : "maze> LOCAL_SEARCH_RATE should be in [0, 1).\n"
244 : );
245 :
246 1 : log.printf(
247 : "maze> LOCAL_SEARCH_RATE read: %f.\n",
248 : local_search_rate_
249 : );
250 :
251 1 : parse("LOCAL_SEARCH_TYPE", local_search_type_);
252 :
253 1 : plumed_massert(
254 : local_search_type_ == "stochastic_hill_climbing" ||
255 : local_search_type_ == "adaptive_random_search",
256 : "maze> LOCAL_SEARCH_TYPE should be: "
257 : "stochastic_hill_climbing, or adaptive_random_search.\n"
258 : );
259 :
260 1 : log.printf(
261 : "maze> LOCAL_SEARCH_TYPE read: %s.\n",
262 : local_search_type_.c_str()
263 : );
264 : }
265 :
266 2 : set_n_global_iterations(n_iter_);
267 :
268 4 : set_label("MEMETIC_SAMPLING");
269 :
270 : start_step_0();
271 :
272 2 : checkRead();
273 2 : }
274 :
275 6 : void Memetic::optimize() {
276 6 : Vector t = solve();
277 :
278 : set_opt(t);
279 6 : set_opt_value(score());
280 6 : }
281 :
282 : } // namespace maze
283 : } // namespace PLMD
|