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:
parent
f128fcd86f
commit
bac6644915
11 changed files with 149 additions and 33 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -33,20 +33,20 @@ class EoSym : public EO<Fitness>, public Sym {
|
|||
static_cast<Sym*>(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 <class Fitness>
|
||||
void EoSym<Fitness>::printOn(ostream& os) const {
|
||||
void EoSym<Fitness>::printOn(std::ostream& os) const {
|
||||
EO<Fitness>::printOn(os);
|
||||
os << ' ';
|
||||
write_raw(os, *this);
|
||||
}
|
||||
|
||||
template <class Fitness>
|
||||
void EoSym<Fitness>::readFrom(istream& is) {
|
||||
void EoSym<Fitness>::readFrom(std::istream& is) {
|
||||
EO<Fitness>::readFrom(is);
|
||||
read_raw(is, *this);
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ void EoSym<Fitness>::readFrom(istream& is) {
|
|||
template <class Fitness>
|
||||
inline std::ostream& operator<<(std::ostream& os, const EoSym<Fitness>& f) { f.printOn(os); return os; }
|
||||
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
|
||||
|
|
|
|||
|
|
@ -39,9 +39,14 @@ string make_prototypes() {
|
|||
}
|
||||
|
||||
// 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);
|
||||
|
||||
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<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";
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
// 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 ostringstream os;
|
||||
os.str("");
|
||||
|
|
@ -83,7 +157,8 @@ multi_function compile(const std::vector<Sym>& 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<Sym>& syms, std::vector<single_function>& 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 ";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
#endif
|
||||
|
||||
static DoubleSet doubleSet; // for quick checking if a constant already exists
|
||||
static vector<bool> 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<double>& ret) {
|
||||
token_t token = sym.token();
|
||||
if (is_constant_flag[token]) {
|
||||
|
|
@ -305,6 +311,12 @@ vector<const FunDef*> 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##_struct>, 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>, 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) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#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);
|
||||
|
|
|
|||
|
|
@ -232,8 +232,11 @@ class ErrorMeasureImpl {
|
|||
vector<ErrorMeasure::result> calc_error(const vector<Sym>& pop) {
|
||||
|
||||
// first declone
|
||||
#if USE_TR1
|
||||
typedef std::tr1::unordered_map<Sym, unsigned, HashSym> HashMap;
|
||||
#else
|
||||
typedef hash_map<Sym, unsigned, HashSym> HashMap;
|
||||
|
||||
#endif
|
||||
HashMap clone_map;
|
||||
vector<Sym> decloned;
|
||||
decloned.reserve(pop.size());
|
||||
|
|
|
|||
|
|
@ -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<const detail::SymKey, detail::SymValue>(key, val)).first;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#if __GNUC__ >= 3
|
||||
#include <backward/hash_map.h>
|
||||
#else
|
||||
#elif __GNUC__ < 3
|
||||
#include <hash_map.h>
|
||||
using std::hash_map;
|
||||
#endif
|
||||
|
|
@ -33,15 +33,23 @@ struct UniqueNodeStats { virtual ~UniqueNodeStats(){} };
|
|||
#include "SymImpl.h"
|
||||
#include "token.h"
|
||||
|
||||
typedef hash_map<detail::SymKey, detail::SymValue, detail::SymKey::Hash> SymMap;
|
||||
typedef SymMap::iterator SymIterator;
|
||||
class Sym;
|
||||
#if __GNUC__ == 444
|
||||
#define USE_TR1 1
|
||||
#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.
|
||||
* 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;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace detail {
|
|||
|
||||
class SymArgsImpl {
|
||||
public:
|
||||
vector<Sym> owned_args;
|
||||
std::vector<Sym> 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<Sym>& v = args.vec();
|
||||
for (unsigned i = 0; i < v.size(); ++i) {
|
||||
hash += ( (v[i].address() >> 3) * primes[i%nprimes]) % HASHMOD;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,16 @@
|
|||
#include "token.h"
|
||||
|
||||
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 {
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Reference in a new issue