File: function_node.h

package info (click to toggle)
evolvotron 0.7.1-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,336 kB
  • sloc: cpp: 10,425; python: 162; sh: 138; makefile: 8
file content (249 lines) | stat: -rw-r--r-- 8,385 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/**************************************************************************/
/*  Copyright 2012 Tim Day                                                */
/*                                                                        */
/*  This file is part of Evolvotron                                       */
/*                                                                        */
/*  Evolvotron is free software: you can redistribute it and/or modify    */
/*  it under the terms of the GNU General Public License as published by  */
/*  the Free Software Foundation, either version 3 of the License, or     */
/*  (at your option) any later version.                                   */
/*                                                                        */
/*  Evolvotron is distributed in the hope that it will be useful,         */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
/*  GNU General Public License for more details.                          */
/*                                                                        */
/*  You should have received a copy of the GNU General Public License     */
/*  along with Evolvotron.  If not, see <http://www.gnu.org/licenses/>.   */
/**************************************************************************/

/*! \file 
  \brief Interfaces for class FunctionNode and derived classes.
*/

#ifndef _function_node_h_
#define _function_node_h_

#include "common.h"

#include "xy.h"
#include "xyz.h"

class FunctionNodeInfo;
class FunctionTop;
class FunctionPreTransform;
class FunctionPostTransform;
class FunctionRegistry;
class MutatableImage;
class MutationParameters;

class Function : boost::noncopyable
{
 public:

  virtual ~Function()
    {}

  //! Convenience wrapper for evaluate (actually, evaluate is protected so can't be called externally anyway)
  const XYZ operator()(const XYZ& p) const
    {
      return evaluate(p);
    }

  //! Weighted evaluate; fastpath for zero weight.
  const XYZ operator()(const real weight,const XYZ& p) const
    {
      return (weight==0.0 ? XYZ(0.0,0.0,0.0) : weight*evaluate(p));
    }

  //! This what distinguishes different types of function.
  virtual const XYZ evaluate(const XYZ&) const
    =0;
};

//! Abstract base class for all kinds of mutatable image node.
/*! MutatableImage declared a friend to help constification of the public accessors.
 */
class FunctionNode : public Function
{
 public:
  friend class MutatableImage;

 private:
  //! The arguments (ie child nodes) for this node.
  boost::ptr_vector<FunctionNode> _args;

  //! The parameters (ie constant values) for this node.
  std::vector<real> _params;
    
  //! Number of iterations for iterative function types.  If zero, indicates non-iterative function.
  /*! \todo Perhaps someday push this out into a derived class.
   */
  uint _iterations;

 protected:

  //! This returns a deep-cloned copy of the node's children.
  std::unique_ptr<boost::ptr_vector<FunctionNode> > cloneargs() const;

  //! This returns a copy of the node's parameters
  const std::vector<real> cloneparams() const;

  //! Obtain some statistics about the image function
  void get_stats(uint& total_nodes,uint& total_parameters,uint& depth,uint& width,real& proportion_constant) const;
  
  //! Check function info against given number of parameters/arguments/iterative-flag.
  /*! Return true on success, false on fail with reasons in report string.
    Mainly for use by derived FunctionBoilerplate template to avoid duplicate code proliferation.
   */
  static bool verify_info(const FunctionNodeInfo& info,unsigned int np,unsigned int na,bool it,std::string& report);

  //! Build argument list.
  /*! Return true on success, false on fail with reasons in report string.
    Mainly for use by derived FunctionBoilerplate template to avoid duplicate code proliferation.
   */
  static bool create_args(const FunctionRegistry&,const FunctionNodeInfo& info,boost::ptr_vector<FunctionNode>& args,std::string& report);

 public:

  //! Returns true if the function is independent of it's position argument.
  /*! This isn't used for optimisation (which would require FunctionNode to have computation-specific state,
      which would wreck plans for reference counted deepclone()), 
      but to cull boring constant images on creation.
      Default implementation (and probably the only sensible one)
      is constant if all args are constant; no args returns false.
   */
  virtual bool is_constant() const;

  //! Internal self consistency check.
  virtual bool ok() const;

  //! Bits give some classification of the function type
  virtual uint self_classification() const
    =0;

  //@{
  //! Query the node as to whether it is a FunctionTop (return null if not).
  virtual const FunctionTop* is_a_FunctionTop() const;
  virtual FunctionTop* is_a_FunctionTop();
  //@}

  //! 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.
  static std::unique_ptr<FunctionNode> stub(const MutationParameters& parameters,bool exciting);

  //! This returns a vector of random parameter values.
  static void stubparams(std::vector<real>&,const MutationParameters& parameters,uint n);

  //! This returns a vector of new random bits of tree.
  static void stubargs(boost::ptr_vector<FunctionNode>&,const MutationParameters& parameters,uint n,bool exciting=false);

  //! Return a suitable starting value for a node's iteration count (assuming it's iterative).
  static uint stubiterations(const MutationParameters& parameters);

  //! Constructor given an array of params and args and an iteration count.
  /*! These MUST be provided; there are no alterative constructors.
   */
  FunctionNode(const std::vector<real>& p,boost::ptr_vector<FunctionNode>& a,uint iter);
  
  //! Build a FunctionNode given a description
  static std::unique_ptr<FunctionNode> create(const FunctionRegistry& function_registry,const FunctionNodeInfo& info,std::string& report);
  
  //! Destructor.
  virtual ~FunctionNode();

  //! Accessor
  void params(const std::vector<real>& p)
    {
      _params=p;
    }

  //! Accessor.
  const std::vector<real>& params() const
    {
      return _params;
    }

  //! Accessor. 
  real param(uint n) const
    {
      assert(n<params().size());
      return params()[n];
    }

  //! Accessor.
  uint iterations() const
    {
      return _iterations;
    }

  //! Accessor.
  const boost::ptr_vector<FunctionNode>& args() const
    {
      return _args;
    }
  
  //! Accessor.
  void args(boost::ptr_vector<FunctionNode>& a)
    {
      _args=a.release();
    }

  //! Accessor. 
  const FunctionNode& arg(uint n) const
    {
      assert(n<args().size());
      return args()[n];
    }

  //! Scramble this node and its leaves up a bit.
  virtual void mutate(const MutationParameters&,bool mutate_own_parameters=true);
  
  //! Return an clone of this image node and all its children.
  virtual std::unique_ptr<FunctionNode> deepclone() const
    =0;

  //! Prune any is_constant() nodes and replace them with an actual constant node
  virtual void simplify_constants();

  //! Return a deepcloned copy of the node's arguments
  virtual std::unique_ptr<boost::ptr_vector<FunctionNode> > deepclone_args() const;
  
  //! Save the function tree.
  virtual std::ostream& save_function(std::ostream& out,uint indent) const
    =0;

 protected:

  //! Save the function tree.  Common code needing a function name.
  std::ostream& save_function(std::ostream& out,uint indent,const std::string& function_name) const;

  //! Accessor (non-const).
  boost::ptr_vector<FunctionNode>& args()
    {
      return _args;
    }

  //! Accessor (non-const).
  std::vector<real>& params()
    {
      return _params;
    }

  //! Accessor. 
  FunctionNode& arg(uint n)
    {
      assert(n<args().size());
      return args()[n];
    }
 protected:
  //@{
  //! Useful constants used when some small sampling step is required (e.g gradient operators).
  static real epsilon() {return 1e-6;}
  static real epsilon2() {return 2.0*epsilon();}
  static real inv_epsilon() {return 1.0/epsilon();}
  static real inv_epsilon2() {return 1.0/epsilon2();}
  static real big_epsilon() {return sqrt(epsilon());}
  //@}
};

#endif