001 /*
002 * Java Genetic Algorithm Library (jenetics-6.0.0).
003 * Copyright (c) 2007-2020 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@gmail.com)
019 */
020 package io.jenetics;
021
022 import static java.util.Objects.requireNonNull;
023 import static io.jenetics.internal.util.Hashes.hash;
024 import static io.jenetics.util.RandomRegistry.random;
025
026 import java.util.Objects;
027 import java.util.function.Predicate;
028 import java.util.function.Supplier;
029
030 import io.jenetics.internal.math.Randoms;
031 import io.jenetics.util.ISeq;
032 import io.jenetics.util.IntRange;
033 import io.jenetics.util.MSeq;
034
035 /**
036 * {@code Gene} implementation, which allows to create genes without explicit
037 * implementing the {@code Gene} interface.
038 *
039 * <pre>{@code
040 * class Main {
041 * // First monday of 2015.
042 * private static final LocalDate MIN_MONDAY = LocalDate.of(2015, 1, 5);
043 *
044 * // Supplier of random 'LocalDate' objects. The implementation is responsible
045 * // for guaranteeing the desired allele restriction. In this case we will
046 * // generate only mondays.
047 * static LocalDate nextRandomMonday() {
048 * return MIN_MONDAY.plusWeeks(RandomRegistry.getRandom().nextInt(1000));
049 * }
050 *
051 * // Create a new 'LocalDate' gene. All other genes, created with
052 * // gene.newInstance(), are calling the 'newRandomMonday' method.
053 * final AnyGene<LocalDate> gene = AnyGene.of(Main::nextRandomMonday);
054 * }
055 * }</pre>
056 * The example above shows how to create {@code LocalDate} genes from a random
057 * {@code LocalDate} supplier. It also shows how to implement a restriction on
058 * the created dates. The usage of the {@code AnyGene} class is useful for
059 * supporting custom allele types without explicit implementation of the
060 * {@code Gene} interface. But the {@code AnyGene} can only be used for a subset
061 * of the existing alterers.
062 *
063 * @see AnyChromosome
064 *
065 * @implNote
066 * This class is immutable and thread-safe.
067 *
068 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
069 * @version 6.0
070 * @since 3.3
071 */
072 public final class AnyGene<A> implements Gene<A, AnyGene<A>> {
073
074 private final A _allele;
075 private final Supplier<? extends A> _supplier;
076 private final Predicate<? super A> _validator;
077
078 private AnyGene(
079 final A allele,
080 final Supplier<? extends A> supplier,
081 final Predicate<? super A> validator
082 ) {
083 _allele = allele;
084 _supplier = requireNonNull(supplier);
085 _validator = requireNonNull(validator);
086 }
087
088 @Override
089 public A allele() {
090 return _allele;
091 }
092
093 @Override
094 public AnyGene<A> newInstance() {
095 return new AnyGene<>(_supplier.get(), _supplier, _validator);
096 }
097
098 @Override
099 public AnyGene<A> newInstance(final A value) {
100 return new AnyGene<>(value, _supplier, _validator);
101 }
102
103 @Override
104 public boolean isValid() {
105 return _validator.test(_allele);
106 }
107
108 @Override
109 public int hashCode() {
110 return hash(_allele, hash(AnyGene.class));
111 }
112
113 @Override
114 public boolean equals(final Object obj) {
115 return obj == this ||
116 obj instanceof AnyGene &&
117 Objects.equals(((AnyGene)obj)._allele, _allele);
118 }
119
120 @Override
121 public String toString() {
122 return Objects.toString(_allele);
123 }
124
125
126 /* *************************************************************************
127 * Static factory methods.
128 * ************************************************************************/
129
130 /**
131 * Create a new {@code AnyGene} instance with the given parameters. New
132 * (random) genes are created with the given allele {@code supplier}.
133 *
134 * @param <A> the allele type
135 * @param allele the actual allele instance the created gene represents.
136 * {@code null} values are allowed.
137 * @param supplier the allele-supplier which is used for creating new,
138 * random alleles
139 * @param validator the validator used for validating the created gene. This
140 * predicate is used in the {@link #isValid()} method.
141 * @return a new {@code AnyGene} with the given parameters
142 * @throws NullPointerException if the {@code supplier} or {@code validator}
143 * is {@code null}
144 */
145 public static <A> AnyGene<A> of(
146 final A allele,
147 final Supplier<? extends A> supplier,
148 final Predicate<? super A> validator
149 ) {
150 return new AnyGene<>(allele, supplier, validator);
151 }
152
153 /**
154 * Create a new {@code AnyGene} instance with the given parameters. New
155 * (random) genes are created with the given allele {@code supplier}. The
156 * {@code validator} predicate of the generated gene will always return
157 * {@code true}.
158 *
159 * @param <A> the allele type
160 * @param allele the actual allele instance the created gene represents.
161 * {@code null} values are allowed.
162 * @param supplier the allele-supplier which is used for creating new,
163 * random alleles
164 * @return a new {@code AnyGene} with the given parameters
165 * @throws NullPointerException if the {@code suppler} is {@code null}
166 */
167 public static <A> AnyGene<A> of(
168 final A allele,
169 final Supplier<? extends A> supplier
170 ) {
171 return new AnyGene<>(allele, supplier, a -> true);
172 }
173
174 /**
175 * Create a new {@code AnyGene} instance with the given allele
176 * {@code supplier}. The {@code validator} predicate of the generated gene
177 * will always return {@code true}.
178 *
179 * @param <A> the allele type
180 * @param supplier the allele-supplier which is used for creating new,
181 * random alleles
182 * @return a new {@code AnyGene} with the given parameters
183 * @throws NullPointerException if one of the parameters is {@code null}
184 */
185 public static <A> AnyGene<A> of(final Supplier<? extends A> supplier) {
186 return new AnyGene<>(supplier.get(), supplier, a -> true);
187 }
188
189 /**
190 * Create a new {@code AnyGene} instance with the given parameters. New
191 * (random) genes are created with the given allele {@code supplier}.
192 *
193 * @param <A> the allele type
194 * @param supplier the allele-supplier which is used for creating new,
195 * random alleles
196 * @param validator the validator used for validating the created gene. This
197 * predicate is used in the {@link #isValid()} method.
198 * @return a new {@code AnyGene} with the given parameters
199 * @throws NullPointerException if one of the parameters is {@code null}
200 */
201 public static <A> AnyGene<A> of(
202 final Supplier<? extends A> supplier,
203 final Predicate<? super A> validator
204 ) {
205 return new AnyGene<>(supplier.get(), supplier, validator);
206 }
207
208 // Create gene sequence.
209 static <A> ISeq<AnyGene<A>> seq(
210 final IntRange lengthRange,
211 final Supplier<? extends A> supplier,
212 final Predicate<? super A> validator
213 ) {
214 return MSeq.<AnyGene<A>>ofLength(Randoms.nextInt(lengthRange, random()))
215 .fill(() -> of(supplier.get(), supplier, validator))
216 .toISeq();
217 }
218
219 }
|