RandomRegistry.java
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&lt;DoubleGene, Double&gt; 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&lt;DoubleGene, Double&gt; ga = ...
069  *         final LCG64ShiftRandom random = new LCG64ShiftRandom(1234)
070  *
071  *         try (Scoped&lt;Random&gt; 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 &mdash; <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 }