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