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