Triển khai API để phân phối xác suất


9

Giới thiệu

Trong thử thách này, nhiệm vụ của bạn là thực hiện một tập hợp các hàm đơn giản cùng nhau tạo thành một thư viện nhỏ có thể sử dụng để phân phối xác suất đơn giản. Để phù hợp với một số ngôn ngữ bí truyền hơn mà mọi người muốn sử dụng ở đây, các triển khai sau đây có thể được chấp nhận:

  1. Một đoạn mã xác định một tập hợp các hàm được đặt tên (hoặc tương đương gần nhất).
  2. Một tập hợp các biểu thức đánh giá các hàm được đặt tên hoặc ẩn danh (hoặc tương đương gần nhất).
  3. Một biểu thức duy nhất đánh giá một số hàm được đặt tên hoặc ẩn danh (hoặc tương đương gần nhất).
  4. Một tập hợp các chương trình độc lập lấy đầu vào từ dòng lệnh, STDIN hoặc tương đương gần nhất và xuất ra STDOUT hoặc tương đương gần nhất.

Chức năng

Bạn sẽ thực hiện các chức năng sau, sử dụng tên ngắn hơn nếu muốn.

  1. uniformmất như là đầu vào hai số dấu chấm động ab, và trả về sự phân bố đồng đều trên [a,b]. Bạn có thể cho rằng a < b; trường hợp a ≥ bkhông xác định.
  2. blendlấy làm đầu vào ba phân phối xác suất P, QR. Nó trả về một phân phối xác suất S, rút ​​ra các giá trị x, yztừ P, QR, tương ứng, và mang lại ynếu x ≥ 0, và znếu x < 0.
  3. overlấy đầu vào là số dấu phẩy động fvà phân phối xác suất Pvà trả về xác suất x ≥ fgiữ cho một số ngẫu nhiên xđược rút ra từ đó P.

Để tham khảo, overcó thể được định nghĩa như sau (trong mã giả):

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)

Bạn có thể giả định rằng tất cả các phân phối xác suất được cung cấp overđược xây dựng bằng cách sử dụng uniformblend, và điều duy nhất người dùng sẽ làm với phân phối xác suất là đưa nó đến blendhoặc over. Bạn có thể sử dụng bất kỳ kiểu dữ liệu thuận tiện nào để thể hiện các bản phân phối: danh sách các số, chuỗi, đối tượng tùy chỉnh, v.v. Điều quan trọng duy nhất là API hoạt động chính xác. Ngoài ra, việc thực hiện của bạn phải mang tính quyết định, theo nghĩa luôn luôn trả lại cùng một đầu ra cho cùng một đầu vào.

Các trường hợp thử nghiệm

Giá trị đầu ra của bạn phải chính xác đến ít nhất hai chữ số sau dấu thập phân trên các trường hợp kiểm tra này.

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
Chúng ta có thể sử dụng các hàm tích hợp để tạo ra chúng không?
Mutador

@ AndréMuta Tôi quên rằng Mathematica có thể đã tích hợp sẵn tất cả những thứ này ... nhưng tôi sẽ cho phép chúng, miễn là chúng tuân theo các quy tắc.
Zgarb

Gợi ý của bạn về cách thể hiện dữ liệu dấu phẩy động trong BrainFuck là gì?
flawr

@flawr Đối với các ngôn ngữ không có số dấu phẩy động riêng, bạn có thể sử dụng bất kỳ mã hóa thuận tiện nào cho số float giữa -10.0 và 10.0 (độc quyền) có chênh lệch tối đa 0,001 giữa các giá trị liên tiếp. Đầu ra phải chính xác trong phạm vi 0,01 cho các trường hợp thử nghiệm.
Zgarb

Câu trả lời:


1

CJam, 58 byte

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

Đây là các toán tử postfix hoạt động trên stack: 2.0 1.0 3.0 U Ois over(2, uniform(1, 3)).

Số điểm

{[\]}là chính chức năng, :U;gán nó cho tên Uvà bật nó. Về cơ bản, đây không phải là một phần của chức năng, vì vậy, theo quy tắc đếm điểm 2, tôi chỉ phải đếm {[\]}. Bđược định nghĩa tương tự.

Tuy nhiên, Olà đệ quy và nếu tôi không chỉ định tên, không có cách nào để lặp lại. Vì vậy, ở đây, tôi có xu hướng đếm :O;phần. Sau đó, tổng số điểm của tôi là 5+5+48=58byte.

Giải trình

Ubật hai đối số và tạo một cặp theo thứ tự ngược lại : a b => [b a].

Bbật ba đối số và thực hiện một bộ ba theo thứ tự xoay : a b c => [b c a].

OCấu trúc của như sau:

{             }: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 Δ.

Tiểu chương trình Γ xử lý phân phối đều liên tục:

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)))

Tiểu chương trình Δ xử lý phân phối hỗn hợp:

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

Hồng ngọc, 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)}

Định nghĩa ba lambdas, u, b, và o. ubchỉ cần tạo các mảng hai phần tử và ba phần tử tương ứng. ogiả sử mảng hai phần tử là phân phối đồng nhất và một phần tử ba phần tử là sự pha trộn của ba phân phối. Trong trường hợp sau, nó gọi chính nó đệ quy.


2

MATLAB, 73

Thời gian cho một chút "lập trình chức năng" trong MATLAB. Đây là 3 chức năng ẩn danh. Đồng nhất và pha trộn được gọi giống như các ví dụ, nhưng đối với overcác đối số nên được hoán đổi. Tôi không thực sự cần một overhai hàm trả về đầu tiên, nhưng vì hình thức fevallà một hàm có thể gọi một hàm.

%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

Bây giờ, hệ thống phân tích và đánh giá của MATLAB là một chút khó khăn để nói rằng ít nhất. Nó không cho phép bạn gọi trực tiếp một chức năng được trả về từ một chức năng. Thay vào đó, trước tiên người ta phải lưu kết quả vào một biến. Ví dụ thứ 4 có thể được thực hiện như sau:

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)

Tuy nhiên, có thể khắc phục điều này bằng cách sử dụng fevalđể gọi tất cả các chức năng. Nếu các định nghĩa sau được sử dụng, thì các ví dụ có thể được đánh giá chính xác như chúng được viết.

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)

Chức năng làm chức năng ... thật là hư hỏng!
Luis Mendo

1

Toán học, 129 116 byte

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

u, bouniform, blendovertương ứng.Wrapper trên các chức năng tiêu chuẩn. Thay thế \uF3D2s bằng ký tự 3 byte. Chỉ cần trả lại 01cho các trường hợp 1, 4 và 7.


1

Python, 146 byte

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)

Chiến lược tương tự như câu trả lời Ruby của histocrat, nhưng trong Python. Để thực hiện đệ quy mà không có bộ kết hợp Z (sẽ tốn kém) xyđược định nghĩa là các hàm trợ giúp để đánh giá các bộ overđối số 2 và 3 chiều dài ( uniformvà các blendđối số, tương ứng).

Các trường hợp thử nghiệm trên ideone


0

Matlab, 104 byte

Tôi hy vọng điều này vẫn hợp lệ, vì điều này chỉ hoạt động đối với các bản phân phối có hỗ trợ trong [-10,10], đây là yêu cầu đối với các ngôn ngữ không có hỗ trợ dấu phẩy động. Vectơ hỗ trợ và độ chính xác có thể được điều chỉnh dễ dàng bằng cách chỉ thay đổi số tương ứng. u,o,blà cho uniform,blend,over. Pdf chỉ được biểu diễn dưới dạng một vectơ rời rạc. Tôi nghĩ rằng phương pháp này có thể dễ dàng được chuyển sang các ngôn ngữ khác.

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;

Bạn có thể kiểm tra chúng nếu bạn xác định các chức năng đó trước và sau đó chỉ cần dán mã này:

[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 có hỗ trợ FP, vì vậy tôi nghĩ rằng điều này sẽ không hợp lệ.
LegionMammal978

Tôi ngần ngại cho phép điều này, vì Matlab hỗ trợ số dấu phẩy động nguyên bản. Nếu bạn có thể thay thế XDbằng MIN_FLOATMAX_FLOAT(hoặc bất cứ điều gì Matlab gọi cho họ), thì đây là một cách tiếp cận hợp lệ.
Zgarb

Có, bạn có thể ouse realmax/ realmin, bạn thậm chí có thể tạo ra một vectơ vượt qua tất cả số dấu phẩy động nếu bạn có đủ bộ nhớ.
flawr
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.