Взвешенная выборка с заменой в Java

Есть ли функция в Java или в такой библиотеке, как Apache Commons Math, которая эквивалентна функции MATLAB случайный образец? В частности, я хочу найти функцию randSample, которая возвращает вектор независимых и одинаково распределенных случайных величин в соответствии с заданным мной распределением вероятностей. Например:

int[] a = randSample(new int[]{0, 1, 2}, 5, new double[]{0.2, 0.3, 0.5})
//        { 0 w.p. 0.2
// a[i] = { 1 w.p. 0.3
//        { 2 w.p. 0.5

Вывод такой же, как код MATLAB randsample([0 1 2], 5, true, [0.2 0.3 0.5]), где true означает выборку с заменой.

Если такой функции не существует, как мне ее написать?

Примечание. Я знаю, что у похожий вопрос был задан вопрос о переполнении стека, но, к сожалению, на него не ответили.


person I Like to Code    schedule 31.12.2013    source источник


Ответы (1)


Я почти уверен, что его не существует, но довольно легко создать функцию, которая будет создавать такие образцы. Во-первых, Java поставляется с генератором случайных чисел, в частности, с функцией Random.nextDouble(), которая может создавать случайные удвоения в диапазоне от 0,0 до 1,0.

import java.util.Random;

double someRandomDouble = Random.nextDouble();
     // This will be a uniformly distributed
     // random variable between 0.0 and 1.0.

Если у вас есть выборка с заменой, если вы конвертируете pdf, который у вас есть в качестве входных данных, в cdf, вы можете использовать случайные двойники, которые предоставляет Java, для создания случайного набора данных, увидев, в какую часть cdf он попадает. Итак, сначала вам нужно преобразовать pdf в cdf.

int [] randsample(int[] values, int numsamples, 
        boolean withReplacement, double [] pdf) {

    if(withReplacement) {
        double[] cdf = new double[pdf.length];
        cdf[0] = pdf[0];
        for(int i=1; i<pdf.length; i++) {
            cdf[i] = cdf[i-1] + pdf[i];
        }

Затем вы создаете массив целых чисел правильного размера для хранения результата и начинаете находить случайные результаты:

        int[] results = new int[numsamples];
        for(int i=0; i<numsamples; i++) {
            int currentPosition = 0;

            while(randomValue > cdf[currentPosition] && currentPosition < cdf.length) {
                currentPosition++; //Check the next one.
            }

            if(currentPosition < cdf.length) { //It worked!
                results[i] = values[currentPosition];
            } else { //It didn't work.. let's fail gracefully I guess.
                results[i] = values[cdf.length-1]; 
                     // And assign it the last value.
            }
        }

        //Now we're done and can return the results!
        return results;
    } else { //Without replacement.
        throw new Exception("This is unimplemented!");
    }
}

Есть некоторая проверка ошибок (убедитесь, что массив значений и массив pdf имеют одинаковый размер) и некоторые другие функции, которые вы можете реализовать, перегрузив это, чтобы предоставить другие функции, но, надеюсь, вам этого достаточно для начала. Ваше здоровье!

person cactus1    schedule 31.12.2013