001 /*
002 * Java Genetic Algorithm Library (jenetics-5.2.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.util;
021
022 import static java.util.Objects.requireNonNull;
023
024 import java.util.Random;
025 import java.util.concurrent.ThreadLocalRandom;
026 import java.util.function.Consumer;
027 import java.util.function.Function;
028 import java.util.function.Supplier;
029
030 /**
031 * This class holds the {@link Random} engine used for the GA. The
032 * {@code RandomRegistry} is thread safe. The registry is initialized with the
033 * {@link ThreadLocalRandom} PRNG, which has a much better performance behavior
034 * than an instance of the {@code Random} class. Alternatively, you can
035 * initialize the registry with one of the PRNG, which are being part of the
036 * library.
037 * <p>
038 *
039 * <b>Setup of a <i>global</i> PRNG</b>
040 *
041 * <pre>{@code
042 * public class GA {
043 * public static void main(final String[] args) {
044 * // Initialize the registry with a ThreadLocal instance of the PRGN.
045 * // This is the preferred way setting a new PRGN.
046 * RandomRegistry.random(new LCG64ShiftRandom.ThreadLocal());
047 *
048 * // Using a thread safe variant of the PRGN. Leads to slower PRN
049 * // generation, but gives you the possibility to set a PRNG seed.
050 * RandomRegistry.random(new LCG64ShiftRandom.ThreadSafe(1234));
051 *
052 * ...
053 * final EvolutionResult<DoubleGene, Double> result = stream
054 * .limit(100)
055 * .collect(toBestEvolutionResult());
056 * }
057 * }
058 * }</pre>
059 * <p>
060 *
061 * <b>Setup of a <i>local</i> PRNG</b><br>
062 *
063 * You can temporarily (and locally) change the implementation of the PRNG. E.g.
064 * for initialize the engine stream with the same initial population.
065 *
066 * <pre>{@code
067 * public class GA {
068 * public static void main(final String[] args) {
069 * // Create a reproducible list of genotypes.
070 * final List<Genotype<DoubleGene>> genotypes =
071 * with(new LCG64ShiftRandom(123), r ->
072 * Genotype.of(DoubleChromosome.of(0, 10)).instances()
073 * .limit(50)
074 * .collect(toList())
075 * );
076 *
077 * final Engine<DoubleGene, Double> engine = ...;
078 * final EvolutionResult<DoubleGene, Double> result = engine
079 * // Initialize the evolution stream with the given genotypes.
080 * .stream(genotypes)
081 * .limit(100)
082 * .collect(toBestEvolutionResult());
083 * }
084 * }
085 * }</pre>
086 * <p>
087 *
088 * @see Random
089 * @see ThreadLocalRandom
090 *
091 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
092 * @since 1.0
093 * @version 3.0
094 */
095 public final class RandomRegistry {
096 private RandomRegistry() {}
097
098 private static final Context<Supplier<Random>> CONTEXT =
099 new Context<>(ThreadLocalRandom::current);
100
101 /**
102 * Return the global {@link Random} object.
103 *
104 * @return the global {@link Random} object.
105 */
106 public static Random random() {
107 return CONTEXT.get().get();
108 }
109
110 /**
111 * Return the global {@link Random} object.
112 *
113 * @return the global {@link Random} object.
114 * @deprecated Use {@link #random()} instead
115 */
116 @Deprecated
117 public static Random getRandom() {
118 return CONTEXT.get().get();
119 }
120
121 /**
122 * Set the new global {@link Random} object for the GA. The given
123 * {@link Random} <b>must</b> be thread safe, which is the case for the
124 * default Java {@code Random} implementation.
125 * <p>
126 * Setting a <i>thread-local</i> random object leads, in general, to a faster
127 * PRN generation, because the given {@code Random} engine don't have to be
128 * thread-safe.
129 *
130 * @see #random(ThreadLocal)
131 *
132 * @param random the new global {@link Random} object for the GA.
133 * @throws NullPointerException if the {@code random} object is {@code null}.
134 */
135 public static void random(final Random random) {
136 requireNonNull(random, "Random must not be null.");
137 CONTEXT.set(() -> random);
138 }
139
140 /**
141 * Set the new global {@link Random} object for the GA. The given
142 * {@link Random} <b>must</b> be thread safe, which is the case for the
143 * default Java {@code Random} implementation.
144 * <p>
145 * Setting a <i>thread-local</i> random object leads, in general, to a faster
146 * PRN generation, because the given {@code Random} engine don't have to be
147 * thread-safe.
148 *
149 * @see #random(ThreadLocal)
150 *
151 * @param random the new global {@link Random} object for the GA.
152 * @throws NullPointerException if the {@code random} object is {@code null}.
153 * @deprecated Use {@link #random(Random)} instead
154 */
155 @Deprecated
156 public static void setRandom(final Random random) {
157 requireNonNull(random, "Random must not be null.");
158 CONTEXT.set(() -> random);
159 }
160
161 /**
162 * Set the new global {@link Random} object for the GA. The given
163 * {@link Random} don't have be thread safe, because the given
164 * {@link ThreadLocal} wrapper guarantees thread safety. Setting a
165 * <i>thread-local</i> random object leads, in general, to a faster
166 * PRN generation, when using a non-blocking PRNG. This is the preferred
167 * way for changing the PRNG.
168 *
169 * @param random the thread-local random engine to use.
170 * @throws NullPointerException if the {@code random} object is {@code null}.
171 */
172 @SuppressWarnings("unchecked")
173 public static void random(final ThreadLocal<? extends Random> random) {
174 requireNonNull(random, "Random must not be null.");
175 CONTEXT.set(random::get);
176 }
177
178 /**
179 * Set the new global {@link Random} object for the GA. The given
180 * {@link Random} don't have be thread safe, because the given
181 * {@link ThreadLocal} wrapper guarantees thread safety. Setting a
182 * <i>thread-local</i> random object leads, in general, to a faster
183 * PRN generation, when using a non-blocking PRNG. This is the preferred
184 * way for changing the PRNG.
185 *
186 * @param random the thread-local random engine to use.
187 * @throws NullPointerException if the {@code random} object is {@code null}.
188 * @deprecated Use {@link #random(ThreadLocal)} instead
189 */
190 @Deprecated
191 @SuppressWarnings("unchecked")
192 public static void setRandom(final ThreadLocal<? extends Random> random) {
193 requireNonNull(random, "Random must not be null.");
194 CONTEXT.set(random::get);
195 }
196
197 /**
198 * Set the random object to it's default value. The <i>default</i> used PRNG
199 * is the {@link ThreadLocalRandom} PRNG.
200 */
201 public static void reset() {
202 CONTEXT.reset();
203 }
204
205 /**
206 * Executes the consumer code using the given {@code random} engine.
207 *
208 * <pre>{@code
209 * final MSeq<Integer> seq = ...
210 * using(new Random(123), r -> {
211 * seq.shuffle();
212 * });
213 * }</pre>
214 *
215 * The example above shuffles the given integer {@code seq} <i>using</i> the
216 * given {@code Random(123)} engine.
217 *
218 * @since 3.0
219 *
220 * @param random the PRNG used within the consumer
221 * @param consumer the consumer which is executed with the <i>scope</i> of
222 * the given {@code random} engine.
223 * @param <R> the type of the random engine
224 * @throws NullPointerException if one of the arguments is {@code null}
225 */
226 public static <R extends Random> void using(
227 final R random,
228 final Consumer<? super R> consumer
229 ) {
230 CONTEXT.with(() -> random, r -> {
231 consumer.accept(random);
232 return null;
233 });
234 }
235
236 /**
237 * Executes the consumer code using the given {@code random} engine.
238 *
239 * <pre>{@code
240 * final MSeq<Integer> seq = ...
241 * using(new LCG64ShiftRandom.ThreadLocal(), r -> {
242 * seq.shuffle();
243 * });
244 * }</pre>
245 *
246 * The example above shuffles the given integer {@code seq} <i>using</i> the
247 * given {@code LCG64ShiftRandom.ThreadLocal()} engine.
248 *
249 * @since 3.0
250 *
251 * @param random the PRNG used within the consumer
252 * @param consumer the consumer which is executed with the <i>scope</i> of
253 * the given {@code random} engine.
254 * @param <R> the type of the random engine
255 * @throws NullPointerException if one of the arguments is {@code null}
256 */
257 public static <R extends Random> void using(
258 final ThreadLocal<R> random,
259 final Consumer<? super R> consumer
260 ) {
261 CONTEXT.with(random::get, r -> {
262 consumer.accept(random.get());
263 return null;
264 });
265 }
266
267 /**
268 * Opens a new {@code Scope} with the given random engine and executes the
269 * given function within it. The following example shows how to create a
270 * reproducible list of genotypes:
271 * <pre>{@code
272 * final List<Genotype<DoubleGene>> genotypes =
273 * with(new LCG64ShiftRandom(123), r ->
274 * Genotype.of(DoubleChromosome.of(0, 10)).instances()
275 * .limit(50)
276 * .collect(toList())
277 * );
278 * }</pre>
279 *
280 * @since 3.0
281 *
282 * @param <R> the type of the random engine
283 * @param <T> the function return type
284 * @param random the PRNG used for the opened scope
285 * @param function the function to apply within the random scope
286 * @return the object returned by the given function
287 * @throws NullPointerException if one of the arguments is {@code null}
288 */
289 public static <R extends Random, T> T with(
290 final R random,
291 final Function<? super R, ? extends T> function
292 ) {
293 return CONTEXT.with(() -> random, s -> function.apply(random));
294 }
295
296 /**
297 * Opens a new {@code Scope} with the given random engine and executes the
298 * given function within it. The following example shows how to create a
299 * reproducible list of genotypes:
300 * <pre>{@code
301 * final List<Genotype<DoubleGene>> genotypes =
302 * with(new LCG64ShiftRandom.ThreadLocal(), random ->
303 * Genotype.of(DoubleChromosome.of(0, 10)).instances()
304 * .limit(50)
305 * .collect(toList())
306 * );
307 * }</pre>
308 *
309 * @since 3.0
310 *
311 * @param <R> the type of the random engine
312 * @param <T> the function return type
313 * @param random the PRNG used for the opened scope
314 * @param function the function to apply within the random scope
315 * @return the object returned by the given function
316 * @throws NullPointerException if one of the arguments is {@code null}.
317 */
318 public static <R extends Random, T> T with(
319 final ThreadLocal<R> random,
320 final Function<? super R, ? extends T> function
321 ) {
322 return CONTEXT.with(random::get, s -> function.apply(random.get()));
323 }
324
325 }
|