Decoders
This section covers the Decoder class in more detail.
Class Summary
The abstract-base class, Decoder , has one function intended to be overridden by sub-classes, decode(), that returns a phenome meaningful to a given Problem, which is usually a sequence of values. There are a number of supplied Decoder classes mostly for converting binary strings into integers or real values.
Note that there is also support for Gray encoding. See BinarytoIntGrayDecoder and BinaryToRealGreyDecoder.
Class API
Decoder
- class leap_ec.decoder.Decoder
- Decoders in LEAP implement how solutions to a problem are represented.
Specifically, a
Decoder
converts anIndividual
’s genotype (which is a format that can easily be manipulated by mutation and recombination operators) into a phenotype (which is a format that can be fed directly into aProblem
object to obtain a fitness value).
Genotypes and phenotypes can be of arbitrary type, from a simple list of numbers to a complex data structure. Choosing a good genotypic representation and genotype-to-phenotype mapping for a given problem domain is a critical part of evolutionary algorithm design: the
Decoder
object that an algorithm uses can have a big impact on the effectiveness of your metaheuristics.In LEAP, a
Decoder
is typically used byIndividual
as an intermediate step in calculating its own fitness.For example, say that we want to use a binary-represented
Individual
to solve a real-valued optimization problem, such asSchwefelProblem
. Here, the genotype is a vector of binary values, whereas the phenotype is its corresponding float vector.We can use a
BinaryToIntDecoder
to express this mapping. And when we initialize an individual, we give it all three pieces of this information:>>> from leap_ec.binary_rep.decoders import BinaryToRealDecoder >>> from leap_ec.individual import Individual >>> from leap_ec.real_rep.problems import SchwefelProblem >>> import numpy as np >>> genome = np.array([0, 1, 1, 0, 1, 0, 1, 1]) >>> decoder = BinaryToRealDecoder((4, -5.12, 5.12), (4, -5.12, 5.12)) # Every 4 bits map to a float on (-5.12, 5.12) >>> ind = Individual(genome, decoder=decoder, problem=SchwefelProblem())
Now we can decode the individual to examine its phenotype:
>>> ind.decode() array([-1.024 , 2.38933333])
This call is just a wrapper for the
Decoder
, which has the same output:>>> decoder.decode(genome) array([-1.024 , 2.38933333])
But now
Individual
also has everything it needs to evaluate its own fitness:>>> ind.evaluate() 836.4453949...
Calling evaluate() also has the side effect of setting the fitness attribute:
>>> ind.fitness 836.4453949...
- __init__()
- abstract decode(genome, *args, **kwargs)
- Parameters
genome – a genome you wish to convert
- Returns
the phenotype associated with that genome
IdentityDecoder
- class leap_ec.decoder.IdentityDecoder
A decoder that maps a genome to itself. This acts as a ‘direct’ or ‘phenotypic’ encoding: Use this when your genotype and phenotype are the same thing.
- __init__()
- decode(genome, *args, **kwargs)
- Returns
the input genome.
For example:
>>> import numpy as np >>> d = IdentityDecoder() >>> d.decode(np.array([0.5, 0.6, 0.7])) array([0.5, 0.6, 0.7])
BinaryToIntDecoder
- class leap_ec.binary_rep.decoders.BinaryToIntDecoder(*descriptors)
A decoder that converts a Boolean-vector genome into an integer-vector phenome.
- __init__(*descriptors)
Constructs a decoder that will convert a binary representation into a corresponding int-value vector.
- Parameters
descriptors – is a test_sequence of integer that determine how the binary test_sequence is to be broken up into chunks for interpretation
- Returns
a function for real-value phenome decoding of a test_sequence of binary digits
The segments parameter indicates the number of (genome) bits per ( phenome) dimension. For example, if we construct the decoder
>>> d = BinaryToIntDecoder(4, 3)
then it will look for a genome of length 7, with the first 4 bits mapped to the first phenotypic value, and the last 3 bits making up the second:
>>> import numpy as np >>> d.decode(np.array([0,0,0,0,1,1,1])) array([0, 7])
- decode(genome, *args, **kwargs)
Converts a Boolean genome to an integer-vector phenome by interpreting each segment of the genome as low-endian binary number.
- Parameters
genome – a list of 0s and 1s representing a Boolean genome
- Returns
a corresponding list of ints representing the integer-vector phenome
For example, a Boolean representation of [1, 12, 5] can be decoded like this:
>>> import numpy as np >>> d = BinaryToIntDecoder(4, 4, 4) >>> b = np.array([0,0,0,1, 1, 1, 0, 0, 0, 1, 1, 0]) >>> d.decode(b) array([ 1, 12, 6])
BinaryToRealDecoderCommon
- class leap_ec.binary_rep.decoders.BinaryToRealDecoderCommon(*segments)
Common implementation for binary to real decoders.
The base classes BinaryToRealDecoder and BinaryToRealGreyDecoder differ by just the underlying binary to integer decoder. Most all the rest of the binary integer to real-value decoding is the same, hence this class.
- __init__(*segments)
- Parameters
segments – is a test_sequence of tuples of the form (number of bits, minimum, maximum) values
- Returns
a function for real-value phenome decoding of a test_sequence of binary digits
- decode(genome, *args, **kwargs)
Convert a list of binary values into a real-valued vector.
BinaryToRealDecoder
- class leap_ec.binary_rep.decoders.BinaryToRealDecoder(*segments)
- __init__(*segments)
This returns a function that will convert a binary representation into a corresponding real-value vector. The segments are a collection of tuples that indicate how many bits per segment, and the corresponding real-value bounds for that segment.
- Parameters
segments – is a test_sequence of tuples of the form (number of bits, minimum, maximum) values
- Returns
a function for real-value phenome decoding of a test_sequence of binary digits
For example, if we construct the decoder then it will look for a genome of length 8, with the first 4 bits mapped to the first phenotypic value, and the last 4 bits making up the second. The traits have a minimum value of -5.12 (corresponding to 0000) and a maximum of 5.12 (corresponding to 1111):
>>> import numpy as np >>> d = BinaryToRealDecoder((4, -5.12, 5.12),(4, -5.12, 5.12)) >>> d.decode(np.array([0, 0, 0, 0, 1, 1, 1, 1])) array([-5.12, 5.12])
BinaryToIntGreyDecoder
- class leap_ec.binary_rep.decoders.BinaryToIntGreyDecoder(*descriptors)
This performs Gray encoding when converting from binary strings.
See also: https://en.wikipedia.org/wiki/Gray_code#Converting_to_and_from_Gray_code
For example, a grey encoded Boolean representation of [1, 8, 4] can be decoded like this:
>>> import numpy as np >>> d = BinaryToIntGreyDecoder(4, 4, 4) >>> b = np.array([0,0,0,1, 1, 1, 0, 0, 0, 1, 1, 0]) >>> d.decode(b) array([1, 8, 4])
- __init__(*descriptors)
Constructs a decoder that will convert a binary representation into a corresponding int-value vector.
- Parameters
descriptors – is a test_sequence of integer that determine how the binary test_sequence is to be broken up into chunks for interpretation
- Returns
a function for real-value phenome decoding of a test_sequence of binary digits
The segments parameter indicates the number of (genome) bits per ( phenome) dimension. For example, if we construct the decoder
>>> d = BinaryToIntDecoder(4, 3)
then it will look for a genome of length 7, with the first 4 bits mapped to the first phenotypic value, and the last 3 bits making up the second:
>>> import numpy as np >>> d.decode(np.array([0,0,0,0,1,1,1])) array([0, 7])
- decode(genome, *args, **kwargs)
Converts a Boolean genome to an integer-vector phenome by interpreting each segment of the genome as low-endian binary number.
- Parameters
genome – a list of 0s and 1s representing a Boolean genome
- Returns
a corresponding list of ints representing the integer-vector phenome
For example, a Boolean representation of [1, 12, 5] can be decoded like this:
>>> import numpy as np >>> d = BinaryToIntDecoder(4, 4, 4) >>> b = np.array([0,0,0,1, 1, 1, 0, 0, 0, 1, 1, 0]) >>> d.decode(b) array([ 1, 12, 6])
BinaryToRealGreyDecoder
- class leap_ec.binary_rep.decoders.BinaryToRealGreyDecoder(*segments)
- __init__(*segments)
This returns a function that will convert a binary representation into a corresponding real-value vector. The segments are a collection of tuples that indicate how many bits per segment, and the corresponding real-value bounds for that segment.
- Parameters
segments – is a test_sequence of tuples of the form (number of bits, minimum, maximum) values :return: a function for real-value phenome decoding of a test_sequence of binary digits
For example, if we construct the decoder then it will look for a genome of length 8, with the first 4 bits mapped to the first phenotypic value, and the last 4 bits making up the second. The traits have a minimum value of -5.12 (corresponding to 0000) and a maximum of 5.12 (corresponding to 1111):
>>> import numpy as np >>> d = BinaryToRealGreyDecoder((4, -5.12, 5.12),(4, -5.12, 5.12)) >>> d.decode(np.array([0, 0, 0, 0, 1, 1, 1, 1])) array([-5.12 , 1.70666667])