added new multi-objective support
This commit is contained in:
parent
283026ed5c
commit
553586d55f
12 changed files with 1049 additions and 9 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
dnl
|
dnl
|
||||||
dnl Change the version number here
|
dnl Change the version number here
|
||||||
AC_INIT([Evolving Objects], [1.02-cvs1], [eodev-help@sourceforge.net], [eo])
|
AC_INIT([Evolving Objects],[1.02-cvs1],[eodev-help@sourceforge.net],[eo])
|
||||||
AC_PREREQ(2.53)
|
AC_PREREQ(2.60)
|
||||||
|
|
||||||
dnl make sure we are compiling from the correct sources
|
dnl make sure we are compiling from the correct sources
|
||||||
AC_CONFIG_SRCDIR(src/eoOp.h)
|
AC_CONFIG_SRCDIR(src/eoOp.h)
|
||||||
|
|
@ -14,7 +14,7 @@ AC_CANONICAL_TARGET
|
||||||
|
|
||||||
dnl automake initialization
|
dnl automake initialization
|
||||||
AM_INIT_AUTOMAKE([gnu dist-bzip2 dist-zip])
|
AM_INIT_AUTOMAKE([gnu dist-bzip2 dist-zip])
|
||||||
AM_CONFIG_HEADER(config.h)
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
dnl Checks for programs.
|
dnl Checks for programs.
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
|
@ -45,7 +45,7 @@ AC_GNUPLOT
|
||||||
AC_TUTORIAL
|
AC_TUTORIAL
|
||||||
|
|
||||||
dnl create makefiles
|
dnl create makefiles
|
||||||
AC_OUTPUT(Makefile \
|
AC_CONFIG_FILES([Makefile \
|
||||||
app/Makefile \
|
app/Makefile \
|
||||||
app/mastermind/Makefile \
|
app/mastermind/Makefile \
|
||||||
app/gprop/Makefile \
|
app/gprop/Makefile \
|
||||||
|
|
@ -59,6 +59,7 @@ AC_OUTPUT(Makefile \
|
||||||
src/ga/Makefile \
|
src/ga/Makefile \
|
||||||
src/other/Makefile \
|
src/other/Makefile \
|
||||||
src/utils/Makefile \
|
src/utils/Makefile \
|
||||||
|
src/moo/Makefile \
|
||||||
test/Makefile \
|
test/Makefile \
|
||||||
tutorial/Makefile \
|
tutorial/Makefile \
|
||||||
tutorial/html/Makefile \
|
tutorial/html/Makefile \
|
||||||
|
|
@ -69,4 +70,5 @@ AC_OUTPUT(Makefile \
|
||||||
tutorial/Lesson5/Makefile \
|
tutorial/Lesson5/Makefile \
|
||||||
tutorial/Templates/Makefile \
|
tutorial/Templates/Makefile \
|
||||||
tutorial/pdf/Makefile \
|
tutorial/pdf/Makefile \
|
||||||
win/Makefile)
|
win/Makefile])
|
||||||
|
AC_OUTPUT
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Makefile.am for eo/src
|
# Makefile.am for eo/src
|
||||||
|
|
||||||
SUBDIRS = es ga gp do utils other
|
SUBDIRS = es ga gp do utils other moo
|
||||||
|
|
||||||
lib_LIBRARIES = libeo.a
|
lib_LIBRARIES = libeo.a
|
||||||
|
|
||||||
|
|
|
||||||
56
eo/src/moo/CMakeLists.txt
Normal file
56
eo/src/moo/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
######################################################################################
|
||||||
|
### 1) Include the sources
|
||||||
|
######################################################################################
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||||
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
######################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
######################################################################################
|
||||||
|
### 2) Define the ga target
|
||||||
|
######################################################################################
|
||||||
|
|
||||||
|
SET(EOMOO_LIB_OUTPUT_PATH ${EO_BINARY_DIR}/lib)
|
||||||
|
SET(LIBRARY_OUTPUT_PATH ${EOMOO_LIB_OUTPUT_PATH})
|
||||||
|
|
||||||
|
SET (EOMOO_SOURCES eoFrontSorter.cpp )
|
||||||
|
|
||||||
|
|
||||||
|
ADD_LIBRARY(eomoo STATIC ${EOMOO_SOURCES})
|
||||||
|
######################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
######################################################################################
|
||||||
|
### 3) Optionnal
|
||||||
|
######################################################################################
|
||||||
|
|
||||||
|
SET(EOMOO_VERSION "1.0.1")
|
||||||
|
SET_TARGET_PROPERTIES(eomoo PROPERTIES VERSION "${EOMOO_VERSION}")
|
||||||
|
|
||||||
|
######################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
######################################################################################
|
||||||
|
### 4) Windows advanced config - especially for Microsoft Visual Studio 8
|
||||||
|
######################################################################################
|
||||||
|
|
||||||
|
IF(CMAKE_CXX_COMPILER MATCHES cl)
|
||||||
|
IF(NOT WITH_SHARED_LIBS)
|
||||||
|
IF(CMAKE_GENERATOR STREQUAL "Visual Studio 8 2005")
|
||||||
|
SET(CMAKE_CXX_FLAGS "/nologo /W3 /Gy")
|
||||||
|
SET(CMAKE_CXX_FLAGS_DEBUG "/MTd /Z7 /Od")
|
||||||
|
SET(CMAKE_CXX_FLAGS_RELEASE "/MT /O2")
|
||||||
|
SET(CMAKE_CXX_FLAGS_MINSIZEREL "/MT /O2")
|
||||||
|
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MTd /Z7 /Od")
|
||||||
|
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE")
|
||||||
|
|
||||||
|
ENDIF(CMAKE_GENERATOR STREQUAL "Visual Studio 8 2005")
|
||||||
|
ENDIF(NOT WITH_SHARED_LIBS)
|
||||||
|
ENDIF(CMAKE_CXX_COMPILER MATCHES cl)
|
||||||
|
######################################################################################
|
||||||
|
|
||||||
9
eo/src/moo/Makefile.am
Normal file
9
eo/src/moo/Makefile.am
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
lib_LIBRARIES = libeomoo.a
|
||||||
|
|
||||||
|
libeomoo_a_SOURCES = eoFrontSorter.cpp
|
||||||
|
|
||||||
|
pkginclude_HEADERS = eoFrontSorter.h \
|
||||||
|
eoMOFitness.h
|
||||||
|
|
||||||
|
AM_CXXFLAGS = -I$(top_srcdir)/src
|
||||||
156
eo/src/moo/eoFrontSorter.cpp
Normal file
156
eo/src/moo/eoFrontSorter.cpp
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
#include <moo/eoFrontSorter.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct CompareOn {
|
||||||
|
unsigned dim;
|
||||||
|
|
||||||
|
CompareOn(unsigned d) : dim(d) {}
|
||||||
|
|
||||||
|
bool operator()(const FitnessInfo& a, const FitnessInfo& b) {
|
||||||
|
return a.fitness[dim] > b.fitness[dim];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
void one_objective(std::vector<FitnessInfo>& fitness, std::vector< std::vector<FitnessInfo> >& front)
|
||||||
|
{
|
||||||
|
std::sort(fitness.begin(), fitness.end(), CompareOn(0));
|
||||||
|
|
||||||
|
front.clear();
|
||||||
|
front.resize(1);
|
||||||
|
front[0].push_back(fitness[0]);
|
||||||
|
for (unsigned i = 1; i < fitness.size(); ++i) {
|
||||||
|
if (fitness[i].fitness[0] < fitness[i-1].fitness[0]) { // keep clones in same front
|
||||||
|
front.push_back( std::vector<FitnessInfo>() );
|
||||||
|
}
|
||||||
|
|
||||||
|
front.back().push_back( fitness[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimization for two objectives. Makes the algorithm run in
|
||||||
|
* complexity O(n log n) where n is the population size
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void two_objectives(std::vector<FitnessInfo>& fitness, std::vector< std::vector<FitnessInfo> >& front)
|
||||||
|
{
|
||||||
|
std::sort(fitness.begin(), fitness.end(), CompareOn(0));
|
||||||
|
|
||||||
|
front.clear();
|
||||||
|
|
||||||
|
std::vector<FitnessInfo> front_leader;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < fitness.size(); ++i) {
|
||||||
|
|
||||||
|
// find front through binary search
|
||||||
|
vector<FitnessInfo>::iterator it = upper_bound( front_leader.begin(), front_leader.end(), fitness[i], CompareOn(1));
|
||||||
|
|
||||||
|
if (it == front_leader.end()) {
|
||||||
|
front_leader.push_back(fitness[i]);
|
||||||
|
front.push_back( vector<FitnessInfo>(1, fitness[i]) );
|
||||||
|
} else {
|
||||||
|
*it = fitness[i]; // new 'best of front in second dimension'
|
||||||
|
front[ it - front_leader.begin() ].push_back(fitness[i]); // add to front of nth dominated solutions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dominates(const FitnessInfo& a, const FitnessInfo& b) {
|
||||||
|
bool better_on_one = false;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < a.fitness.size(); ++i) {
|
||||||
|
if (a.fitness[i] < b.fitness[i]) return false; // worse on at least one other objective
|
||||||
|
if (a.fitness[i] > b.fitness[i]) better_on_one = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return better_on_one;
|
||||||
|
}
|
||||||
|
|
||||||
|
void m_objectives(std::vector<FitnessInfo>& fitness, std::vector< std::vector<FitnessInfo> >& front) {
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
std::vector<std::vector<unsigned> > S(fitness.size()); // which individuals does guy i dominate
|
||||||
|
std::vector<unsigned> n(fitness.size()); // how many individuals dominate guy i
|
||||||
|
|
||||||
|
unsigned j;
|
||||||
|
for (i = 0; i < fitness.size(); ++i)
|
||||||
|
{
|
||||||
|
for (j = 0; j < fitness.size(); ++j)
|
||||||
|
{
|
||||||
|
if ( dominates(fitness[i], fitness[j]) )
|
||||||
|
{ // i dominates j
|
||||||
|
S[i].push_back(j); // add j to i's domination list
|
||||||
|
}
|
||||||
|
else if (dominates(fitness[j], fitness[i]))
|
||||||
|
{ // j dominates i, increment count for i, add i to the domination list of j
|
||||||
|
n[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
front.clear();
|
||||||
|
front.resize(1);
|
||||||
|
// get the first front out
|
||||||
|
for (i = 0; i < fitness.size(); ++i)
|
||||||
|
{
|
||||||
|
if (n[i] == 0)
|
||||||
|
{
|
||||||
|
front.back().push_back( fitness[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!front.back().empty())
|
||||||
|
{
|
||||||
|
front.push_back(vector<FitnessInfo>());
|
||||||
|
vector<FitnessInfo>& last_front = front[front.size()-2];
|
||||||
|
|
||||||
|
// Calculate which individuals are in the next front;
|
||||||
|
|
||||||
|
for (i = 0; i < last_front.size(); ++i)
|
||||||
|
{
|
||||||
|
for (j = 0; j < S[ last_front[i].index ].size(); ++j)
|
||||||
|
{
|
||||||
|
unsigned dominated_individual = S[ last_front[i].index ][j];
|
||||||
|
n[dominated_individual]--; // As we remove individual i -- being part of the current front -- it no longer dominates j
|
||||||
|
|
||||||
|
if (n[dominated_individual] == 0) // it should be in the current front
|
||||||
|
{
|
||||||
|
front.back().push_back( fitness[dominated_individual] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
front.pop_back(); // last front is empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void front_sorter_impl(std::vector<FitnessInfo>& fitness, std::vector< std::vector<FitnessInfo> >& front_indices) {
|
||||||
|
switch (fitness[0].fitness.size())
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
one_objective(fitness, front_indices);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
two_objectives(fitness, front_indices);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default :
|
||||||
|
{
|
||||||
|
m_objectives(fitness, front_indices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
85
eo/src/moo/eoFrontSorter.h
Normal file
85
eo/src/moo/eoFrontSorter.h
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
eoNDSorting.h
|
||||||
|
(c) Maarten Keijzer, Marc Schoenauer, 2001
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
|
||||||
|
Marc.Schoenauer@polytechnique.fr
|
||||||
|
mkeijzer@dhi.dk
|
||||||
|
*/
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef eoFrontSorter_h
|
||||||
|
#define eoFrontSorter_h
|
||||||
|
|
||||||
|
#include <EO.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <eoPop.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
// small helper structs to store the multi-objective information. To be used in the implementation
|
||||||
|
|
||||||
|
struct FitnessInfo {
|
||||||
|
std::vector<double> fitness; // preprocessed fitness -> all maximizing
|
||||||
|
unsigned index; // index into population
|
||||||
|
|
||||||
|
FitnessInfo() {}
|
||||||
|
FitnessInfo(const std::vector<double>& fitness_, unsigned index_) : fitness(fitness_), index(index_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void front_sorter_impl(std::vector<FitnessInfo>& fitness, std::vector< std::vector<FitnessInfo> >& fronts);
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reassembles population into a set of fronts;
|
||||||
|
*/
|
||||||
|
template <class EOT>
|
||||||
|
class eoFrontSorter : public eoUF< const eoPop<EOT>&, const std::vector< std::vector<detail::FitnessInfo> >& >
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<detail::FitnessInfo > fitness;
|
||||||
|
std::vector< std::vector<detail::FitnessInfo> > fronts;
|
||||||
|
|
||||||
|
public :
|
||||||
|
|
||||||
|
typedef typename EOT::Fitness::fitness_traits Traits;
|
||||||
|
|
||||||
|
typedef std::vector< std::vector<detail::FitnessInfo> > front_t;
|
||||||
|
|
||||||
|
const std::vector<std::vector<detail::FitnessInfo> >& operator()(const eoPop<EOT>& _pop)
|
||||||
|
{
|
||||||
|
fitness.resize(_pop.size());
|
||||||
|
for (unsigned i = 0; i < _pop.size(); ++i) {
|
||||||
|
std::vector<double> f;
|
||||||
|
|
||||||
|
for (unsigned j = 0; j < Traits::nObjectives(); ++j) {
|
||||||
|
if (Traits::maximizing(j) != 0) f.push_back( Traits::maximizing(j) * _pop[i].fitness()[j]);
|
||||||
|
}
|
||||||
|
fitness[i] = detail::FitnessInfo(f, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::front_sorter_impl(fitness, fronts);
|
||||||
|
|
||||||
|
return fronts;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
174
eo/src/moo/eoMOFitness.h
Normal file
174
eo/src/moo/eoMOFitness.h
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// eoMOFitness.h
|
||||||
|
// (c) Maarten Keijzer and Marc Schoenauer, 2007
|
||||||
|
/*
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Contact: mak@dhi.dk
|
||||||
|
Marc.Schoenauer@inria.fr
|
||||||
|
*/
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef _eoMOFitness_h
|
||||||
|
#define _eoMOFitness_h
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eoMOFitnessTraits: a traits class to specify
|
||||||
|
* the number of objectives and which one are maximizing or not
|
||||||
|
* See test/t-eoParetoFitness for its use.
|
||||||
|
*
|
||||||
|
* If you define your own, make sure you make the functions static!
|
||||||
|
*/
|
||||||
|
class eoMOFitnessTraits
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
static unsigned nObjectives() { return 2; }
|
||||||
|
static double maximizing(int which) { return 1; } // by default: all are maximizing, zero will lead to ignored fitness, negative minimizes
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
eoMOFitness class: std::vector of doubles with overloaded comparison operators. Comparison is done
|
||||||
|
on 'worth'. This worth needs to be set elsewhere. The template argument FitnessTraits defaults to eMOFitnessTraits, which
|
||||||
|
can be replaces at will by any other class that implements the static functions defined therein.
|
||||||
|
|
||||||
|
Note that the comparison defines a partial order, so that
|
||||||
|
!(a < b) && !(b <a) does not neccessarily imply that (a==b)
|
||||||
|
The other way around does hold.
|
||||||
|
*/
|
||||||
|
template <class FitnessTraits = eoMOFitnessTraits>
|
||||||
|
class eoMOFitness : public std::vector<double>
|
||||||
|
{
|
||||||
|
double worth; // used for sorting and selection, by definition, bigger is better
|
||||||
|
bool validWorth;
|
||||||
|
public :
|
||||||
|
|
||||||
|
typedef FitnessTraits fitness_traits;
|
||||||
|
|
||||||
|
eoMOFitness(double def = 0.0) : std::vector<double>(FitnessTraits::nObjectives(),def), validWorth(false) {}
|
||||||
|
|
||||||
|
// Ctr from a std::vector<double>
|
||||||
|
eoMOFitness(std::vector<double> & _v) : std::vector<double>(_v), validWorth(false) {}
|
||||||
|
|
||||||
|
/** access to the traits characteristics (so you don't have to write
|
||||||
|
* a lot of typedef's around
|
||||||
|
*/
|
||||||
|
static void setUp(unsigned _n, std::vector<bool> & _b) {FitnessTraits::setUp(_n, _b);}
|
||||||
|
static bool maximizing(unsigned _i) { return FitnessTraits::maximizing(_i);}
|
||||||
|
|
||||||
|
void setWorth(double worth_) {
|
||||||
|
worth = worth_;
|
||||||
|
validWorth = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
double getWorth() const {
|
||||||
|
if (!validWorth) {
|
||||||
|
throw std::runtime_error("invalid worth");
|
||||||
|
}
|
||||||
|
return worth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Partial order based on Pareto-dominance
|
||||||
|
//bool operator<(const eoMOFitness<FitnessTraits>& _other) const
|
||||||
|
bool dominates(const eoMOFitness<FitnessTraits>& _other) const
|
||||||
|
{
|
||||||
|
bool dom = false;
|
||||||
|
|
||||||
|
const std::vector<double>& performance = *this;
|
||||||
|
const std::vector<double>& otherperformance = _other;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < FitnessTraits::nObjectives(); ++i)
|
||||||
|
{
|
||||||
|
double maxim = FitnessTraits::maximizing(i);
|
||||||
|
double aval = maxim * performance[i];
|
||||||
|
double bval = maxim * otherperformance[i];
|
||||||
|
|
||||||
|
if (aval != bval)
|
||||||
|
{
|
||||||
|
if (aval < bval)
|
||||||
|
{
|
||||||
|
return false; // cannot dominate
|
||||||
|
}
|
||||||
|
// else aval < bval
|
||||||
|
dom = true; // for the moment: goto next objective
|
||||||
|
}
|
||||||
|
//else they're equal in this objective, goto next
|
||||||
|
}
|
||||||
|
|
||||||
|
return dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// compare *not* on dominance, but on worth
|
||||||
|
bool operator<(const eoMOFitness<FitnessTraits>& _other) const
|
||||||
|
{
|
||||||
|
return getWorth() > _other.getWorth();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(const eoMOFitness<FitnessTraits>& _other) const
|
||||||
|
{
|
||||||
|
return _other < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<=(const eoMOFitness<FitnessTraits>& _other) const
|
||||||
|
{
|
||||||
|
return getWorth() >= _other.getWorth();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(const eoMOFitness<FitnessTraits>& _other) const
|
||||||
|
{
|
||||||
|
return _other <= *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const eoMOFitness<FitnessTraits>& _other) const
|
||||||
|
{ // check if they're all within tolerance
|
||||||
|
return getWorth() == _other.getWorth();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const eoMOFitness<FitnessTraits>& _other) const
|
||||||
|
{ return ! operator==(_other); }
|
||||||
|
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const eoMOFitness<FitnessTraits>& fitness)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < fitness.size(); ++i)
|
||||||
|
{
|
||||||
|
os << fitness[i] << ' ';
|
||||||
|
}
|
||||||
|
os << fitness.validWorth << ' ' << fitness.worth;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::istream& operator>>(std::istream& is, eoMOFitness<FitnessTraits>& fitness)
|
||||||
|
{
|
||||||
|
fitness = eoMOFitness<FitnessTraits>();
|
||||||
|
for (unsigned i = 0; i < fitness.size(); ++i)
|
||||||
|
{
|
||||||
|
is >> fitness[i];
|
||||||
|
}
|
||||||
|
is >> fitness.validWorth >> fitness.worth;
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
123
eo/src/moo/eoNSGA_II_Replacement.h
Normal file
123
eo/src/moo/eoNSGA_II_Replacement.h
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
#ifndef eoNSGA_II_Replacement_h
|
||||||
|
#define eoNSGA_II_Replacement_h
|
||||||
|
|
||||||
|
#include <moo/eoFrontSorter.h>
|
||||||
|
#include <eoReplacement.h>
|
||||||
|
|
||||||
|
/** @brief Fast Elitist Non-Dominant Sorting Genetic Algorithm
|
||||||
|
|
||||||
|
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_std::vector will give the right order
|
||||||
|
|
||||||
|
*/
|
||||||
|
template <class EOT>
|
||||||
|
class eoNSGA_II_Replacement : public eoReplacement<EOT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void operator()(eoPop<EOT>& parents, eoPop<EOT>& offspring) {
|
||||||
|
unsigned origSize = parents.size();
|
||||||
|
|
||||||
|
std::copy(offspring.begin(), offspring.end(), std::back_inserter(parents));
|
||||||
|
|
||||||
|
typename eoFrontSorter<EOT>::front_t front = sorter(parents);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < front.size(); ++i) {
|
||||||
|
assign_worths(front[i], front.size() - i, parents);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort on worth (assuming eoMOFitness)
|
||||||
|
std::sort(parents.begin(), parents.end());
|
||||||
|
|
||||||
|
// truncate
|
||||||
|
parents.resize(origSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eoFrontSorter<EOT> sorter;
|
||||||
|
|
||||||
|
private:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// _cf points into the elements that consist of the current front
|
||||||
|
void assign_worths(const std::vector<detail::FitnessInfo>& front, unsigned rank, eoPop<EOT>& parents) {
|
||||||
|
|
||||||
|
typedef typename EOT::Fitness::fitness_traits traits;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
unsigned nObjectives = traits::nObjectives(); //_pop[_cf[0]].fitness().size();
|
||||||
|
|
||||||
|
std::vector<double> niche_distance(front.size());
|
||||||
|
|
||||||
|
for (unsigned o = 0; o < nObjectives; ++o)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<std::pair<double, unsigned> > performance(front.size());
|
||||||
|
for (i =0; i < front.size(); ++i)
|
||||||
|
{
|
||||||
|
performance[i].first = front[i].fitness[o];
|
||||||
|
performance[i].second = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(performance.begin(), performance.end(), compare_nodes()); // a lambda operator would've been nice here
|
||||||
|
|
||||||
|
std::vector<double> nc(front.size(), 0.0);
|
||||||
|
|
||||||
|
for (i = 1; i < front.size()-1; ++i)
|
||||||
|
{ // and yet another level of indirection
|
||||||
|
nc[performance[i].second] = performance[i+1].first - performance[i-1].first;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set boundary at max_dist + 1 (so it will get chosen over all the others
|
||||||
|
//nc[performance[0].second] += 0;
|
||||||
|
nc[performance.back().second] += std::numeric_limits<double>::infinity(); // best on objective
|
||||||
|
|
||||||
|
for (i = 0; i < nc.size(); ++i)
|
||||||
|
{
|
||||||
|
niche_distance[i] += nc[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we've got niche_distances, scale them between (0, 1), making sure that infinities get maximum rank
|
||||||
|
|
||||||
|
double max = 0;
|
||||||
|
for (unsigned i = 0; i < niche_distance[i]; ++i) {
|
||||||
|
if (niche_distance[i] != std::numeric_limits<double>::infinity()) {
|
||||||
|
max = std::max(max, niche_distance[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < front.size(); ++i) {
|
||||||
|
double dist = niche_distance[i];
|
||||||
|
if (dist == std::numeric_limits<double>::infinity()) {
|
||||||
|
dist = 1.0;
|
||||||
|
} else {
|
||||||
|
dist /= (1+max);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned idx = front[i].index;
|
||||||
|
|
||||||
|
typename EOT::Fitness f = parents[idx].fitness();
|
||||||
|
f.setWorth(rank + dist);
|
||||||
|
//std::cout << "Base rank " << rank << " dist " << dist << " result " << (rank+dist) << std::endl;
|
||||||
|
|
||||||
|
parents[idx].fitness(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
150
eo/src/moo/eoNSGA_IIa_Replacement.h
Normal file
150
eo/src/moo/eoNSGA_IIa_Replacement.h
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
#ifndef eoNSGA_IIa_Replacement_h
|
||||||
|
#define eoNSGA_IIa_Replacement_h
|
||||||
|
|
||||||
|
#include <moo/eoFrontSorter.h>
|
||||||
|
#include <eoReplacement.h>
|
||||||
|
|
||||||
|
/** @brief Fast Elitist Non-Dominant Sorting Genetic Algorithm
|
||||||
|
|
||||||
|
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_std::vector will give the right order
|
||||||
|
|
||||||
|
*/
|
||||||
|
template <class EOT>
|
||||||
|
class eoNSGA_IIa_Replacement : public eoReplacement<EOT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void operator()(eoPop<EOT>& parents, eoPop<EOT>& offspring) {
|
||||||
|
unsigned origSize = parents.size();
|
||||||
|
|
||||||
|
std::copy(offspring.begin(), offspring.end(), std::back_inserter(parents));
|
||||||
|
|
||||||
|
typename eoFrontSorter<EOT>::front_t front = sorter(parents);
|
||||||
|
|
||||||
|
unsigned rank = parents.size();
|
||||||
|
for (unsigned i = 0; i < front.size(); ++i) {
|
||||||
|
rank = assign_worths(front[i], rank, parents);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort on worth (assuming eoMOFitness)
|
||||||
|
std::sort(parents.begin(), parents.end());
|
||||||
|
|
||||||
|
// truncate
|
||||||
|
parents.resize(origSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
eoFrontSorter<EOT> sorter;
|
||||||
|
|
||||||
|
double distance(const std::vector<double>& f1, const std::vector<double>& f2, const std::vector<double>& range) {
|
||||||
|
double dist = 0;
|
||||||
|
for (unsigned i = 0; i < f1.size(); ++i) {
|
||||||
|
double d = (f1[i] - f2[i])/range[i];
|
||||||
|
dist += d*d;
|
||||||
|
}
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned assign_worths(const std::vector<detail::FitnessInfo>& front, unsigned rank, eoPop<EOT>& parents) {
|
||||||
|
|
||||||
|
unsigned nDim = front[0].fitness.size();
|
||||||
|
|
||||||
|
// find boundary points
|
||||||
|
std::vector<unsigned> processed(nDim);
|
||||||
|
|
||||||
|
for (unsigned i = 1; i < front.size(); ++i) {
|
||||||
|
for (unsigned dim = 0; dim < nDim; ++dim) {
|
||||||
|
if (front[i].fitness[dim] > front[processed[dim]].fitness[dim]) {
|
||||||
|
processed[dim] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign fitness to processed
|
||||||
|
for (unsigned i = 0; i < processed.size(); ++i) {
|
||||||
|
typename EOT::Fitness f = parents[ front[ processed[i] ].index].fitness();
|
||||||
|
f.setWorth(rank);
|
||||||
|
parents[ front[ processed[i] ].index ].fitness(f);
|
||||||
|
}
|
||||||
|
rank--;
|
||||||
|
|
||||||
|
// calculate ranges
|
||||||
|
std::vector<double> mins(nDim, std::numeric_limits<double>::infinity());
|
||||||
|
for (unsigned dim = 0; dim < nDim; ++dim) {
|
||||||
|
for (unsigned i = 0; i < nDim; ++i) {
|
||||||
|
mins[dim] = std::min( mins[dim], front[ processed[i] ].fitness[dim] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> range(nDim);
|
||||||
|
for (unsigned dim = 0; dim < nDim; ++dim) {
|
||||||
|
range[dim] = front[ processed[dim] ].fitness[dim] - mins[dim];
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate distances
|
||||||
|
std::vector<double> distances(front.size(), std::numeric_limits<double>::infinity());
|
||||||
|
|
||||||
|
unsigned selected = 0;
|
||||||
|
// select based on maximum distance to nearest processed point
|
||||||
|
for (unsigned i = 0; i < front.size(); ++i) {
|
||||||
|
|
||||||
|
for (unsigned k = 0; k < processed.size(); ++k) {
|
||||||
|
|
||||||
|
if (i==processed[k]) {
|
||||||
|
distances[i] = -1.0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double d = distance( front[i].fitness, front[ processed[k] ].fitness, range );
|
||||||
|
|
||||||
|
if (d < distances[i]) {
|
||||||
|
distances[i] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distances[i] > distances[selected]) {
|
||||||
|
selected = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while (processed.size() < front.size()) {
|
||||||
|
|
||||||
|
// set worth
|
||||||
|
typename EOT::Fitness f = parents[ front[selected].index ].fitness();
|
||||||
|
f.setWorth(rank--);
|
||||||
|
parents[ front[selected].index ].fitness(f);
|
||||||
|
distances[selected] = -1;
|
||||||
|
|
||||||
|
processed.push_back(selected);
|
||||||
|
|
||||||
|
selected = 0;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < front.size(); ++i) {
|
||||||
|
if (distances[i] < 0) continue;
|
||||||
|
|
||||||
|
double d = distance(front[i].fitness, front[processed.back()].fitness, range);
|
||||||
|
|
||||||
|
if (d < distances[i]) {
|
||||||
|
distances[i] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distances[i] > distances[selected]) {
|
||||||
|
selected = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return rank;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
75
eo/src/moo/eoNSGA_I_Replacement.h
Normal file
75
eo/src/moo/eoNSGA_I_Replacement.h
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
#ifndef __EONDSorting_I_h
|
||||||
|
#define __EONDSorting_I_h
|
||||||
|
|
||||||
|
#include <moo/eoFrontSorter.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
The original Non Dominated Sorting algorithm from Srinivas and Deb
|
||||||
|
*/
|
||||||
|
template <class EOT>
|
||||||
|
class eoNSGA_I_Replacement : public eoReplacement<EOT>
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
eoNSGA_I_Replacement(double _nicheSize) : nicheSize(_nicheSize) {}
|
||||||
|
|
||||||
|
void operator()(eoPop<EOT>& parents, eoPop<EOT>& offspring) {
|
||||||
|
|
||||||
|
unsigned origSize = parents.size();
|
||||||
|
|
||||||
|
std::copy(offspring.begin(), offspring.end(), std::back_inserter(parents));
|
||||||
|
|
||||||
|
typename eoFrontSorter<EOT>::front_t front = sorter(parents);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < front.size(); ++i) {
|
||||||
|
assign_worths(front[i], front.size() - i, parents);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort on worth (assuming eoMOFitness)
|
||||||
|
std::sort(parents.begin(), parents.end());
|
||||||
|
|
||||||
|
// truncate
|
||||||
|
parents.resize(origSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void assign_worths(const std::vector<detail::FitnessInfo>& front, unsigned rank, eoPop<EOT>& parents) {
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < front.size(); ++i)
|
||||||
|
{ // calculate whether the other points lie within the nice
|
||||||
|
double niche_count = 0;
|
||||||
|
|
||||||
|
for (unsigned j = 0; j < front.size(); ++j)
|
||||||
|
{
|
||||||
|
if (i == j)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double dist = 0.0;
|
||||||
|
|
||||||
|
for (unsigned k = 0; k < front[j].fitness.size(); ++k)
|
||||||
|
{
|
||||||
|
double d = front[i].fitness[k] - front[j].fitness[k];
|
||||||
|
dist += d*d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dist < nicheSize)
|
||||||
|
{
|
||||||
|
niche_count += 1.0 - pow(dist / nicheSize,2.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned idx = front[i].index;
|
||||||
|
typename EOT::Fitness f = parents[idx].fitness();
|
||||||
|
f.setWorth(rank + niche_count);
|
||||||
|
parents[ idx ].fitness(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
double nicheSize;
|
||||||
|
eoFrontSorter<EOT> sorter;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
## Makefile.am for eo/test
|
## Makefile.am for eo/test
|
||||||
##
|
##
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
LIBEO = $(top_builddir)/src/libeo.a
|
LIBEO = $(top_builddir)/src/libeo.a
|
||||||
LIBEOUTILS = $(top_builddir)/src/utils/libeoutils.a
|
LIBEOUTILS = $(top_builddir)/src/utils/libeoutils.a
|
||||||
LIBES = $(top_builddir)/src/es/libes.a
|
LIBES = $(top_builddir)/src/es/libes.a
|
||||||
LIBGA = $(top_builddir)/src/ga/libga.a
|
LIBGA = $(top_builddir)/src/ga/libga.a
|
||||||
LIBCMA = $(top_builddir)/src/es/libcma.a
|
LIBCMA = $(top_builddir)/src/es/libcma.a
|
||||||
|
LIBMOO = $(top_builddir)/src/moo/libeomoo.a
|
||||||
|
|
||||||
# PLEASE don't break the line (see create_batch.sh)
|
# PLEASE don't break the line (see create_batch.sh)
|
||||||
check_PROGRAMS = t-eoParetoFitness \
|
check_PROGRAMS = t-eoParetoFitness \
|
||||||
|
|
@ -41,7 +41,9 @@ check_PROGRAMS = t-eoParetoFitness \
|
||||||
t-eoCMAES \
|
t-eoCMAES \
|
||||||
t-eoSecondsElapsedContinue\
|
t-eoSecondsElapsedContinue\
|
||||||
t-eoRNG \
|
t-eoRNG \
|
||||||
t-eoEasyPSO
|
t-eoEasyPSO \
|
||||||
|
t-eoNSGA \
|
||||||
|
t-eoFrontSorter
|
||||||
|
|
||||||
TESTS = $(check_PROGRAMS) \
|
TESTS = $(check_PROGRAMS) \
|
||||||
run_tests # This script can be used to check command-line arguments
|
run_tests # This script can be used to check command-line arguments
|
||||||
|
|
@ -49,7 +51,7 @@ TESTS = $(check_PROGRAMS) \
|
||||||
noinst_HEADERS = binary_value.h real_value.h RoyalRoad.h
|
noinst_HEADERS = binary_value.h real_value.h RoyalRoad.h
|
||||||
|
|
||||||
|
|
||||||
DEPS = $(LIBGA) $(LIBES) $(LIBCMA) $(LIBEOUTILS) $(LIBEO)
|
DEPS = $(LIBGA) $(LIBES) $(LIBCMA) $(LIBEOUTILS) $(LIBEO) $(LIBMOO)
|
||||||
INCLUDES = -I$(top_srcdir)/src -I$(srcdir)/../src
|
INCLUDES = -I$(top_srcdir)/src -I$(srcdir)/../src
|
||||||
LIBS = $(DEPS)
|
LIBS = $(DEPS)
|
||||||
|
|
||||||
|
|
@ -96,3 +98,6 @@ t_eoCMAES_SOURCES = t-eoCMAES.cpp
|
||||||
t_eoRNG_SOURCES = t-eoRNG.cpp
|
t_eoRNG_SOURCES = t-eoRNG.cpp
|
||||||
t_eoSecondsElapsedContinue_SOURCES = t-eoSecondsElapsedContinue.cpp
|
t_eoSecondsElapsedContinue_SOURCES = t-eoSecondsElapsedContinue.cpp
|
||||||
t_eoEasyPSO_SOURCES = t-eoEasyPSO.cpp
|
t_eoEasyPSO_SOURCES = t-eoEasyPSO.cpp
|
||||||
|
t_eoNSGA_SOURCES = t-eoNSGA.cpp
|
||||||
|
t_eoFrontSorter_SOURCES = t-eoFrontSorter.cpp
|
||||||
|
|
||||||
|
|
|
||||||
205
eo/test/t-eoNSGA.cpp
Normal file
205
eo/test/t-eoNSGA.cpp
Normal file
|
|
@ -0,0 +1,205 @@
|
||||||
|
|
||||||
|
#include <eo>
|
||||||
|
|
||||||
|
#include <moo/eoMOFitness.h>
|
||||||
|
#include <moo/eoNSGA_I_Replacement.h>
|
||||||
|
#include <moo/eoNSGA_II_Replacement.h>
|
||||||
|
#include <moo/eoNSGA_IIa_Replacement.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Look: overloading the maximization without overhead (thing can be inlined)
|
||||||
|
class MinimizingFitnessTraits : public eoMOFitnessTraits
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
static double maximizing(int) { return -1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef eoMOFitness<MinimizingFitnessTraits> fitness_type;
|
||||||
|
|
||||||
|
const unsigned chromsize=5;
|
||||||
|
const double minval = -15;
|
||||||
|
const double maxval = 15;
|
||||||
|
|
||||||
|
struct eoDouble : public EO<fitness_type>
|
||||||
|
{
|
||||||
|
double value[chromsize];
|
||||||
|
};
|
||||||
|
|
||||||
|
class Mutate : public eoMonOp<eoDouble>
|
||||||
|
{
|
||||||
|
bool operator()(eoDouble& _eo)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < chromsize; ++i)
|
||||||
|
{
|
||||||
|
if (rng.flip(1./chromsize))
|
||||||
|
_eo.value[i] += rng.normal() * 0.1 * _eo.value[i];
|
||||||
|
|
||||||
|
if (_eo.value[i] < minval)
|
||||||
|
_eo.value[i] = minval;
|
||||||
|
else if (_eo.value[i] > maxval)
|
||||||
|
_eo.value[i] = maxval;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Eval : public eoEvalFunc<eoDouble>
|
||||||
|
{
|
||||||
|
void operator()(eoDouble& _eo)
|
||||||
|
{
|
||||||
|
vector<double> x(_eo.value, _eo.value + chromsize);
|
||||||
|
fitness_type f;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Eval2 : public eoEvalFunc<eoDouble>
|
||||||
|
{
|
||||||
|
void operator()(eoDouble& _eo)
|
||||||
|
{
|
||||||
|
vector<double> x(_eo.value, _eo.value + chromsize);
|
||||||
|
fitness_type f;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < chromsize; ++i)
|
||||||
|
{
|
||||||
|
f[0] += x[i] * x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
f[1] =
|
||||||
|
3 * x[0] + 2 * x[1]
|
||||||
|
- x[2]/3 + 0.01*pow(x[3] - x[4], 3);
|
||||||
|
|
||||||
|
_eo.fitness(f);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Eval3 : public eoEvalFunc<eoDouble>
|
||||||
|
{
|
||||||
|
void operator()(eoDouble& _eo)
|
||||||
|
{
|
||||||
|
double x = _eo.value[0];
|
||||||
|
fitness_type f;
|
||||||
|
|
||||||
|
f[0] = x * x;
|
||||||
|
double y = x-10;
|
||||||
|
f[1] = y * y;
|
||||||
|
|
||||||
|
_eo.fitness(f);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Init : public eoInit<eoDouble>
|
||||||
|
{
|
||||||
|
void operator()(eoDouble& _eo)
|
||||||
|
{
|
||||||
|
_eo.value[0] = rng.uniform();
|
||||||
|
|
||||||
|
double range = maxval - minval;
|
||||||
|
|
||||||
|
for (unsigned i = 1; i < chromsize; ++i)
|
||||||
|
_eo.value[i] = rng.uniform() * range + minval;
|
||||||
|
_eo.invalidate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test pareto dominance and perf2worth, and while you're at it, test the eoGnuPlot monitor as well
|
||||||
|
void the_main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
Init init;
|
||||||
|
Eval eval;
|
||||||
|
Mutate mutate;
|
||||||
|
|
||||||
|
eoParser parser(argc, argv);
|
||||||
|
eoState state;
|
||||||
|
|
||||||
|
unsigned num_gen = parser.createParam(unsigned(50), "num_gen", "number of generations to run", 'g').value();
|
||||||
|
unsigned pop_size = parser.createParam(unsigned(100), "pop_size", "population size", 'p').value();
|
||||||
|
bool use_nsga1 = parser.createParam(false, "nsga1", "Use nsga 1").value();
|
||||||
|
|
||||||
|
eoPop<eoDouble> pop(pop_size, init);
|
||||||
|
|
||||||
|
// binary tournament selection
|
||||||
|
eoDetTournamentSelect<eoDouble> select;
|
||||||
|
|
||||||
|
// One general operator
|
||||||
|
eoProportionalOp<eoDouble> opsel;
|
||||||
|
opsel.add(mutate, 1.0);
|
||||||
|
|
||||||
|
// the breeder
|
||||||
|
eoGeneralBreeder<eoDouble> breeder(select, opsel);
|
||||||
|
|
||||||
|
// replacement
|
||||||
|
eoNSGA_IIa_Replacement<eoDouble> nsga1;
|
||||||
|
eoNSGA_II_Replacement<eoDouble> nsga2;
|
||||||
|
eoReplacement<eoDouble>& replace = use_nsga1 ? static_cast<eoReplacement<eoDouble>&>(nsga1) : static_cast<eoReplacement<eoDouble>&>(nsga2);
|
||||||
|
|
||||||
|
unsigned long generation = 0;
|
||||||
|
eoGenContinue<eoDouble> gen(num_gen, generation);
|
||||||
|
eoCheckPoint<eoDouble> cp(gen);
|
||||||
|
|
||||||
|
eoMOFitnessStat<eoDouble> fitness0(0, "FirstObjective");
|
||||||
|
eoMOFitnessStat<eoDouble> fitness1(1, "SecondObjective");
|
||||||
|
|
||||||
|
cp.add(fitness0);
|
||||||
|
cp.add(fitness1);
|
||||||
|
|
||||||
|
eoGnuplot1DSnapshot snapshot("pareto");
|
||||||
|
//snapshot.with(eoGnuplot::Points(3));
|
||||||
|
|
||||||
|
cp.add(snapshot);
|
||||||
|
|
||||||
|
snapshot.add(fitness0);
|
||||||
|
snapshot.add(fitness1);
|
||||||
|
|
||||||
|
// the algo
|
||||||
|
eoEasyEA<eoDouble> ea(cp, eval, breeder, replace);
|
||||||
|
|
||||||
|
if (parser.userNeedsHelp())
|
||||||
|
{
|
||||||
|
parser.printHelp(std::cout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply<eoDouble>(eval, pop);
|
||||||
|
|
||||||
|
eoPop<eoDouble> nothing;
|
||||||
|
replace(pop, nothing); // calculates worths
|
||||||
|
|
||||||
|
ea(pop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
the_main(argc, argv);
|
||||||
|
return 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
the_main(argc, argv);
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "Exception thrown: " << e.what() << std::endl;
|
||||||
|
throw e; // make sure it does not pass the test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Local Variables:
|
||||||
|
// mode: C++
|
||||||
|
// c-file-style: "Stroustrup"
|
||||||
|
// End:
|
||||||
Reference in a new issue