Sample uniformly at random from an n-dimensional unit simplex

前端 未结 5 1888
礼貌的吻别
礼貌的吻别 2020-12-14 02:36

Sampling uniformly at random from an n-dimensional unit simplex is the fancy way to say that you want n random numbers such that

  • they are all non-negative,
相关标签:
5条回答
  • 2020-12-14 02:51

    I'm with zdav: the Dirichlet distribution seems to be the easiest way ahead, and the algorithm for sampling the Dirichlet distribution which zdav refers to is also presented on the Wikipedia page on the Dirichlet distribution.

    Implementationwise, it is a bit of an overhead to do the full Dirichlet distribution first, as all you really need is n random Gamma[1,1] samples. Compare below
    Simple implementation

    SimplexSample[n_, opts:OptionsPattern[RandomReal]] :=
      (#/Total[#])& @ RandomReal[GammaDistribution[1,1],n,opts]
    

    Full Dirichlet implementation

    DirichletDistribution/:Random`DistributionVector[
     DirichletDistribution[alpha_?(VectorQ[#,Positive]&)],n_Integer,prec_?Positive]:=
        Block[{gammas}, gammas = 
            Map[RandomReal[GammaDistribution[#,1],n,WorkingPrecision->prec]&,alpha];
          Transpose[gammas]/Total[gammas]]
    
    SimplexSample2[n_, opts:OptionsPattern[RandomReal]] := 
      (#/Total[#])& @ RandomReal[DirichletDistribution[ConstantArray[1,{n}]],opts]
    

    Timing

    Timing[Table[SimplexSample[10,WorkingPrecision-> 20],{10000}];]
    Timing[Table[SimplexSample2[10,WorkingPrecision-> 20],{10000}];]
    Out[159]= {1.30249,Null}
    Out[160]= {3.52216,Null}
    

    So the full Dirichlet is a factor of 3 slower. If you need m>1 samplepoints at a time, you could probably win further by doing (#/Total[#]&)/@RandomReal[GammaDistribution[1,1],{m,n}].

    0 讨论(0)
  • 2020-12-14 02:54

    I have created an algorithm for uniform random generation over a simplex. You can find the details in the paper in the following link: http://www.tandfonline.com/doi/abs/10.1080/03610918.2010.551012#.U5q7inJdVNY

    Briefly speaking, you can use following recursion formulas to find the random points over the n-dimensional simplex:

    x1=1-R11/n-1

    xk=(1-Σi=1kxi)(1-Rk1/n-k), k=2, ..., n-1

    xn=1-Σi=1n-1xi

    Where R_i's are random number between 0 and 1.

    Now I am trying to make an algorithm to generate random uniform samples from constrained simplex.that is intersection between a simplex and a convex body.

    0 讨论(0)
  • 2020-12-14 03:00

    Here's a nice concise implementation of the second algorithm from Wikipedia:

    SimplexSample[n_] := Rest@# - Most@# &[Sort@Join[{0,1}, RandomReal[{0,1}, n-1]]]
    

    That's adapted from here: http://www.mofeel.net/1164-comp-soft-sys-math-mathematica/14968.aspx (Originally it had Union instead of Sort@Join -- the latter is slightly faster.)

    (See comments for some evidence that this is correct!)

    0 讨论(0)
  • 2020-12-14 03:07

    This code can work:

    samples[n_] := Differences[Join[{0}, Sort[RandomReal[Range[0, 1], n - 1]], {1}]]
    

    Basically you just choose n - 1 places on the interval [0,1] to split it up then take the size of each of the pieces using Differences.

    A quick run of Timing on this shows that it's a little faster than Janus's first answer.

    0 讨论(0)
  • 2020-12-14 03:08

    After a little digging around, I found this page which gives a nice implementation of the Dirichlet Distribution. From there it seems like it would be pretty simple to follow Wikipedia's method 1. This seems like the best way to do it.

    As a test:

    In[14]:= RandomReal[DirichletDistribution[{1,1}],WorkingPrecision->25]
    Out[14]= {0.8428995243540368880268079,0.1571004756459631119731921}
    In[15]:= Total[%]
    Out[15]= 1.000000000000000000000000
    

    A plot of 100 samples:

    alt text http://www.public.iastate.edu/~zdavkeos/simplex-sample.png

    0 讨论(0)
提交回复
热议问题