3 added 1204 characters in body
source | link
pdf = x \[Function] x/22;
cdf = x \[Function] Evaluate[Integrate[pdf[t], {t, 0, x}]]
cdfinv = y \[Function] 2 Sqrt[y]
rand = cdfinv[RandomReal[{0, 1}, {1000000}]]; // RepeatedTiming // First

0.009

One million random number is a percent of a second.

Plotting a histogram to check the distribution is correct:

distro = ProbabilityDistribution[x/2, {x, 0, 2}];
rand = RandomVariate[distro, 1000000]; // RepeatedTiming // First

0.08

For some reason, it is significantly slower...

A listable approach

n = 1000000;2000000;
First@RepeatedTiming[

  x = RandomReal[{0, 2}, n];
  y = RandomReal[{0, 1}, n];
  rand = Pick[x, UnitStep[Subtract[pdf[x], y]], 1]; 

  ]

0.062

This generates about half a million random numbers at oncewith 0.062 seconds. I would strongly discourage methods that use Append repeatedly, because the will quadratic complexity and are very memory bound (each time Append is called, you have to copy the full array).

An approach with Internal`Bag

This is very, very slow, also because random numbers a more efficiently created in bulks instead of one-by-one.

n = 1000000;
Do[
   x = RandomReal[{0, 2}];
   y = RandomReal[{0, 1}];
   If[y <= pdf[x], Internal`StuffBag[bag, x]];
   ,
   {n}
   ]; // RepeatedTiming // First
rand = Internal`BagPart[bag, All];

3.2

This takes about 3.2 seconds...

An approach with Compile and Internal`Bag

Compiling the latter can be faster by more than two orders of magnitude, though.

cf = Block[{x},
   With[{pdfx = pdf[x]},
    Compile[{{n, _Integer}},
     Block[{x, y, bag},
      bag = Internal`Bag[Most[{0.}]];
      Do[
       x = RandomReal[{0, 2}];
       y = RandomReal[{0, 1}];
       If[y <= pdfx, Internal`StuffBag[bag, x]];
       ,
       {n}
       ];
      Internal`BagPart[bag, All]
      ],
     CompilationTarget -> "C",
     RuntimeAttributes -> {Listable},
     Parallelization -> True,
     RuntimeOptions -> "Speed"
     ]
    ]
   ];

n = 1000000;
rand = Join @@ cf[ConstantArray[n/4, {4}]]; // RepeatedTiming // First

0.022

pdf = x \[Function] x/2
cdf = x \[Function] Evaluate[Integrate[pdf[t], {t, 0, x}]]
cdfinv = y \[Function] 2 Sqrt[y]
rand = cdfinv[RandomReal[{0, 1}, {1000000}]];

Plotting a histogram to check the distribution is correct:

distro = ProbabilityDistribution[x/2, {x, 0, 2}];
rand = RandomVariate[distro, 1000000];
n = 1000000;
x = RandomReal[{0, 2}, n];
y = RandomReal[{0, 1}, n];
rand = Pick[x, UnitStep[Subtract[pdf[x], y]], 1];

This generates about half a million random numbers at once. I would strongly discourage methods that use Append repeatedly, because the will quadratic complexity and are very memory bound (each time Append is called, you have to copy the full array).

pdf = x \[Function] x/2;
cdf = x \[Function] Evaluate[Integrate[pdf[t], {t, 0, x}]]
cdfinv = y \[Function] 2 Sqrt[y]
rand = cdfinv[RandomReal[{0, 1}, {1000000}]]; // RepeatedTiming // First

0.009

One million random number is a percent of a second.

Plotting a histogram to check the distribution is correct:

distro = ProbabilityDistribution[x/2, {x, 0, 2}];
rand = RandomVariate[distro, 1000000]; // RepeatedTiming // First

0.08

For some reason, it is significantly slower...

A listable approach

n = 2000000;
First@RepeatedTiming[

  x = RandomReal[{0, 2}, n];
  y = RandomReal[{0, 1}, n];
  rand = Pick[x, UnitStep[Subtract[pdf[x], y]], 1]; 

  ]

0.062

This generates about a million random numbers with 0.062 seconds. I would strongly discourage methods that use Append repeatedly, because the will quadratic complexity and are very memory bound (each time Append is called, you have to copy the full array).

An approach with Internal`Bag

This is very, very slow, also because random numbers a more efficiently created in bulks instead of one-by-one.

n = 1000000;
Do[
   x = RandomReal[{0, 2}];
   y = RandomReal[{0, 1}];
   If[y <= pdf[x], Internal`StuffBag[bag, x]];
   ,
   {n}
   ]; // RepeatedTiming // First
rand = Internal`BagPart[bag, All];

3.2

This takes about 3.2 seconds...

An approach with Compile and Internal`Bag

Compiling the latter can be faster by more than two orders of magnitude, though.

cf = Block[{x},
   With[{pdfx = pdf[x]},
    Compile[{{n, _Integer}},
     Block[{x, y, bag},
      bag = Internal`Bag[Most[{0.}]];
      Do[
       x = RandomReal[{0, 2}];
       y = RandomReal[{0, 1}];
       If[y <= pdfx, Internal`StuffBag[bag, x]];
       ,
       {n}
       ];
      Internal`BagPart[bag, All]
      ],
     CompilationTarget -> "C",
     RuntimeAttributes -> {Listable},
     Parallelization -> True,
     RuntimeOptions -> "Speed"
     ]
    ]
   ];

n = 1000000;
rand = Join @@ cf[ConstantArray[n/4, {4}]]; // RepeatedTiming // First

0.022

2 added 514 characters in body
source | link

Inverse CDF method

Here, try this; it should be faster:

pdf = x \[Function] x/2
cdf = x \[Function] Evaluate[Integrate[pdf[t], {t, 0, x}]]
cdfinv = y \[Function] 2 Sqrt[y]
rand = cdfinv[RandomReal[{0, 1}, {1000000}]];

Plotting a histogram to check the distribution is correct:

Histogram[rand]

enter image description here

Actually, there is also a built-in method for this. It goes like this:

distro = ProbabilityDistribution[x/2, {x, 0, 2}];
rand = RandomVariate[distro, 1000000];

Acceptance/rejection method

If you insist on using the "acceptance/rejection method" (better know as Monte Carlo method, you can do this:

n = 1000000;
x = RandomReal[{0, 2}, n];
y = RandomReal[{0, 1}, n];
rand = Pick[x, UnitStep[Subtract[pdf[x], y]], 1];

This generates about half a million random numbers at once. I would strongly discourage methods that use Append repeatedly, because the will quadratic complexity and are very memory bound (each time Append is called, you have to copy the full array).

Here, try this; it should be faster:

pdf = x \[Function] x/2
cdf = x \[Function] Evaluate[Integrate[pdf[t], {t, 0, x}]]
cdfinv = y \[Function] 2 Sqrt[y]
rand = cdfinv[RandomReal[{0, 1}, {1000000}]];

Plotting a histogram to check the distribution is correct:

Histogram[rand]

enter image description here

Actually, there is also a built-in method for this. It goes like this:

distro = ProbabilityDistribution[x/2, {x, 0, 2}];
rand = RandomVariate[distro, 1000000];

Inverse CDF method

Here, try this; it should be faster:

pdf = x \[Function] x/2
cdf = x \[Function] Evaluate[Integrate[pdf[t], {t, 0, x}]]
cdfinv = y \[Function] 2 Sqrt[y]
rand = cdfinv[RandomReal[{0, 1}, {1000000}]];

Plotting a histogram to check the distribution is correct:

Histogram[rand]

enter image description here

Actually, there is also a built-in method for this. It goes like this:

distro = ProbabilityDistribution[x/2, {x, 0, 2}];
rand = RandomVariate[distro, 1000000];

Acceptance/rejection method

If you insist on using the "acceptance/rejection method" (better know as Monte Carlo method, you can do this:

n = 1000000;
x = RandomReal[{0, 2}, n];
y = RandomReal[{0, 1}, n];
rand = Pick[x, UnitStep[Subtract[pdf[x], y]], 1];

This generates about half a million random numbers at once. I would strongly discourage methods that use Append repeatedly, because the will quadratic complexity and are very memory bound (each time Append is called, you have to copy the full array).

1
source | link

Here, try this; it should be faster:

pdf = x \[Function] x/2
cdf = x \[Function] Evaluate[Integrate[pdf[t], {t, 0, x}]]
cdfinv = y \[Function] 2 Sqrt[y]
rand = cdfinv[RandomReal[{0, 1}, {1000000}]];

Plotting a histogram to check the distribution is correct:

Histogram[rand]

enter image description here

Actually, there is also a built-in method for this. It goes like this:

distro = ProbabilityDistribution[x/2, {x, 0, 2}];
rand = RandomVariate[distro, 1000000];