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 Implementation of class MutationParameters.
22 */
23
24
25
26 #include "mutation_parameters.h"
27
28 #include "function_registration.h"
29 #include "function_registry.h"
30 #include "function_constant.h"
31 #include "function_identity.h"
32 #include "function_transform.h"
33
MutationParameters(uint seed,bool ac,bool debug_mode)34 MutationParameters::MutationParameters(uint seed,bool ac,bool debug_mode)
35 :_function_registry(new FunctionRegistry())
36 ,_r01(seed)
37 ,_r_negexp(seed,1.0)
38 ,_autocool_reset_state(ac)
39 ,_debug_mode(debug_mode)
40 {
41 reset();
42 }
43
~MutationParameters()44 MutationParameters::~MutationParameters()
45 {}
46
reset()47 void MutationParameters::reset()
48 {
49 _autocool_enable=_autocool_reset_state;
50 _autocool_halflife=20;
51 _autocool_generations=0;
52
53 _base_magnitude_parameter_variation=0.25;
54
55 _base_probability_parameter_reset=0.05;
56 _base_probability_glitch=0.05;
57 _base_probability_shuffle=0.05;
58 _base_probability_insert=0.05;
59 _base_probability_substitute=0.05;
60
61 _proportion_basic=0.6;
62
63 _proportion_constant=0.5;
64 _identity_supression=1.0;
65
66 //! \todo Could do with _max_initial_iterations being higher (64?) for fractal type things but it slows things down too much.
67 _max_initial_iterations=16;
68 _base_probability_iterations_change_step=0.25;
69 _base_probability_iterations_change_jump=0.02;
70
71 _function_weighting.clear();
72 for (
73 FunctionRegistry::Registrations::const_iterator it=_function_registry->registrations().begin();
74 it!=_function_registry->registrations().end();
75 it++
76 )
77 {
78 if (_debug_mode)
79 {
80 const FunctionRegistration*const fn=
81 #if BOOST_VERSION >= 103400
82 it->second;
83 #else
84 &*it;
85 #endif
86 real initial_weight=(fn->name()=="FunctionNoiseOneChannel" ? 1.0 : 1.0/1024.0);
87 _function_weighting.insert(std::make_pair(fn,initial_weight));
88 }
89 else
90 {
91 real initial_weight=1.0;
92 const FunctionRegistration*const fn=
93 #if BOOST_VERSION >= 103400
94 it->second;
95 #else
96 &*it;
97 #endif
98 if (fn->classification() & FnIterative) initial_weight=1.0/1024.0; // Ouch iterative functions are expensive
99 if (fn->classification() & FnFractal) initial_weight=1.0/1024.0; // Yuk fractals are ugly
100 _function_weighting.insert(std::make_pair(fn,initial_weight));
101 }
102 }
103
104 recalculate_function_stuff();
105
106 report_change();
107 }
108
decay_factor() const109 real MutationParameters::decay_factor() const
110 {
111 assert(_autocool_halflife!=0);
112 return (_autocool_enable ? pow(0.5,_autocool_generations/static_cast<double>(_autocool_halflife)) : 1.0);
113 }
114
general_cool(real f)115 void MutationParameters::general_cool(real f)
116 {
117 _base_magnitude_parameter_variation*=f;
118
119 _base_probability_parameter_reset*=f;
120 _base_probability_glitch*=f;
121 _base_probability_shuffle*=f;
122 _base_probability_insert*=f;
123 _base_probability_substitute*=f;
124
125 _base_probability_iterations_change_step*=f;
126 _base_probability_iterations_change_jump*=f;
127
128 report_change();
129 }
130
131 /*! This returns a random bit of image tree.
132 It needs to be capable of generating any sort of node we have.
133 \warning Too much probability of highly branching nodes could result in infinite sized stubs.
134 \todo Compute (statistically) the expected number of nodes in a stub.
135 */
random_function_stub(bool exciting) const136 std::unique_ptr<FunctionNode> MutationParameters::random_function_stub(bool exciting) const
137 {
138 // Base mutations are Constant or Identity types.
139 // (Identity can be Identity or PositionTransformed, proportions depending on identity_supression parameter)
140 const real base=proportion_basic();
141
142 const real r=(exciting ? base+(1.0-base)*r01() : r01());
143
144 if (r<(1.0-proportion_constant())*identity_supression()*base)
145 {
146 return FunctionTransform::stubnew(*this,false);
147 }
148 else if (r<(1.0-proportion_constant())*base)
149 {
150 return FunctionIdentity::stubnew(*this,false);
151 }
152 else if (r<base)
153 {
154 return FunctionConstant::stubnew(*this,false);
155 }
156 else
157 {
158 return random_function();
159 }
160 }
161
random_function() const162 std::unique_ptr<FunctionNode> MutationParameters::random_function() const
163 {
164 const FunctionRegistration* fn_reg=random_weighted_function_registration();
165 return (*(fn_reg->stubnew_fn()))(*this,false);
166 }
167
random_weighted_function_registration() const168 const FunctionRegistration* MutationParameters::random_weighted_function_registration() const
169 {
170 const real r=r01();
171
172 const std::map<real,const FunctionRegistration*>::const_iterator it=_function_pick.lower_bound(r);
173
174 // Just in case last key isn't quite 1.0
175 if (it!=_function_pick.end())
176 {
177 return (*it).second;
178 }
179 else
180 {
181 return (*(_function_pick.rbegin())).second;
182 }
183 }
184
random_function_branching_ratio() const185 real MutationParameters::random_function_branching_ratio() const
186 {
187 real weighted_args=0.0;
188
189 for (
190 std::map<const FunctionRegistration*,real>::const_iterator it=_function_weighting.begin();
191 it!=_function_weighting.end();
192 it++
193 )
194 {
195 weighted_args+=(*it).second*(*it).first->args();
196 }
197 return weighted_args/_function_weighting_total;
198 }
199
change_function_weighting(const FunctionRegistration * fn,real w)200 void MutationParameters::change_function_weighting(const FunctionRegistration* fn,real w)
201 {
202 _function_weighting[fn]=w;
203 recalculate_function_stuff();
204 report_change();
205 }
206
randomize_function_weightings_for_classifications(uint classification_mask)207 void MutationParameters::randomize_function_weightings_for_classifications(uint classification_mask)
208 {
209 for (
210 std::map<const FunctionRegistration*,real>::iterator it=_function_weighting.begin();
211 it!=_function_weighting.end();
212 it++
213 )
214 {
215 if (classification_mask==0 || classification_mask==static_cast<uint>(-1) || ((*it).first->classification() & classification_mask))
216 {
217 const int i=static_cast<int>(floor(11.0*r01()));
218 (*it).second=pow(2,-i);
219 }
220 }
221
222 recalculate_function_stuff();
223
224 report_change();
225 }
226
get_weighting(const FunctionRegistration * fn)227 real MutationParameters::get_weighting(const FunctionRegistration* fn)
228 {
229 std::map<const FunctionRegistration*,real>::const_iterator it=_function_weighting.find(fn);
230 assert(it!=_function_weighting.end());
231 return (*it).second;
232 }
233
recalculate_function_stuff()234 void MutationParameters::recalculate_function_stuff()
235 {
236 _function_weighting_total=0.0;
237 for (
238 std::map<const FunctionRegistration*,real>::const_iterator it=_function_weighting.begin();
239 it!=_function_weighting.end();
240 it++
241 )
242 _function_weighting_total+=(*it).second;
243
244 real normalised=0.0;
245 _function_pick.clear();
246 for (
247 std::map<const FunctionRegistration*,real>::const_iterator it=_function_weighting.begin();
248 it!=_function_weighting.end();
249 it++
250 )
251 {
252 normalised+=(*it).second/_function_weighting_total;
253 _function_pick.insert(std::make_pair(normalised,(*it).first));
254 }
255 }
256
report_change()257 void MutationParameters::report_change()
258 {}
259
260