Я предполагаю, что вы хотите генерировать случайные x
значения, распределение которых определяется плотностью y(x)
.
Часто желательно получить интегральную функцию распределения путем интегрирования плотности и использовать выборку обратного преобразования для генерации x
значений. В вашем случае CDF - это многочлен третьего порядка, который не учитывает простое решение с кубическим корнем, поэтому вам придется использовать числовой решатель, чтобы найти обратное. Время рассмотреть альтернативы.
Другой вариант - использовать метод принятия / отклонения . После проверки производной становится ясно, что ваша плотность является выпуклой, поэтому легко создать ограничивающую функцию b(x)
, нарисовав прямую линию от f(0)
до f(1)
. Это дает b(x) = 1/3 + 5x/3
. Эта ограничивающая функция имеет область 7/6, в то время как ваша f(x)
имеет область 1, поскольку она является действительной плотностью. Следовательно, 6/7 точек, сгенерированных равномерно при b(x)
, также попадут под f(x)
, и только 1 из 7 попыток потерпит неудачу в схеме отказа. Вот сюжет f(x)
и b(x)
:
Поскольку b(x)
является линейным, легко генерировать значения x
, используя его в качестве распределения после масштабирования до 6/7, чтобы сделать его действительной функцией распределения. Алгоритм, выраженный в псевдокоде, затем становится:
function generate():
while TRUE:
x <- (sqrt(1 + 35 * U(0,1)) - 1) / 5 # inverse CDF transform of b(x)
if U(0, b(x)) <= f(x):
return x
end while
end function
, где U(a,b)
означает генерацию значения, равномерно распределенного между a
и b
, f(x)
- ваша плотность, а b(x)
- ограничивающая функция, описанная выше.
Я реализовал алгоритм, описанный выше, чтобы сгенерировать 100 000 возможных значений, из которых 14 199 (~ 1/7) были отклонены, как и ожидалось. Конечные результаты представлены на следующей гистограмме, которую вы можете сравнить с f(x)
на графике выше.