Decoders

This section covers the Decoder class in more detail.

Class Summary

_images/decoder_class_diagram.svg

Fig. 6 The Decoder abstract-base class This class diagram shows the detail for Decoder, which is an abstract base class (ABC). It has just a single abstract function, decode(), that is intended to be defined by subclasses.

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

Inheritance diagram of leap_ec.decoder.Decoder
class leap_ec.decoder.Decoder
Decoders in LEAP implement how solutions to a problem are represented.

Specifically, a Decoder converts an Individual’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 a Problem 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 by Individual 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 as SchwefelProblem. 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

Inheritance diagram of leap_ec.decoder.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

Inheritance diagram of leap_ec.binary_rep.decoders.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

Inheritance diagram of leap_ec.binary_rep.decoders.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

Inheritance diagram of leap_ec.binary_rep.decoders.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

Inheritance diagram of leap_ec.binary_rep.decoders.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

Inheritance diagram of leap_ec.binary_rep.decoders.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])