- Type Parameters:
T
- the argument type of given problemG
- theGene
type used for encoding the argument typeT
- All Known Subinterfaces:
InvertibleCodec<T,
G>
A problem
The
Calling the
Codec
contains the information about how to encode a given
argument type into a Genotype
. It also lets convert the encoded
Genotype
back to the argument type. The engine creation and the
implementation of the fitness function can be heavily simplified by using
a Codec
class. The example given in the Engine
documentation
can be simplified as follows:
public class RealFunction {
// The conversion from the 'Genotype' to the argument type of the fitness
// function is performed by the given 'Codec'. You can concentrate on the
// implementation, because you are not bothered with the conversion code.
private static double eval(final double x) {
return cos(0.5 + sin(x)) * cos(x);
}
public static void main(final String[] args) {
final Engine<DoubleGene, Double> engine = Engine
// Create an Engine.Builder with the "pure" fitness function
// and the appropriate Codec.
.build(RealFunction::eval, Codecs.ofScalar(DoubleRange.of(0, 2*PI)))
.build();
...
}
}
Codec
needed for the above usage example, will look like this:
final DoubleRange domain = DoubleRange.of(0, 2*PI);
final Codec<Double, DoubleGene> codec = Codec.of(
Genotype.of(DoubleChromosome.of(domain)),
gt -> gt.chromosome().gene().allele()
);
of(Factory, Function)
method is the usual way for
creating new Codec
instances.- Since:
- 3.2
- Version:
- 3.6
- See Also:
-
Method Summary
Modifier and TypeMethodDescriptiondefault T
decoder()
Return the decoder function which transforms the genotype back to the original problem domain representation.encoding()
Return the genotype factory for creating genotypes with the right encoding for the given problem.Create a newCodec
with the mapped result type.of
(Codec<A, G> codec1, Codec<B, G> codec2, BiFunction<A, B, T> decoder) Converts two givenCodec
instances into one.Create a newCodec
object with the givenencoding
anddecoder
function.Combines the givencodecs
into one codec.default InvertibleCodec<T,
G> toInvertibleCodec
(Function<? super T, Genotype<G>> encoder) Converts this codec into an invertible codec, by using the givenencoder
(inversion) function.
-
Method Details
-
encoding
Return the genotype factory for creating genotypes with the right encoding for the given problem. The genotype created with this factory must work together with thedecoder()
function, which transforms the genotype into an object of the problem domain.final Codec<SomeObject, DoubleGene> codec = ... final Genotype<DoubleGene> gt = codec.encoding().newInstance(); final SomeObject arg = codec.decoder().apply(gt);
- Returns:
- the genotype (factory) representation of the problem domain
- See Also:
-
decoder
Return the decoder function which transforms the genotype back to the original problem domain representation.- Returns:
- genotype decoder
- See Also:
-
decode
Converts the givenGenotype
to the target typeCodec
. This is a shortcut forfinal Codec<SomeObject, DoubleGene> codec = ... final Genotype<DoubleGene> gt = codec.encoding().newInstance(); final SomeObject arg = codec.decoder().apply(gt);
- Parameters:
genotype
- the genotype to be converted- Returns:
- the converted genotype
- Throws:
NullPointerException
- if the givengenotype
isnull
- Since:
- 3.6
-
map
Create a newCodec
with the mapped result type. The following example creates a double codec whose values are not uniformly distributed between[0..1)
. Instead, the values now follow an exponential function.This method can also be used for creating non-trivial codes like split ranges, as shown in the following example, where only values between [0, 2) and [8, 10) are valid.final Codec<Double, DoubleGene> c = Codecs.ofScalar(DoubleRange.of(0, 1)) .map(Math::exp);
+--+--+--+--+--+--+--+--+--+--+ | | | | | | | | | | | 0 1 2 3 4 5 6 7 8 9 10 |-----|xxxxxxxxxxxxxxxxx|-----| ^ |llllllll|rrrrrrrr| ^ | | | | +-------+ +------+
final Codec<Double, DoubleGene> codec = Codecs .ofScalar(DoubleRange.of(0, 10)) .map(v -> { if (v >= 2 && v < 8) { return v < 5 ? ((v - 2)/3)*2 : ((8 - v)/3)*2 + 8; } return v; });
- Type Parameters:
B
- the new argument type of the given problem- Parameters:
mapper
- the mapper function- Returns:
- a new
Codec
with the mapped result type - Throws:
NullPointerException
- if the mapper isnull
.- Since:
- 4.0
- See Also:
-
toInvertibleCodec
Converts this codec into an invertible codec, by using the givenencoder
(inversion) function.- Parameters:
encoder
- the (inverse) encoder function- Returns:
- a new invertible codec
- Throws:
NullPointerException
- if the givenencoder
isnull
-
of
static <T,G extends Gene<?, Codec<T,G>> G> of(Factory<Genotype<G>> encoding, Function<? super Genotype<G>, ? extends T> decoder) Create a newCodec
object with the givenencoding
anddecoder
function.- Type Parameters:
G
- theGene
typeT
- the fitness function argument type in the problem domain- Parameters:
encoding
- the genotype factory used for creating newGenotypes
decoder
- decoder function, which converts aGenotype
to a value in the problem domain- Returns:
- a new
Codec
object with the given parameters - Throws:
NullPointerException
- if one of the arguments isnull
.
-
of
static <A,B, Codec<T,T, G extends Gene<?, G>> G> of(Codec<A, G> codec1, Codec<B, G> codec2, BiFunction<A, B, T> decoder) Converts two givenCodec
instances into one. This lets you divide a problem into sub problems and combine them again.The following example shows how to combine two codecs, which converts a
LongGene
to aLocalDate
, to a codec which combines the twoLocalDate
object (these are the argument types of the component codecs) to aDuration
.final Codec<LocalDate, LongGene> dateCodec1 = Codec.of( Genotype.of(LongChromosome.of(0, 10_000)), gt -> LocalDate.ofEpochDay(gt.gene().longValue()) ); final Codec<LocalDate, LongGene> dateCodec2 = Codec.of( Genotype.of(LongChromosome.of(1_000_000, 10_000_000)), gt -> LocalDate.ofEpochDay(gt.gene().longValue()) ); final Codec<Duration, LongGene> durationCodec = Codec.of( dateCodec1, dateCodec2, (d1, d2) -> Duration.ofDays(d2.toEpochDay() - d1.toEpochDay()) ); final Engine<LongGene, Long> engine = Engine .builder(Duration::toMillis, durationCodec) .build(); final Phenotype<LongGene, Long> pt = engine.stream() .limit(100) .collect(EvolutionResult.toBestPhenotype()); System.out.println(pt); final Duration duration = durationCodec.decoder() .apply(pt.genotype()); System.out.println(duration);
- Type Parameters:
G
- the gene typeA
- the argument type of the first codecB
- the argument type of the second codecT
- the argument type of the compound codec- Parameters:
codec1
- the first codeccodec2
- the second codecdecoder
- the decoder which combines the two argument types from the given codecs, to the argument type of the resulting codec.- Returns:
- a new codec which combines the given
codec1
andcodec2
- Throws:
NullPointerException
- if one of the arguments isnull
- Since:
- 3.3
-
of
static <T,G extends Gene<?, Codec<T,G>> G> of(ISeq<? extends Codec<?, G>> codecs, Function<? super Object[], ? extends T> decoder) Combines the givencodecs
into one codec. This lets you divide a problem into sub problems and combine them again.The following example combines more than two sub-codecs into one.
final Codec<LocalDate, LongGene> dateCodec = Codec.of( Genotype.of(LongChromosome.of(0, 10_000)), gt -> LocalDate.ofEpochDay(gt.getGene().longValue()) ); final Codec<Duration, LongGene> durationCodec = Codec.of( ISeq.of(dateCodec, dateCodec, dateCodec), dates -> { final LocalDate ld1 = (LocalDate)dates[0]; final LocalDate ld2 = (LocalDate)dates[1]; final LocalDate ld3 = (LocalDate)dates[2]; return Duration.ofDays( ld1.toEpochDay() + ld2.toEpochDay() - ld3.toEpochDay() ); } ); final Engine<LongGene, Long> engine = Engine .builder(Duration::toMillis, durationCodec) .build(); final Phenotype<LongGene, Long> pt = engine.stream() .limit(100) .collect(EvolutionResult.toBestPhenotype()); System.out.println(pt); final Duration duration = durationCodec.decoder() .apply(pt.genotype()); System.out.println(duration);
- Type Parameters:
G
- the gene typeT
- the argument type of the compound codec- Parameters:
codecs
- theCodec
sequence of the sub-problemsdecoder
- the decoder which combines the argument types from the given codecs, to the argument type of the resulting codec.- Returns:
- a new codec which combines the given
codecs
- Throws:
NullPointerException
- if one of the arguments isnull
IllegalArgumentException
- if the givencodecs
sequence is empty- Since:
- 3.3
-