001 /*
002 * Java Genetic Algorithm Library (jenetics-2.0.2).
003 * Copyright (c) 2007-2014 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.util;
021
022 import static java.util.Objects.requireNonNull;
023
024 import java.util.Random;
025 import java.util.concurrent.ThreadLocalRandom;
026
027 import org.jenetics.internal.util.Context;
028 import org.jenetics.internal.util.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 * [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.setRandom(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.setRandom(new LCG64ShiftRandom.ThreadSafe(1234));
051 *
052 * ...
053 * final GeneticAlgorithm<DoubleGene, Double> ga = ...
054 * ga.evolve(100);
055 * }
056 * }
057 * [/code]
058 * <p>
059 *
060 * <b>Setup of a <i>local</i> PRNG</b><br>
061 *
062 * You can temporarily (and locally) change the implementation of the PRNG.
063 *
064 * [code]
065 * public class GA {
066 * public static void main(final String[] args) {
067 * ...
068 * final GeneticAlgorithm<DoubleGene, Double> ga = ...
069 * final LCG64ShiftRandom random = new LCG64ShiftRandom(1234)
070 *
071 * try (Scoped<Random> scope = RandomRegistry.scope(random)) {
072 * // Easy access the random engine of the opened scope.
073 * assert(scope.get() == random);
074 *
075 * // Only the 'setup' step uses the new PRGN.
076 * ga.setup();
077 * }
078 *
079 * ga.evolve(100);
080 * }
081 * }
082 * [/code]
083 * <p>
084 *
085 * @see Random
086 * @see ThreadLocalRandom
087 * @see LCG64ShiftRandom
088 *
089 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
090 * @since 1.0
091 * @version 2.0 — <em>$Date: 2014-04-15 $</em>
092 */
093 public final class RandomRegistry extends StaticObject {
094 private RandomRegistry() {}
095
096 // Default random engine used.
097 private static final Supplier<Random> DEFAULT = new Supplier<Random>() {
098 @Override
099 public Random get() {
100 return ThreadLocalRandom.current();
101 }
102 };
103
104 private static final Context<Supplier<Random>> CONTEXT =
105 new Context<>(DEFAULT);
106
107 /**
108 * Return the global {@link Random} object.
109 *
110 * @return the global {@link Random} object.
111 */
112 public static Random getRandom() {
113 return CONTEXT.get().get();
114 }
115
116 /**
117 * Set the new global {@link Random} object for the GA. The given
118 * {@link Random} <b>must</b> be thread safe, which is the case for the
119 * default Java {@code Random} implementation.
120 * <p>
121 * Setting a <i>thread-local</i> random object leads, in general, to a faster
122 * PRN generation, because the given {@code Random} engine don't have to be
123 * thread-safe.
124 *
125 * @see #setRandom(ThreadLocal)
126 *
127 * @param random the new global {@link Random} object for the GA.
128 * @throws NullPointerException if the {@code random} object is {@code null}.
129 */
130 public static void setRandom(final Random random) {
131 requireNonNull(random, "Random must not be null.");
132 CONTEXT.set(new RandomSupplier<>(random));
133 }
134
135 /**
136 * Set the new global {@link Random} object for the GA. The given
137 * {@link Random} don't have be thread safe, because the given
138 * {@link ThreadLocal} wrapper guarantees thread safety. Setting a
139 * <i>thread-local</i> random object leads, in general, to a faster
140 * PRN generation, when using a non-blocking PRNG. This is the preferred
141 * way for changing the PRNG.
142 *
143 * @param random the thread-local random engine to use.
144 * @throws NullPointerException if the {@code random} object is {@code null}.
145 */
146 @SuppressWarnings("unchecked")
147 public static void setRandom(final ThreadLocal<? extends Random> random) {
148 requireNonNull(random, "Random must not be null.");
149 CONTEXT.set((Supplier<Random>)new ThreadLocalRandomSupplier<>(random));
150 }
151
152 /**
153 * Set the random object to it's default value. The <i>default</i> used PRNG
154 * is the {@link ThreadLocalRandom} PRNG.
155 */
156 public static void reset() {
157 CONTEXT.reset();
158 }
159
160 /**
161 * Opens a new {@code Scope} with the given random engine.
162 *
163 * @param <R> the type of the random engine
164 * @param random the PRNG used for the opened scope.
165 * @return the scope with the given random object.
166 */
167 @SuppressWarnings("unchecked")
168 public static <R extends Random> Scoped<R> scope(final R random) {
169 final RandomSupplier<R> supplier = new RandomSupplier<>(random);
170 return CONTEXT.scope((Supplier<Random>) supplier, supplier);
171 }
172
173 /**
174 * Opens a new {@code Scope} with the given random engine.
175 *
176 * @param <R> the type of the random engine
177 * @param random the PRNG used for the opened scope.
178 * @return the scope with the given random object.
179 */
180 @SuppressWarnings("unchecked")
181 public static <R extends Random> Scoped<R> scope(final ThreadLocal<R> random) {
182 final ThreadLocalRandomSupplier<R> supplier =
183 new ThreadLocalRandomSupplier<>(random);
184
185 return CONTEXT.scope((Supplier<Random>) supplier, supplier);
186 }
187
188 /* *************************************************************************
189 * Some private helper classes.
190 * ************************************************************************/
191
192 private final static class RandomSupplier<R extends Random>
193 implements Supplier<R>
194 {
195 private final R _random;
196
197 RandomSupplier(final R random) {
198 _random = requireNonNull(random, "Random must not be null.");
199 }
200
201 @Override
202 public final R get() {
203 return _random;
204 }
205 }
206
207 private final static class ThreadLocalRandomSupplier<R extends Random>
208 implements Supplier<R>
209 {
210 private final ThreadLocal<R> _random;
211
212 ThreadLocalRandomSupplier(final ThreadLocal<R> random) {
213 _random = requireNonNull(random, "Random must not be null.");
214 }
215
216 @Override
217 public final R get() {
218 return _random.get();
219 }
220 }
221
222 }
|