实施用于概率分布的API


9

介绍

在这个挑战中,您的任务是实现一组简单的函数,这些函数共同构成一个用于简单概率分布的可用小型库。为了适应人们喜欢在这里使用的一些更深奥的语言,可以接受以下实现:

  1. 定义命名函数(或最接近的对等函数)集合的代码段。
  2. 表达式集合,这些表达式的结果为命名或匿名函数(或最接近的等效函数)。
  3. 单个表达式,其结果为几个命名或匿名函数(或最接近的对等函数)。
  4. 独立程序的集合,这些独立程序从命令行,STDIN或最接近的等效项获取输入,并输出到STDOUT或最接近的等效项。

功能

您应实现以下功能,并根据需要使用较短的名称。

  1. uniform将两个浮点数a和作为输入b,并返回的均匀分布[a,b]。你可以假设a < b; 情况a ≥ b是不确定的。
  2. blend将三种概率分布作为输入PQR。它返回一个概率分布S,其平值xyzPQR分别和的产率y,如果x ≥ 0z如果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都是使用uniform和构造的blend,并且用户要做的唯一事情就是将其提供给blendover。您可以使用任何方便的数据类型来表示分布:数字,字符串,自定义对象等的列表。唯一重要的是API可以正常工作。同样,在始终为相同的输入返回相同的输出的意义上,您的实现必须是确定性的。

测试用例

在这些测试用例上,您的输出值应正确至小数点后至少两位数。

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
我们可以使用内置函数来制作它们吗?
Mutador

@AndréMuta我忘记了Mathematica可能已经内置了所有这些功能...但是只要他们遵守规则,我将允许它们。
Zgarb

您对如何在BrainFuck中表示浮点数据有何建议?
瑕疵的

@flawr对于没有本机浮点数的语言,您可以对-10.0和10.0(不包括)之间的浮点使用任何方便的编码,连续值之间的差异最多为0.001。对于测试用例,输出应精确到0.01个差异以内。
Zgarb 2015年

Answers:


1

CJam,58个字节

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

这些是在堆栈上工作的postfix运算符:2.0 1.0 3.0 U Ois over(2, uniform(1, 3))

分数计数

{[\]}是函数本身,:U;将其分配给名称U并弹出。从本质上讲,这不是函数的一部分,因此根据计分规则2,我只需要计数{[\]}B的定义与此类似。

但是,它O是递归的,如果我不指定名称,则无法递归。所以在这里,我倾向于计算一下:O;。那么我的总分是5+5+48=58字节。

说明

U弹出两个参数并以相反的顺序配对:a b => [b a]

B弹出三个参数,并按旋转顺序排列三元组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

红宝石,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)}

定义了三个lambda表达式,ub,和ou并分别b创建两个元素和三个元素的数组。o假设二元素数组是均匀分布,而三元素数组是三个分布的混合。在后一种情况下,它以递归方式调用自己。


2

MATLAB,73

是时候在MATLAB中进行一些“函数式编程”了。这是3个匿名函数。均匀和混合的调用方式与示例相同,但over应交换参数。over自前两个返回函数以来,我实际上并不需要a,但是形式上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的解析和评估系统有点奇怪。它不允许您直接调用从函数返回的函数。相反,必须首先将结果保存到变量中。第四个示例可以如下所示:

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)

函数制作函数... 多么不正当!
路易斯·门多

1

Mathematica,129 116字节

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

ubouniformblendoverrespectively.Wrapper超过标准功能。将\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被定义为评估辅助功能over(用于2-和3-长度参数元组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

我很犹豫是否允许这样做,因为Matlab本机支持浮点数。如果您可以用and (和任何Matlab称呼它们)替换Xand ,那么这是一种有效的方法。DMIN_FLOATMAX_FLOAT
Zgarb 2015年

是的,您可以使用realmax/ realmin,如果您有足够的内存,甚至可以创建一个通过所有浮点数的向量。
瑕疵的
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.