New crossover features: Order, Bounds, Standard deviation
This commit is contained in:
parent
cb0f81b3e1
commit
62ab4f9a16
107
Breeder.cpp
107
Breeder.cpp
@ -29,23 +29,51 @@ namespace BitEvolver
|
|||||||
std::shared_ptr<Chromosome> mama,
|
std::shared_ptr<Chromosome> mama,
|
||||||
std::shared_ptr<Chromosome> papa,
|
std::shared_ptr<Chromosome> papa,
|
||||||
Enums::CrossoverType crossover_type,
|
Enums::CrossoverType crossover_type,
|
||||||
double crossover_rate,
|
Enums::CrossoverOrder crossover_order,
|
||||||
|
Enums::CrossoverBounds crossover_bounds,
|
||||||
|
double crossover_point,
|
||||||
|
double crossover_point_std,
|
||||||
double mutation_rate
|
double mutation_rate
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
std::shared_ptr<Chromosome> kiddo;
|
std::shared_ptr<Chromosome>
|
||||||
int bit_length;
|
parent_primary,
|
||||||
|
parent_secondary,
|
||||||
|
kiddo
|
||||||
|
;
|
||||||
|
|
||||||
//
|
// Choose primary / secondary parents
|
||||||
bit_length = mama->GetBitCount();
|
switch( crossover_order )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
case Enums::CrossoverOrder::MamaPapa:
|
||||||
|
parent_primary = mama;
|
||||||
|
parent_secondary = papa;
|
||||||
|
break;
|
||||||
|
|
||||||
// Directly copy the mama
|
//
|
||||||
kiddo = std::shared_ptr<Chromosome>(new Chromosome(this->random, bit_length));
|
case Enums::CrossoverOrder::ByFitness:
|
||||||
*kiddo = *mama;
|
if ( mama->GetFitness() > papa->GetFitness() ) {
|
||||||
|
parent_primary = mama;
|
||||||
|
parent_secondary = papa;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
parent_primary = papa;
|
||||||
|
parent_secondary = mama;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Apply crossover
|
// Directly copy the primary parent first
|
||||||
this->ApplyCrossover(kiddo, papa, crossover_type, crossover_rate);
|
kiddo = std::shared_ptr<Chromosome>(new Chromosome(this->random, parent_primary->GetBitCount()));
|
||||||
|
*kiddo = *parent_primary;
|
||||||
|
|
||||||
|
// Apply crossover with the secondary parent
|
||||||
|
this->ApplyCrossover(
|
||||||
|
kiddo, parent_secondary,
|
||||||
|
crossover_type, crossover_bounds, crossover_point, crossover_point_std
|
||||||
|
);
|
||||||
|
|
||||||
// Apply mutation
|
// Apply mutation
|
||||||
this->Mutate(kiddo, mutation_rate);
|
this->Mutate(kiddo, mutation_rate);
|
||||||
@ -80,39 +108,56 @@ namespace BitEvolver
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
int Breeder::PickRandomCrossoverPoint(std::shared_ptr<Chromosome> chromosome, double crossover_rate)
|
int Breeder::PickRandomCrossoverPoint(
|
||||||
|
std::shared_ptr<Chromosome> chromosome,
|
||||||
|
Enums::CrossoverBounds crossover_bounds,
|
||||||
|
double crossover_point,
|
||||||
|
double crossover_point_std
|
||||||
|
)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
double crossover_point_double;
|
int crossover_point_index;
|
||||||
int crossover_point;
|
|
||||||
int bit_count;
|
int bit_count;
|
||||||
|
double random_double;
|
||||||
|
|
||||||
//
|
//
|
||||||
bit_count = chromosome->GetBitCount();
|
bit_count = chromosome->GetBitCount();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Choose a double between [0.0,1.0] for the crossover point.
|
Choose a double between [0.0,1.0] for the crossover point.
|
||||||
Use normal distribution, with the mean to the default point,
|
Use normal distribution, with the mean and std from the parameters.
|
||||||
and 1.0 as the std.
|
|
||||||
That way, there is still randomness to the crossover point,
|
That way, there is still randomness to the crossover point,
|
||||||
but it still generally sticks near the default
|
but it still generally sticks near the chosen point.
|
||||||
*/
|
*/
|
||||||
crossover_point_double = this->random->GetNormal(crossover_rate, 1.0);
|
random_double = this->random->GetNormal(crossover_point, crossover_point_std);
|
||||||
|
|
||||||
// Apply to the actual int length
|
// Apply to the actual int length
|
||||||
crossover_point = crossover_point_double * bit_count;
|
crossover_point_index = floor(random_double * bit_count);
|
||||||
|
|
||||||
// Loop around to keep in bounds
|
// Loop around to keep in bounds?
|
||||||
while ( crossover_point < 0 )
|
if ( crossover_bounds == Enums::CrossoverBounds::Wrap ) {
|
||||||
{
|
while ( crossover_point_index < 0 )
|
||||||
crossover_point += bit_count;
|
{
|
||||||
|
crossover_point_index += bit_count;
|
||||||
|
}
|
||||||
|
while ( crossover_point_index >= bit_count)
|
||||||
|
{
|
||||||
|
crossover_point_index -= bit_count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while ( crossover_point >= bit_count)
|
else if ( crossover_bounds == Enums::CrossoverBounds::Clip ) {
|
||||||
{
|
if ( crossover_point_index < 0 ) {
|
||||||
crossover_point -= bit_count;
|
crossover_point_index = 0;
|
||||||
|
}
|
||||||
|
else if ( crossover_point_index >= bit_count ) {
|
||||||
|
crossover_point_index = bit_count-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
throw std::runtime_error("Breeder::PickRandomCrossoverPoint() - Invalid crossover_bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
return crossover_point;
|
return crossover_point_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -120,13 +165,15 @@ namespace BitEvolver
|
|||||||
std::shared_ptr<Chromosome> kiddo,
|
std::shared_ptr<Chromosome> kiddo,
|
||||||
std::shared_ptr<Chromosome> parent,
|
std::shared_ptr<Chromosome> parent,
|
||||||
Enums::CrossoverType crossover_type,
|
Enums::CrossoverType crossover_type,
|
||||||
double crossover_rate
|
Enums::CrossoverBounds crossover_bounds,
|
||||||
|
double crossover_point,
|
||||||
|
double crossover_point_std
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
int
|
int
|
||||||
bits_count,
|
bits_count,
|
||||||
crossover_point,
|
crossover_point_index,
|
||||||
i
|
i
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -142,11 +189,11 @@ namespace BitEvolver
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pick random crossover point
|
// Pick random crossover point
|
||||||
crossover_point = this->PickRandomCrossoverPoint(kiddo, crossover_rate);
|
crossover_point_index = this->PickRandomCrossoverPoint(kiddo, crossover_bounds, crossover_point, crossover_point_std);
|
||||||
|
|
||||||
// Begin copying the parent at the crossover point and beyond
|
// Begin copying the parent at the crossover point and beyond
|
||||||
// (not before)
|
// (not before)
|
||||||
for ( i=crossover_point; i<bits_count; i++) {
|
for ( i=crossover_point_index; i<bits_count; i++) {
|
||||||
kiddo->SetBit( i, parent->GetBit(i) );
|
kiddo->SetBit( i, parent->GetBit(i) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
Breeder.h
16
Breeder.h
@ -21,7 +21,10 @@ namespace BitEvolver
|
|||||||
std::shared_ptr<class Chromosome> mama,
|
std::shared_ptr<class Chromosome> mama,
|
||||||
std::shared_ptr<class Chromosome> papa,
|
std::shared_ptr<class Chromosome> papa,
|
||||||
Enums::CrossoverType crossover_type,
|
Enums::CrossoverType crossover_type,
|
||||||
double crossover_rate,
|
Enums::CrossoverOrder crossover_order,
|
||||||
|
Enums::CrossoverBounds crossover_bounds,
|
||||||
|
double crossover_point,
|
||||||
|
double crossover_point_std,
|
||||||
double mutation_rate
|
double mutation_rate
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -35,12 +38,19 @@ namespace BitEvolver
|
|||||||
std::shared_ptr<class Random> random;
|
std::shared_ptr<class Random> random;
|
||||||
|
|
||||||
//
|
//
|
||||||
int PickRandomCrossoverPoint(std::shared_ptr<class Chromosome> chromosome, double crossover_rate);
|
int PickRandomCrossoverPoint(
|
||||||
|
std::shared_ptr<class Chromosome> chromosome,
|
||||||
|
Enums::CrossoverBounds crossover_bounds,
|
||||||
|
double crossover_point,
|
||||||
|
double crossover_point_std
|
||||||
|
);
|
||||||
void ApplyCrossover(
|
void ApplyCrossover(
|
||||||
std::shared_ptr<class Chromosome> kiddo,
|
std::shared_ptr<class Chromosome> kiddo,
|
||||||
std::shared_ptr<class Chromosome> parent,
|
std::shared_ptr<class Chromosome> parent,
|
||||||
Enums::CrossoverType crossover_type,
|
Enums::CrossoverType crossover_type,
|
||||||
double crossover_rate
|
Enums::CrossoverBounds crossover_bounds,
|
||||||
|
double crossover_point,
|
||||||
|
double crossover_point_std
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
16
Enums.h
16
Enums.h
@ -16,6 +16,22 @@ namespace BitEvolver
|
|||||||
Sexual
|
Sexual
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
enum class CrossoverOrder
|
||||||
|
{
|
||||||
|
//
|
||||||
|
MamaPapa,
|
||||||
|
ByFitness
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
enum class CrossoverBounds
|
||||||
|
{
|
||||||
|
//
|
||||||
|
Clip,
|
||||||
|
Wrap
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
enum class ElitismType
|
enum class ElitismType
|
||||||
{
|
{
|
||||||
|
@ -56,7 +56,12 @@ namespace BitEvolver
|
|||||||
|
|
||||||
//
|
//
|
||||||
this->SetCrossoverType(Population::DEFAULT_CROSSOVER_TYPE);
|
this->SetCrossoverType(Population::DEFAULT_CROSSOVER_TYPE);
|
||||||
|
this->SetCrossoverOrder(Population::DEFAULT_CROSSOVER_ORDER);
|
||||||
|
this->SetCrossoverBounds(Population::DEFAULT_CROSSOVER_BOUNDS);
|
||||||
this->SetCrossoverPoint(Population::DEFAULT_CROSSOVER_POINT);
|
this->SetCrossoverPoint(Population::DEFAULT_CROSSOVER_POINT);
|
||||||
|
this->SetCrossoverPointStandardDeviation(Population::DEFAULT_CROSSOVER_POINT_STD);
|
||||||
|
|
||||||
|
//
|
||||||
this->SetMutationRate(Population::DEFAULT_MUTATION_RATE);
|
this->SetMutationRate(Population::DEFAULT_MUTATION_RATE);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -165,6 +170,48 @@ namespace BitEvolver
|
|||||||
return fitness_average;
|
return fitness_average;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void Population::SetCrossoverType(Enums::CrossoverType t)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
this->crossover_type = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
Enums::CrossoverType Population::GetCrossoverType()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
return this->crossover_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void Population::SetCrossoverOrder(Enums::CrossoverOrder o)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
this->crossover_order = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
Enums::CrossoverOrder Population::GetCrossoverOrder()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
return this->crossover_order;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void Population::SetCrossoverBounds(Enums::CrossoverBounds b)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
this->crossover_bounds = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
Enums::CrossoverBounds Population::GetCrossoverBounds()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
return this->crossover_bounds;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
void Population::SetCrossoverPoint(double p)
|
void Population::SetCrossoverPoint(double p)
|
||||||
{
|
{
|
||||||
@ -180,17 +227,17 @@ namespace BitEvolver
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
void Population::SetCrossoverType(Enums::CrossoverType t)
|
void Population::SetCrossoverPointStandardDeviation(double std)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
this->crossover_type = t;
|
this->crossover_point_std = std;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
Enums::CrossoverType Population::GetCrossoverType()
|
double Population::GetCrossoverPointStandardDeviation()
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
return this->crossover_type;
|
return this->crossover_point_std;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -709,15 +756,14 @@ namespace BitEvolver
|
|||||||
mama = this->roulette_wheel->Spin();
|
mama = this->roulette_wheel->Spin();
|
||||||
papa = this->roulette_wheel->Spin();
|
papa = this->roulette_wheel->Spin();
|
||||||
|
|
||||||
//
|
|
||||||
//cout << "Roulette Wheel (mama): " << mama->ToString() << endl;
|
|
||||||
//cout << "Roulette Wheel (papa): " << papa->ToString() << endl;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
kiddo = this->breeder->Breed(
|
kiddo = this->breeder->Breed(
|
||||||
mama, papa,
|
mama, papa,
|
||||||
this->crossover_type,
|
this->crossover_type,
|
||||||
|
this->crossover_order,
|
||||||
|
this->crossover_bounds,
|
||||||
this->crossover_point,
|
this->crossover_point,
|
||||||
|
this->crossover_point_std,
|
||||||
this->mutation_rate
|
this->mutation_rate
|
||||||
);
|
);
|
||||||
|
|
||||||
|
31
Population.h
31
Population.h
@ -48,10 +48,17 @@ namespace BitEvolver
|
|||||||
double GetAverageFitness(std::vector<std::shared_ptr<class Chromosome>> _chromosomes);
|
double GetAverageFitness(std::vector<std::shared_ptr<class Chromosome>> _chromosomes);
|
||||||
|
|
||||||
//
|
//
|
||||||
void SetCrossoverPoint(double p);
|
|
||||||
double GetCrossoverPoint();
|
|
||||||
void SetCrossoverType(Enums::CrossoverType t);
|
void SetCrossoverType(Enums::CrossoverType t);
|
||||||
Enums::CrossoverType GetCrossoverType();
|
Enums::CrossoverType GetCrossoverType();
|
||||||
|
void SetCrossoverOrder(Enums::CrossoverOrder o);
|
||||||
|
Enums::CrossoverOrder GetCrossoverOrder();
|
||||||
|
void SetCrossoverBounds(Enums::CrossoverBounds b);
|
||||||
|
Enums::CrossoverBounds GetCrossoverBounds();
|
||||||
|
void SetCrossoverPoint(double p);
|
||||||
|
double GetCrossoverPoint();
|
||||||
|
void SetCrossoverPointStandardDeviation(double std);
|
||||||
|
double GetCrossoverPointStandardDeviation();
|
||||||
|
|
||||||
//
|
//
|
||||||
void SetMutationRate(double r);
|
void SetMutationRate(double r);
|
||||||
double GetMutationRate();
|
double GetMutationRate();
|
||||||
@ -76,14 +83,17 @@ namespace BitEvolver
|
|||||||
void PrintPopulation(std::vector<std::shared_ptr<class Chromosome>> _chromosomes);
|
void PrintPopulation(std::vector<std::shared_ptr<class Chromosome>> _chromosomes);
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const static int DEFAULT_POPULATION_SIZE = 100;
|
const static int DEFAULT_POPULATION_SIZE = 100;
|
||||||
const static Enums::ElitismType DEFAULT_ELITISM_TYPE = Enums::ElitismType::Rate;
|
const static Enums::ElitismType DEFAULT_ELITISM_TYPE = Enums::ElitismType::Rate;
|
||||||
constexpr static double DEFAULT_ELITISM_RATE = 0.01;
|
constexpr static double DEFAULT_ELITISM_RATE = 0.01;
|
||||||
const static int DEFAULT_ELITISM_COUNT = 1;
|
const static int DEFAULT_ELITISM_COUNT = 1;
|
||||||
constexpr static double DEFAULT_MUTATION_RATE = 0.01;
|
constexpr static double DEFAULT_MUTATION_RATE = 0.01;
|
||||||
//
|
//
|
||||||
const static Enums::CrossoverType DEFAULT_CROSSOVER_TYPE = Enums::CrossoverType::Sexual;
|
const static Enums::CrossoverType DEFAULT_CROSSOVER_TYPE = Enums::CrossoverType::Sexual;
|
||||||
const static int DEFAULT_CROSSOVER_POINT = 0.7;
|
const static Enums::CrossoverOrder DEFAULT_CROSSOVER_ORDER = Enums::CrossoverOrder::MamaPapa;
|
||||||
|
const static Enums::CrossoverBounds DEFAULT_CROSSOVER_BOUNDS = Enums::CrossoverBounds::Wrap;
|
||||||
|
constexpr static double DEFAULT_CROSSOVER_POINT = 0.7;
|
||||||
|
constexpr static double DEFAULT_CROSSOVER_POINT_STD = 0.25;
|
||||||
|
|
||||||
//
|
//
|
||||||
private:
|
private:
|
||||||
@ -100,7 +110,10 @@ namespace BitEvolver
|
|||||||
|
|
||||||
//
|
//
|
||||||
Enums::CrossoverType crossover_type;
|
Enums::CrossoverType crossover_type;
|
||||||
|
Enums::CrossoverOrder crossover_order;
|
||||||
|
Enums::CrossoverBounds crossover_bounds;
|
||||||
double crossover_point;
|
double crossover_point;
|
||||||
|
double crossover_point_std;
|
||||||
double mutation_rate;
|
double mutation_rate;
|
||||||
Enums::ElitismType elitism_type;
|
Enums::ElitismType elitism_type;
|
||||||
double elitism_rate;
|
double elitism_rate;
|
||||||
|
Loading…
Reference in New Issue
Block a user