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 Interfaces for class FunctionNode and derived classes.
22 */
23 
24 #ifndef _function_node_h_
25 #define _function_node_h_
26 
27 #include "common.h"
28 
29 #include "xy.h"
30 #include "xyz.h"
31 
32 class FunctionNodeInfo;
33 class FunctionTop;
34 class FunctionPreTransform;
35 class FunctionPostTransform;
36 class FunctionRegistry;
37 class MutatableImage;
38 class MutationParameters;
39 
40 class Function : boost::noncopyable
41 {
42  public:
43 
~Function()44   virtual ~Function()
45     {}
46 
47   //! Convenience wrapper for evaluate (actually, evaluate is protected so can't be called externally anyway)
operator()48   const XYZ operator()(const XYZ& p) const
49     {
50       return evaluate(p);
51     }
52 
53   //! Weighted evaluate; fastpath for zero weight.
operator()54   const XYZ operator()(const real weight,const XYZ& p) const
55     {
56       return (weight==0.0 ? XYZ(0.0,0.0,0.0) : weight*evaluate(p));
57     }
58 
59   //! This what distinguishes different types of function.
60   virtual const XYZ evaluate(const XYZ&) const
61     =0;
62 };
63 
64 //! Abstract base class for all kinds of mutatable image node.
65 /*! MutatableImage declared a friend to help constification of the public accessors.
66  */
67 class FunctionNode : public Function
68 {
69  public:
70   friend class MutatableImage;
71 
72  private:
73   //! The arguments (ie child nodes) for this node.
74   boost::ptr_vector<FunctionNode> _args;
75 
76   //! The parameters (ie constant values) for this node.
77   std::vector<real> _params;
78 
79   //! Number of iterations for iterative function types.  If zero, indicates non-iterative function.
80   /*! \todo Perhaps someday push this out into a derived class.
81    */
82   uint _iterations;
83 
84  protected:
85 
86   //! This returns a deep-cloned copy of the node's children.
87   std::unique_ptr<boost::ptr_vector<FunctionNode> > cloneargs() const;
88 
89   //! This returns a copy of the node's parameters
90   const std::vector<real> cloneparams() const;
91 
92   //! Obtain some statistics about the image function
93   void get_stats(uint& total_nodes,uint& total_parameters,uint& depth,uint& width,real& proportion_constant) const;
94 
95   //! Check function info against given number of parameters/arguments/iterative-flag.
96   /*! Return true on success, false on fail with reasons in report string.
97     Mainly for use by derived FunctionBoilerplate template to avoid duplicate code proliferation.
98    */
99   static bool verify_info(const FunctionNodeInfo& info,unsigned int np,unsigned int na,bool it,std::string& report);
100 
101   //! Build argument list.
102   /*! Return true on success, false on fail with reasons in report string.
103     Mainly for use by derived FunctionBoilerplate template to avoid duplicate code proliferation.
104    */
105   static bool create_args(const FunctionRegistry&,const FunctionNodeInfo& info,boost::ptr_vector<FunctionNode>& args,std::string& report);
106 
107  public:
108 
109   //! Returns true if the function is independent of it's position argument.
110   /*! This isn't used for optimisation (which would require FunctionNode to have computation-specific state,
111       which would wreck plans for reference counted deepclone()),
112       but to cull boring constant images on creation.
113       Default implementation (and probably the only sensible one)
114       is constant if all args are constant; no args returns false.
115    */
116   virtual bool is_constant() const;
117 
118   //! Internal self consistency check.
119   virtual bool ok() const;
120 
121   //! Bits give some classification of the function type
122   virtual uint self_classification() const
123     =0;
124 
125   //@{
126   //! Query the node as to whether it is a FunctionTop (return null if not).
127   virtual const FunctionTop* is_a_FunctionTop() const;
128   virtual FunctionTop* is_a_FunctionTop();
129   //@}
130 
131   //! This returns a new random bit of tree.  Setting the "exciting" flag avoids basic node types, but only at the top level of the stub tree.
132   static std::unique_ptr<FunctionNode> stub(const MutationParameters& parameters,bool exciting);
133 
134   //! This returns a vector of random parameter values.
135   static void stubparams(std::vector<real>&,const MutationParameters& parameters,uint n);
136 
137   //! This returns a vector of new random bits of tree.
138   static void stubargs(boost::ptr_vector<FunctionNode>&,const MutationParameters& parameters,uint n,bool exciting=false);
139 
140   //! Return a suitable starting value for a node's iteration count (assuming it's iterative).
141   static uint stubiterations(const MutationParameters& parameters);
142 
143   //! Constructor given an array of params and args and an iteration count.
144   /*! These MUST be provided; there are no alterative constructors.
145    */
146   FunctionNode(const std::vector<real>& p,boost::ptr_vector<FunctionNode>& a,uint iter);
147 
148   //! Build a FunctionNode given a description
149   static std::unique_ptr<FunctionNode> create(const FunctionRegistry& function_registry,const FunctionNodeInfo& info,std::string& report);
150 
151   //! Destructor.
152   virtual ~FunctionNode();
153 
154   //! Accessor
params(const std::vector<real> & p)155   void params(const std::vector<real>& p)
156     {
157       _params=p;
158     }
159 
160   //! Accessor.
params()161   const std::vector<real>& params() const
162     {
163       return _params;
164     }
165 
166   //! Accessor.
param(uint n)167   real param(uint n) const
168     {
169       assert(n<params().size());
170       return params()[n];
171     }
172 
173   //! Accessor.
iterations()174   uint iterations() const
175     {
176       return _iterations;
177     }
178 
179   //! Accessor.
args()180   const boost::ptr_vector<FunctionNode>& args() const
181     {
182       return _args;
183     }
184 
185   //! Accessor.
args(boost::ptr_vector<FunctionNode> & a)186   void args(boost::ptr_vector<FunctionNode>& a)
187     {
188       _args=a.release();
189     }
190 
191   //! Accessor.
arg(uint n)192   const FunctionNode& arg(uint n) const
193     {
194       assert(n<args().size());
195       return args()[n];
196     }
197 
198   //! Scramble this node and its leaves up a bit.
199   virtual void mutate(const MutationParameters&,bool mutate_own_parameters=true);
200 
201   //! Return an clone of this image node and all its children.
202   virtual std::unique_ptr<FunctionNode> deepclone() const
203     =0;
204 
205   //! Prune any is_constant() nodes and replace them with an actual constant node
206   virtual void simplify_constants();
207 
208   //! Return a deepcloned copy of the node's arguments
209   virtual std::unique_ptr<boost::ptr_vector<FunctionNode> > deepclone_args() const;
210 
211   //! Save the function tree.
212   virtual std::ostream& save_function(std::ostream& out,uint indent) const
213     =0;
214 
215  protected:
216 
217   //! Save the function tree.  Common code needing a function name.
218   std::ostream& save_function(std::ostream& out,uint indent,const std::string& function_name) const;
219 
220   //! Accessor (non-const).
args()221   boost::ptr_vector<FunctionNode>& args()
222     {
223       return _args;
224     }
225 
226   //! Accessor (non-const).
params()227   std::vector<real>& params()
228     {
229       return _params;
230     }
231 
232   //! Accessor.
arg(uint n)233   FunctionNode& arg(uint n)
234     {
235       assert(n<args().size());
236       return args()[n];
237     }
238  protected:
239   //@{
240   //! Useful constants used when some small sampling step is required (e.g gradient operators).
epsilon()241   static real epsilon() {return 1e-6;}
epsilon2()242   static real epsilon2() {return 2.0*epsilon();}
inv_epsilon()243   static real inv_epsilon() {return 1.0/epsilon();}
inv_epsilon2()244   static real inv_epsilon2() {return 1.0/epsilon2();}
big_epsilon()245   static real big_epsilon() {return sqrt(epsilon());}
246   //@}
247 };
248 
249 #endif
250