ใช้ API สำหรับการแจกแจงความน่าจะเป็น


9

บทนำ

ในความท้าทายนี้งานของคุณคือการใช้คอลเลกชันของฟังก์ชั่นที่เรียบง่ายที่รวมกันเป็นห้องสมุดขนาดเล็กที่ใช้งานได้สำหรับการแจกแจงความน่าจะเป็นแบบง่าย เพื่อรองรับภาษาที่ลึกลับกว่าบางคนที่ต้องการใช้ที่นี่การใช้งานต่อไปนี้เป็นที่ยอมรับ:

  1. ส่วนย่อยของรหัสกำหนดคอลเลกชันของฟังก์ชันที่มีชื่อ (หรือเทียบเท่าที่ใกล้เคียงที่สุด)
  2. คอลเลกชันของนิพจน์ที่ประเมินฟังก์ชันที่ระบุชื่อหรือไม่ระบุชื่อ (หรือเทียบเท่าที่ใกล้เคียงที่สุด)
  3. นิพจน์เดียวที่ประเมินไปยังฟังก์ชันที่ระบุชื่อหรือไม่ระบุชื่อหลายรายการ (หรือเทียบเท่าที่ใกล้เคียงที่สุด)
  4. คอลเล็กชันของโปรแกรมอิสระที่รับอินพุตจากบรรทัดรับคำสั่ง STDIN หรือเทียบเท่าที่ใกล้เคียงที่สุดและเอาต์พุตไปยัง STDOUT หรือเทียบเท่าที่ใกล้เคียงที่สุด

ส่วนฟังก์ชั่น

คุณจะต้องใช้ฟังก์ชั่นต่อไปนี้โดยใช้ชื่อที่สั้นลงหากต้องการ

  1. uniformใช้เวลาเป็น input ตัวเลขสองจุดลอยaและและผลตอบแทนการกระจายชุดบนb [a,b]คุณสามารถสันนิษฐานได้ว่าa < b; กรณีa ≥ bไม่ได้กำหนด
  2. blendจะเป็นสามแจกแจงความน่าจะปัจจัยการผลิตP, และQ Rมันกลับกระจายความน่าจะเป็นSที่ดึงค่าx, yและzจากP, QและRตามลำดับและอัตราผลตอบแทนyถ้าx ≥ 0และถ้าzx < 0
  3. overใช้เวลาเป็น input จำนวนจุดลอยfและการกระจายความน่าจะเป็นPและผลตอบแทนที่น่าจะเป็นที่x ≥ fถือสำหรับจำนวนสุ่มมาจากxP

สำหรับการอ้างอิงoverสามารถกำหนดได้ดังต่อไปนี้ (ใน pseudocode):

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และว่าสิ่งเดียวที่ผู้ใช้จะทำอย่างไรกับการกระจายความน่าจะเป็นคือการให้อาหารมันหรือblend overคุณสามารถใช้ประเภทข้อมูลที่สะดวกเพื่อแสดงการแจกแจง: รายการตัวเลข, สตริง, วัตถุที่กำหนดเองและอื่น ๆ สิ่งสำคัญเพียงอย่างเดียวคือ 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

คำตอบ:


1

CJam, 58 ไบต์

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

เหล่านี้เป็นผู้ประกอบการ postfix ว่าการทำงานในกอง: คือ2.0 1.0 3.0 U Oover(2, uniform(1, 3))

นับคะแนน

{[\]}เป็นฟังก์ชั่นของตัวเอง:U;กำหนดให้กับชื่อUและปรากฏมัน โดยพื้นฐานแล้วนี่ไม่ใช่ส่วนหนึ่งของฟังก์ชันดังนั้นด้วยกฎการนับคะแนน 2 ฉันต้องนับ{[\]}เท่านั้น Bถูกกำหนดในทำนองเดียวกัน

อย่างไรก็ตามOเป็นแบบเรียกซ้ำและหากฉันไม่ได้ระบุชื่อจะไม่มีวิธีการเรียกคืน ดังนั้นที่นี่ฉันจะโน้มน้าวให้นับ:O;ส่วน จากนั้นคะแนนของฉันคือ5+5+48=58ไบต์ทั้งหมด

คำอธิบาย

Uดึงอาร์กิวเมนต์สองตัวและทำให้คู่อยู่ในลำดับย้อนกลับ: a b => [b a].

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

กำหนดสาม lambdas, u, และb และเพียงแค่สร้างอาร์เรย์สององค์ประกอบและสามองค์ประกอบตามลำดับ สมมติว่าอาร์เรย์สององค์ประกอบเป็นการแจกแจงแบบเดียวกันและองค์ประกอบสามองค์ประกอบเป็นการผสมผสานของการแจกแจงสามแบบ ในกรณีหลังมันเรียกตัวเองซ้ำoubo


2

MATLAB, 73

เวลาสำหรับ "การเขียนโปรแกรมใช้งานได้" ใน MATLAB เหล่านี้เป็นฟังก์ชั่นที่ไม่ระบุชื่อ 3 รายการ รูปแบบและการผสมผสานที่เรียกว่าแบบเดียวกับตัวอย่าง แต่สำหรับoverการขัดแย้งควรสลับ ฉันไม่ต้องการจริงๆoverตั้งแต่ฟังก์ชั่นส่งคืนสองตัวแรก แต่ในฐานะที่เป็นทางการ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

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]&

u, bและoมีuniform, blendและoverrespectively.Wrapper มากกว่าฟังก์ชั่นมาตรฐาน แทนที่\uF3D2s ด้วยอักขระ 3 ไบต์ เพียงแค่ส่งคืน0และ1สำหรับกรณีที่ 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)

กลยุทธ์เดียวกับคำตอบรูบี้ของฮิสโทแคต แต่ใน Python หากต้องการเรียกซ้ำโดยไม่มี Z-combinator (ซึ่งจะมีราคาแพง) xและyถูกกำหนดเป็นฟังก์ชันตัวช่วยที่ประเมินค่าoverอันดับของอาร์กิวเมนต์อันดับ 2 และ 3 ความยาว ( uniformและblendอาร์กิวเมนต์ตามลำดับ)

กรณีทดสอบบน 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 รองรับตัวเลขทศนิยม หากคุณสามารถแทนที่XและDด้วยMIN_FLOATและMAX_FLOAT(หรืออะไรก็ตามที่เรียกว่า Matlab) นี่เป็นแนวทางที่ถูกต้อง
Zgarb

ใช่คุณสามารถใช้realmax/ realminคุณสามารถสร้างเวกเตอร์ที่มีจำนวนจุดลอยตัวทั้งหมดหากคุณมีหน่วยความจำเพียงพอ
ข้อบกพร่อง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.