確率分布のAPIを実装する


9

前書き

この課題の課題は、単純な確率分布に対して使用可能なミニライブラリを形成する単純な関数のコレクションを実装することです。ここで使用したい難解な言語のいくつかに対応するために、次の実装が受け入れられます。

  1. 名前付き関数(または最も近いもの)のコレクションを定義するコードスニペット。
  2. 名前付き関数または無名関数(または最も近い同等物)に評価される式のコレクション。
  3. 複数の名前付き関数または匿名関数(または最も近い同等物)に評価される単一の式。
  4. コマンドライン、STDINまたは最も近い同等物から入力を取り、STDOUTまたは最も近い同等物に出力する独立したプログラムのコレクション。

機能

必要に応じて短い名前を使用して、次の関数を実装する必要があります。

  1. uniform2つの浮動小数点数aとを入力として取りb、の一様分布を返します[a,b]。あなたはそれを仮定することができa < bます。ケースa ≥ bは未定義です。
  2. blend入力として3つの確率分布を取りPQそしてR。確率分布を返します。確率分布はS、値xyおよびzfrom PQおよびRをそれぞれ描画し、yif x ≥ 0およびzif を生成しx < 0ます。
  3. over入力として浮動小数点数fと確率分布を取り、から抽出された乱数Pに対してx ≥ f保持される確率を返します。xP

参考までに、over次のように定義できます(疑似コード)。

over(f, uniform(a, b)):
    if f <= a: return 1.0
    else if f >= b: return 0.0
    else: return (b - f)/(b - a)

over(f, blend(P, Q, R)):
    p = over(0.0, P)
    return p*over(f, Q) + (1-p)*over(f, R)

あなたは、与えられたすべての確率分布をすると仮定することができますover使用して構築されているuniformblend、ユーザーが、確率分布をどうしようとしている唯一のものであることにそれを養うためにblendover。数値、文字列、カスタムオブジェクトなどのリストを使用して、分布を表す任意の便利なデータ型を使用できます。重要なのは、APIが正しく機能することだけです。また、同じ入力に対して常に同じ出力を返すという意味で、実装確定的でなければなりません

テストケース

これらのテストケースでは、出力値は小数点以下2桁まで正確である必要があります。

over(4.356, uniform(-4.873, 2.441)) -> 0.0
over(2.226, uniform(-1.922, 2.664)) -> 0.09550806803314438
over(-4.353, uniform(-7.929, -0.823)) -> 0.49676329862088375
over(-2.491, uniform(-0.340, 6.453)) -> 1.0
over(0.738, blend(uniform(-5.233, 3.384), uniform(2.767, 8.329), uniform(-2.769, 6.497))) -> 0.7701533851999125
over(-3.577, blend(uniform(-3.159, 0.070), blend(blend(uniform(-4.996, 4.851), uniform(-7.516, 1.455), uniform(-0.931, 7.292)), blend(uniform(-5.437, -0.738), uniform(-8.272, -2.316), uniform(-3.225, 1.201)), uniform(3.097, 6.792)), uniform(-8.215, 0.817))) -> 0.4976245638164541
over(3.243, blend(blend(uniform(-4.909, 2.003), uniform(-4.158, 4.622), blend(uniform(0.572, 5.874), uniform(-0.573, 4.716), blend(uniform(-5.279, 3.702), uniform(-6.564, 1.373), uniform(-6.585, 2.802)))), uniform(-3.148, 2.015), blend(uniform(-6.235, -5.629), uniform(-4.647, -1.056), uniform(-0.384, 2.050)))) -> 0.0
over(-3.020, blend(blend(uniform(-0.080, 6.148), blend(uniform(1.691, 6.439), uniform(-7.086, 2.158), uniform(3.423, 6.773)), uniform(-1.780, 2.381)), blend(uniform(-1.754, 1.943), uniform(-0.046, 6.327), blend(uniform(-6.667, 2.543), uniform(0.656, 7.903), blend(uniform(-8.673, 3.639), uniform(-7.606, 1.435), uniform(-5.138, -2.409)))), uniform(-8.008, -0.317))) -> 0.4487803553043079

2
組み込み関数を使用してそれらを作成できますか?
ムタドール

@AndréMutaMathematicaにはおそらくこれらすべての機能が組み込まれていることを忘れていました...しかし、ルールに従う限り、それらを許可します。
Zgarb

BrainFuckで浮動小数点データを表現する方法についての提案はありますか?
flawr

@flawrネイティブ浮動小数点数を持たない言語の場合、連続する値の差が最大でも0.001である-10.0から10.0(排他的)までの浮動小数点数に便利なエンコーディングを使用できます。テストケースの出力は、0.01以内の正確さである必要があります。
Zgarb

回答:


1

CJam、58バイト

{[\]}:U;
{[@]}:B;
{_,2={~1$-@@-\/0e>1e<}{6Yb@f*\.{O})[_1@-].*:+}?}:O;

これらはスタックで機能する後置演算子です:2.0 1.0 3.0 U Ois over(2, uniform(1, 3))

スコアカウント

{[\]}関数自体であり:U;、名前に割り当ててUポップします。基本的に、これは関数の一部ではないので、スコアカウントルール2によって、カウントするだけで済みます{[\]}B同様に定義されます。

ただし、Oは再帰的であり、名前を指定しない場合、再帰する方法はありません。だからここで、私はその:O;部分を数える傾向があります。次に、私のスコアは5+5+48=58合計バイトです。

説明

U2つの引数をポップし、逆の順序でペアを作成しますa b => [b a]

B3つの引数をポップし、順番にトリプルを作成しますa b c => [b c a]

Oの構造は次のとおりです。

{             }:O;   Define O as this function:
 _,2=        ?       If the argument list's length is 2:
     {~Γ}            Append the list to the stack and execute subprogram Γ.
         {~Δ}        Else, do the same, but execute subprogram Δ.

サブプログラムΓは、均一な分布を処理します。

Executed ops      Explanation   Stack contents
============      ===========   ==============
                  Initial       f; b; a
1$                Copy b        f; b; a; b
  -               Difference    f; b; (a-b)
   @@             Rotate x2     (a-b); f, b
     -            Difference    (a-b); (f-b)
      \/          Flip divide   (f-b)/(a-b)
        0e>       Clamp low     max(0, (f-b)/(a-b))
           1e<    Clamp high    min(1, max(0, (f-b)/(a-b)))

サブプログラムΔは混合分布を処理します。

Executed ops              Explanation    Stack contents
============              ===========    ==============
                          Initial        f; [Q R P]
6Yb                       Push [1,1,0]   f; [Q R P]; [1 1 0]
   @                      Rotate         [Q R P]; [1 1 0]; f
    f*                    Multiply each  [Q R P]; [f f 0]
      \                   Swap           [f f 0]; [Q R P]
       .{O}               Pairwise O     [q r p]
           )              Uncons         [q r] p
            [_1@-]        [p, 1-p]       [q r] [p 1-p]
                  .*:+    Dot product    q*p+r*(1-p)

2

Ruby、103

u=b=->*a{a}
o=->f,d{d[2]?(p=o[0,d[0]])*o[f,d[1]]+(1-p)*o[f,d[2]]:(f<a=d[0])?1:(f>b=d[1])?0:(b-f)/(b-a)}

、3つのラムダを定義しubouそして、bばかりにそれぞれ2つの要素との三要素の配列を作成します。oは、2要素の配列が均一分布であり、3要素の配列が3つの分布の混合であると想定しています。後者の場合、それ自体を再帰的に呼び出します。


2

MATLAB、73

MATLABでの「関数型プログラミング」の時間です。これらは3つの匿名関数です。Uniformとblendは例と同じ方法で呼び出されますがover、引数は交換する必要があります。over最初の2つのreturn関数は本当に必要ありませんが、形式としてfevalは関数を呼び出すことができる関数です。

%uniform
@(a,b)@(x)(x<b)*min(1,(b-x)/(b-a))
%blend
@(P,Q,R)@(x)P(0)*(Q(x)-R(x))+R(x)
%over
@feval

さて、MATLABの解析および評価システムは控えめに言っても少し不安定です。関数から返された関数を直接呼び出すことはできません。代わりに、最初に結果を変数に保存する必要があります。4番目の例は次のように実行できます。

x=uniform(-5.233,3.384);y=uniform(2.767,8.329);z=uniform(-2.769,6.497);over(blend(x,y,z),0.738)

ただし、を使用fevalしてすべての関数を呼び出すことにより、これを回避することができます。次の定義が使用されている場合、例は記述されているとおりに評価できます。

uniform=@(a,b)@(x)(x<b)*min(1,(b-x)/(b-a))
blend=@(P,Q,R)@(x)feval(P,0)*(feval(Q,x)-feval(R,x))+feval(R,x)
over=@(x,f)feval(f,x)

関数が関数を作る... なんとひどい!
Luis Mendo 2015年

1

Mathematica、129116バイト

u=UniformDistribution@{##}&;b=If[x<0,z,y]~TransformedDistribution~{x\uF3D2#,y\uF3D2#2,z\uF3D2#3}&;o=Probability[x>=#,x\uF3D2#2]&

ubおよびouniform、それぞれ、、blendおよびoverです。標準関数のラッパー。\uF3D2sを3バイト文字に置き換えます。戻るだけ01、ケース1、4、7の場合。


1

Python、146バイト

u=lambda*a:a
b=u
x=lambda f,a,b:[int(f<=a),(b-f)/(b-a)][a<f<b]
y=lambda f,p,q,r:o(0,p)*o(f,q)+(1-o(0,p))*o(f,r)
o=lambda f,p:[x,y][len(p)-2](f,*p)

ヒストクラートのRubyの回答と同じ戦略ですが、Pythonを使用します。(コストがかかる)Z-コンビネータずに再帰を行うため、x及びy評価ヘルパー関数として定義されているover2-および(3-length引数タプルuniformblendそれぞれの引数)。

ideoneのテストケース


0

Matlab、104バイト

浮動小数点サポートのない言語の要件である[-10,10]のサポートがあるディストリビューションでのみ機能するため、これがまだ有効であることを願っています。サポートベクトルと精度は、対応する数値を変更するだけで簡単に調整できます。u,o,bのためuniform,blend,overです。pdfは単に離散ベクトルとして表されます。このアプローチは他の言語に簡単に転用できると思います。

D=1e-4;X=-10:D:10;
u=@(a,b)(1/(b-a))*(a<X&X<b);
o=@(x,d)sum(d.*(X>x))*D;
b=@(p,q,r)o(0,p).*q+(1-o(0,p)).*r;

最初にこれらの関数を定義してから、次のコードを貼り付けるだけでテストできます。

[o(4.356, u(-4.873, 2.441)) , 0.0;
o(2.226, u(-1.922, 2.664)) , 0.09550806803314438;
o(-4.353, u(-7.929, -0.823)) , 0.49676329862088375;
o(-2.491, u(-0.340, 6.453)) , 1.0;
o(0.738, b(u(-5.233, 3.384), u(2.767, 8.329), u(-2.769, 6.497))) , 0.7701533851999125;
o(-3.577, b(u(-3.159, 0.070), b(b(u(-4.996, 4.851), u(-7.516, 1.455), u(-0.931, 7.292)), b(u(-5.437, -0.738), u(-8.272, -2.316), u(-3.225, 1.201)), u(3.097, 6.792)), u(-8.215, 0.817))) , 0.4976245638164541;
o(3.243, b(b(u(-4.909, 2.003), u(-4.158, 4.622), b(u(0.572, 5.874), u(-0.573, 4.716), b(u(-5.279, 3.702), u(-6.564, 1.373), u(-6.585, 2.802)))), u(-3.148, 2.015), b(u(-6.235, -5.629), u(-4.647, -1.056), u(-0.384, 2.050)))) , 0.0;
o(-3.020, b(b(u(-0.080, 6.148), b(u(1.691, 6.439), u(-7.086, 2.158), u(3.423, 6.773)), u(-1.780, 2.381)), b(u(-1.754, 1.943), u(-0.046, 6.327), b(u(-6.667, 2.543), u(0.656, 7.903), b(u(-8.673, 3.639), u(-7.606, 1.435), u(-5.138, -2.409)))), u(-8.008, -0.317))) , 0.4487803553043079]

MatlabはFPをサポートしているので、これは無効だと思います。
LegionMammal978 2015年

Matlabは浮動小数点数をネイティブでサポートしているので、これを許可するのをためらっています。Xand DMIN_FLOATand MAX_FLOAT(またはMatlabが呼び出すもの)を置き換えることができる場合、これは有効なアプローチです。
Zgarb 2015年

はい、realmax/ realminを使用できます。十分なメモリがある場合は、すべての浮動小数点数を通過するベクトルを作成することもできます。
flawr
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.