Генерация гладкого случайного тренда (случайного блуждания) в JavaScript

Я ищу реализацию JavaScript алгоритма случайного блуждания/случайного тренда. Мне нужно что-то, что будет придерживаться тренда (то есть просто случайные дельты не будут отображаться), оставаясь при этом в определенных границах. Я попытался записать что-то навскидку, выбирая числа на основе средневзвешенного значения (вес был рассчитан с использованием функции Гаусса), и в итоге получил более гладкую линию (недостаточно хорошую). Затем я применил менее прямой подход и попытался поискать в Интернете, и хотя я нашел несколько набросков, не было ничего достаточно конкретного, что я мог бы понять.

Как оказалось (первоначально я не знал об этом), кажется, уже существует семейство алгоритмов, которые используют уравнение Гаусса для создания случайного тренда. Но, несмотря на многочасовые поиски, я не смог найти ничего, кроме абстрактных уравнений, которые мне были бесполезны. Лучшее, что мне удалось найти, это этот блог, где он показывает картинку случайных данных, как я ищу. Он перечисляет уравнения, но я понятия не имею, что они на самом деле должны означать (мне кажется, что это даже не полное решение).

Какие алгоритмы уже существуют (предпочтительно JavaScript или C-подобные реализации) для генерации таких данных?


person Wasabi Fan    schedule 27.02.2014    source источник
comment
Вот первый релевантный поисковый запрос, который мне пришел в голову (хотя могут быть и другие): google.com/#q=smooth+random+walk+алгоритм   -  person Anderson Green    schedule 27.02.2014
comment
Это то, что вы ищете? Это лучшее, что я смог понять, глядя на ссылку в блог, который вы разместили. Это первый график в блоге, 10 графиков по 100 шагов.   -  person Xotic750    schedule 27.02.2014
comment
@Xotic750 Вот дерьмо! Это работает очень хорошо! Можете ли вы немного объяснить, как это работает, чтобы я мог изменить его, если это необходимо? Например, как я могу увеличить его распространение или как я могу ограничить его значения?   -  person Wasabi Fan    schedule 27.02.2014
comment
Добавлено в качестве ответа, улучшены функции, чтобы дать вам немного больше контроля. Вы можете выбрать количество steps в randomWalk для управления спредом. Чтобы ограничить значения, создайте функцию, которая изменяет значения boxMullerRandom, и передайте эту функцию в randomWalk. graph просто для красоты, чтобы показать, как он работает, используйте любой граф или данные по своему усмотрению.   -  person Xotic750    schedule 28.02.2014


Ответы (1)


Вот что я придумал, прочитав блог, на который вы ссылались. Насколько я могу судить, это то, что автор сделал для своего первого графика.

CSS

#container {
    min-width: 310px;
    height: 400px;
    margin: 0 auto;
}

HTML

<div id="container"></div>

Javascript

Box–Muller transform для создания Gaussian Random Numbers

var boxMullerRandom = (function () {
    var phase = 0,
        RAND_MAX,
        array,
        random,
        x1, x2, w, z;

    if (crypto && typeof crypto.getRandomValues === 'function') {
        RAND_MAX = Math.pow(2, 32) - 1;
        array = new Uint32Array(1);
        random = function () {
            crypto.getRandomValues(array);

            return array[0] / RAND_MAX;
        };
    } else {
        random = Math.random;
    }

    return function () {
        if (!phase) {
            do {
                x1 = 2.0 * random() - 1.0;
                x2 = 2.0 * random() - 1.0;
                w = x1 * x1 + x2 * x2;
            } while (w >= 1.0);

            w = Math.sqrt((-2.0 * Math.log(w)) / w);
            z = x1 * w;
        } else {
            z = x2 * w;
        }

        phase ^= 1;

        return z;
    }
}());

Random Walk генератор

function randomWalk(steps, randFunc) {
    steps = steps >>> 0 || 100;
    if (typeof randFunc !== 'function') {
        randFunc = boxMullerRandom;
    }

    var points = [],
        value = 0,
        t;

    for (t = 0; t < steps; t += 1) {
        value += randFunc();
        points.push([t, value]);
    }

    return points;
}

Вспомогательная функция для получения значений Y из точек случайного обхода

function getYValues(points) {
    return points.map(function (point) {
        return point[1];
    });
}

Вспомогательная функция для создания графиков X для графика

function generatePlots(howMany) {
    howMany = howMany >>> 0 || 10;
    var plots = [],
        index;

    for (index = 0; index < howMany; index += 1) {
        plots.push({
            name: 'plot' + index,
            data: getYValues(randomWalk())
        });
    }

    return plots;
}

Создайте график результатов, используя jQuery и highcharts.js

$('#container').highcharts({
    title: {
        text: 'Random Walk',
        x: -20 //center
    },
    subtitle: {
        text: 'Random Walk',
        x: -20
    },
    xAxis: {
        type: 'linear'
    },
    yAxis: {
        title: {
            text: 'Value'
        },
        plotLines: [{
            value: 0,
            width: 1,
            color: '#808080'
        }]
    },
    tooltip: {
        valueSuffix: ' units'
    },
    legend: {
        layout: 'vertical',
        align: 'right',
        verticalAlign: 'middle',
        borderWidth: 0
    },
    series: generatePlots(10)
});

На jsFiddle

person Xotic750    schedule 27.02.2014
comment
Спасибо! Я попробую это в ближайшее время. - person Wasabi Fan; 28.02.2014