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 for FunctionTop
22 */
23
24 #include "function_boilerplate_instantiate.h"
25 #include "function_top.h"
26
27 #include "mutation_parameters.h"
28 #include "transform.h"
29
evaluate(const XYZ & p) const30 const XYZ FunctionTop::evaluate(const XYZ& p) const
31 {
32 const Transform space_transform(params(),0);
33 const XYZ sp(space_transform.transformed(p));
34 const XYZ v(arg(0)(sp));
35 const XYZ tv(tanh(0.5*v.x()),tanh(0.5*v.y()),tanh(0.5*v.z()));
36 // ...each component of tv is in [-1,1] so the transform parameters define a rhomboid in colour space.
37 const Transform colour_transform(params(),12);
38 return colour_transform.transformed(tv);
39 }
40
initial(const MutationParameters & parameters,const FunctionRegistration * specific_fn,bool unwrapped)41 std::unique_ptr<FunctionTop> FunctionTop::initial(const MutationParameters& parameters,const FunctionRegistration* specific_fn,bool unwrapped)
42 {
43 std::unique_ptr<FunctionNode> fn;
44
45 do
46 {
47 if (specific_fn)
48 {
49 fn=(*(specific_fn->stubnew_fn()))(parameters,true);
50 }
51 else
52 {
53 // This one is crucial: we REALLY want something interesting to happen within here.
54 fn=FunctionNode::stub(parameters,true);
55 }
56
57 assert(fn->ok());
58
59 if (fn->is_constant() && !(specific_fn && specific_fn->name()=="FunctionConstant"))
60 {
61 fn.reset();
62 }
63 }
64 while (!fn.get());
65
66 assert(fn->ok());
67
68 boost::ptr_vector<FunctionNode> a;
69 a.push_back(fn.release());
70
71 const TransformIdentity ti;
72 std::vector<real> tiv=ti.get_columns();
73 std::vector<real> p;
74 p.insert(p.end(),tiv.begin(),tiv.end());
75 p.insert(p.end(),tiv.begin(),tiv.end());
76
77 std::unique_ptr<FunctionTop> fn_top(new FunctionTop(p,a,0));
78 if (unwrapped)
79 {
80 // For unwrapped just allow a scale factor and scramble colours
81 fn_top->concatenate_pretransform_on_right(TransformScale(parameters.rnegexp()));
82 fn_top->reset_posttransform_parameters(parameters);
83 }
84 else
85 {
86 fn_top->reset_pretransform_parameters(parameters);
87 fn_top->reset_posttransform_parameters(parameters);
88 }
89 return fn_top;
90 }
91
mutate(const MutationParameters & parameters,bool mutate_own_parameters)92 void FunctionTop::mutate(const MutationParameters& parameters,bool mutate_own_parameters)
93 {
94 FunctionNode::mutate(parameters,false);
95
96 if (mutate_own_parameters)
97 {
98
99 if (parameters.r01()<parameters.effective_probability_parameter_reset())
100 {
101 reset_pretransform_parameters(parameters);
102 }
103 else
104 {
105 mutate_pretransform_parameters(parameters);
106 }
107
108 if (parameters.r01()<parameters.effective_probability_parameter_reset())
109 {
110 reset_posttransform_parameters(parameters);
111 }
112 else
113 {
114 mutate_posttransform_parameters(parameters);
115 }
116 }
117 }
118
concatenate_pretransform_on_right(const Transform & transform)119 void FunctionTop::concatenate_pretransform_on_right(const Transform& transform)
120 {
121 Transform current_transform(params(),0);
122 current_transform.concatenate_on_right(transform);
123 for (uint i=0;i<12;i++)
124 params()[i]=current_transform.get_columns()[i];
125 }
126
interesting_pretransform(const MutationParameters & parameters,const real k)127 const Transform FunctionTop::interesting_pretransform(const MutationParameters& parameters,const real k)
128 {
129 Transform t=TransformIdentity();
130
131 XYZ origin(0.0,0.0,0.0);
132 if (parameters.r01()<0.5)
133 {
134 origin.x(parameters.rnegexp());
135 origin.y(parameters.rnegexp());
136 if (parameters.r01()<0.5) origin.z(parameters.rnegexp());
137 }
138
139 t.concatenate_on_right(TransformTranslate(-origin));
140
141 if (parameters.r01()<0.5)
142 {
143 t.concatenate_on_right(TransformScale(1.0+k*(parameters.rnegexp()-1.0)));
144 }
145 else
146 {
147 t.concatenate_on_right(TransformScale(XYZ(1.0+k*(parameters.rnegexp()-1.0),1.0+k*(parameters.rnegexp()-1.0),1.0+k*(parameters.rnegexp()-1.0))));
148 }
149
150 if (k==1.0)
151 {
152 while (parameters.r01()<0.125) t.concatenate_on_right(TransformScale(2.0));
153 while (parameters.r01()<0.125) t.concatenate_on_right(TransformScale(0.5));
154 }
155 else if (parameters.r01()<parameters.effective_probability_parameter_reset())
156 {
157 do
158 {
159 t.concatenate_on_right(TransformScale(2.0));
160 }
161 while (parameters.r01()<0.125);
162
163 while (parameters.r01()<0.125)
164 {
165 t.concatenate_on_right(TransformScale(0.5));
166 }
167 }
168
169 if (k==1.0)
170 {
171 if (parameters.r01()<0.0625) t.concatenate_on_right(TransformRotateX(0.5*M_PI*(parameters.r01()<0.5 ? 1.0 : -1.0)));
172 if (parameters.r01()<0.0625) t.concatenate_on_right(TransformRotateY(0.5*M_PI*(parameters.r01()<0.5 ? 1.0 : -1.0)));
173 if (parameters.r01()<0.0625) t.concatenate_on_right(TransformRotateZ(0.5*M_PI*(parameters.r01()<0.5 ? 1.0 : -1.0)));
174 }
175
176 if (parameters.r01()<0.5)
177 {
178 t.concatenate_on_right(TransformRotateZ(k*2.0*M_PI*parameters.r01()));
179 }
180 if (parameters.r01()<0.125)
181 {
182 t.concatenate_on_right(TransformRotateX(k*2.0*M_PI*parameters.r01()));
183 }
184 if (parameters.r01()<0.125)
185 {
186 t.concatenate_on_right(TransformRotateY(k*2.0*M_PI*parameters.r01()));
187 }
188
189 t.concatenate_on_right(TransformTranslate(origin));
190
191 XYZ translate(0.0,0.0,0.0);
192 if (parameters.r01()<0.5)
193 {
194 translate.x(k*parameters.rnegexp());
195 translate.y(k*parameters.rnegexp());
196 if (parameters.r01()<0.5) translate.z(k*parameters.rnegexp());
197 }
198 t.concatenate_on_right(TransformTranslate(k*translate));
199
200 return t;
201 }
202
mutate_pretransform_parameters(const MutationParameters & parameters)203 void FunctionTop::mutate_pretransform_parameters(const MutationParameters& parameters)
204 {
205 concatenate_pretransform_on_right(interesting_pretransform(parameters,parameters.effective_magnitude_parameter_variation()));
206 //! \todo: Could have a small probability of orthoganalizing the basis vectors.
207 }
208
reset_pretransform_parameters(const MutationParameters & parameters)209 void FunctionTop::reset_pretransform_parameters(const MutationParameters& parameters)
210 {
211 const Transform t=interesting_pretransform(parameters,1.0);
212 const std::vector<real> p(t.get_columns());
213 for (uint i=0;i<11;i++)
214 params()[i]=p[i];
215 }
216
mutate_posttransform_parameters(const MutationParameters & parameters)217 void FunctionTop::mutate_posttransform_parameters(const MutationParameters& parameters)
218 {
219 for (uint i=12;i<23;i++)
220 params()[i]+=parameters.effective_magnitude_parameter_variation()*(parameters.r01()<0.5 ? -parameters.rnegexp() : parameters.rnegexp());
221 }
222
reset_posttransform_parameters(const MutationParameters & parameters)223 void FunctionTop::reset_posttransform_parameters(const MutationParameters& parameters)
224 {
225 std::vector<real> p;
226 stubparams(p,parameters,12);
227 for (uint i=0;i<11;i++)
228 params()[12+i]=p[i];
229 }
230