Sample uniformly at random from an n-dimensional unit simplex

前端 未结 5 1887
礼貌的吻别
礼貌的吻别 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}].

提交回复
热议问题