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
|