diff --git a/eo/contrib/mathsym/GNUmakefile b/eo/contrib/mathsym/GNUmakefile index 47235658..c3f635c4 100644 --- a/eo/contrib/mathsym/GNUmakefile +++ b/eo/contrib/mathsym/GNUmakefile @@ -1,7 +1,7 @@ -COMPILEFLAGS=-Wno-deprecated -g -Wall -Wshadow #-DINTERVAL_DEBUG -OPTFLAGS= -O3 -DNDEBUG +COMPILEFLAGS=-Wno-deprecated -g -Wall #-DINTERVAL_DEBUG +OPTFLAGS= #-O3 -DNDEBUG -PROFILE_FLAGS=-pg +PROFILE_FLAGS=#-pg INCLUDES=-I. -Isym -Ifun -Igen -Ieval -Iregression -I../../src -Ieo_interface -I.. @@ -33,7 +33,7 @@ distclean: clean rm -rf tcc symreg: libsym.a symreg.o $(EXTLIBS) - $(CXX) -o symreg symreg.o libsym.a $(LIBS) $(PROFILE_FLAGS) + $(CXX) -o symreg symreg.o libsym.a $(LIBS) $(PROFILE_FLAGS) libsym.a: $(OBJS) rm libsym.a; ar cq $(SYMLIB) $(OBJS) diff --git a/eo/contrib/mathsym/eo_interface/eoSym.h b/eo/contrib/mathsym/eo_interface/eoSym.h index e30e06e1..9c266b12 100644 --- a/eo/contrib/mathsym/eo_interface/eoSym.h +++ b/eo/contrib/mathsym/eo_interface/eoSym.h @@ -33,20 +33,20 @@ class EoSym : public EO, public Sym { static_cast(this)->operator=(sym); } - virtual void printOn(ostream& os) const; - virtual void readFrom(istream& is); + virtual void printOn(std::ostream& os) const; + virtual void readFrom(std::istream& is); }; template -void EoSym::printOn(ostream& os) const { +void EoSym::printOn(std::ostream& os) const { EO::printOn(os); os << ' '; write_raw(os, *this); } template -void EoSym::readFrom(istream& is) { +void EoSym::readFrom(std::istream& is) { EO::readFrom(is); read_raw(is, *this); } @@ -54,7 +54,7 @@ void EoSym::readFrom(istream& is) { template inline std::ostream& operator<<(std::ostream& os, const EoSym& f) { f.printOn(os); return os; } template -inline istream& operator>>(std::istream& is, EoSym& f) { f.readFrom(is); return is; } +inline std::istream& operator>>(std::istream& is, EoSym& f) { f.readFrom(is); return is; } #endif diff --git a/eo/contrib/mathsym/eval/sym_compile.cpp b/eo/contrib/mathsym/eval/sym_compile.cpp index da491dbe..ded623df 100644 --- a/eo/contrib/mathsym/eval/sym_compile.cpp +++ b/eo/contrib/mathsym/eval/sym_compile.cpp @@ -39,9 +39,14 @@ string make_prototypes() { } // contains variable names, like 'a0', 'a1', etc. or regular code -typedef hash_map HashMap; -HashMap::iterator find_entry(Sym sym, ostream& os, HashMap& map) { +#if USE_TR1 +typedef std::tr1::unordered_map HashMap; +#else +typedef hash_map HashMap; +#endif + +HashMap::iterator find_entry(const Sym& sym, ostream& os, HashMap& map) { HashMap::iterator result = map.find(sym); if (result == map.end()) { // new entry @@ -68,13 +73,82 @@ HashMap::iterator find_entry(Sym sym, ostream& os, HashMap& map) { return result; } -void write_entry(Sym sym, ostream& os, HashMap& map, unsigned out) { - HashMap::iterator it = find_entry(sym, os, map); +// prints 'num' in reverse notation. Does not matter as it's a unique id +string make_var(unsigned num) { + string str = "a"; + do { + str += char('0' + (num % 10)); + num /= 10; + } while (num); + return str; +} + +HashMap::iterator find_entry2(const Sym& sym, string& str, HashMap& map) { + HashMap::iterator result = map.find(sym); + + if (result == map.end()) { // new entry + const SymVec& args = sym.args(); + + vector argstr(args.size()); + for (unsigned i = 0; i < args.size(); ++i) { + argstr[i] = find_entry2(args[i], str, map)->second; + } + + string var = make_var(map.size()); // map.size(): unique id + + // write out the code + const FunDef& fun = get_element(sym.token()); + string code = fun.c_print(argstr, vector() ); + str += "double " + var + "=" + code + ";\n"; + + result = map.insert( make_pair(sym, var ) ).first; // only want iterator + } + + return result; +} + +void write_entry(const Sym& sym, ostream& os, HashMap& map, unsigned out) { + string s; + HashMap::iterator it = find_entry2(sym, s, map); + os << s; os << "y[" << out << "]=" << it->second << ";\n"; } +template +string to_string(T t) { + ostringstream os; + os << t; + return os.str(); +} + +void write_entry(const Sym& sym, string& str, HashMap& map, unsigned out) { + HashMap::iterator it = find_entry2(sym, str, map); + + str += "y[" + to_string(out) + "]=" + it->second + ";\n"; +} + multi_function compile(const std::vector& syms) { + // static stream to avoid fragmentation of these LARGE strings + static string str; + + str += make_prototypes(); + + str += "double func(const double* x, double* y) { \n "; + + HashMap map(Sym::get_dag().size()); + + for (unsigned i = 0; i < syms.size(); ++i) { + write_entry(syms[i], str, map, i); + } + + str += ";}"; + + return (multi_function) symc_make(str.c_str(), "func"); +} + +multi_function compile2(const std::vector& syms) { + // static stream to avoid fragmentation of these LARGE strings static ostringstream os; os.str(""); @@ -83,7 +157,8 @@ multi_function compile(const std::vector& syms) { os << "double func(const double* x, double* y) { \n "; - HashMap map; + HashMap map(Sym::get_dag().size()); + for (unsigned i = 0; i < syms.size(); ++i) { write_entry(syms[i], os, map, i); @@ -143,7 +218,7 @@ void compile(const std::vector& syms, std::vector& functio os.str(""); os << make_prototypes(); - HashMap map; + HashMap map(Sym::get_dag().size()); for (unsigned i = 0; i < syms.size(); ++i) { os << "double func" << i << "(const double* x) { return "; diff --git a/eo/contrib/mathsym/fun/FunDef.cpp b/eo/contrib/mathsym/fun/FunDef.cpp index e6290bef..1cbffd09 100644 --- a/eo/contrib/mathsym/fun/FunDef.cpp +++ b/eo/contrib/mathsym/fun/FunDef.cpp @@ -120,7 +120,11 @@ struct HashDouble{ } }; +#if USE_TR1 +typedef std::tr1::unordered_map DoubleSet; +#else typedef hash_map DoubleSet; +#endif static DoubleSet doubleSet; // for quick checking if a constant already exists static vector is_constant_flag; @@ -186,6 +190,7 @@ bool is_constant(token_t token) { extern Sym default_const() { return SymConst(rng.normal()); } /* The functions */ +namespace { class Var : public FunDef { public : @@ -247,7 +252,8 @@ class Const : public FunDef { string name() const { return "parameter"; } }; - +} // namespace + void get_constants(Sym sym, vector& ret) { token_t token = sym.token(); if (is_constant_flag[token]) { @@ -305,6 +311,12 @@ vector get_defined_functions() { return res; } +FunDef* make_var(int idx) { return new Var(idx); } +FunDef* make_const(double value) { return new Const(value); } + + +namespace { + class Sum : public FunDef { public : @@ -478,6 +490,8 @@ struct Min { string name() const { return "min"; } }; +} // namespace + string prototypes = "double pow(double, double);"; string get_prototypes() { return prototypes; } unsigned add_prototype(string str) { prototypes += string("double ") + str + "(double);"; return prototypes.size(); } @@ -488,6 +502,7 @@ token_t add_function(FunDef* function, token_t where) { return 0; } +namespace { #define FUNCDEF(funcname) struct funcname##_struct { \ double operator()(double val) const { return funcname(val); }\ @@ -498,9 +513,6 @@ token_t add_function(FunDef* function, token_t where) { static const token_t funcname##_token_static = add_function( new Unary, funcname##_token);\ unsigned funcname##_size = add_prototype(#funcname); -FunDef* make_var(int idx) { return new Var(idx); } -FunDef* make_const(double value) { return new Const(value); } - static token_t ssum_token = add_function( new Sum , sum_token); static token_t sprod_token = add_function( new Prod, prod_token); static token_t sinv_token = add_function( new Unary, inv_token); @@ -524,11 +536,14 @@ FUNCDEF(atanh); FUNCDEF(exp); FUNCDEF(log); +} // namespace double sqr(double x) { return x*x; } +namespace { FUNCDEF(sqr); FUNCDEF(sqrt); +} // namespace /* Serialization */ void write_raw(ostream& os, const Sym& sym) { diff --git a/eo/contrib/mathsym/fun/FunDef.h b/eo/contrib/mathsym/fun/FunDef.h index 9c722098..6f517602 100644 --- a/eo/contrib/mathsym/fun/FunDef.h +++ b/eo/contrib/mathsym/fun/FunDef.h @@ -21,6 +21,7 @@ #include #include #include +#include #include "Sym.h" #include "Interval.h" @@ -142,7 +143,7 @@ extern std::string get_prototypes(); // reading and writing in internal format extern std::string write_raw(const Sym& sym); -extern void write_raw(ostream& os, const Sym& sym); +extern void write_raw(std::ostream& os, const Sym& sym); extern Sym read_raw(std::string str); extern Sym read_raw(std::istream& is); extern void read_raw(std::istream& is, Sym& sym); diff --git a/eo/contrib/mathsym/regression/ErrorMeasure.cpp b/eo/contrib/mathsym/regression/ErrorMeasure.cpp index 968bdfef..047681ad 100644 --- a/eo/contrib/mathsym/regression/ErrorMeasure.cpp +++ b/eo/contrib/mathsym/regression/ErrorMeasure.cpp @@ -232,8 +232,11 @@ class ErrorMeasureImpl { vector calc_error(const vector& pop) { // first declone +#if USE_TR1 + typedef std::tr1::unordered_map HashMap; +#else typedef hash_map HashMap; - +#endif HashMap clone_map; vector decloned; decloned.reserve(pop.size()); diff --git a/eo/contrib/mathsym/sym/Sym.cpp b/eo/contrib/mathsym/sym/Sym.cpp index b426e111..6b456316 100644 --- a/eo/contrib/mathsym/sym/Sym.cpp +++ b/eo/contrib/mathsym/sym/Sym.cpp @@ -46,7 +46,7 @@ size_t get_depth(const SymVec& vec) { return dp; } -Sym::Sym(token_t tok, const SymVec& args_) +Sym::Sym(token_t tok, const SymVec& args_) : node(dag.end()) { detail::SymKey key(tok, detail::SymArgs(args_)); detail::SymValue val; @@ -64,7 +64,7 @@ Sym::Sym(token_t tok, const SymVec& args_) else incref(); } -Sym::Sym(token_t tok, const Sym& a) { +Sym::Sym(token_t tok, const Sym& a) : node(dag.end()) { SymVec args_; args_.push_back(a); detail::SymKey key(tok, detail::SymArgs(args_)); detail::SymValue val; @@ -82,7 +82,7 @@ Sym::Sym(token_t tok, const Sym& a) { else incref(); } -Sym::Sym(token_t tok) { +Sym::Sym(token_t tok) : node(dag.end()) { detail::SymKey key(tok); detail::SymValue val; node = dag.insert(pair(key, val)).first; diff --git a/eo/contrib/mathsym/sym/Sym.h b/eo/contrib/mathsym/sym/Sym.h index 3bbf2049..cccf4aaa 100644 --- a/eo/contrib/mathsym/sym/Sym.h +++ b/eo/contrib/mathsym/sym/Sym.h @@ -22,7 +22,7 @@ #if __GNUC__ >= 3 #include -#else +#elif __GNUC__ < 3 #include using std::hash_map; #endif @@ -33,15 +33,23 @@ struct UniqueNodeStats { virtual ~UniqueNodeStats(){} }; #include "SymImpl.h" #include "token.h" -typedef hash_map SymMap; -typedef SymMap::iterator SymIterator; -class Sym; +#if __GNUC__ == 444 +#define USE_TR1 1 +#else +#define USE_TR1 0 +#endif -typedef std::vector SymVec; +#if USE_TR1 +#include +typedef std::tr1::unordered_map SymMap; +#else +typedef hash_map SymMap; +#endif + +typedef SymMap::iterator SymIterator; /* Sym is the tree, for which all the nodes are stored in a hash table. * This makes checking for equality O(1) */ - class Sym { public: @@ -67,7 +75,7 @@ class Sym /* Unique Stats are user defined */ UniqueNodeStats* extra_stats() const { return empty()? 0 : node->second.uniqueNodeStats; } - int hashcode() const { detail::SymKey::Hash hash; return hash(node->first); } + int hashcode() const { return node->first.get_hash_code(); } //detail::SymKey::Hash hash; return hash(node->first); } // Friends, need to touch the node friend struct detail::SymKey::Hash; diff --git a/eo/contrib/mathsym/sym/SymImpl.cpp b/eo/contrib/mathsym/sym/SymImpl.cpp index a0f3d701..b2d568a6 100644 --- a/eo/contrib/mathsym/sym/SymImpl.cpp +++ b/eo/contrib/mathsym/sym/SymImpl.cpp @@ -21,7 +21,7 @@ namespace detail { class SymArgsImpl { public: - vector owned_args; + std::vector owned_args; }; size_t SymArgs::len() const { @@ -76,7 +76,7 @@ int SymKey::calc_hash() const { unsigned long hash = unsigned(token); hash *= PRIMET; - const SymVec& v = args.vec(); + const std::vector& v = args.vec(); for (unsigned i = 0; i < v.size(); ++i) { hash += ( (v[i].address() >> 3) * primes[i%nprimes]) % HASHMOD; } diff --git a/eo/contrib/mathsym/sym/SymImpl.h b/eo/contrib/mathsym/sym/SymImpl.h index 105796c7..aa14c3d8 100644 --- a/eo/contrib/mathsym/sym/SymImpl.h +++ b/eo/contrib/mathsym/sym/SymImpl.h @@ -22,6 +22,16 @@ #include "token.h" class Sym; + +#if __GNUC__ > 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#include +typedef std::vector > std::vector; +//typedef std::vector SymVec; +#else +typedef std::vector SymVec; +#endif + + namespace detail { class SymArgsImpl; @@ -47,8 +57,8 @@ class SymArgs { class SymKey { public: - SymKey(token_t _token) : args(), token(_token) {} - SymKey(token_t _token, const detail::SymArgs& _args) : args(_args), token(_token) {} + SymKey(token_t _token) : args(), token(_token), hash_code(calc_hash()) {} + SymKey(token_t _token, const detail::SymArgs& _args) : args(_args), token(_token), hash_code(calc_hash()) {} private: @@ -69,8 +79,11 @@ class SymKey // fixates (i.e. claims memory) for the embedded vector of Syms void fixate() const { args.fixate(); } + int get_hash_code() const { return hash_code; } + private: int calc_hash() const; + int hash_code; }; struct SymValue diff --git a/eo/contrib/mathsym/symreg.cpp b/eo/contrib/mathsym/symreg.cpp index 0f29ff54..406546ea 100644 --- a/eo/contrib/mathsym/symreg.cpp +++ b/eo/contrib/mathsym/symreg.cpp @@ -306,6 +306,7 @@ int main(int argc, char* argv[]) { genmon.add(avgSize); genmon.add(dagSize); genmon.add(sumSize); + genmon.add(term); // add generation counter checkpoint.add(genmon);