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

org.apache.commons.rng.sampling.PermutationSampler Maven / Gradle / Ivy

Go to download

The Apache Commons RNG Sampling module provides samplers for various distributions.

There is a newer version: 1.6
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

package org.apache.commons.rng.sampling;

import org.apache.commons.rng.UniformRandomProvider;

/**
 * Class for representing permutations
 * of a sequence of integers.
 *
 * 

Sampling uses {@link UniformRandomProvider#nextInt(int)}.

* *

This class also contains utilities for shuffling an {@code int[]} array in-place.

*/ public class PermutationSampler implements SharedStateObjectSampler { /** Domain of the permutation. */ private final int[] domain; /** Size of the permutation. */ private final int size; /** RNG. */ private final UniformRandomProvider rng; /** * Creates a generator of permutations. * *

The {@link #sample()} method will generate an integer array of * length {@code k} whose entries are selected randomly, without * repetition, from the integers 0, 1, ..., {@code n}-1 (inclusive). * The returned array represents a permutation of {@code n} taken * {@code k}.

* * @param rng Generator of uniformly distributed random numbers. * @param n Domain of the permutation. * @param k Size of the permutation. * @throws IllegalArgumentException if {@code n <= 0} or {@code k <= 0} * or {@code k > n}. */ public PermutationSampler(UniformRandomProvider rng, int n, int k) { SubsetSamplerUtils.checkSubset(n, k); domain = natural(n); size = k; this.rng = rng; } /** * @param rng Generator of uniformly distributed random numbers. * @param source Source to copy. */ private PermutationSampler(UniformRandomProvider rng, PermutationSampler source) { // Do not clone the domain. This ensures: // 1. Thread safety as the domain may be shuffled during the clone // and an incomplete shuffle swap step can result in duplicates and // missing elements in the array. // 2. If the argument RNG is an exact match for the RNG in the source // then the output sequence will differ unless the domain is currently // in natural order. domain = PermutationSampler.natural(source.domain.length); size = source.size; this.rng = rng; } /** * @return a random permutation. * * @see #PermutationSampler(UniformRandomProvider,int,int) */ @Override public int[] sample() { return SubsetSamplerUtils.partialSample(domain, size, rng, true); } /** * {@inheritDoc} * * @since 1.3 */ @Override public PermutationSampler withUniformRandomProvider(UniformRandomProvider rng) { return new PermutationSampler(rng, this); } /** * Shuffles the entries of the given array. * * @see #shuffle(UniformRandomProvider,int[],int,boolean) * * @param rng Random number generator. * @param list Array whose entries will be shuffled (in-place). */ public static void shuffle(UniformRandomProvider rng, int[] list) { shuffle(rng, list, list.length - 1, true); } /** * Shuffles the entries of the given array, using the * * Fisher-Yates algorithm. * The {@code start} and {@code towardHead} parameters select which part * of the array is randomized and which is left untouched. * *

Sampling uses {@link UniformRandomProvider#nextInt(int)}.

* * @param rng Random number generator. * @param list Array whose entries will be shuffled (in-place). * @param start Index at which shuffling begins. * @param towardHead Shuffling is performed for index positions between * {@code start} and either the end (if {@code false}) or the beginning * (if {@code true}) of the array. */ public static void shuffle(UniformRandomProvider rng, int[] list, int start, boolean towardHead) { if (towardHead) { // Visit all positions from start to 0. // Do not visit 0 to avoid a swap with itself. for (int i = start; i > 0; i--) { // Swap index with any position down to 0 SubsetSamplerUtils.swap(list, i, rng.nextInt(i + 1)); } } else { // Visit all positions from the end to start. // Start is not visited to avoid a swap with itself. for (int i = list.length - 1; i > start; i--) { // Swap index with any position down to start. // Note: i - start + 1 is the number of elements remaining. SubsetSamplerUtils.swap(list, i, rng.nextInt(i - start + 1) + start); } } } /** * Creates an array representing the natural number {@code n}. * * @param n Natural number. * @return an array whose entries are the numbers 0, 1, ..., {@code n}-1. * If {@code n == 0}, the returned array is empty. */ public static int[] natural(int n) { final int[] a = new int[n]; for (int i = 0; i < n; i++) { a[i] = i; } return a; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy