Constant mutation + simplification added
This commit is contained in:
parent
05790afc21
commit
4042798417
9 changed files with 225 additions and 46 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
COMPILEFLAGS=-Wno-deprecated -g -Wall -Wshadow #-DINTERVAL_DEBUG
|
COMPILEFLAGS=-Wno-deprecated -g -Wall -Wshadow #-DINTERVAL_DEBUG
|
||||||
OPTFLAGS= -O2 -DNDEBUG
|
OPTFLAGS= -O2 -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..
|
||||||
|
|
||||||
|
|
@ -16,9 +16,9 @@ VPATH=sym fun gen eval regression eo_interface
|
||||||
|
|
||||||
CXXSOURCES=FunDef.cpp Sym.cpp SymImpl.cpp SymOps.cpp sym_compile.cpp TreeBuilder.cpp LanguageTable.cpp\
|
CXXSOURCES=FunDef.cpp Sym.cpp SymImpl.cpp SymOps.cpp sym_compile.cpp TreeBuilder.cpp LanguageTable.cpp\
|
||||||
Dataset.cpp ErrorMeasure.cpp Scaling.cpp TargetInfo.cpp BoundsCheck.cpp util.cpp NodeSelector.cpp\
|
Dataset.cpp ErrorMeasure.cpp Scaling.cpp TargetInfo.cpp BoundsCheck.cpp util.cpp NodeSelector.cpp\
|
||||||
eoSymCrossover.cpp
|
eoSymCrossover.cpp sym_operations.cpp eoSymMutate.cpp
|
||||||
|
|
||||||
PROGRAMS=test/test test/test_compile test/testeo
|
TESTPROGRAMS=test/test_compile test/testeo test/test_simplify
|
||||||
|
|
||||||
OBJS= $(CXXSOURCES:.cpp=.o) c_compile.o
|
OBJS= $(CXXSOURCES:.cpp=.o) c_compile.o
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ all: tcc/ symreg
|
||||||
include $(CXXSOURCES:.cpp=.d) symreg.d
|
include $(CXXSOURCES:.cpp=.d) symreg.d
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm *.o *.d $(PROGRAMS) $(SYMLIB) symreg || true
|
rm *.o *.d $(TESTPROGRAMS) $(SYMLIB) symreg || true
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -rf tcc
|
rm -rf tcc
|
||||||
|
|
@ -38,11 +38,8 @@ symreg: libsym.a symreg.o $(EXTLIBS)
|
||||||
libsym.a: $(OBJS)
|
libsym.a: $(OBJS)
|
||||||
rm libsym.a; ar cq $(SYMLIB) $(OBJS)
|
rm libsym.a; ar cq $(SYMLIB) $(OBJS)
|
||||||
|
|
||||||
check: $(PROGRAMS)
|
check: $(TESTPROGRAMS)
|
||||||
test/test && test/test_compile && test/testeo && echo "all tests succeeded"
|
test/test_compile && test/testeo && test_simplify && echo "all tests succeeded"
|
||||||
|
|
||||||
test/test: test/test.o ${SYMLIB}
|
|
||||||
$(CXX) -o test/test test/test.o ${SYMLIB} ${LIBS}
|
|
||||||
|
|
||||||
test/test_compile: test/test_compile.o ${SYMLIB}
|
test/test_compile: test/test_compile.o ${SYMLIB}
|
||||||
$(CXX) -o test/test_compile test/test_compile.o $(SYMLIB) ${LIBS}
|
$(CXX) -o test/test_compile test/test_compile.o $(SYMLIB) ${LIBS}
|
||||||
|
|
@ -50,6 +47,9 @@ test/test_compile: test/test_compile.o ${SYMLIB}
|
||||||
test/testeo: test/testeo.o ${SYMLIB}
|
test/testeo: test/testeo.o ${SYMLIB}
|
||||||
$(CXX) -o test/testeo test/testeo.o $(SYMLIB) ${LIBS}
|
$(CXX) -o test/testeo test/testeo.o $(SYMLIB) ${LIBS}
|
||||||
|
|
||||||
|
test/test_simplify: test/test_simplify.o $(SYMLIB)
|
||||||
|
$(CXX) -o test/test_simplify test/test_simplify.o $(SYMLIB) ${LIBS}
|
||||||
|
|
||||||
# eo
|
# eo
|
||||||
../../src/libeo.a:
|
../../src/libeo.a:
|
||||||
make -C ../../src
|
make -C ../../src
|
||||||
|
|
|
||||||
72
eo/contrib/mathsym/eo_interface/eoSymMutate.cpp
Normal file
72
eo/contrib/mathsym/eo_interface/eoSymMutate.cpp
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2005 Maarten Keijzer
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <eoSymMutate.h>
|
||||||
|
#include <FunDef.h>
|
||||||
|
#include <utils/eoRNG.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
std::pair<Sym, bool> do_mutate(Sym sym, double p, const LanguageTable& table) {
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
SymVec args = sym.args();
|
||||||
|
if (rng.flip(p)) {
|
||||||
|
token_t new_token = table.get_random_function( args.size());
|
||||||
|
if (new_token != sym.token()) changed = true;
|
||||||
|
sym = Sym(new_token, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < args.size(); ++i) {
|
||||||
|
std::pair<Sym,bool> r = do_mutate(args[i], p, table);
|
||||||
|
changed |= r.second;
|
||||||
|
if (r.second)
|
||||||
|
args[i] = r.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
return std::make_pair(Sym(sym.token(), args), true);
|
||||||
|
// else
|
||||||
|
return std::make_pair(sym, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// these two can (should?) move to an impl file
|
||||||
|
bool mutate(Sym& sym, double p, const LanguageTable& table) {
|
||||||
|
std::pair<Sym, bool> r = do_mutate(sym, p, table);
|
||||||
|
sym = r.first;
|
||||||
|
return r.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool mutate_constants(Sym& sym, double stdev) {
|
||||||
|
|
||||||
|
vector<double> values = get_constants(sym);
|
||||||
|
|
||||||
|
if (values.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < values.size(); ++i) {
|
||||||
|
values[i] += rng.normal() * stdev;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym = set_constants(sym, values);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -53,6 +53,8 @@ class eoSymSubtreeMutate : public eoMonOp<EoType> {
|
||||||
* is_rate_absolute : don't rescale the rate to the size of the tree
|
* is_rate_absolute : don't rescale the rate to the size of the tree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
extern bool mutate(Sym& sym, double p, const LanguageTable& table);
|
||||||
|
|
||||||
template <class EoType>
|
template <class EoType>
|
||||||
class eoSymNodeMutate : public eoMonOp<EoType> {
|
class eoSymNodeMutate : public eoMonOp<EoType> {
|
||||||
|
|
||||||
|
|
@ -60,35 +62,6 @@ class eoSymNodeMutate : public eoMonOp<EoType> {
|
||||||
double own_mutation_rate;
|
double own_mutation_rate;
|
||||||
bool own_is_rate_absolute;
|
bool own_is_rate_absolute;
|
||||||
|
|
||||||
// these two can (should?) move to an impl file
|
|
||||||
bool mutate(Sym& sym, double p) {
|
|
||||||
std::pair<Sym, bool> r = do_mutate(sym, p);
|
|
||||||
sym = r.first;
|
|
||||||
return r.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<Sym, bool> do_mutate(Sym sym, double p) {
|
|
||||||
|
|
||||||
bool changed = false;
|
|
||||||
SymVec args = sym.args();
|
|
||||||
if (rng.flip(p)) {
|
|
||||||
token_t new_token = table.get_random_function( args.size());
|
|
||||||
if (new_token != sym.token()) changed = true;
|
|
||||||
sym = Sym(new_token, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < args.size(); ++i) {
|
|
||||||
std::pair<Sym,bool> r = do_mutate(args[i], p);
|
|
||||||
changed |= r.second;
|
|
||||||
if (r.second)
|
|
||||||
args[i] = r.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
|
||||||
return std::make_pair(Sym(sym.token(), args), true);
|
|
||||||
// else
|
|
||||||
return std::make_pair(sym, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
@ -114,9 +87,29 @@ class eoSymNodeMutate : public eoMonOp<EoType> {
|
||||||
double p = mutation_rate;
|
double p = mutation_rate;
|
||||||
if (!is_rate_absolute) p /= _eo.size();
|
if (!is_rate_absolute) p /= _eo.size();
|
||||||
|
|
||||||
return mutate(_eo, p);
|
return mutate(_eo, p, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple constant mutation class, adds gaussian noise (configurable variance) to the individuals
|
||||||
|
**/
|
||||||
|
extern bool mutate_constants(Sym& sym, double stdev);
|
||||||
|
template <class EoType>
|
||||||
|
class eoSymConstantMutate : public eoMonOp<EoType> {
|
||||||
|
|
||||||
|
double& stdev;
|
||||||
|
|
||||||
|
|
||||||
|
public :
|
||||||
|
eoSymConstantMutate(double& _stdev) : stdev(_stdev) {}
|
||||||
|
|
||||||
|
bool operator()(EoType& _eo) {
|
||||||
|
return mutate_constants(_eo, stdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ string make_prototypes() {
|
||||||
return prot;
|
return prot;
|
||||||
}
|
}
|
||||||
|
|
||||||
// contains variable names, like 'a0', 'a1', etc.
|
// contains variable names, like 'a0', 'a1', etc. or regular code
|
||||||
typedef hash_map<Sym, string, HashSym> HashMap;
|
typedef hash_map<Sym, string, HashSym> HashMap;
|
||||||
|
|
||||||
HashMap::iterator find_entry(Sym sym, ostream& os, HashMap& map) {
|
HashMap::iterator find_entry(Sym sym, ostream& os, HashMap& map) {
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,7 @@ Sym set_constants(Sym sym, vector<double>::const_iterator& it) {
|
||||||
|
|
||||||
SymVec args = sym.args();
|
SymVec args = sym.args();
|
||||||
for (unsigned i = 0; i < args.size(); ++i) {
|
for (unsigned i = 0; i < args.size(); ++i) {
|
||||||
args[i] = set_constants(sym, it);
|
args[i] = set_constants(args[i], it);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Sym(token, args);
|
return Sym(token, args);
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,12 @@ extern bool is_constant(token_t token);
|
||||||
/** Create variable */
|
/** Create variable */
|
||||||
extern Sym SymVar(unsigned idx);
|
extern Sym SymVar(unsigned idx);
|
||||||
|
|
||||||
|
/** simplifies a sym (sym_operations.cpp) */
|
||||||
|
extern Sym simplify(Sym sym);
|
||||||
|
|
||||||
|
/** differentiates a sym to a token (sym_operations.cpp) */
|
||||||
|
extern Sym differentiate(Sym sym, token_t var_token);
|
||||||
|
|
||||||
/* Add function to the language table (and take a guess at the arity) */
|
/* Add function to the language table (and take a guess at the arity) */
|
||||||
class LanguageTable;
|
class LanguageTable;
|
||||||
extern void add_function_to_table(LanguageTable& table, token_t token);
|
extern void add_function_to_table(LanguageTable& table, token_t token);
|
||||||
|
|
|
||||||
76
eo/contrib/mathsym/fun/sym_operations.cpp
Normal file
76
eo/contrib/mathsym/fun/sym_operations.cpp
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2005 Maarten Keijzer
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <FunDef.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
Sym simplify_constants(Sym sym) {
|
||||||
|
|
||||||
|
SymVec args = sym.args();
|
||||||
|
token_t token = sym.token();
|
||||||
|
|
||||||
|
bool has_changed = false;
|
||||||
|
bool all_constants = true;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < args.size(); ++i) {
|
||||||
|
|
||||||
|
Sym arg = simplify_constants(args[i]);
|
||||||
|
|
||||||
|
if (arg != args[i]) {
|
||||||
|
has_changed = true;
|
||||||
|
}
|
||||||
|
args[i] = arg;
|
||||||
|
|
||||||
|
|
||||||
|
all_constants &= is_constant(args[i].token());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size() == 0) return sym; // variable or constant
|
||||||
|
|
||||||
|
|
||||||
|
if (all_constants) {
|
||||||
|
// evaluate
|
||||||
|
|
||||||
|
vector<double> dummy;
|
||||||
|
|
||||||
|
vector<double> vals(args.size());
|
||||||
|
for (unsigned i = 0; i < vals.size(); ++i) {
|
||||||
|
vals[i] = eval(sym, dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sym result = SymConst( get_element(token).eval(vals, dummy) );
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_changed) {
|
||||||
|
return Sym(token, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sym;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// currently only simplifies constants
|
||||||
|
Sym simplify(Sym sym) {
|
||||||
|
|
||||||
|
return simplify_constants(sym);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -168,16 +168,42 @@ class ErrorMeasureImpl {
|
||||||
|
|
||||||
vector<ErrorMeasure::result> calc_error(const vector<Sym>& pop) {
|
vector<ErrorMeasure::result> calc_error(const vector<Sym>& pop) {
|
||||||
|
|
||||||
|
// first declone
|
||||||
|
typedef hash_map<Sym, unsigned, HashSym> HashMap;
|
||||||
|
|
||||||
|
HashMap clone_map;
|
||||||
|
vector<Sym> decloned;
|
||||||
|
decloned.reserve(pop.size());
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < pop.size(); ++i) {
|
||||||
|
HashMap::iterator it = clone_map.find(pop[i]);
|
||||||
|
|
||||||
|
if (it == clone_map.end()) { // new
|
||||||
|
clone_map[ pop[i] ] = decloned.size();
|
||||||
|
decloned.push_back(pop[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluate
|
||||||
|
vector<ErrorMeasure::result> dresult;
|
||||||
// currently we can only accumulate simple measures such as absolute and mean_squared
|
// currently we can only accumulate simple measures such as absolute and mean_squared
|
||||||
switch(measure) {
|
switch(measure) {
|
||||||
case ErrorMeasure::mean_squared:
|
case ErrorMeasure::mean_squared:
|
||||||
case ErrorMeasure::absolute:
|
case ErrorMeasure::absolute:
|
||||||
return multi_function_eval(pop);
|
dresult = multi_function_eval(decloned);
|
||||||
|
break;
|
||||||
case ErrorMeasure::mean_squared_scaled:
|
case ErrorMeasure::mean_squared_scaled:
|
||||||
return single_function_eval(pop);
|
dresult = single_function_eval(decloned);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vector<ErrorMeasure::result>();
|
vector<ErrorMeasure::result> result(pop.size());
|
||||||
|
for (unsigned i = 0; i < result.size(); ++i) {
|
||||||
|
result[i] = dresult[ clone_map[pop[i]] ];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -244,11 +244,17 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
NodeSelector& node_selector = select<NodeSelector>(use_uniform, random_sel, biased_sel);
|
NodeSelector& node_selector = select<NodeSelector>(use_uniform, random_sel, biased_sel);
|
||||||
|
|
||||||
eoProportionalOp<EoType> genetic_operator;
|
//eoProportionalOp<EoType> genetic_operator;
|
||||||
|
eoSequentialOp<EoType> genetic_operator;
|
||||||
|
|
||||||
eoSymSubtreeMutate<EoType> submutate(builder, node_selector);
|
eoSymSubtreeMutate<EoType> submutate(builder, node_selector);
|
||||||
genetic_operator.add( submutate, subtree_mut_prob);
|
genetic_operator.add( submutate, subtree_mut_prob);
|
||||||
|
|
||||||
|
// todo, make this parameter, etc
|
||||||
|
double std = 0.01;
|
||||||
|
eoSymConstantMutate<EoType> constmutate(std);
|
||||||
|
genetic_operator.add( constmutate, 0.1);
|
||||||
|
|
||||||
eoSymNodeMutate<EoType> nodemutate(table);
|
eoSymNodeMutate<EoType> nodemutate(table);
|
||||||
genetic_operator.add(nodemutate, node_mut_prob);
|
genetic_operator.add(nodemutate, node_mut_prob);
|
||||||
|
|
||||||
|
|
|
||||||
Reference in a new issue