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