1 /**************************************************************************/
2 /*  Copyright 2012 Tim Day                                                */
3 /*                                                                        */
4 /*  This file is part of Evolvotron                                       */
5 /*                                                                        */
6 /*  Evolvotron is free software: you can redistribute it and/or modify    */
7 /*  it under the terms of the GNU General Public License as published by  */
8 /*  the Free Software Foundation, either version 3 of the License, or     */
9 /*  (at your option) any later version.                                   */
10 /*                                                                        */
11 /*  Evolvotron is distributed in the hope that it will be useful,         */
12 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
13 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
14 /*  GNU General Public License for more details.                          */
15 /*                                                                        */
16 /*  You should have received a copy of the GNU General Public License     */
17 /*  along with Evolvotron.  If not, see <http://www.gnu.org/licenses/>.   */
18 /**************************************************************************/
19 
20 /*! \file
21   \brief Interface for class MutationParameters.
22 */
23 
24 #ifndef _mutation_parameters_h_
25 #define _mutation_parameters_h_
26 
27 #include "common.h"
28 #include "random.h"
29 
30 class FunctionNode;
31 class FunctionRegistration;
32 class FunctionRegistry;
33 
34 //! Class encapsulating mutation parameters.
35 /*! For example, magnitude of variations, probability of leaves being dropped.
36   Also provides a random number generator.
37  */
38 class MutationParameters
39 {
40  private:
41 
42   const std::unique_ptr<FunctionRegistry> _function_registry;
43 
44  protected:
45 
46   //! A random number generator.
47   /*! Declared mutable so we can pass const MutationParameters& around and still do useful work with it.
48    */
49   mutable Random01 _r01;
50 
51   //! Negative-exponential generator might be useful too.
52   mutable RandomNegExp _r_negexp;
53 
54   //! Specifies the base magnitude of random changes the function parameters.
55   real _base_magnitude_parameter_variation;
56 
57   //! Specifies the base probability of a the parameter set being completely reset.
58   real _base_probability_parameter_reset;
59 
60   //! Specifies the base probability of a child being dropped and replaced with a new random stub.
61   real _base_probability_glitch;
62 
63   //! Specifies the base probability of all child nodes being reordered.
64   real _base_probability_shuffle;
65 
66   //! Specifies the base probability of a random stub being inserted before a child.
67   real _base_probability_insert;
68 
69   //! Specifies the base probability of a node being replaced with an alternate type.
70   real _base_probability_substitute;
71 
72   //! Specifies the proportion of basic node types.
73   real _proportion_basic;
74 
75   //! Specifies the proportion of Constant nodes vs Position type nodes.
76   real _proportion_constant;
77 
78   //! Specifies the probability of a using a FunctionNodePositionTransformed instead of FunctionNodePosition
79   real _identity_supression;
80 
81   //! The maximum number of iterations an iterative function node can have initially.
82   uint _max_initial_iterations;
83 
84   //! The base probability of the number of iterations changing by plus or minus 1.
85   real _base_probability_iterations_change_step;
86 
87   //! The base probability of the number of iterations changing by times or divide 2.
88   real _base_probability_iterations_change_jump;
89 
90   //! Individual weighting modifiers for each function type
91   /*! Will only be applied to random functions we're asked for.
92     The bulk of nodes are created by FunctionNode and are boring to keep the branching ratio down.
93     \todo Implement a branching ratio query method.
94    */
95   std::map<const FunctionRegistration*,real> _function_weighting;
96 
97   //! Total of function weights, for normalisation.
98   real _function_weighting_total;
99 
100   //! Map from [0,1] to a function registration, taking weights into account.
101   std::map<real,const FunctionRegistration*> _function_pick;
102 
103   //! What state a reset should return autocool to.
104   const bool _autocool_reset_state;
105 
106   //! Whether autocooling is being applied.
107   bool _autocool_enable;
108 
109   //! Number of generations at which parameters will be half cooled.
110   uint _autocool_halflife;
111 
112   //! Count of number of generations for decay cooling.
113   uint _autocool_generations;
114 
115   //! Just use SingleChannelNoise for almost all functions (useful for debugging).
116   const bool _debug_mode;
117 
118   void recalculate_function_stuff();
119 
120  public:
121   //! Trivial constructor.
122   MutationParameters(uint seed,bool ac,bool debug_mode);
123 
124   //! Trivial destructor.
125   virtual ~MutationParameters();
126 
127   //! Accessor.
function_registry()128   const FunctionRegistry& function_registry() const
129     {
130       return *_function_registry;
131     }
132 
133   //! Reset to initial values.
134   void reset();
135 
136   //! Multiply most parameters by the given factor
137   void general_cool(real f);
138 
139   //! Returns a reference to the random number generator.
140   /*! Need this for e.g RandomXYZInSphere constructor.
141    */
rng01()142   Random01& rng01() const
143     {
144       return _r01;
145     }
146 
147   //! Return a number in the range [0,1)
r01()148   real r01() const
149     {
150       return _r01();
151     }
152 
rnegexp()153   real rnegexp() const
154     {
155       return _r_negexp();
156     }
157 
158   //! Accessor, with decay.
effective_magnitude_parameter_variation()159   real effective_magnitude_parameter_variation() const
160     {
161       return base_magnitude_parameter_variation()*decay_factor();
162     }
163   //! Accessor.
base_magnitude_parameter_variation()164   real base_magnitude_parameter_variation() const
165     {
166       return _base_magnitude_parameter_variation;
167     }
168   //! Accessor.
base_magnitude_parameter_variation(real v)169   void base_magnitude_parameter_variation(real v)
170     {
171       _base_magnitude_parameter_variation=v;
172       report_change();
173     }
174 
175   //! Accessor, with decay.
effective_probability_parameter_reset()176   real effective_probability_parameter_reset() const
177     {
178       return base_probability_parameter_reset()*decay_factor();
179     }
180   //! Accessor.
base_probability_parameter_reset()181   real base_probability_parameter_reset() const
182     {
183       return _base_probability_parameter_reset;
184     }
185   //! Accessor.
base_probability_parameter_reset(real v)186   void base_probability_parameter_reset(real v)
187     {
188       _base_probability_parameter_reset=v;
189       report_change();
190     }
191 
192   //! Accessor, with decay.
effective_probability_glitch()193   real effective_probability_glitch() const
194     {
195       return base_probability_glitch()*decay_factor();
196     }
197   //! Accessor.
base_probability_glitch()198   real base_probability_glitch() const
199     {
200       return _base_probability_glitch;
201     }
202   //! Accessor.
base_probability_glitch(real v)203   void base_probability_glitch(real v)
204     {
205       _base_probability_glitch=v;
206       report_change();
207     }
208 
209   //! Accessor, with decay.
effective_probability_shuffle()210   real effective_probability_shuffle() const
211     {
212       return base_probability_shuffle()*decay_factor();
213     }
214   //! Accessor.
base_probability_shuffle()215   real base_probability_shuffle() const
216     {
217       return _base_probability_shuffle;
218     }
219   //! Accessor.
base_probability_shuffle(real v)220   void base_probability_shuffle(real v)
221     {
222       _base_probability_shuffle=v;
223       report_change();
224     }
225 
226   //! Accessor, with decay.
effective_probability_insert()227   real effective_probability_insert() const
228     {
229       return base_probability_insert()*decay_factor();
230     }
231   //! Accessor.
base_probability_insert()232   real base_probability_insert() const
233     {
234       return _base_probability_insert;
235     }
236   //! Accessor.
base_probability_insert(real v)237   void base_probability_insert(real v)
238     {
239       _base_probability_insert=v;
240       report_change();
241     }
242 
243   //! Accessor.
effective_probability_substitute()244   real effective_probability_substitute() const
245     {
246       return base_probability_substitute()*decay_factor();
247     }
248   //! Accessor.
base_probability_substitute()249   real base_probability_substitute() const
250     {
251       return _base_probability_substitute;
252     }
253   //! Accessor.
base_probability_substitute(real v)254   void base_probability_substitute(real v)
255     {
256       _base_probability_substitute=v;
257       report_change();
258     }
259 
260   //! Accessor.
proportion_constant()261   real proportion_constant() const
262     {
263       return _proportion_constant;
264     }
265   //! Accessor.
proportion_constant(real v)266   void proportion_constant(real v)
267     {
268       _proportion_constant=v;
269       report_change();
270     }
271 
272   //! Accessor.
identity_supression()273   real identity_supression() const
274     {
275       return _identity_supression;
276     }
277   //! Accessor.
identity_supression(real v)278   void identity_supression(real v)
279     {
280       _identity_supression=v;
281       report_change();
282     }
283 
284   //! Accessor.
max_initial_iterations()285   uint max_initial_iterations() const
286     {
287       return _max_initial_iterations;
288     }
289   //! Accessor.
max_initial_iterations(uint v)290   void max_initial_iterations(uint v)
291     {
292       _max_initial_iterations=v;
293       report_change();
294     }
295 
296   //! Accessor, with decay.
effective_probability_iterations_change_step()297   real effective_probability_iterations_change_step() const
298     {
299       return base_probability_iterations_change_step()*decay_factor();
300     }
301   //! Accessor.
base_probability_iterations_change_step()302   real base_probability_iterations_change_step() const
303     {
304       return _base_probability_iterations_change_step;
305     }
306   //! Accessor.
base_probability_iterations_change_step(real v)307   void base_probability_iterations_change_step(real v)
308     {
309       _base_probability_iterations_change_step=v;
310       report_change();
311     }
312 
313   //! Accessor, with decay.
effective_probability_iterations_change_jump()314   real effective_probability_iterations_change_jump() const
315     {
316       return base_probability_iterations_change_jump()*decay_factor();
317     }
318   //! Accessor.
base_probability_iterations_change_jump()319   real base_probability_iterations_change_jump() const
320     {
321       return _base_probability_iterations_change_jump;
322     }
323   //! Accessor.
base_probability_iterations_change_jump(real v)324   void base_probability_iterations_change_jump(real v)
325     {
326       _base_probability_iterations_change_jump=v;
327       report_change();
328     }
329 
330   //! Accessor.
proportion_basic()331   real proportion_basic() const
332     {
333       return _proportion_basic;
334     }
335   //! Accessor.
proportion_basic(real p)336   void proportion_basic(real p)
337     {
338       _proportion_basic=p;
339       report_change();
340     }
341 
342   //! Accessor.
autocool_enable()343   bool autocool_enable() const
344     {
345       return _autocool_enable;
346     }
347   //! Accessor.
autocool_enable(bool v)348   void autocool_enable(bool v)
349     {
350       _autocool_enable=v;
351       std::clog << "Autocooling " << (autocool_enable() ? "ON" : "OFF") << "\n";
352       report_change();
353     }
354 
355   //! Accessor.
autocool_halflife()356   int autocool_halflife() const
357     {
358       return _autocool_halflife;
359     }
360   //! Accessor.
autocool_halflife(int v)361   void autocool_halflife(int v)
362     {
363       _autocool_halflife=v;
364       report_change();
365     }
366 
367   //! Accessor
autocool_generations()368   int autocool_generations() const
369     {
370       return _autocool_generations;
371     }
372   //! Accessor.
autocool_generations(int v)373   void autocool_generations(int v)
374     {
375       _autocool_generations=v;
376       report_change();
377     }
378   //! Accessor.
autocool_generations_increment()379   void autocool_generations_increment()
380     {
381       _autocool_generations++;
382       report_change();
383     }
384 
385   //! Calculate branching ratio for above calls
386   /* Call user should be checking this and diluting with boring nodes to keep it under control
387    */
388   real random_function_branching_ratio() const;
389 
390   //! This returns a new random bit of tree.
391   /*! Setting the "exciting" flag avoids the most basic node types, but only at the top level of the stub tree.
392    */
393   std::unique_ptr<FunctionNode> random_function_stub(bool exciting) const;
394 
395   void change_function_weighting(const FunctionRegistration* fn,real w);
396 
397   void randomize_function_weightings_for_classifications(uint classification_mask);
398 
399   real get_weighting(const FunctionRegistration* fn);
400 
401  protected:
402 
403   //! Compute current decay factor
404   real decay_factor() const;
405 
406   //! Return a random function appropriately biased by current settings
407   std::unique_ptr<FunctionNode> random_function() const;
408 
409   //! Return a random function registration, appropriately biased by current settings
410   const FunctionRegistration* random_weighted_function_registration() const;
411 
412   //! Intended for Qt-world subclass to override to emit signal.
413   virtual void report_change();
414 };
415 
416 #endif
417