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 Interface for abstract base class FunctionBoilerplate.
22 And implementation given that it's a template.
23 */
24
25 #ifndef _function_boilerplate_h_
26 #define _function_boilerplate_h_
27
28 #include "common.h"
29
30 #include "function_node.h"
31 #include "function_node_info.h"
32 #include "function_registry.h"
33 #include "margin.h"
34
35 //! Template class to generate boilerplate for virtual methods.
36 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION> class FunctionBoilerplate : public FunctionNode
37 {
38 public:
39 typedef FunctionNode Superclass;
40
41 //! Constructor
42 /*! \warning Careful to pass an appropriate initial iteration count for iterative functions.
43 */
44 FunctionBoilerplate(const std::vector<real>& p,boost::ptr_vector<FunctionNode>& a,uint iter);
45
46 //! Destructor.
47 virtual ~FunctionBoilerplate();
48
49 //! Accessor providing function name
50 virtual const char* thisname() const
51 =0;
52
53 //! Registration member returns a reference to class meta-information.
54 static const FunctionRegistration get_registration(const char* fn_name);
55
56 //! Bits give some classification of the function type
type_classification()57 static uint type_classification() {return CLASSIFICATION;}
58
59 //! Bits give some classification of the function type
60 virtual uint self_classification() const;
61
62 //! Factory method to create a stub node for this type
63 static std::unique_ptr<FunctionNode> stubnew(const MutationParameters& mutation_parameters,bool exciting);
64
65 //! Factory method to create a node given contents.
66 /*! Returns null if there's a problem, in which case explanation is in report
67 */
68 static std::unique_ptr<FunctionNode> create(const FunctionRegistry& function_registry,const FunctionNodeInfo& info,std::string& report);
69
70 //! Return a deeploned copy.
71 virtual std::unique_ptr<FunctionNode> deepclone() const;
72
73 //! Return a deeploned copy with more specific type (but of course this can't be virtual).
74 std::unique_ptr<FUNCTION> typed_deepclone() const;
75
76 //! Internal self-consistency check. We can add some extra checks.
77 virtual bool ok() const;
78
79 //! Save this node.
80 virtual std::ostream& save_function(std::ostream& out,uint indent) const;
81 };
82
83 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION>
FunctionBoilerplate(const std::vector<real> & p,boost::ptr_vector<FunctionNode> & a,uint iter)84 FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::FunctionBoilerplate(const std::vector<real>& p,boost::ptr_vector<FunctionNode>& a,uint iter)
85 :FunctionNode(p,a,iter)
86 {
87 assert(params().size()==PARAMETERS);
88 assert(args().size()==ARGUMENTS);
89 assert((iter==0 && !ITERATIVE) || (iter!=0 && ITERATIVE));
90 }
91
92 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION>
~FunctionBoilerplate()93 FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::~FunctionBoilerplate()
94 {}
95
96 //! Provide a complete registration for the function
97 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION>
get_registration(const char * fn_name)98 const FunctionRegistration FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::get_registration(const char* fn_name)
99 {
100 return FunctionRegistration
101 (
102 std::string(fn_name),
103 &FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::stubnew,
104 &FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::create,
105 PARAMETERS,
106 ARGUMENTS,
107 ITERATIVE,
108 FUNCTION::type_classification()
109 );
110 }
111
112 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION>
self_classification()113 uint FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::self_classification() const
114 {
115 return CLASSIFICATION;
116 }
117
118 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION>
stubnew(const MutationParameters & mutation_parameters,bool exciting)119 std::unique_ptr<FunctionNode> FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::stubnew(const MutationParameters& mutation_parameters,bool exciting)
120 {
121 static constexpr uint _PARAMETERS=PARAMETERS;
122 static constexpr uint _ARGUMENTS=ARGUMENTS;
123
124 std::vector<real> params;
125 stubparams(params,mutation_parameters,_PARAMETERS);
126
127 boost::ptr_vector<FunctionNode> args;
128 stubargs(args,mutation_parameters,_ARGUMENTS,exciting);
129
130 return std::unique_ptr<FunctionNode>
131 (
132 new FUNCTION
133 (
134 params,
135 args,
136 (ITERATIVE ? stubiterations(mutation_parameters) : 0)
137 )
138 );
139 }
140
141 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION>
create(const FunctionRegistry & function_registry,const FunctionNodeInfo & info,std::string & report)142 std::unique_ptr<FunctionNode> FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::create(const FunctionRegistry& function_registry,const FunctionNodeInfo& info,std::string& report)
143 {
144 if (!verify_info(info,PARAMETERS,ARGUMENTS,ITERATIVE,report)) return std::unique_ptr<FunctionNode>();
145
146 boost::ptr_vector<FunctionNode> args;
147 if (!create_args(function_registry,info,args,report)) return std::unique_ptr<FunctionNode>();
148
149 return std::unique_ptr<FunctionNode>(new FUNCTION(info.params(),args,info.iterations()));
150 }
151
152 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION>
deepclone()153 std::unique_ptr<FunctionNode> FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::deepclone() const
154 {
155 return std::unique_ptr<FunctionNode>(typed_deepclone());
156 }
157
158 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION>
typed_deepclone()159 std::unique_ptr<FUNCTION> FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::typed_deepclone() const
160 {
161 return std::unique_ptr<FUNCTION>(new FUNCTION(cloneparams(),*cloneargs(),iterations()));
162 }
163
164 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION>
ok()165 bool FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::ok() const
166 {
167 return (
168 params().size()==PARAMETERS
169 &&
170 args().size()==ARGUMENTS
171 &&
172 ((iterations()==0 && !ITERATIVE) || (iterations()!=0 && ITERATIVE))
173 &&
174 FunctionNode::ok()
175 );
176 }
177
178 template <typename FUNCTION,uint PARAMETERS,uint ARGUMENTS,bool ITERATIVE,uint CLASSIFICATION>
save_function(std::ostream & out,uint indent)179 std::ostream& FunctionBoilerplate<FUNCTION,PARAMETERS,ARGUMENTS,ITERATIVE,CLASSIFICATION>::save_function(std::ostream& out,uint indent) const
180 {
181 return Superclass::save_function(out,indent,thisname());
182 }
183
184 #define FN_CTOR_DCL(FN) FN(const std::vector<real>& p,boost::ptr_vector<FunctionNode>& a,uint iter);
185 #define FN_CTOR_IMP(FN) FN::FN(const std::vector<real>& p,boost::ptr_vector<FunctionNode>& a,uint iter) :Superclass(p,a,iter) {}
186
187 #define FN_DTOR_DCL(FN) virtual ~FN();
188 #define FN_DTOR_IMP(FN) FN::~FN() {}
189
190 #define FN_VNAME_DCL(FN) virtual const char* thisname() const;
191 #define FN_VNAME_IMP(FN) const char* FN::thisname() const {return FN::classname();}
192
193 #define FN_SNAME_DCL(FN) static const char* classname();
194 #define FN_SNAME_IMP(FN) const char* FN::classname() {return #FN;}
195
196 #define FUNCTION_BEGIN(FN,NP,NA,IT,CL) \
197 class FN : public FunctionBoilerplate<FN,NP,NA,IT,CL> \
198 {public: \
199 typedef FunctionBoilerplate<FN,NP,NA,IT,CL> Superclass; \
200 FN_CTOR_DCL(FN) \
201 FN_DTOR_DCL(FN) \
202 FN_VNAME_DCL(FN) \
203 FN_SNAME_DCL(FN)
204
205 //! Macro to push registrations through to registry.
206 /*! Used by register_all_functions.h/register_all_functions.cpp
207 */
208 #define REGISTER(R,FN) R.register_function(FN::get_registration(#FN));
209 #define REGISTER_DCL(FN) extern void register_ ## FN(FunctionRegistry&);
210 #define REGISTER_IMP(FN) void register_ ## FN(FunctionRegistry& r){REGISTER(r,FN);}
211
212 #ifdef FUNCTION_BOILERPLATE_INSTANTIATE
213 #define FUNCTION_END(FN) };FN_CTOR_IMP(FN);FN_DTOR_IMP(FN);FN_VNAME_IMP(FN);FN_SNAME_IMP(FN);REGISTER_IMP(FN);
214 #else
215 #define FUNCTION_END(FN) };REGISTER_DCL(FN);
216 #endif
217
218 #endif
219