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 10423 : PLUMED_REGISTER_ACTION(Memetic, "MAZE_MEMETIC_SAMPLING")
84 :
85 3 : void Memetic::registerKeywords(Keywords& keys) {
86 3 : Optimizer::registerKeywords(keys);
87 :
88 6 : keys.add(
89 : "compulsory",
90 : "CAPACITY",
91 : "Sampling set size."
92 : );
93 :
94 6 : keys.add(
95 : "compulsory",
96 : "MUTATION_RATE",
97 : "Probability of mutation."
98 : );
99 :
100 6 : keys.add(
101 : "compulsory",
102 : "MATING_RATE",
103 : "Probability of mating."
104 : );
105 :
106 6 : keys.add(
107 : "compulsory",
108 : "CAUCHY_ALPHA",
109 : "Mean of Cauchy distribution for sampling."
110 : );
111 :
112 6 : keys.add(
113 : "compulsory",
114 : "CAUCHY_BETA",
115 : "Spread of Cauchy distribution for sampling."
116 : );
117 :
118 6 : keys.addFlag(
119 : "LOCAL_SEARCH_ON",
120 : false,
121 : "Turn local search on."
122 : );
123 :
124 6 : keys.add(
125 : "optional",
126 : "N_LOCAL_ITER",
127 : "Number of local search iterations."
128 : );
129 :
130 9 : keys.add(
131 : "optional",
132 : "LOCAL_SEARCH_RATE",
133 : "Rate of mutation in local search."
134 : );
135 :
136 9 : keys.add(
137 : "optional",
138 : "LOCAL_SEARCH_TYPE",
139 : "Type of local search."
140 : );
141 3 : }
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 : {
152 2 : log.printf("maze> Memetic sampling.\n");
153 :
154 4 : if (keywords.exists("CAPACITY")) {
155 2 : parse("CAPACITY", capacity_);
156 :
157 2 : plumed_massert(
158 : capacity_ > 0,
159 : "maze> CAPACITY should be explicitly specified and positive.\n"
160 : );
161 :
162 2 : log.printf(
163 : "maze> CAPACITY read: %u.\n",
164 : capacity_
165 : );
166 : }
167 :
168 4 : if (keywords.exists("MUTATION_RATE")) {
169 2 : parse("MUTATION_RATE", mutation_rate_);
170 :
171 2 : plumed_massert(
172 : mutation_rate_ > 0 && mutation_rate_ <= 1,
173 : "maze> MUTATION_RATE should be in [0, 1).\n"
174 : );
175 :
176 2 : log.printf(
177 : "maze> MUTATION_RATE read: %f.\n",
178 : mutation_rate_
179 : );
180 : }
181 :
182 4 : if (keywords.exists("MATING_RATE")) {
183 2 : parse("MATING_RATE", mating_rate_);
184 :
185 2 : plumed_massert(
186 : mating_rate_ > 0 && mating_rate_ <= 1,
187 : "maze> MATING_RATE should be in [0, 1).\n"
188 : );
189 :
190 2 : log.printf(
191 : "maze> MATING_RATE read: %f.\n",
192 : mating_rate_
193 : );
194 : }
195 :
196 4 : if (keywords.exists("CAUCHY_ALPHA")) {
197 2 : parse("CAUCHY_ALPHA", cauchy_mean_alpha_);
198 :
199 2 : log.printf(
200 : "maze> CAUCHY_ALPHA read: %f.\n",
201 : cauchy_mean_alpha_
202 : );
203 : }
204 :
205 4 : if (keywords.exists("CAUCHY_BETA")) {
206 2 : parse("CAUCHY_BETA", cauchy_mean_beta_);
207 :
208 2 : plumed_massert(
209 : cauchy_mean_beta_ > 0,
210 : "maze> CAUCHY_BETA should be explicitly specified and positive.\n"
211 : );
212 :
213 2 : log.printf(
214 : "maze> CAUCHY_BETA read: %f.\n",
215 : cauchy_mean_beta_
216 : );
217 : }
218 :
219 4 : if (keywords.exists("LOCAL_SEARCH_ON")) {
220 2 : parseFlag("LOCAL_SEARCH_ON", local_search_on_);
221 :
222 2 : log.printf("maze> LOCAL_SEARCH_ON enabled: %d.\n", local_search_on_);
223 : }
224 :
225 2 : if (local_search_on_) {
226 1 : parse("N_LOCAL_ITER", n_local_iterations_);
227 :
228 1 : plumed_massert(
229 : n_local_iterations_ > 0,
230 : "maze> N_LOCAL_ITER should be explicitly specified and positive.\n"
231 : );
232 :
233 1 : log.printf(
234 : "maze> N_LOCAL_ITER read: %u.\n",
235 : n_local_iterations_
236 : );
237 :
238 1 : parse("LOCAL_SEARCH_RATE", local_search_rate_);
239 :
240 1 : plumed_massert(
241 : local_search_rate_ > 0 && local_search_rate_ <= 1,
242 : "maze> LOCAL_SEARCH_RATE should be in [0, 1).\n"
243 : );
244 :
245 1 : log.printf(
246 : "maze> LOCAL_SEARCH_RATE read: %f.\n",
247 : local_search_rate_
248 : );
249 :
250 2 : parse("LOCAL_SEARCH_TYPE", local_search_type_);
251 :
252 1 : plumed_massert(
253 : local_search_type_ == "stochastic_hill_climbing" ||
254 : local_search_type_ == "adaptive_random_search",
255 : "maze> LOCAL_SEARCH_TYPE should be: "
256 : "stochastic_hill_climbing, or adaptive_random_search.\n"
257 : );
258 :
259 1 : log.printf(
260 : "maze> LOCAL_SEARCH_TYPE read: %s.\n",
261 : local_search_type_.c_str()
262 : );
263 : }
264 :
265 2 : set_n_global_iterations(n_iter_);
266 :
267 4 : set_label("MEMETIC_SAMPLING");
268 :
269 : start_step_0();
270 :
271 2 : checkRead();
272 2 : }
273 :
274 4 : Memetic::~Memetic() {
275 2 : delete neighbor_list_;
276 :
277 : members_.clear();
278 4 : }
279 :
280 6 : void Memetic::optimize() {
281 6 : Vector t = solve();
282 :
283 : set_opt(t);
284 6 : set_opt_value(score());
285 6 : }
286 :
287 : } // namespace maze
288 : } // namespace PLMD
|