1
0
mirror of https://github.com/paboyle/Grid.git synced 2025-04-09 21:50:45 +01:00

Hadrons: genetic scheduler improvement

This commit is contained in:
Antonin Portelli 2016-12-07 09:00:45 +09:00
parent 49c3eeb378
commit 51322da6f8
2 changed files with 102 additions and 52 deletions

View File

@ -61,10 +61,12 @@ public:
friend std::ostream & operator<<(std::ostream &out, friend std::ostream & operator<<(std::ostream &out,
const GeneticScheduler<T> &s) const GeneticScheduler<T> &s)
{ {
out << "[";
for (auto &p: s.population_) for (auto &p: s.population_)
{ {
out << p.second << ": " << p.first << std::endl; out << p.first << ", ";
} }
out << "\b\b]";
return out; return out;
} }
@ -72,10 +74,10 @@ private:
// randomly initialize population // randomly initialize population
void initPopulation(void); void initPopulation(void);
// genetic operators // genetic operators
const std::vector<T> & selection(void); std::vector<T> * select1(void);
void crossover(const std::vector<T> &c1, std::pair<std::vector<T> *, std::vector<T> *> select2(void);
const std::vector<T> &c2); void crossover(void);
void mutation(std::vector<T> &c); void mutation(void);
private: private:
Graph<T> &graph_; Graph<T> &graph_;
const ObjFunc &func_; const ObjFunc &func_;
@ -115,38 +117,35 @@ int GeneticScheduler<T>::getMinValue(void)
template <typename T> template <typename T>
void GeneticScheduler<T>::nextGeneration(void) void GeneticScheduler<T>::nextGeneration(void)
{ {
std::uniform_real_distribution<double> dis(0., 1.);
// random initialization of the population if necessary // random initialization of the population if necessary
if (population_.size() != par_.popSize) if (population_.size() != par_.popSize)
{ {
initPopulation(); initPopulation();
} }
LOG(Debug) << "Starting population:\n" << *this << std::endl;
// mating
for (unsigned int i = 0; i < par_.popSize/2; ++i)
{
auto &p1 = selection(), &p2 = selection();
crossover(p1, p2);
}
// random mutations // random mutations
auto buf = population_; PARALLEL_FOR_LOOP
population_.clear(); for (unsigned int i = 0; i < par_.popSize; ++i)
for (auto &c: buf)
{ {
if (dis(gen_) < par_.mutationRate) mutation();
{
mutation(c.second);
}
population_.emplace(func_(c.second), c.second);
} }
LOG(Debug) << "After mutations:\n" << *this << std::endl;
// mating
PARALLEL_FOR_LOOP
for (unsigned int i = 0; i < par_.popSize/2; ++i)
{
crossover();
}
LOG(Debug) << "After mating:\n" << *this << std::endl;
// grim reaper // grim reaper
auto it = population_.begin(); auto it = population_.begin();
std::advance(it, par_.popSize); std::advance(it, par_.popSize);
population_.erase(it, population_.end()); population_.erase(it, population_.end());
LOG(Debug) << "After grim reaper:\n" << *this << std::endl;
} }
// randomly initialize population ////////////////////////////////////////////// // randomly initialize population //////////////////////////////////////////////
@ -164,37 +163,66 @@ void GeneticScheduler<T>::initPopulation(void)
// genetic operators /////////////////////////////////////////////////////////// // genetic operators ///////////////////////////////////////////////////////////
template <typename T> template <typename T>
const std::vector<T> & GeneticScheduler<T>::selection(void) std::vector<T> * GeneticScheduler<T>::select1(void)
{
std::uniform_int_distribution<unsigned int> pdis(0, population_.size() - 1);
auto it = population_.begin();
std::advance(it, pdis(gen_));
return &(it->second);
}
template <typename T>
std::pair<std::vector<T> *, std::vector<T> *> GeneticScheduler<T>::select2(void)
{ {
std::vector<double> prob; std::vector<double> prob;
unsigned int ind;
std::vector<T> *p1, *p2;
for (auto &c: population_) for (auto &c: population_)
{ {
prob.push_back(1./c.first); prob.push_back(1./c.first);
} }
std::discrete_distribution<unsigned int> dis(prob.begin(), prob.end()); do
auto rIt = population_.begin(); {
std::advance(rIt, dis(gen_)); double probCpy;
std::discrete_distribution<unsigned int> dis1(prob.begin(), prob.end());
auto rIt = population_.begin();
ind = dis1(gen_);
std::advance(rIt, ind);
p1 = &(rIt->second);
probCpy = prob[ind];
prob[ind] = 0.;
std::discrete_distribution<unsigned int> dis2(prob.begin(), prob.end());
rIt = population_.begin();
std::advance(rIt, dis2(gen_));
p2 = &(rIt->second);
prob[ind] = probCpy;
} while (p1 == p2);
return rIt->second; return std::make_pair(p1, p2);
} }
template <typename T> template <typename T>
void GeneticScheduler<T>::crossover(const std::vector<T> &p1, void GeneticScheduler<T>::crossover(void)
const std::vector<T> &p2)
{ {
std::uniform_int_distribution<unsigned int> dis(0, p1.size() - 1); auto p = select2();
unsigned int cut = dis(gen_); auto &p1 = *(p.first),
&p2 = *(p.second);
std::uniform_int_distribution<unsigned int> dis2(0, p1.size() - 1);
unsigned int cut = dis2(gen_);
std::vector<T> c1, c2, buf; std::vector<T> c1, c2, buf;
auto cross = [&buf, cut](std::vector<T> &c, const std::vector<T> &p1, auto cross = [&buf, cut](std::vector<T> &c, const std::vector<T> &p1,
const std::vector<T> &p2) const std::vector<T> &p2)
{ {
buf = p2; buf = p1;
for (unsigned int i = 0; i < cut; ++i) for (unsigned int i = 0; i < cut; ++i)
{ {
c.push_back(p1[i]); c.push_back(p2[i]);
buf.erase(std::find(buf.begin(), buf.end(), p1[i])); buf.erase(std::find(buf.begin(), buf.end(), p2[i]));
} }
for (unsigned int i = 0; i < buf.size(); ++i) for (unsigned int i = 0; i < buf.size(); ++i)
{ {
@ -204,31 +232,51 @@ void GeneticScheduler<T>::crossover(const std::vector<T> &p1,
cross(c1, p1, p2); cross(c1, p1, p2);
cross(c2, p2, p1); cross(c2, p2, p1);
population_.emplace(func_(c1), c1); PARALLEL_CRITICAL
population_.emplace(func_(c2), c2); {
population_.emplace(func_(c1), c1);
population_.emplace(func_(c2), c2);
}
} }
template <typename T> template <typename T>
void GeneticScheduler<T>::mutation(std::vector<T> &c) void GeneticScheduler<T>::mutation(void)
{ {
std::uniform_int_distribution<unsigned int> dis(0, c.size() - 1); std::uniform_real_distribution<double> mdis(0., 1.);
unsigned int cut = dis(gen_);
Graph<T> g = graph_;
std::vector<T> buf;
for (unsigned int i = cut; i < c.size(); ++i) if (mdis(gen_) < par_.mutationRate)
{ {
g.removeVertex(c[i]); auto &c = *select1();
std::uniform_int_distribution<unsigned int> cdis(0, c.size() - 1);
unsigned int cut = cdis(gen_);
std::vector<T> buf1, buf2;
Graph<T> g1 = graph_, g2 = graph_;
for (unsigned int i = 0; i < cut; ++i)
{
g1.removeVertex(c[i]);
}
for (unsigned int i = cut; i < c.size(); ++i)
{
g2.removeVertex(c[i]);
}
if (g1.size() > 0)
{
buf1 = g1.topoSort(gen_);
}
if (g2.size() > 0)
{
buf2 = g2.topoSort(gen_);
}
for (unsigned int i = cut; i < c.size(); ++i)
{
buf2.push_back(buf1[i - cut]);
}
PARALLEL_CRITICAL
{
population_.emplace(func_(buf2), buf2);
}
} }
if (g.size() > 0)
{
buf = g.topoSort(gen_);
}
for (unsigned int i = cut; i < c.size(); ++i)
{
buf.push_back(c[i]);
}
c = buf;
} }
END_HADRONS_NAMESPACE END_HADRONS_NAMESPACE

View File

@ -46,11 +46,13 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
#endif #endif
#define PARALLEL_NESTED_LOOP2 _Pragma("omp parallel for collapse(2)") #define PARALLEL_NESTED_LOOP2 _Pragma("omp parallel for collapse(2)")
#define PARALLEL_REGION _Pragma("omp parallel") #define PARALLEL_REGION _Pragma("omp parallel")
#define PARALLEL_CRITICAL _Pragma("omp critical")
#else #else
#define PARALLEL_FOR_LOOP #define PARALLEL_FOR_LOOP
#define PARALLEL_FOR_LOOP_INTERN #define PARALLEL_FOR_LOOP_INTERN
#define PARALLEL_NESTED_LOOP2 #define PARALLEL_NESTED_LOOP2
#define PARALLEL_REGION #define PARALLEL_REGION
#define PARALLEL_CRITICAL
#endif #endif
namespace Grid { namespace Grid {