Skip to content

Commit e437ed4

Browse files
committed
Implement simple crossover
1 parent 8610aa6 commit e437ed4

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

src/Population.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,26 @@ public function select($number)
4141
return collect($this->solutions)->sortByDesc('fitness')->take($number);
4242
}
4343

44+
public function crossover($parents)
45+
{
46+
$numParents = $parents->count();
47+
$familySize = 2 * $this->size / $numParents;
48+
$chromosomeCount = sizeof($parents->first()->chromosomes());
49+
50+
if (is_int($familySize)) {
51+
$this->solutions = $parents->shuffle()->chunk(2)->map(function ($parents) use ($familySize, $chromosomeCount) {
52+
$children = [];
53+
for ($i = 0; $i < $familySize; $i++) {
54+
$crossover = mt_rand(0, $chromosomeCount);
55+
$left = array_slice($parents->first()->chromosomes(), 0, $crossover);
56+
$right = array_slice($parents->last()->chromosomes(), $crossover);
57+
$children[] = new $this->model(['chromosomes' => array_merge($left, $right)]);
58+
}
59+
return $children;
60+
})->flatten();
61+
}
62+
}
63+
4464
public function mutate()
4565
{
4666
$this->solutions = collect($this->solutions)->map(function ($solution) {

src/Solution.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ abstract public function genome();
1212

1313
abstract public function evaluate($data);
1414

15+
public function __construct($params = null)
16+
{
17+
if ($params) {
18+
foreach ($params as $key => $value) {
19+
$this->$key = $value;
20+
}
21+
}
22+
}
23+
1524
public function initialise()
1625
{
1726
$this->chromosomes = collect($this->genome())->map(function ($definition) {

tests/PopulationTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ public function apply_selection_strategy()
6464
$this->assertEquals([1052, 771, 758, 683, 641, 607], $selections->pluck('fitness')->toArray());
6565
}
6666

67+
/** @test */
68+
public function apply_crossover_strategy()
69+
{
70+
$population = new Population(Integers::class, 12);
71+
$selections = collect($population->solutions())->take(6);
72+
$this->assertEquals([64, -39, 1], $population->solutions()[0]->chromosomes());
73+
74+
$population->crossover($selections);
75+
$this->assertEquals([82, -93, 0], $population->solutions()[0]->chromosomes());
76+
$this->assertEquals([82, -39, 1], $population->solutions()[2]->chromosomes());
77+
}
78+
6779
/** @test */
6880
public function apply_mutation_strategy()
6981
{

0 commit comments

Comments
 (0)