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