All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.jenetics.util.RandomRegistry Maven / Gradle / Ivy

There is a newer version: 8.1.0
Show newest version
/*
 * Java Genetic Algorithm Library (jenetics-4.0.0).
 * Copyright (c) 2007-2017 Franz Wilhelmstötter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Author:
 *    Franz Wilhelmstötter ([email protected])
 */
package io.jenetics.util;

import static java.util.Objects.requireNonNull;

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import io.jenetics.internal.util.require;

/**
 * This class holds the {@link Random} engine used for the GA. The
 * {@code RandomRegistry} is thread safe. The registry is initialized with the
 * {@link ThreadLocalRandom} PRNG, which has a much better performance behavior
 * than an instance of the {@code Random} class. Alternatively, you can
 * initialize the registry with one of the PRNG, which are being part of the
 * library.
 * 

* * Setup of a global PRNG * *

{@code
 * public class GA {
 *     public static void main(final String[] args) {
 *         // Initialize the registry with a ThreadLocal instance of the PRGN.
 *         // This is the preferred way setting a new PRGN.
 *         RandomRegistry.setRandom(new LCG64ShiftRandom.ThreadLocal());
 *
 *         // Using a thread safe variant of the PRGN. Leads to slower PRN
 *         // generation, but gives you the possibility to set a PRNG seed.
 *         RandomRegistry.setRandom(new LCG64ShiftRandom.ThreadSafe(1234));
 *
 *         ...
 *         final EvolutionResult result = stream
 *             .limit(100)
 *             .collect(toBestEvolutionResult());
 *     }
 * }
 * }
*

* * Setup of a local PRNG
* * You can temporarily (and locally) change the implementation of the PRNG. E.g. * for initialize the engine stream with the same initial population. * *

{@code
 * public class GA {
 *     public static void main(final String[] args) {
 *         // Create a reproducible list of genotypes.
 *         final List> genotypes =
 *             with(new LCG64ShiftRandom(123), r ->
 *                 Genotype.of(DoubleChromosome.of(0, 10)).instances()
 *                     .limit(50)
 *                     .collect(toList())
 *             );
 *
 *         final Engine engine = ...;
 *         final EvolutionResult result = engine
 *              // Initialize the evolution stream with the given genotypes.
 *             .stream(genotypes)
 *             .limit(100)
 *             .collect(toBestEvolutionResult());
 *     }
 * }
 * }
*

* * @see Random * @see ThreadLocalRandom * * @author Franz Wilhelmstötter * @since 1.0 * @version 3.0 */ public final class RandomRegistry { private RandomRegistry() {require.noInstance();} private static final Context> CONTEXT = new Context<>(ThreadLocalRandom::current); /** * Return the global {@link Random} object. * * @return the global {@link Random} object. */ public static Random getRandom() { return CONTEXT.get().get(); } static Random random() { return CONTEXT.get().get(); } /** * Set the new global {@link Random} object for the GA. The given * {@link Random} must be thread safe, which is the case for the * default Java {@code Random} implementation. *

* Setting a thread-local random object leads, in general, to a faster * PRN generation, because the given {@code Random} engine don't have to be * thread-safe. * * @see #setRandom(ThreadLocal) * * @param random the new global {@link Random} object for the GA. * @throws NullPointerException if the {@code random} object is {@code null}. */ public static void setRandom(final Random random) { requireNonNull(random, "Random must not be null."); CONTEXT.set(() -> random); } /** * Set the new global {@link Random} object for the GA. The given * {@link Random} don't have be thread safe, because the given * {@link ThreadLocal} wrapper guarantees thread safety. Setting a * thread-local random object leads, in general, to a faster * PRN generation, when using a non-blocking PRNG. This is the preferred * way for changing the PRNG. * * @param random the thread-local random engine to use. * @throws NullPointerException if the {@code random} object is {@code null}. */ @SuppressWarnings("unchecked") public static void setRandom(final ThreadLocal random) { requireNonNull(random, "Random must not be null."); CONTEXT.set(random::get); } /** * Set the random object to it's default value. The default used PRNG * is the {@link ThreadLocalRandom} PRNG. */ public static void reset() { CONTEXT.reset(); } /** * Executes the consumer code using the given {@code random} engine. * *

{@code
	 * final MSeq seq = ...
	 * using(new Random(123), r -> {
	 *     seq.shuffle();
	 * });
	 * }
* * The example above shuffles the given integer {@code seq} using the * given {@code Random(123)} engine. * * @since 3.0 * * @param random the PRNG used within the consumer * @param consumer the consumer which is executed with the scope of * the given {@code random} engine. * @param the type of the random engine * @throws NullPointerException if one of the arguments is {@code null} */ public static void using( final R random, final Consumer consumer ) { CONTEXT.with(() -> random, r -> { consumer.accept(random); return null; }); } /** * Executes the consumer code using the given {@code random} engine. * *
{@code
	 * final MSeq seq = ...
	 * using(new LCG64ShiftRandom.ThreadLocal(), r -> {
	 *     seq.shuffle();
	 * });
	 * }
* * The example above shuffles the given integer {@code seq} using the * given {@code LCG64ShiftRandom.ThreadLocal()} engine. * * @since 3.0 * * @param random the PRNG used within the consumer * @param consumer the consumer which is executed with the scope of * the given {@code random} engine. * @param the type of the random engine * @throws NullPointerException if one of the arguments is {@code null} */ public static void using( final ThreadLocal random, final Consumer consumer ) { CONTEXT.with(random::get, r -> { consumer.accept(random.get()); return null; }); } /** * Opens a new {@code Scope} with the given random engine and executes the * given function within it. The following example shows how to create a * reproducible list of genotypes: *
{@code
	 * final List> genotypes =
	 *     with(new LCG64ShiftRandom(123), r ->
	 *         Genotype.of(DoubleChromosome.of(0, 10)).instances()
	 *            .limit(50)
	 *            .collect(toList())
	 *     );
	 * }
* * @since 3.0 * * @param the type of the random engine * @param the function return type * @param random the PRNG used for the opened scope * @param function the function to apply within the random scope * @return the object returned by the given function * @throws NullPointerException if one of the arguments is {@code null} */ public static T with( final R random, final Function function ) { return CONTEXT.with(() -> random, s -> function.apply(random)); } /** * Opens a new {@code Scope} with the given random engine and executes the * given function within it. The following example shows how to create a * reproducible list of genotypes: *
{@code
	 * final List> genotypes =
	 *     with(new LCG64ShiftRandom.ThreadLocal(), random ->
	 *         Genotype.of(DoubleChromosome.of(0, 10)).instances()
	 *            .limit(50)
	 *            .collect(toList())
	 *     );
	 * }
* * @since 3.0 * * @param the type of the random engine * @param the function return type * @param random the PRNG used for the opened scope * @param function the function to apply within the random scope * @return the object returned by the given function * @throws NullPointerException if one of the arguments is {@code null}. */ public static T with( final ThreadLocal random, final Function function ) { return CONTEXT.with(random::get, s -> function.apply(random.get())); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy