Ok, made an eoParetoFitness class, which meant that I could roll back a few changes in EO.h (phew).

Also changed eoSelectFromWorth etc.
This commit is contained in:
maartenkeijzer 2001-03-16 12:08:26 +00:00
commit d09c216b61
11 changed files with 215 additions and 110 deletions

View file

@ -4,7 +4,7 @@
## ##
############################################################################### ###############################################################################
SUBDIRS = src test win tutorial app SUBDIRS = src test win app tutorial
#Directory for documents #Directory for documents
DOCDIR = ~/public_html/eodocs DOCDIR = ~/public_html/eodocs
#Directory for indices -- not useful for the user #Directory for indices -- not useful for the user
@ -17,10 +17,6 @@ EXTRA_DIST=LICENSE
lib: lib:
pushd src; $(MAKE) all; popd pushd src; $(MAKE) all; popd
# The test directory should be run explicitely, to check if nothing is broken
test: test/run_tests test/Makefile
pushd test; touch run_tests; $(MAKE) all; ./run_tests; popd
# so that make doc always compiles the doc ... # so that make doc always compiles the doc ...
doc: doc/eo.cfg doc: doc/eo.cfg
pushd doc; $(MAKE) doc; touch eo.cfg; popd pushd doc; $(MAKE) doc; touch eo.cfg; popd

View file

@ -56,8 +56,8 @@ echo
echo "Now type 'make' to compile $PROG." echo "Now type 'make' to compile $PROG."
echo "And if you have Doxygen installed, type 'make doc' to generate $PROG documentation." echo "And if you have Doxygen installed, type 'make doc' to generate $PROG documentation."
echo echo
echo "WARNING: Compiling all test programs can take some time." #echo "WARNING: Compiling all test programs can take some time."
echo "But you don't have to: you can simply type" #echo "But you don't have to: you can simply type"
echo " 'make lib'" #echo " 'make lib'"
echo "and then go in your application dir (or in the tutorial dir)" #echo "and then go in your application dir (or in the tutorial dir)"
echo "and there type 'make'" #echo "and there type 'make'"

View file

@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(src/eo) AC_INIT(src/eo)
dnl Change the version number here dnl Change the version number here
AM_INIT_AUTOMAKE(eo, 0.9.11) AM_INIT_AUTOMAKE(eo, 0.9.2)
dnl Checks for maintainer mode dnl Checks for maintainer mode
AM_MAINTAINER_MODE AM_MAINTAINER_MODE

View file

@ -31,61 +31,6 @@
#include <eoObject.h> // eoObject #include <eoObject.h> // eoObject
#include <eoPersistent.h> // eoPersistent #include <eoPersistent.h> // eoPersistent
/// Functions for reading and writing non-scalar fitnesses, should probably go to seperate file
template <class T>
ostream& print_fitness(ostream& _os, const std::vector<T>& vec)
{
_os << vec.size() << ' ';
std::copy(vec.begin(), vec.end(), ostream_iterator<T>(_os));
return _os;
}
/// Functions for reading and writing non-scalar fitnesses, should probably go to seperate file
template <class T, class U>
ostream& print_fitness(ostream& _os, const std::pair<T, U>& pair)
{
return _os << pair.first << ' ' << pair.second;
}
/// Functions for reading and writing non-scalar fitnesses, should probably go to seperate file
template <class T>
ostream& print_fitness(ostream& _os, const T& t)
{ // general, try operator<<
return _os << t;
}
/// Functions for reading and writing non-scalar fitnesses, should probably go to seperate file
template <class T>
istream& read_fitness(istream& _is, vector<T>& vec)
{
unsigned sz;
_is >> sz;
vec.resize(sz);
for (unsigned i = 0; i < vec.size(); ++i)
{
_is >> vec[i];
}
return _is;
}
/// Functions for reading and writing non-scalar fitnesses, should probably go to seperate file
template <class T, class U>
istream& read_fitness(istream& _is, pair<T, U>& pair)
{
_is >> pair.first;
_is >> pair.second;
return _is;
}
/// Functions for reading and writing non-scalar fitnesses, should probably go to seperate file
template <class T>
istream& read_fitness(istream& _is, T& t)
{
_is >> t;
return _is;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** EO is a base class for evolvable objects, that is, the subjects of /** EO is a base class for evolvable objects, that is, the subjects of
evolution. EOs have only got a fitness, which at the same time needs to be evolution. EOs have only got a fitness, which at the same time needs to be
@ -158,7 +103,7 @@ public:
* @throw runtime_exception If a valid object can't be read. * @throw runtime_exception If a valid object can't be read.
*/ */
virtual void readFrom(istream& _is) { virtual void readFrom(istream& _is) {
read_fitness(_is, repFitness); _is >> repFitness;
if (_is) if (_is)
invalidFitness = false; invalidFitness = false;
else else
@ -173,7 +118,7 @@ public:
if (invalid()) if (invalid())
_os << "INVALID "; _os << "INVALID ";
else else
print_fitness(_os, repFitness) << ' '; // trailing space to make reading in that much easier _os << repFitness << ' '; // trailing space to make reading in that much easier
} }
//@} //@}
@ -186,4 +131,3 @@ private:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#endif EO_H #endif EO_H

View file

@ -62,6 +62,8 @@ class eoDominanceMap : public eoUF<const eoPop<EoType>&, void>, public std::vect
fitnesses.clear(); fitnesses.clear();
} }
bool maximize(unsigned objective) const { return maximizes[objective]; }
/** /**
Update or create the dominance map Update or create the dominance map
*/ */

View file

@ -32,16 +32,25 @@
#include <eoDominanceMap.h> #include <eoDominanceMap.h>
/** /**
Non dominated sorting Non dominated sorting, it *is a* vector of doubles, the integer part is the rank (to which front it belongs),
the fractional part the niching penalty or distance penalty or whatever penalty you want to squeeze into
the bits.
*/ */
template <class EOT> template <class EOT>
class eoNDSorting : public eoPerf2Worth<EOT, double> class eoNDSorting : public eoPerf2Worth<EOT, double>
{ {
public : public :
eoNDSorting(eoDominanceMap<EOT>& _dominanceMap, double _nicheSize) : eoNDSorting(eoDominanceMap<EOT>& _dominanceMap) :
eoPerf2Worth<EOT, double>(), dominanceMap(_dominanceMap), nicheSize(_nicheSize) {} eoPerf2Worth<EOT, double>(), dominanceMap(_dominanceMap) {}
/** Pure virtual function that calculates the 'distance' for each element to the current front
Implement to create your own nondominated sorting algorithm. The size of the returned vector
should be equal to the size of the current_front.
*/
virtual vector<double> niche_penalty(const vector<unsigned>& current_front, const eoPop<EOT>& _pop) = 0;
/// Do the work
void operator()(const eoPop<EOT>& _pop) void operator()(const eoPop<EOT>& _pop)
{ {
dominanceMap(_pop); dominanceMap(_pop);
@ -83,20 +92,20 @@ class eoNDSorting : public eoPerf2Worth<EOT, double>
} }
// Now we have the indices to the current front in current_front, do the niching // Now we have the indices to the current front in current_front, do the niching
vector<double> niche_count = niche_penalty(current_front, _pop);
// As I don't have my reference text with me some homespun savagery if (niche_count.size() != current_front.size())
{
throw logic_error("eoNDSorting: niche and front should have the same size");
}
ranks = dominanceMap.sum_dominants(); // how many do you dominate double max_niche = *max_element(niche_count.begin(), niche_count.end());
double max_rank = *std::max_element(ranks.begin(), ranks.end());
for (unsigned i = 0; i < current_front.size(); ++i) for (unsigned i = 0; i < current_front.size(); ++i)
{ {
// punish the ones that dominate the most individuals (sounds strange huh?) value()[current_front[i]] = dominance_level + niche_count[i] / (max_niche + 1);
value()[current_front[i]] = dominance_level + ranks[i] / (max_rank + 1);
} }
dominance_level++; // go to the next front dominance_level++; // go to the next front
} }
@ -110,10 +119,123 @@ class eoNDSorting : public eoPerf2Worth<EOT, double>
} }
const eoDominanceMap<EOT>& map() const;
private : private :
eoDominanceMap<EOT>& dominanceMap; eoDominanceMap<EOT>& dominanceMap;
};
/**
The original Non Dominated Sorting algorithm from Srinivas and Deb
*/
template <class EOT>
class eoNDSorting_I : public eoNDSorting<EOT>
{
public :
eoNDSorting_I(eoDominanceMap<EOT>& _map, double _nicheSize) : eoNDSorting<EOT>(_map), nicheSize(_nicheSize) {}
vector<double> niche_penalty(const vector<unsigned>& current_front, const eoPop<EOT>& _pop)
{
vector<double> niche_count(current_front.size(), 0.);
for (unsigned i = 0; i < current_front.size(); ++i)
{ // calculate whether the other points lie within the nice
for (unsigned j = 0; j < current_front.size(); ++j)
{
if (i == j)
continue;
double dist = 0.0;
for (unsigned k = 0; k < _pop[current_front[j]].fitness().size(); ++k)
{
double d = _pop[current_front[i]].fitness()[k] - _pop[current_front[j]].fitness()[k];
dist += d*d;
}
if (dist < nicheSize)
{
niche_count[i] += 1.0 - pow(dist / nicheSize,2.);
}
}
}
return niche_count;
}
private :
double nicheSize; double nicheSize;
}; };
/**
Adapted from Deb, Agrawal, Pratab and Meyarivan: A Fast Elitist Non-Dominant Sorting Genetic Algorithm for MultiObjective Optimization: NSGA-II
KanGAL Report No. 200001
Note that this class does not do the sorting per se, but the sorting of it worth_vector will give the right order
The crowding distance is calculated as the sum of the distances to the nearest neighbours. As we need to return the
penalty value, we have to invert that and invert it again in the base class, but such is life, sigh
*/
template <class EOT>
class eoNDSorting_II : public eoNDSorting<EOT>
{
public:
eoNDSorting_II(eoDominanceMap<EOT>& _map) : eoNDSorting<EOT>(_map) {}
typedef std::pair<double, unsigned> double_index_pair;
class compare_nodes
{
public :
bool operator()(const double_index_pair& a, const double_index_pair& b) const
{
return a.first < b.first;
}
};
vector<double> niche_penalty(const vector<unsigned>& _cf, const eoPop<EOT>& _pop)
{
vector<double> niche_count(_cf.size(), 0.);
unsigned nObjectives = _pop[_cf[0]].fitness().size();
for (unsigned o = 0; o < nObjectives; ++o)
{
vector<pair<double, unsigned> > performance(_cf.size());
for (unsigned i =0; i < _cf.size(); ++i)
{
performance[i].first = _pop[_cf[i]].fitness()[o];
performance[i].second = i;
}
sort(performance.begin(), performance.end(), compare_nodes()); // a lambda operator would've been nice here
vector<double> nc(niche_count.size(), 0.0);
for (unsigned i = 1; i < _cf.size()-1; ++i)
{ // and yet another level of indirection
nc[performance[i].second] = performance[i+1].first - performance[i-1].first;
}
double max_dist = *max_element(nc.begin(), nc.end());
// set boundary penalty at 0 (so it will get chosen over all the others
nc[performance[0].second] = 0;
nc[performance.back().second] = 0;
for (unsigned i = 0; i < nc.size(); ++i)
{
niche_count[i] += (max_dist + 1) - nc[i];
}
}
return niche_count;
}
};
#endif #endif

View file

@ -74,8 +74,7 @@ protected:
eoPerf2Worth<EOT, WorthType> & perf2Worth; eoPerf2Worth<EOT, WorthType> & perf2Worth;
#ifndef NDEBUG #ifndef NDEBUG
vector<typename EOT::Fitness> fitness; // for debugging purposes, to check that the perf2worth and pop are in sync std::vector<typename EOT::Fitness> fitness;
void check_sync(unsigned index, const EOT& _eo) void check_sync(unsigned index, const EOT& _eo)
{ {
if (fitness[index] != _eo.fitness()) if (fitness[index] != _eo.fitness())

View file

@ -58,13 +58,15 @@ class eoGnuplot1DSnapshot: public eoFileSnapshot, public eoGnuplot
eoGnuplot1DSnapshot(std::string _dirname, unsigned _frequency = 1, eoGnuplot1DSnapshot(std::string _dirname, unsigned _frequency = 1,
std::string _filename = "gen", std::string _delim = " ") : std::string _filename = "gen", std::string _delim = " ") :
eoFileSnapshot(_dirname, _frequency, _filename, _delim), eoFileSnapshot(_dirname, _frequency, _filename, _delim),
eoGnuplot(_filename,"set data style points") eoGnuplot(_filename,"set data style points"),
pointSize(5)
{} {}
// Ctor // Ctor
eoGnuplot1DSnapshot(eoFileSnapshot & _fSnapshot) : eoGnuplot1DSnapshot(eoFileSnapshot & _fSnapshot) :
eoFileSnapshot(_fSnapshot), eoFileSnapshot(_fSnapshot),
eoGnuplot(_fSnapshot.baseFileName(),"set data style points") eoGnuplot(_fSnapshot.baseFileName(),"set data style points"),
pointSize(5)
{} {}
// Dtor // Dtor
@ -75,7 +77,9 @@ class eoGnuplot1DSnapshot: public eoFileSnapshot, public eoGnuplot
/// Class name. /// Class name.
virtual string className() const { return "eoGnuplot1DSnapshot"; } virtual string className() const { return "eoGnuplot1DSnapshot"; }
unsigned pointSize;
private: private:
}; };
// the following should be placed in a separate eoGnuplot1DMonitor.cpp // the following should be placed in a separate eoGnuplot1DMonitor.cpp
@ -96,7 +100,7 @@ inline eoMonitor& eoGnuplot1DSnapshot::operator() (void)
os << "plot"; os << "plot";
os << " '" << getFileName().c_str() << os << " '" << getFileName().c_str() <<
"' notitle with points ps 5" ; "' notitle with points ps " << pointSize ;
os << "\n"; os << "\n";
os << '\0'; os << '\0';
PipeComSend( gpCom, buff ); PipeComSend( gpCom, buff );

View file

@ -13,9 +13,9 @@ LDADDS = $(top_builddir)/src/utils/libeoutils.a $(top_builddir)/src/libeo.a
CXXFLAGS = -g -Wall CXXFLAGS = -g -Wall
############################################################################### ###############################################################################
check_PROGRAMS = t-eoPareto t-eofitness t-eoRandom t-eobin t-eoStateAndParser t-eoCheckpointing t-eoSSGA \ check_PROGRAMS = t-eoParetoFitness t-eoPareto t-eofitness t-eoRandom t-eobin t-eoStateAndParser t-eoCheckpointing t-eoSSGA \
t-eoExternalEO t-eoSymreg t-eo t-eoReplacement t-eoSelect t-eoGenOp t-eoGA t-eoVector t-eoExternalEO t-eoSymreg t-eo t-eoReplacement t-eoSelect t-eoGenOp t-eoGA t-eoVector
TESTS=run_tests t-eoVector t-eoRandom t-eoSSGA t-eoPareto TESTS=run_tests t-eoVector t-eoRandom t-eoSSGA t-eoPareto t-eoParetoFitness
# removing temporarily t-eoESFull # removing temporarily t-eoESFull
#noinst_PROGRAMS = t-eofitness t-eobin t-eoStateAndParser t-eoCheckpointing t-eoExternalEO t-eoESFull t-eoSymreg t-eo t-eoReplacement t-eoSelect t-eoGenOp t-eoGA #noinst_PROGRAMS = t-eofitness t-eobin t-eoStateAndParser t-eoCheckpointing t-eoExternalEO t-eoESFull t-eoSymreg t-eo t-eoReplacement t-eoSelect t-eoGenOp t-eoGA
@ -128,3 +128,8 @@ t_eoPareto_LDFLAGS = -lm
t_eoPareto_LDADD = $(LDADDS) t_eoPareto_LDADD = $(LDADDS)
############################################################################### ###############################################################################
t_eoParetoFitness_SOURCES = t-eoParetoFitness.cpp
t_eoParetoFitness_DEPENDENCIES = $(DEPS) $(top_builddir)/src/ga/libga.a
t_eoParetoFitness_LDFLAGS = -lm
t_eoParetoFitness_LDADD = $(LDADDS)
###############################################################################

View file

@ -3,20 +3,42 @@
//#include <utils/eoMOFitnessStat.h> //#include <utils/eoMOFitnessStat.h>
#include <eoNDSorting.h> #include <eoNDSorting.h>
#include <eoParetoFitness.h>
using namespace std; using namespace std;
typedef vector<double> fitness_type;
class MinimizingFitnessTraits : public eoParetoFitnessTraits
{
public :
static bool maximizing(int) { return false; }
};
typedef eoParetoFitness<MinimizingFitnessTraits> fitness_type;
const unsigned chromsize=3;
const double minval = -5;
const double maxval = 5;
struct eoDouble : public EO<fitness_type> struct eoDouble : public EO<fitness_type>
{ {
double value; double value[chromsize];
}; };
class Mutate : public eoMonOp<eoDouble> class Mutate : public eoMonOp<eoDouble>
{ {
bool operator()(eoDouble& _eo) bool operator()(eoDouble& _eo)
{ {
_eo.value += rng.normal() * 0.1 * _eo.value; for (unsigned i = 0; i < chromsize; ++i)
{
if (rng.flip(1./10.))
_eo.value[i] += rng.normal() * 0.05 * _eo.value[i];
if (_eo.value[i] < minval)
_eo.value[i] = minval;
else if (_eo.value[i] > maxval)
_eo.value[i] = maxval;
}
return true; return true;
} }
}; };
@ -25,10 +47,18 @@ class Eval : public eoEvalFunc<eoDouble>
{ {
void operator()(eoDouble& _eo) void operator()(eoDouble& _eo)
{ {
double v = _eo.value; vector<double> x(_eo.value, _eo.value + chromsize);
fitness_type f(2); fitness_type f;
f[1] = v * v;
f[0] = (v - 1.) * (v - 1.); for (unsigned i = 0; i < chromsize; ++i)
{
if (i < chromsize-1)
{
f[0] += -10.0 * exp(-0.2 * sqrt(x[i]*x[i] + x[i+1]*x[i+1]));
}
f[1] += pow(fabs(x[i]), 0.8) + 5 * pow(sin(x[i]),3.);
}
_eo.fitness(f); _eo.fitness(f);
} }
@ -38,7 +68,10 @@ class Init : public eoInit<eoDouble>
{ {
void operator()(eoDouble& _eo) void operator()(eoDouble& _eo)
{ {
_eo.value = rng.normal() * 10.; _eo.value[0] = rng.uniform();
for (unsigned i = 1; i < chromsize; ++i)
_eo.value[i] = rng.uniform() * 10. - 5;
_eo.invalidate(); _eo.invalidate();
} }
}; };
@ -51,8 +84,8 @@ void the_main()
Eval eval; Eval eval;
Mutate mutate; Mutate mutate;
unsigned num_gen = 10; unsigned num_gen = 500;
unsigned pop_size = 50; unsigned pop_size = 100;
eoPop<eoDouble> pop(pop_size, init); eoPop<eoDouble> pop(pop_size, init);
vector<bool> maximizes(2, false); // minimize both objectives vector<bool> maximizes(2, false); // minimize both objectives
@ -62,7 +95,8 @@ void the_main()
// Pareto ranking needs a dominance map // Pareto ranking needs a dominance map
//eoParetoRanking<eoDouble> perf2worth(dominance); //eoParetoRanking<eoDouble> perf2worth(dominance);
eoNDSorting<eoDouble> perf2worth(dominance, 0.0); //eoNDSorting_I<eoDouble> perf2worth(dominance, 0.5);
eoNDSorting_II<eoDouble> perf2worth(dominance);
// Three selectors // Three selectors
eoDetTournamentWorthSelect<eoDouble> select1(perf2worth, 3); eoDetTournamentWorthSelect<eoDouble> select1(perf2worth, 3);
@ -78,7 +112,7 @@ void the_main()
eoGeneralBreeder<eoDouble> breeder2(select2, opsel); eoGeneralBreeder<eoDouble> breeder2(select2, opsel);
eoGeneralBreeder<eoDouble> breeder3(select3, opsel); eoGeneralBreeder<eoDouble> breeder3(select3, opsel);
// Comma replacement // replacement
eoCommaReplacement<eoDouble> replace; eoCommaReplacement<eoDouble> replace;
unsigned long generation = 0; unsigned long generation = 0;

View file

@ -1,5 +1,4 @@
EXTRA_DIST=eo_win.dsw eo.dsp esfull.dsp t_eobin.dsp t_eoCheckpointing.dsp t_eofitness.dsp \ EXTRA_DIST=eo.dsw eo.dsp
t_eoFunctor.dsp t_externalEO.dsp t_StateAndParser.dsp t_eoSymreg.dsp