Individuals¶
This section covers the class Individual in more detail.
Class Summary¶
An Individual poses a unique instance of a solution to the associated Problem. Each Individual has a genome, which contains state representing that posed solution. The genome can be a sequence or a matrix or a tree or some other data structure, but in practice a genome is usually a binary or a real-value sequence. Every Individual is connected to an associated Problem and relies on the Problem to evaluate its fitness and to compare itself with another Individual to determine the better of the two.
The clone() method will create a duplicate of a given Individual; the new Individual gets a deep copy of the genome and refers to the same Problem and Decoder. evaluate() calls evaluate_imp()`that, in turn, calls `decode()`to translate the `genome into phenomes, or values meaningful to the Problem, and then passes those values to the Problem where it returns a fitness. This fitness is then assigned to the Individual.
The reason for the indirection using evaluate_imp() is that evaluate_imp() allows sub-classes to pass ancillary information to Problem during evaluation. For example, an Individual may have a UUID that the Problem needs in order to create a file or sub-directory using that UUID. evaluate_imp() can be over-ridden in a sub-class to pass along the UUID in addition to the decoded genome.
The @total_ordering class wrapper is used to expand the member functions __lt__() and __eq__() that are, in turn, heavily used in sorting, selection, and comparison operators.
RobustIndividual¶
RobustIndividual is a sub-class of Individual that over-rides evaluate() to handle exceptions thrown during evaluation. If no exceptions are thrown, then self.is_viable is set to True. If an exception happens, then the following occurs:
self.is_viable is set to False
self.fitness is set to math.nan
self.exception is assigned the Exception object
In turn, this class has another sub-class leap_ec.distributed.individual.DistributedIndividual.
Class API¶
-
class
leap_ec.individual.
Individual
(genome, decoder=None, problem=None)¶ Represents a single solution to a Problem.
We represent an Individual by a genome and a fitness. Individual also maintains a reference to the Problem it will be evaluated on, and an decoder, which defines how genomes are converted into phenomes for fitness evaluation.
-
__init__
(genome, decoder=None, problem=None)¶ Initialize an Individual with a given genome.
We also require Individual`s to maintain a reference to the `Problem:
>>> from leap_ec.binary_rep.problems import MaxOnes >>> from leap_ec.decoder import IdentityDecoder >>> ind = Individual([0, 0, 1, 0, 1], decoder=IdentityDecoder(), problem=MaxOnes()) >>> ind.genome [0, 0, 1, 0, 1]
Fitness defaults to None:
>>> ind.fitness is None True
- Parameters
genome – is the genome representing the solution. This can be any arbitrary type that your mutation operators, probes, etc., know how to read and manipulate—a list, class, etc.
decoder – is a function or callable that converts a genome into a phenome.
problem – is the Problem associated with this individual.
-
clone
()¶ Create a ‘clone’ of this Individual, copying the genome, but not fitness.
A deep copy of the genome will be created, so if your Individual has a custom genome type, it’s important that it implements the __deepcopy__() method.
>>> from leap_ec.binary_rep.problems import MaxOnes >>> from leap_ec.decoder import IdentityDecoder >>> ind = Individual([0, 1, 1, 0], IdentityDecoder(), MaxOnes()) >>> ind_copy = ind.clone() >>> ind_copy.genome == ind.genome True >>> ind_copy.problem == ind.problem True >>> ind_copy.decoder == ind.decoder True
-
classmethod
create_population
(n, initialize, decoder, problem)¶ A convenience method for initializing a population of the appropriate subtype.
- Parameters
n – The size of the population to generate
initialize – A function f(m) that initializes a genome
decoder – The decoder to attach individuals to
problem – The problem to attach individuals to
- Returns
A list of n individuals of this class’s (or subclass’s) type
-
decode
(*args, **kwargs)¶ - Returns
the decoded value for this individual
-
evaluate
()¶ determine this individual’s fitness
This is done by outsourcing the fitness evaluation to the associated Problem object since it “knows” what is good or bad for a given phenome.
- See also
ScalarProblem.worse_than
- Returns
the calculated fitness
-
evaluate_imp
()¶ This is the evaluate ‘implementation’ called by self.evaluate(). It’s intended to be optionally over-ridden by sub-classes to give an opportunity to pass in ancillary data to the evaluate process either by tailoring the problem interface or that of the given decoder.
-
classmethod
evaluate_population
(population)¶ Convenience function for bulk serial evaluation of a given population
- Parameters
population – to be evaluated
- Returns
evaluated population
-
-
class
leap_ec.individual.
RobustIndividual
(genome, decoder=None, problem=None)¶ This adds exception handling for evaluations
After evaluation self.is_viable is set to True if all went well. However, if an exception is thrown during evaluation, the following happens:
self.is_viable is set to False
self.fitness is set to math.nan
self.exception is assigned the exception
-
evaluate
()¶ determine this individual’s fitness
Note that if an exception is thrown during evaluation, the fitness is set to NaN and self.is_viable to False; also, the returned exception is assigned to self.exception for possible later inspection. If the individual was successfully evaluated, self.is_viable is set to true. NaN fitness values will figure into comparing individuals in that NaN will always be considered worse than non-NaN fitness values.
- Returns
the calculated fitness