CompositeAlterer.java
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;
021 
022 import static java.lang.String.format;
023 import static org.jenetics.internal.util.Equality.eq;
024 import static org.jenetics.util.ISeq.toISeq;
025 
026 import java.util.function.Function;
027 import java.util.stream.Collectors;
028 import java.util.stream.Stream;
029 
030 import org.jenetics.internal.util.Hash;
031 
032 import org.jenetics.util.ISeq;
033 import org.jenetics.util.Seq;
034 
035 /**
036  * Combines several alterers to one.
037  *
038  * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
039  * @since 1.0
040  * @version 3.0
041  */
042 final class CompositeAlterer<
043     G extends Gene<?, G>,
044     C extends Comparable<? super C>
045 >
046     extends AbstractAlterer<G, C>
047 {
048 
049     private final ISeq<Alterer<G, C>> _alterers;
050 
051     /**
052      * Combine the given alterers.
053      *
054      * @param alterers the alterers to combine.
055      * @throws NullPointerException if one of the alterers is {@code null}.
056      */
057     public CompositeAlterer(final Seq<Alterer<G, C>> alterers) {
058         super(1.0);
059         _alterers = normalize(alterers);
060     }
061 
062     private static <G extends Gene<?, G>, C extends Comparable<? super C>>
063     ISeq<Alterer<G, C>> normalize(final Seq<Alterer<G, C>> alterers) {
064         final Function<Alterer<G, C>, Stream<Alterer<G, C>>> mapper =
065             a -> a instanceof CompositeAlterer<?, ?>
066                 ? ((CompositeAlterer<G, C>)a).getAlterers().stream()
067                 : Stream.of(a);
068 
069         return alterers.stream()
070             .flatMap(mapper)
071             .collect(toISeq());
072     }
073 
074     @Override
075     public int alter(final Population<G, C> population, final long generation) {
076         return _alterers.stream()
077             .mapToInt(a -> a.alter(population, generation))
078             .sum();
079     }
080 
081     /**
082      * Return the alterers this alterer consists of. The returned array is sealed
083      * and cannot be changed.
084      *
085      * @return the alterers this alterer consists of.
086      */
087     public ISeq<Alterer<G, C>> getAlterers() {
088         return _alterers;
089     }
090 
091     @Override
092     public int hashCode() {
093         return Hash.of(getClass()).and(_alterers).value();
094     }
095 
096     @Override
097     public boolean equals(final Object obj) {
098         return obj instanceof CompositeAlterer &&
099             eq(((CompositeAlterer)obj)._alterers, _alterers);
100     }
101 
102     @Override
103     public String toString() {
104         return format(
105             "%s:\n%s", getClass().getSimpleName(),
106             _alterers.stream()
107                 .map(a -> "   - " + a)
108                 .collect(Collectors.joining("\n"))
109         );
110     }
111 
112     /**
113      * Combine the given alterers.
114      *
115      * @param <G> the gene type
116      * @param <C> the fitness function result type
117      * @param alterers the alterers to combine.
118      * @return a new alterer which consists of the given one
119      * @throws NullPointerException if one of the alterers is {@code null}.
120      */
121     @SafeVarargs
122     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
123     CompositeAlterer<G, C> of(final Alterer<G, C>... alterers) {
124         return new CompositeAlterer<>(ISeq.of(alterers));
125     }
126 
127     /**
128      * Joins the given alterer and returns a new CompositeAlterer object. If one
129      * of the given alterers is a CompositeAlterer the sub alterers of it are
130      * unpacked and appended to the newly created CompositeAlterer.
131      *
132      * @param <T> the gene type of the alterers.
133      *
134      * @param <C> the fitness function result type
135      * @param a1 the first alterer.
136      * @param a2 the second alterer.
137      * @return a new CompositeAlterer object.
138      * @throws NullPointerException if one of the given alterer is {@code null}.
139      */
140     public static <T extends Gene<?, T>, C extends Comparable<? super C>>
141     CompositeAlterer<T, C> join(
142         final Alterer<T, C> a1,
143         final Alterer<T, C> a2
144     ) {
145         return CompositeAlterer.of(a1, a2);
146     }
147 }