Skip to main content
replaced http://mathematica.stackexchange.com/ with https://mathematica.stackexchange.com/
Source Link

One can use many simultaneous random chains. It considerably speeds up the simulation. Also we can implement own distribution (see Defining Distributional Generators here)

ClearAll[lifetime]
lifetime /: Random`DistributionVector[lifetime[size_, chains_ : 200], n_, prec_] := 
 Module[{m, t, res, pos},
   Flatten[Table[
      m = ConstantArray[-1, size chains];
      t = 0;
      res = ConstantArray[0, chains];
      While[Min[res] == 0, t++;
       pos = Range@chains + chains RandomInteger[size - 1, chains];
       m[[pos]] *= -1;
       res += UnitStep[-res] UnitStep[Total@Partition[m, chains] - size] t;
       ];
      res, {⌈n/chains⌉}]][[1 ;; n]]
   ];

Here size is the size of the list, chains is the number of simultaneous chains (the default value 200 is optimal) and n is the number of generated numbers. Now we can use it as a regular distribution with RandomVariate

N@Mean@RandomVariate[lifetime[6], 100000]

83.4748

Histogram[RandomVariate[lifetime[6], 100000], {0, 150, 2}, AxesOrigin -> 0]

enter image description here

The speed is several times faster then heropup's uncompiled version because I use packed arrayspacked arrays.

One can put the code above to Compile:

lifetimeCFun = Compile[{{size, _Integer}, {chains, _Integer}, {n, _Integer}}, 
   Module[{m, t, res, pos},
    Flatten[Table[
       m = ConstantArray[-1, size chains];
       t = 0;
       res = ConstantArray[0, chains];
       While[Min[res] == 0, t++;
        pos = Range@chains + chains RandomInteger[size - 1, chains];
        m[[pos]] *= -1;
        res += UnitStep[-res] UnitStep[Total@Partition[m, chains] - size] t;
        ];
       res, {⌈n/chains⌉}]][[1 ;; n]]
    ], CompilationTarget -> "C", RuntimeOptions -> "Speed"];

lifetimeC /: Random`DistributionVector[lifetimeC[size_, chains_ : 200], n_, prec_] := 
   lifetimeCFun[size, chains, n];

The speed of my compiled solution is comparable to heropup's compiled solution.

One can use many simultaneous random chains. It considerably speeds up the simulation. Also we can implement own distribution (see Defining Distributional Generators here)

ClearAll[lifetime]
lifetime /: Random`DistributionVector[lifetime[size_, chains_ : 200], n_, prec_] := 
 Module[{m, t, res, pos},
   Flatten[Table[
      m = ConstantArray[-1, size chains];
      t = 0;
      res = ConstantArray[0, chains];
      While[Min[res] == 0, t++;
       pos = Range@chains + chains RandomInteger[size - 1, chains];
       m[[pos]] *= -1;
       res += UnitStep[-res] UnitStep[Total@Partition[m, chains] - size] t;
       ];
      res, {⌈n/chains⌉}]][[1 ;; n]]
   ];

Here size is the size of the list, chains is the number of simultaneous chains (the default value 200 is optimal) and n is the number of generated numbers. Now we can use it as a regular distribution with RandomVariate

N@Mean@RandomVariate[lifetime[6], 100000]

83.4748

Histogram[RandomVariate[lifetime[6], 100000], {0, 150, 2}, AxesOrigin -> 0]

enter image description here

The speed is several times faster then heropup's uncompiled version because I use packed arrays.

One can put the code above to Compile:

lifetimeCFun = Compile[{{size, _Integer}, {chains, _Integer}, {n, _Integer}}, 
   Module[{m, t, res, pos},
    Flatten[Table[
       m = ConstantArray[-1, size chains];
       t = 0;
       res = ConstantArray[0, chains];
       While[Min[res] == 0, t++;
        pos = Range@chains + chains RandomInteger[size - 1, chains];
        m[[pos]] *= -1;
        res += UnitStep[-res] UnitStep[Total@Partition[m, chains] - size] t;
        ];
       res, {⌈n/chains⌉}]][[1 ;; n]]
    ], CompilationTarget -> "C", RuntimeOptions -> "Speed"];

lifetimeC /: Random`DistributionVector[lifetimeC[size_, chains_ : 200], n_, prec_] := 
   lifetimeCFun[size, chains, n];

The speed of my compiled solution is comparable to heropup's compiled solution.

One can use many simultaneous random chains. It considerably speeds up the simulation. Also we can implement own distribution (see Defining Distributional Generators here)

ClearAll[lifetime]
lifetime /: Random`DistributionVector[lifetime[size_, chains_ : 200], n_, prec_] := 
 Module[{m, t, res, pos},
   Flatten[Table[
      m = ConstantArray[-1, size chains];
      t = 0;
      res = ConstantArray[0, chains];
      While[Min[res] == 0, t++;
       pos = Range@chains + chains RandomInteger[size - 1, chains];
       m[[pos]] *= -1;
       res += UnitStep[-res] UnitStep[Total@Partition[m, chains] - size] t;
       ];
      res, {⌈n/chains⌉}]][[1 ;; n]]
   ];

Here size is the size of the list, chains is the number of simultaneous chains (the default value 200 is optimal) and n is the number of generated numbers. Now we can use it as a regular distribution with RandomVariate

N@Mean@RandomVariate[lifetime[6], 100000]

83.4748

Histogram[RandomVariate[lifetime[6], 100000], {0, 150, 2}, AxesOrigin -> 0]

enter image description here

The speed is several times faster then heropup's uncompiled version because I use packed arrays.

One can put the code above to Compile:

lifetimeCFun = Compile[{{size, _Integer}, {chains, _Integer}, {n, _Integer}}, 
   Module[{m, t, res, pos},
    Flatten[Table[
       m = ConstantArray[-1, size chains];
       t = 0;
       res = ConstantArray[0, chains];
       While[Min[res] == 0, t++;
        pos = Range@chains + chains RandomInteger[size - 1, chains];
        m[[pos]] *= -1;
        res += UnitStep[-res] UnitStep[Total@Partition[m, chains] - size] t;
        ];
       res, {⌈n/chains⌉}]][[1 ;; n]]
    ], CompilationTarget -> "C", RuntimeOptions -> "Speed"];

lifetimeC /: Random`DistributionVector[lifetimeC[size_, chains_ : 200], n_, prec_] := 
   lifetimeCFun[size, chains, n];

The speed of my compiled solution is comparable to heropup's compiled solution.

Source Link
ybeltukov
  • 43.9k
  • 5
  • 109
  • 215

One can use many simultaneous random chains. It considerably speeds up the simulation. Also we can implement own distribution (see Defining Distributional Generators here)

ClearAll[lifetime]
lifetime /: Random`DistributionVector[lifetime[size_, chains_ : 200], n_, prec_] := 
 Module[{m, t, res, pos},
   Flatten[Table[
      m = ConstantArray[-1, size chains];
      t = 0;
      res = ConstantArray[0, chains];
      While[Min[res] == 0, t++;
       pos = Range@chains + chains RandomInteger[size - 1, chains];
       m[[pos]] *= -1;
       res += UnitStep[-res] UnitStep[Total@Partition[m, chains] - size] t;
       ];
      res, {⌈n/chains⌉}]][[1 ;; n]]
   ];

Here size is the size of the list, chains is the number of simultaneous chains (the default value 200 is optimal) and n is the number of generated numbers. Now we can use it as a regular distribution with RandomVariate

N@Mean@RandomVariate[lifetime[6], 100000]

83.4748

Histogram[RandomVariate[lifetime[6], 100000], {0, 150, 2}, AxesOrigin -> 0]

enter image description here

The speed is several times faster then heropup's uncompiled version because I use packed arrays.

One can put the code above to Compile:

lifetimeCFun = Compile[{{size, _Integer}, {chains, _Integer}, {n, _Integer}}, 
   Module[{m, t, res, pos},
    Flatten[Table[
       m = ConstantArray[-1, size chains];
       t = 0;
       res = ConstantArray[0, chains];
       While[Min[res] == 0, t++;
        pos = Range@chains + chains RandomInteger[size - 1, chains];
        m[[pos]] *= -1;
        res += UnitStep[-res] UnitStep[Total@Partition[m, chains] - size] t;
        ];
       res, {⌈n/chains⌉}]][[1 ;; n]]
    ], CompilationTarget -> "C", RuntimeOptions -> "Speed"];

lifetimeC /: Random`DistributionVector[lifetimeC[size_, chains_ : 200], n_, prec_] := 
   lifetimeCFun[size, chains, n];

The speed of my compiled solution is comparable to heropup's compiled solution.