Реалізуйте API для розподілу ймовірностей


9

Вступ

У цьому завданні ваше завдання полягає в реалізації колекції простих функцій, які разом утворюють корисну міні-бібліотеку для простого розподілу ймовірностей. Для розміщення деяких з більш езотеричних мов, якими люблять користуватися тут, прийнятні такі реалізації:

  1. Фрагмент коду, що визначає колекцію названих функцій (або найближчих еквівалентів).
  2. Сукупність виразів, що оцінюються за іменованими або анонімними функціями (або найближчими еквівалентами).
  3. Один вираз, який оцінює декілька названих або анонімних функцій (або найближчих еквівалентів).
  4. Колекція незалежних програм, які приймають вхідні дані з командного рядка, STDIN або найближчого еквівалента і виводять в STDOUT або найближчий еквівалент.

Функції

Ви повинні реалізувати наступні функції, використовуючи короткі назви за бажанням.

  1. uniformприймає за вхід два числа з плаваючою комою aі b, і повертає рівномірний розподіл [a,b]. Ви можете припустити, що a < b; справа a ≥ bне визначена.
  2. blendприймає в якості вхідних сигналів трьох імовірнісних розподілів P, Qі R. Він повертає розподіл ймовірності S, який витягує значення x, yі zз P, Qі R, відповідно, і приносить, yякщо x ≥ 0і zякщо x < 0.
  3. overприймає за вхід число з плаваючою комою fта розподіл ймовірності Pта повертає ймовірність, яка x ≥ fмає місце для випадкового числа, xпроведеного з P.

Для довідки 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, і що єдине, що користувач збирається зробити при розподілі ймовірностей, - це подати його на 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
Чи можемо ми використовувати вбудовані функції для їх виготовлення?
Мутадор

@ AndréMuta Я забув, що Mathematica, ймовірно, має вбудовані версії для всього цього ... але я збираюся їх дозволити, якщо вони дотримуються правил.
Згарб

Яка ваша пропозиція щодо представлення даних з плаваючою комою в 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 Oє 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)}

Визначає три лямбда, u, b, і o. uі bпросто створити двоелементний і триелементний масиви відповідно. oприпускає, що двоелементний масив є рівномірним розподілом, а триелементним - це суміш трьох розподілів. В останньому випадку він називає себе рекурсивно.


2

МАТЛАБ, 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 - це щонайменше нелегко. Це не дозволяє вам безпосередньо викликати функцію, повернуту з функції. Натомість спочатку потрібно зберегти результат у змінній. Четвертий приклад можна зробити наступним чином:

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

Математика, 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і overвідповідно. Оберніть стандартні функції. Замініть \uF3D2s на 3-байтний символ. Просто повертається 0і 1для випадків 1, 4 і 7.


1

Пітон, 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-комбінатора (що було б затратно), xі yвони визначаються як допоміжні функції, які оцінюють over2- та 3-довжинні кортежі аргументів ( uniformі blendаргументи відповідно).

Тестові приклади на ideone


0

Матлаб, 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 називає їх), то це правильний підхід.
Згарб

Так, ви могли б увімкнути realmax/ realmin, ви навіть можете зробити вектор, який проходить через все число з плаваючою комою, якщо у вас достатньо пам'яті.
flawr
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.