New crossover features: Order, Bounds, Standard deviation

This commit is contained in:
2018-04-14 19:58:13 -07:00
parent cb0f81b3e1
commit 62ab4f9a16
5 changed files with 182 additions and 50 deletions

View File

@ -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) );
}