This repository has been archived by the owner on Feb 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Selection.cs
97 lines (93 loc) · 4.05 KB
/
Selection.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace LevelGenerator
{
/// Alias for the coordinate of MAP-Elites matrix.
using Coordinate = System.ValueTuple<int, int>;
/// This class holds the selector operator.
public class Selection
{
/// The error message of not enough competitors.
public static readonly string NOT_ENOUGH_COMPETITORS =
"There are not enough individuals in the entered population to " +
"perform this operation.";
/// Select individuals from the MAP-Elites population.
///
/// This function ensures that the same individual will not be selected
/// for the same selection process. To do so, we use an auxiliary list
/// composed of the individuals' coordinates in the MAP-Elites
/// population. Instead of selecting directly an individual, we select
/// its coordinate from the auxiliary list and remove it then it is not
/// available for the next selection.
public static Individual[] Select(
int _amount,
int _competitors,
Population _pop,
ref Random _rand
) {
// Get the list of Elites' coordinates (the available competitors)
List<Coordinate> avco = _pop.GetElitesCoordinates();
// Ensure the population size is enough for the tournament
Debug.Assert(
avco.Count - _amount > _competitors,
NOT_ENOUGH_COMPETITORS
);
// Select `_amount` individuals
Individual[] individuals = new Individual[_amount];
for (int i = 0; i < _amount; i++)
{
// Perform tournament selection with `_competitors` competitors
(Coordinate coordinate, Individual individual) = Tournament(
_competitors, // Number of competitors
_pop, // Population
avco, // List of available competitors
ref _rand // Random number generator
);
// Select an individual and remove it from available competitors
individuals[i] = individual;
avco.Remove(coordinate);
}
return individuals;
}
/// Perform tournament selection of a single individual.
///
/// This function ensures that the same individual will not be selected
/// for the same tournament selection process. To do so, we apply the
/// same process explained in `Select` function.
static (Coordinate, Individual) Tournament(
int _competitors,
Population _pop,
List<Coordinate> _avco,
ref Random _rand
) {
// List of available competitors
List<Coordinate> avco = new List<Coordinate>(_avco);
// Initialize the auxiliary variables
Individual[] competitors = new Individual[_competitors];
Coordinate[] coordinates = new Coordinate[_competitors];
// Select the competitors randomly from the available coordinate
// then remove the competitor from available competitors
for (int i = 0; i < _competitors; i++)
{
Coordinate rc = Common.RandomElementFromList(avco, ref _rand);
competitors[i] = _pop.map[rc.Item1, rc.Item2];
coordinates[i] = rc;
avco.Remove(rc);
}
// Find the tournament winner and its coordinate in the population
Individual winner = null;
Coordinate coordinate = (Common.UNKNOWN, Common.UNKNOWN);
for (int i = 0; i < _competitors; i++)
{
if (Fitness.IsBest(competitors[i], winner))
{
winner = competitors[i];
coordinate = coordinates[i];
}
}
// Return the tournament winner and its coordinate
return (coordinate, winner);
}
}
}