New crossover features: Order, Bounds, Standard deviation
This commit is contained in:
107
Breeder.cpp
107
Breeder.cpp
@ -29,23 +29,51 @@ namespace BitEvolver
|
||||
std::shared_ptr<Chromosome> mama,
|
||||
std::shared_ptr<Chromosome> papa,
|
||||
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
|
||||
)
|
||||
{
|
||||
//
|
||||
std::shared_ptr<Chromosome> kiddo;
|
||||
int bit_length;
|
||||
std::shared_ptr<Chromosome>
|
||||
parent_primary,
|
||||
parent_secondary,
|
||||
kiddo
|
||||
;
|
||||
|
||||
//
|
||||
bit_length = mama->GetBitCount();
|
||||
// Choose primary / secondary parents
|
||||
switch( crossover_order )
|
||||
{
|
||||
//
|
||||
case Enums::CrossoverOrder::MamaPapa:
|
||||
parent_primary = mama;
|
||||
parent_secondary = papa;
|
||||
break;
|
||||
|
||||
//
|
||||
case Enums::CrossoverOrder::ByFitness:
|
||||
if ( mama->GetFitness() > papa->GetFitness() ) {
|
||||
parent_primary = mama;
|
||||
parent_secondary = papa;
|
||||
}
|
||||
else{
|
||||
parent_primary = papa;
|
||||
parent_secondary = mama;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Directly copy the mama
|
||||
kiddo = std::shared_ptr<Chromosome>(new Chromosome(this->random, bit_length));
|
||||
*kiddo = *mama;
|
||||
// Directly copy the primary parent first
|
||||
kiddo = std::shared_ptr<Chromosome>(new Chromosome(this->random, parent_primary->GetBitCount()));
|
||||
*kiddo = *parent_primary;
|
||||
|
||||
// Apply crossover
|
||||
this->ApplyCrossover(kiddo, papa, crossover_type, crossover_rate);
|
||||
// Apply crossover with the secondary parent
|
||||
this->ApplyCrossover(
|
||||
kiddo, parent_secondary,
|
||||
crossover_type, crossover_bounds, crossover_point, crossover_point_std
|
||||
);
|
||||
|
||||
// Apply mutation
|
||||
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;
|
||||
int crossover_point_index;
|
||||
int bit_count;
|
||||
double random_double;
|
||||
|
||||
//
|
||||
bit_count = chromosome->GetBitCount();
|
||||
|
||||
/**
|
||||
Choose a double between [0.0,1.0] for the crossover point.
|
||||
Use normal distribution, with the mean to the default point,
|
||||
and 1.0 as the std.
|
||||
Use normal distribution, with the mean and std from the parameters.
|
||||
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
|
||||
crossover_point = crossover_point_double * bit_count;
|
||||
crossover_point_index = floor(random_double * bit_count);
|
||||
|
||||
// Loop around to keep in bounds
|
||||
while ( crossover_point < 0 )
|
||||
{
|
||||
crossover_point += bit_count;
|
||||
// Loop around to keep in bounds?
|
||||
if ( crossover_bounds == Enums::CrossoverBounds::Wrap ) {
|
||||
while ( crossover_point_index < 0 )
|
||||
{
|
||||
crossover_point_index += bit_count;
|
||||
}
|
||||
while ( crossover_point_index >= bit_count)
|
||||
{
|
||||
crossover_point_index -= bit_count;
|
||||
}
|
||||
}
|
||||
while ( crossover_point >= bit_count)
|
||||
{
|
||||
crossover_point -= bit_count;
|
||||
else if ( crossover_bounds == Enums::CrossoverBounds::Clip ) {
|
||||
if ( crossover_point_index < 0 ) {
|
||||
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> parent,
|
||||
Enums::CrossoverType crossover_type,
|
||||
double crossover_rate
|
||||
Enums::CrossoverBounds crossover_bounds,
|
||||
double crossover_point,
|
||||
double crossover_point_std
|
||||
)
|
||||
{
|
||||
//
|
||||
int
|
||||
bits_count,
|
||||
crossover_point,
|
||||
crossover_point_index,
|
||||
i
|
||||
;
|
||||
|
||||
@ -142,11 +189,11 @@ namespace BitEvolver
|
||||
}
|
||||
|
||||
// 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
|
||||
// (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) );
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user