    001/*-
    002 *******************************************************************************
    003 * Copyright (c) 2011, 2016 Diamond Light Source Ltd.
    004 * All rights reserved. This program and the accompanying materials
    005 * are made available under the terms of the Eclipse Public License v1.0
    006 * which accompanies this distribution, and is available at
    007 * http://www.eclipse.org/legal/epl-v10.html
    008 *
    009 * Contributors:
    010 *    Peter Chang - initial API and implementation and/or initial documentation
    011 *******************************************************************************/
    012
    013package org.eclipse.january.dataset;
    014
    015
    016import java.io.IOException;
    017
    018import org.apache.commons.math3.random.MersenneTwister;
    019import org.apache.commons.math3.random.RandomDataGenerator;
    020import org.apache.commons.math3.random.RandomGenerator;
    021import org.eclipse.january.IMonitor;
    022import org.eclipse.january.io.ILazyLoader;
    023
    024/**
    025 * Class to hold methods to create random datasets
    026 *
    027 * Emulates numpy.random
    028 */
    029public class Random {
    030        private final static RandomGenerator generator = new MersenneTwister();
    031        private final static RandomDataGenerator prng = new RandomDataGenerator(generator);
    032
    033        /**
    034         * @param seed value for generator
    035         */
    036        public static void seed(final int seed) {
    037                generator.setSeed(seed);
    038        }
    039
    040        /**
    041         * @param seed values for generator
    042         */
    043        public static void seed(final int[] seed) {
    044                generator.setSeed(seed);
    045        }
    046
    047        /**
    048         * @param seed value for generator
    049         */
    050        public static void seed(final long seed) {
    051                generator.setSeed(seed);
    052        }
    053
    054        /**
    055         * @param shape output shape
    056         * @return an array of values sampled from a uniform distribution between 0 (inclusive) and 1 (exclusive)
    057         */
    058        public static DoubleDataset rand(final int... shape) {
    059                DoubleDataset data = DatasetFactory.zeros(DoubleDataset.class, shape);
    060                double[] buf = data.getData();
    061
    062                for (int i = 0; i < buf.length; i++) {
    063                        buf[i] = generator.nextDouble();
    064                }
    065
    066                return data;
    067        }
    068
    069        /**
    070         * @param low lower exclusive bound
    071         * @param high upper exclusive bound
    072         * @param shape output shape
    073         * @return an array of values sampled from a uniform distribution between low and high (both exclusive)
    074         */
    075        public static DoubleDataset rand(double low, double high, final int... shape) {
    076                DoubleDataset data = DatasetFactory.zeros(DoubleDataset.class, shape);
    077                double[] buf = data.getData();
    078
    079                for (int i = 0; i < buf.length; i++) {
    080                        buf[i] = prng.nextUniform(low, high);
    081                }
    082
    083                return data;
    084        }
    085
    086        /**
    087         * @param shape output shape
    088         * @return an array of values sampled from a Gaussian distribution with mean 0 and variance 1
    089         *
    090         * (The term Gaussian here is a description of a shape of data taken from the mathematician of the
    091         * same name Carl Friedrich Gauss  http://en.wikipedia.org/wiki/Carl_Friedrich_Gauss born in 1777.)
    092         */
    093        public static DoubleDataset randn(final int... shape) {
    094                DoubleDataset data = DatasetFactory.zeros(DoubleDataset.class, shape);
    095                double[] buf = data.getData();
    096
    097                for (int i = 0; i < buf.length; i++) {
    098                        buf[i] = generator.nextGaussian();
    099                }
    100
    101                return data;
    102        }
    103
    104        /**
    105         * @param mean mean of distribution
    106         * @param std standard deviation
    107         * @param shape output shape
    108         * @return an array of values sampled from a Gaussian distribution with given mean and standard deviation
    109         */
    110        public static DoubleDataset randn(double mean, double std, final int... shape) {
    111                DoubleDataset data = DatasetFactory.zeros(DoubleDataset.class, shape);
    112                double[] buf = data.getData();
    113
    114                for (int i = 0; i < buf.length; i++) {
    115                        buf[i] = prng.nextGaussian(mean, std);
    116                }
    117
    118                return data;
    119        }
    120
    121        /**
    122         * @param low lower inclusive bound
    123         * @param high upper exclusive bound
    124         * @param shape output shape
    125         * @return an array of values sampled from a discrete uniform distribution in range [low, high)
    126         */
    127        public static IntegerDataset randint(final int low, final int high, final int[] shape) {
    128                return random_integers(low, high-1, shape);
    129        }
    130
    131        /**
    132         * @param low lower inclusive bound
    133         * @param high upper inclusive bound
    134         * @param shape output shape
    135         * @return an array of values sampled from a discrete uniform distribution in range [low, high]
    136         */
    137        public static IntegerDataset random_integers(final int low, final int high, final int[] shape) {
    138                IntegerDataset data = DatasetFactory.zeros(IntegerDataset.class, shape);
    139                int[] buf = data.getData();
    140
    141                if (low == high) {
    142                        for (int i = 0; i < buf.length; i++) {
    143                                buf[i] = low;
    144                        }
    145                } else {
    146                        for (int i = 0; i < buf.length; i++) {
    147                                buf[i] = prng.nextInt(low, high);
    148                        }
    149                }
    150
    151                return data;
    152        }
    153
    154        /**
    155         * @param beta mean
    156         * @param shape output shape
    157         * @return an array of values sampled from an exponential distribution with mean beta
    158         */
    159        public static DoubleDataset exponential(final double beta, final int... shape) {
    160                DoubleDataset data = DatasetFactory.zeros(DoubleDataset.class, shape);
    161                double[] buf = data.getData();
    162
    163                for (int i = 0; i < buf.length; i++) {
    164                        buf[i] = prng.nextExponential(beta);
    165                }
    166
    167                return data;
    168        }
    169
    170        /**
    171         * @param lam Poisson parameter
    172         * @param shape output shape
    173         * @return an array of values sampled from an exponential distribution with mean lambda
    174         */
    175        public static IntegerDataset poisson(final double lam, final int... shape) {
    176                IntegerDataset data = DatasetFactory.zeros(IntegerDataset.class, shape);
    177                int[] buf = data.getData();
    178
    179                for (int i = 0; i < buf.length; i++) {
    180                        buf[i] = (int) prng.nextPoisson(lam);
    181                }
    182
    183                return data;
    184        }
    185
    186        /**
    187         * @param shape output shape
    188         * @return a lazy dataset with uniformly distributed random numbers
    189         */
    190        public static ILazyDataset lazyRand(int... shape) {
    191                return lazyRand("random", DoubleDataset.class, shape);
    192        }
    193
    194        /**
    195         * @param name dataset name
    196         * @param shape output shape
    197         * @return a lazy dataset with uniformly distributed random numbers
    198         */
    199        public static ILazyDataset lazyRand(String name, int... shape) {
    200                return lazyRand(name, DoubleDataset.class, shape);
    201        }
    202
    203        /**
    204         * @param dtype dataset type
    205         * @param name dataset name
    206         * @param shape output shape
    207         * @return a lazy dataset with uniformly distributed random numbers
    208         * @deprecated Use {@link #lazyRand(String, Class, int...)}
    209         */
    210        @Deprecated
    211        public static ILazyDataset lazyRand(int dtype, String name, int... shape) {
    212                return lazyRand(name, DTypeUtils.getInterface(dtype), shape);
    213        }
    214
    215        /**
    216         * @param name dataset name
    217         * @param clazz dataset sub-interface
    218         * @param shape output shape
    219         * @return a lazy dataset with uniformly distributed random numbers
    220         * @since 2.3
    221         */
    222        public static ILazyDataset lazyRand(String name, final Class<? extends Dataset> clazz, int... shape) {
    223
    224                return new LazyDataset(new ILazyLoader() {
    225                        private static final long serialVersionUID = ILazyLoader.serialVersionUID;
    226
    227                        @Override
    228                        public boolean isFileReadable() {
    229                                return true;
    230                        }
    231
    232                        @Override
    233                        public IDataset getDataset(IMonitor mon, SliceND slice) throws IOException {
    234                                return rand(slice.getShape()).cast(clazz);
    235                        }
    236                },
    237                name, clazz, shape);
    238        }
    239}