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