001 /*
002 * Java Genetic Algorithm Library (jenetics-3.5.0).
003 * Copyright (c) 2007-2016 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics.engine;
021
022 import static java.util.Objects.requireNonNull;
023
024 import java.util.function.Function;
025
026 import org.jenetics.Chromosome;
027 import org.jenetics.Gene;
028 import org.jenetics.Genotype;
029 import org.jenetics.util.Factory;
030 import org.jenetics.util.ISeq;
031
032 /**
033 * Composites a list of codecs into one {@code Codec} class.
034 *
035 * @param <G> the gene type
036 * @param <T> the argument type of the compound codec
037 *
038 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
039 * @version 3.3
040 * @since 3.3
041 */
042 final class CompositeCodec<T, G extends Gene<?, G>> implements Codec<T, G> {
043
044 private final ISeq<? extends Codec<?, G>> _codecs;
045 private final Function<? super Object[], ? extends T> _decoder;
046
047 private final int[] _lengths;
048 private final Genotype<G> _encoding;
049
050 /**
051 * Combines the given {@code codecs} into one codec. This lets you divide
052 * a problem into sub problems and combine them again.
053 *
054 * @param codecs the {@code Codec} sequence of the sub-problems
055 * @param decoder the decoder which combines the argument types from the
056 * given given codecs, to the argument type of the resulting codec.
057 * @throws NullPointerException if one of the arguments is {@code null}
058 */
059 CompositeCodec(
060 final ISeq<? extends Codec<?, G>> codecs,
061 final Function<? super Object[], ? extends T> decoder
062 ) {
063 _codecs = requireNonNull(codecs);
064 _decoder = requireNonNull(decoder);
065
066 final ISeq<Genotype<G>> genotypes = _codecs
067 .map(c -> c.encoding() instanceof Genotype<?>
068 ? (Genotype<G>)c.encoding()
069 : c.encoding().newInstance());
070
071 _lengths = genotypes.stream()
072 .mapToInt(Genotype::length)
073 .toArray();
074
075 _encoding = Genotype.of(
076 genotypes.stream()
077 .flatMap(Genotype::stream)
078 .collect(ISeq.toISeq())
079 );
080 }
081
082 @Override
083 public Factory<Genotype<G>> encoding() {
084 return _encoding;
085 }
086
087 @Override
088 public Function<Genotype<G>, T> decoder() {
089 return gt -> _decoder.apply(groups(gt));
090 }
091
092 private Object[] groups(final Genotype<G> genotype) {
093 final Object[] groups = new Object[_codecs.length()];
094 final ISeq<Chromosome<G>> chromosomes = genotype.toSeq();
095
096 int start = 0;
097 for (int i = 0; i < _codecs.length(); ++i) {
098 final int end = start + _lengths[i];
099 final Genotype<G> gt = Genotype.of(chromosomes.subSeq(start, end));
100
101 groups[i] = _codecs.get(i).decoder().apply(gt);
102 start = end;
103 }
104
105 return groups;
106 }
107
108 }
|