node.h

00001 /*
00002     This library is free software; you can redistribute it and/or modify
00003     it under the terms of the GNU General Public License as published by
00004     the Free Software Foundation; either version 2 of the License, or
00005     (at your option) any later version.
00006     
00007     This library is distributed in the hope that it will be useful,
00008     but WITHOUT ANY WARRANTY; without even the implied warranty of
00009     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00010     Lesser General Public License for more details.
00011  
00012     You should have received a copy of the GNU General Public License
00013     along with this library; if not, write to the Free Software
00014     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00015  
00016     Contact: todos@geneura.ugr.es, http://geneura.ugr.es
00017              jeggermo@liacs.nl
00018 */
00019 
00020 #ifndef _NODE_H
00021 #define _NODE_H
00022 
00023 
00024 
00025 #include <iostream>
00026 #include <string>
00027 #include <cmath> // for finite(double) function
00028 
00029 using namespace gp_parse_tree;
00030 using namespace std;
00031 
00032 
00033 /* A new Operation and Node class for even more flexibility.
00034 
00035    Improvements over the t-eoSymreg code are:
00036    
00037    * No hardcoded functions or operators. The Operation and Node class below
00038      allow you to specify your own unary and binary functions as well as
00039      binary operators (like +,-,*,/). Moreover you can detemine if you want
00040      to allow primitve subroutines with either one or two arguments.
00041      
00042      If a Node has a subroutine Operation it will take evaluate the first 
00043      (and possible second) child branch and use them as input variables for
00044      the remaining second (or third) child branch.
00045 */
00046 
00047 
00048 typedef enum {Variable, UFunction, BFunction, BOperator, Const} Type;
00049 
00050 typedef double (*BinaryFunction)(const double,const double); 
00051 typedef double (*UnaryFunction)(const double);
00052 
00053 struct Operation
00054 {
00055         public:
00056                 
00057                 typedef unsigned int VariableID;
00058                 typedef string Label;
00059 
00060         
00061                 // if your compiler allows you to have nameless unions you can make this a
00062                 // union by removing the //'s below
00063                 
00064                 //union
00065                 //{
00066                         UnaryFunction uFunction;
00067                         BinaryFunction bFunction;
00068                         VariableID id;
00069                         double constant;
00070                 //};
00071         
00072                 
00073         
00074                 Label label;
00075                 Type type;
00076         
00077                 // the default constructor results in a constant with value 0
00078                 Operation() : constant(0),  label("0"), type(Const){};
00079                 // two possible constructors for Unary Functions
00080                 Operation(UnaryFunction _uf, Label _label): uFunction(_uf), label(_label), type(UFunction) {};
00081                 Operation(Label _label, UnaryFunction _uf): uFunction(_uf), label(_label), type(UFunction) {};
00082                 
00083                 // Watch out there are two constructors using pointers two binary functions:
00084                 // Binary Function (printed as label(subtree0,subtree1)  (e.g. pow(x,y))
00085                 // Binary Operator (printed as (subtree0 label subtree1) (e.g. x^y)
00086                 // The difference is purely cosmetic.
00087                 
00088                 // If you specify the label before the function pointer -> Binary Function
00089                 Operation(Label _label, BinaryFunction _bf): bFunction(_bf), label(_label), type(BFunction) {};
00090                 // If you specify the function pointer before the label -> Binary Operator
00091                 Operation(BinaryFunction _bf, Label _label): bFunction(_bf), label(_label), type(BOperator) {};
00092                 
00093                 // A constructor for variables
00094                 Operation(VariableID _id, Label _label): id(_id), label(_label), type(Variable) {};
00095                 // A constructor for constants
00096                 Operation(double _constant, Label _label): constant(_constant), label(_label), type(Const) {};
00097                 
00098                 
00099                 Operation(const Operation &_op)
00100                 {
00101                         switch(_op.type)
00102                         {
00103                                 case Variable: id = _op.id; break;
00104                                 case UFunction: uFunction = _op.uFunction;  break;
00105                                 case BFunction: bFunction = _op.bFunction; break;
00106                                 case BOperator: bFunction = _op.bFunction; break;
00107                                 case Const: constant = _op.constant;  break;
00108                         }
00109                         type = _op.type;
00110                         label = _op.label;
00111                 };
00112                 virtual ~Operation(){};
00113         
00114 };
00115 
00116 
00117 class Node
00118 {
00119         private:
00120                 Operation op;
00121                 
00122         public:
00123         
00124                 Node(void): op(Operation()){};
00125                 Node(Operation &_op) : op(_op){};
00126                 virtual ~Node(void) {}
00127                 
00128                 int arity(void) const 
00129                 {
00130                         switch(op.type)
00131                         {
00132                                 case Variable: return 0;
00133                                 case UFunction: return 1;
00134                                 case BFunction: return 2;
00135                                 case BOperator: return 2;
00136                                 case Const: return 0;
00137                         }                       
00138                         return 0;       
00139                 }
00140                 
00141                 void randomize(void) {}
00142                 
00143                 template<class Children>
00144                 void operator()(double& result, Children args, vector<double> &var) const
00145                 {
00146                         double result0;
00147                         double result1;
00148                         
00149                         
00150                         switch(op.type)
00151                         {
00152                                 case Variable:  result = var[op.id%var.size()]; //%var.size() used in the case of Subroutines and as a security measure
00153                                                 break;
00154                                 case UFunction: args[0].apply(result0, var);
00155                                                 result = op.uFunction(result0); 
00156                                                 break;
00157                                 case BFunction: 
00158                                 case BOperator: args[0].apply(result0, var);
00159                                                 args[1].apply(result1, var);    
00160                                                 result = op.bFunction(result0,result1);
00161                                                 break;
00162                                 case Const:     result = op.constant;
00163                                                 break;  
00164                                 
00165                         }
00166                         
00167                 }
00168                 
00169                 template<class Children>
00170                 void operator()(string& result, Children args) const
00171                 {
00172                         
00173                         string subtree0;
00174                         string subtree1;
00175                         string subtree2;
00176                         
00177                         switch(op.type)
00178                         {
00179                                 
00180                                 case Variable:  
00181                                 case Const:     result += op.label;
00182                                                 break;
00183                                         
00184                                 case UFunction: result += op.label;
00185                                                 result += "(";
00186                                                 args[0].apply(subtree0);
00187                                                 result += subtree0;
00188                                                 result += ")";
00189                                                 break;
00190                                 case BFunction: result += op.label;
00191                                                 result += "(";
00192                                                 args[0].apply(subtree0);
00193                                                 result += subtree0;
00194                                                 result += ",";
00195                                                 args[1].apply(subtree1);
00196                                                 result += subtree1;
00197                                                 result += ")";
00198                                                 break;                                                          
00199                                 case BOperator: result += "(";
00200                                                 args[0].apply(subtree0);
00201                                                 result += subtree0;
00202                                                 result += op.label;
00203                                                 args[1].apply(subtree1);
00204                                                 result += subtree1;
00205                                                 result += ")";
00206                                                 break;
00207                                 default: result += "ERROR in Node::operator(string,...) \n"; break;             
00208                         }
00209                 }
00210                 
00211                 Operation getOp(void) const {return op;}
00212         
00213 };
00214 
00215                 
00216                 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 //-----------------------------------------------------------
00226 // saving, loading LETS LEAVE IT OUT FOR NOW
00227 
00228 
00229 
00230 std::ostream& operator<<(std::ostream& os, const Node& eot)
00231 {
00232     Operation op(eot.getOp());
00233     
00234     os << (eot.getOp()).label;
00235     return os;
00236 }
00237 
00238 
00239 // we can't load because we are using function pointers. Instead we prevent a compiler warning by calling the arity() function.
00240 std::istream& operator>>(std::istream& is, Node& eot)
00241 {
00242     eot.arity();
00243     return is;
00244 }
00245 
00246 
00247 
00248 #endif

Generated on Thu Oct 19 05:06:41 2006 for EO by  doxygen 1.3.9.1