Solved some issues and prepared the library for using unordered_map instead of hash_map (C++ TR1). Can only use this when g++-4.0.3 is out

This commit is contained in:
maartenkeijzer 2005-10-15 21:27:47 +00:00
commit bac6644915
11 changed files with 149 additions and 33 deletions

View file

@ -1,7 +1,7 @@
COMPILEFLAGS=-Wno-deprecated -g -Wall -Wshadow #-DINTERVAL_DEBUG COMPILEFLAGS=-Wno-deprecated -g -Wall #-DINTERVAL_DEBUG
OPTFLAGS= -O3 -DNDEBUG OPTFLAGS= #-O3 -DNDEBUG
PROFILE_FLAGS=-pg PROFILE_FLAGS=#-pg
INCLUDES=-I. -Isym -Ifun -Igen -Ieval -Iregression -I../../src -Ieo_interface -I.. INCLUDES=-I. -Isym -Ifun -Igen -Ieval -Iregression -I../../src -Ieo_interface -I..
@ -33,7 +33,7 @@ distclean: clean
rm -rf tcc rm -rf tcc
symreg: libsym.a symreg.o $(EXTLIBS) 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) libsym.a: $(OBJS)
rm libsym.a; ar cq $(SYMLIB) $(OBJS) rm libsym.a; ar cq $(SYMLIB) $(OBJS)

View file

@ -33,20 +33,20 @@ class EoSym : public EO<Fitness>, public Sym {
static_cast<Sym*>(this)->operator=(sym); static_cast<Sym*>(this)->operator=(sym);
} }
virtual void printOn(ostream& os) const; virtual void printOn(std::ostream& os) const;
virtual void readFrom(istream& is); virtual void readFrom(std::istream& is);
}; };
template <class Fitness> template <class Fitness>
void EoSym<Fitness>::printOn(ostream& os) const { void EoSym<Fitness>::printOn(std::ostream& os) const {
EO<Fitness>::printOn(os); EO<Fitness>::printOn(os);
os << ' '; os << ' ';
write_raw(os, *this); write_raw(os, *this);
} }
template <class Fitness> template <class Fitness>
void EoSym<Fitness>::readFrom(istream& is) { void EoSym<Fitness>::readFrom(std::istream& is) {
EO<Fitness>::readFrom(is); EO<Fitness>::readFrom(is);
read_raw(is, *this); read_raw(is, *this);
} }
@ -54,7 +54,7 @@ void EoSym<Fitness>::readFrom(istream& is) {
template <class Fitness> template <class Fitness>
inline std::ostream& operator<<(std::ostream& os, const EoSym<Fitness>& f) { f.printOn(os); return os; } inline std::ostream& operator<<(std::ostream& os, const EoSym<Fitness>& f) { f.printOn(os); return os; }
template <class Fitness> template <class Fitness>
inline istream& operator>>(std::istream& is, EoSym<Fitness>& f) { f.readFrom(is); return is; } inline std::istream& operator>>(std::istream& is, EoSym<Fitness>& f) { f.readFrom(is); return is; }
#endif #endif

View file

@ -39,9 +39,14 @@ string make_prototypes() {
} }
// contains variable names, like 'a0', 'a1', etc. or regular code // contains variable names, like 'a0', 'a1', etc. or regular code
typedef hash_map<Sym, string, HashSym> HashMap;
HashMap::iterator find_entry(Sym sym, ostream& os, HashMap& map) { #if USE_TR1
typedef std::tr1::unordered_map<Sym, string, HashSym> HashMap;
#else
typedef hash_map<Sym, string, HashSym> HashMap;
#endif
HashMap::iterator find_entry(const Sym& sym, ostream& os, HashMap& map) {
HashMap::iterator result = map.find(sym); HashMap::iterator result = map.find(sym);
if (result == map.end()) { // new entry if (result == map.end()) { // new entry
@ -68,13 +73,82 @@ HashMap::iterator find_entry(Sym sym, ostream& os, HashMap& map) {
return result; return result;
} }
void write_entry(Sym sym, ostream& os, HashMap& map, unsigned out) { // prints 'num' in reverse notation. Does not matter as it's a unique id
HashMap::iterator it = find_entry(sym, os, map); 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<string> 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<string>() );
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"; os << "y[" << out << "]=" << it->second << ";\n";
} }
template <class T>
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<Sym>& syms) { multi_function compile(const std::vector<Sym>& 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<Sym>& syms) {
// static stream to avoid fragmentation of these LARGE strings // static stream to avoid fragmentation of these LARGE strings
static ostringstream os; static ostringstream os;
os.str(""); os.str("");
@ -83,7 +157,8 @@ multi_function compile(const std::vector<Sym>& syms) {
os << "double func(const double* x, double* y) { \n "; 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) { for (unsigned i = 0; i < syms.size(); ++i) {
write_entry(syms[i], os, map, i); write_entry(syms[i], os, map, i);
@ -143,7 +218,7 @@ void compile(const std::vector<Sym>& syms, std::vector<single_function>& functio
os.str(""); os.str("");
os << make_prototypes(); os << make_prototypes();
HashMap map; HashMap map(Sym::get_dag().size());
for (unsigned i = 0; i < syms.size(); ++i) { for (unsigned i = 0; i < syms.size(); ++i) {
os << "double func" << i << "(const double* x) { return "; os << "double func" << i << "(const double* x) { return ";

View file

@ -120,7 +120,11 @@ struct HashDouble{
} }
}; };
#if USE_TR1
typedef std::tr1::unordered_map<double, token_t> DoubleSet;
#else
typedef hash_map<double, token_t, HashDouble> DoubleSet; typedef hash_map<double, token_t, HashDouble> DoubleSet;
#endif
static DoubleSet doubleSet; // for quick checking if a constant already exists static DoubleSet doubleSet; // for quick checking if a constant already exists
static vector<bool> is_constant_flag; static vector<bool> is_constant_flag;
@ -186,6 +190,7 @@ bool is_constant(token_t token) {
extern Sym default_const() { return SymConst(rng.normal()); } extern Sym default_const() { return SymConst(rng.normal()); }
/* The functions */ /* The functions */
namespace {
class Var : public FunDef { class Var : public FunDef {
public : public :
@ -247,7 +252,8 @@ class Const : public FunDef {
string name() const { return "parameter"; } string name() const { return "parameter"; }
}; };
} // namespace
void get_constants(Sym sym, vector<double>& ret) { void get_constants(Sym sym, vector<double>& ret) {
token_t token = sym.token(); token_t token = sym.token();
if (is_constant_flag[token]) { if (is_constant_flag[token]) {
@ -305,6 +311,12 @@ vector<const FunDef*> get_defined_functions() {
return res; 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 { class Sum : public FunDef {
public : public :
@ -478,6 +490,8 @@ struct Min {
string name() const { return "min"; } string name() const { return "min"; }
}; };
} // namespace
string prototypes = "double pow(double, double);"; string prototypes = "double pow(double, double);";
string get_prototypes() { return prototypes; } string get_prototypes() { return prototypes; }
unsigned add_prototype(string str) { prototypes += string("double ") + str + "(double);"; return prototypes.size(); } 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; return 0;
} }
namespace {
#define FUNCDEF(funcname) struct funcname##_struct { \ #define FUNCDEF(funcname) struct funcname##_struct { \
double operator()(double val) const { return funcname(val); }\ 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##_struct>, funcname##_token);\ static const token_t funcname##_token_static = add_function( new Unary<funcname##_struct>, funcname##_token);\
unsigned funcname##_size = add_prototype(#funcname); 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 ssum_token = add_function( new Sum , sum_token);
static token_t sprod_token = add_function( new Prod, prod_token); static token_t sprod_token = add_function( new Prod, prod_token);
static token_t sinv_token = add_function( new Unary<Inv>, inv_token); static token_t sinv_token = add_function( new Unary<Inv>, inv_token);
@ -524,11 +536,14 @@ FUNCDEF(atanh);
FUNCDEF(exp); FUNCDEF(exp);
FUNCDEF(log); FUNCDEF(log);
} // namespace
double sqr(double x) { return x*x; } double sqr(double x) { return x*x; }
namespace {
FUNCDEF(sqr); FUNCDEF(sqr);
FUNCDEF(sqrt); FUNCDEF(sqrt);
} // namespace
/* Serialization */ /* Serialization */
void write_raw(ostream& os, const Sym& sym) { void write_raw(ostream& os, const Sym& sym) {

View file

@ -21,6 +21,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <iostream>
#include "Sym.h" #include "Sym.h"
#include "Interval.h" #include "Interval.h"
@ -142,7 +143,7 @@ extern std::string get_prototypes();
// reading and writing in internal format // reading and writing in internal format
extern std::string write_raw(const Sym& sym); 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::string str);
extern Sym read_raw(std::istream& is); extern Sym read_raw(std::istream& is);
extern void read_raw(std::istream& is, Sym& sym); extern void read_raw(std::istream& is, Sym& sym);

View file

@ -232,8 +232,11 @@ class ErrorMeasureImpl {
vector<ErrorMeasure::result> calc_error(const vector<Sym>& pop) { vector<ErrorMeasure::result> calc_error(const vector<Sym>& pop) {
// first declone // first declone
#if USE_TR1
typedef std::tr1::unordered_map<Sym, unsigned, HashSym> HashMap;
#else
typedef hash_map<Sym, unsigned, HashSym> HashMap; typedef hash_map<Sym, unsigned, HashSym> HashMap;
#endif
HashMap clone_map; HashMap clone_map;
vector<Sym> decloned; vector<Sym> decloned;
decloned.reserve(pop.size()); decloned.reserve(pop.size());

View file

@ -46,7 +46,7 @@ size_t get_depth(const SymVec& vec) {
return dp; 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::SymKey key(tok, detail::SymArgs(args_));
detail::SymValue val; detail::SymValue val;
@ -64,7 +64,7 @@ Sym::Sym(token_t tok, const SymVec& args_)
else incref(); 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); SymVec args_; args_.push_back(a);
detail::SymKey key(tok, detail::SymArgs(args_)); detail::SymKey key(tok, detail::SymArgs(args_));
detail::SymValue val; detail::SymValue val;
@ -82,7 +82,7 @@ Sym::Sym(token_t tok, const Sym& a) {
else incref(); else incref();
} }
Sym::Sym(token_t tok) { Sym::Sym(token_t tok) : node(dag.end()) {
detail::SymKey key(tok); detail::SymKey key(tok);
detail::SymValue val; detail::SymValue val;
node = dag.insert(pair<const detail::SymKey, detail::SymValue>(key, val)).first; node = dag.insert(pair<const detail::SymKey, detail::SymValue>(key, val)).first;

View file

@ -22,7 +22,7 @@
#if __GNUC__ >= 3 #if __GNUC__ >= 3
#include <backward/hash_map.h> #include <backward/hash_map.h>
#else #elif __GNUC__ < 3
#include <hash_map.h> #include <hash_map.h>
using std::hash_map; using std::hash_map;
#endif #endif
@ -33,15 +33,23 @@ struct UniqueNodeStats { virtual ~UniqueNodeStats(){} };
#include "SymImpl.h" #include "SymImpl.h"
#include "token.h" #include "token.h"
typedef hash_map<detail::SymKey, detail::SymValue, detail::SymKey::Hash> SymMap; #if __GNUC__ == 444
typedef SymMap::iterator SymIterator; #define USE_TR1 1
class Sym; #else
#define USE_TR1 0
#endif
typedef std::vector<Sym> SymVec; #if USE_TR1
#include <tr1/unordered_map>
typedef std::tr1::unordered_map<detail::SymKey, detail::SymValue, detail::SymKey::Hash> SymMap;
#else
typedef hash_map<detail::SymKey, detail::SymValue, detail::SymKey::Hash> SymMap;
#endif
typedef SymMap::iterator SymIterator;
/* Sym is the tree, for which all the nodes are stored in a hash table. /* Sym is the tree, for which all the nodes are stored in a hash table.
* This makes checking for equality O(1) */ * This makes checking for equality O(1) */
class Sym class Sym
{ {
public: public:
@ -67,7 +75,7 @@ class Sym
/* Unique Stats are user defined */ /* Unique Stats are user defined */
UniqueNodeStats* extra_stats() const { return empty()? 0 : node->second.uniqueNodeStats; } 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 // Friends, need to touch the node
friend struct detail::SymKey::Hash; friend struct detail::SymKey::Hash;

View file

@ -21,7 +21,7 @@ namespace detail {
class SymArgsImpl { class SymArgsImpl {
public: public:
vector<Sym> owned_args; std::vector<Sym> owned_args;
}; };
size_t SymArgs::len() const { size_t SymArgs::len() const {
@ -76,7 +76,7 @@ int SymKey::calc_hash() const {
unsigned long hash = unsigned(token); unsigned long hash = unsigned(token);
hash *= PRIMET; hash *= PRIMET;
const SymVec& v = args.vec(); const std::vector<Sym>& v = args.vec();
for (unsigned i = 0; i < v.size(); ++i) { for (unsigned i = 0; i < v.size(); ++i) {
hash += ( (v[i].address() >> 3) * primes[i%nprimes]) % HASHMOD; hash += ( (v[i].address() >> 3) * primes[i%nprimes]) % HASHMOD;
} }

View file

@ -22,6 +22,16 @@
#include "token.h" #include "token.h"
class Sym; class Sym;
#if __GNUC__ > 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#include <ext/pool_allocator.h>
typedef std::vector<Sym, __gnu_cxx::__pool_alloc<Sym> > std::vector<Sym>;
//typedef std::vector<Sym> SymVec;
#else
typedef std::vector<Sym> SymVec;
#endif
namespace detail { namespace detail {
class SymArgsImpl; class SymArgsImpl;
@ -47,8 +57,8 @@ class SymArgs {
class SymKey class SymKey
{ {
public: public:
SymKey(token_t _token) : 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) {} SymKey(token_t _token, const detail::SymArgs& _args) : args(_args), token(_token), hash_code(calc_hash()) {}
private: private:
@ -69,8 +79,11 @@ class SymKey
// fixates (i.e. claims memory) for the embedded vector of Syms // fixates (i.e. claims memory) for the embedded vector of Syms
void fixate() const { args.fixate(); } void fixate() const { args.fixate(); }
int get_hash_code() const { return hash_code; }
private: private:
int calc_hash() const; int calc_hash() const;
int hash_code;
}; };
struct SymValue struct SymValue

View file

@ -306,6 +306,7 @@ int main(int argc, char* argv[]) {
genmon.add(avgSize); genmon.add(avgSize);
genmon.add(dagSize); genmon.add(dagSize);
genmon.add(sumSize); genmon.add(sumSize);
genmon.add(term); // add generation counter
checkpoint.add(genmon); checkpoint.add(genmon);