Browse code

Use OptionalFloats instead of pair<bool, float>

Tom Sherman authored on 23/08/2018 22:31:43
Showing4 changed files

... ...
@@ -70,9 +70,8 @@ protected:
70 70
     void acceptExchange(AtomicProposal *prop, float d1, unsigned r1,
71 71
         unsigned c1, unsigned r2, unsigned c2);
72 72
 
73
-    std::pair<float, bool> gibbsMass(AlphaParameters alpha, GapsRng *rng);
74
-    std::pair<float, bool> gibbsMass(AlphaParameters alpha, float m1, float m2,
75
-        GapsRng *rng);
73
+    OptionalFloat gibbsMass(AlphaParameters alpha, GapsRng *rng);
74
+    OptionalFloat gibbsMass(AlphaParameters alpha, float m1, float m2, GapsRng *rng);
76 75
 
77 76
 public:
78 77
 
... ...
@@ -346,7 +345,7 @@ void GibbsSampler<T, MatA, MatB>::birth(AtomicProposal *prop)
346 345
     if (impl()->canUseGibbs(row, col))
347 346
     {
348 347
         AlphaParameters alpha = impl()->alphaParameters(row, col);
349
-        mass = gibbsMass(alpha, &(prop->rng)).first;
348
+        mass = gibbsMass(alpha, &(prop->rng)).value; // 0 if it fails
350 349
     }
351 350
     else
352 351
     {
... ...
@@ -386,10 +385,10 @@ void GibbsSampler<T, MatA, MatB>::death(AtomicProposal *prop)
386 385
     AlphaParameters alpha = impl()->alphaParameters(row, col);
387 386
     if (impl()->canUseGibbs(row, col))
388 387
     {
389
-        std::pair<float, bool> gMass = gibbsMass(alpha, &(prop->rng));
390
-        if (gMass.second)
388
+        OptionalFloat gMass = gibbsMass(alpha, &(prop->rng));
389
+        if (gMass.hasValue)
391 390
         {
392
-            rebirthMass = gMass.first;
391
+            rebirthMass = gMass.value;
393 392
         }
394 393
     }
395 394
 
... ...
@@ -454,16 +453,15 @@ void GibbsSampler<T, MatA, MatB>::exchange(AtomicProposal *prop)
454 453
     if (impl()->canUseGibbs(r1, c1, r2, c2))
455 454
     {
456 455
         AlphaParameters alpha = impl()->alphaParameters(r1, c1, r2, c2);
457
-        std::pair<float, bool> gMass = gibbsMass(alpha, m1, m2, &(prop->rng));
458
-        if (gMass.second)
456
+        OptionalFloat gMass = gibbsMass(alpha, m1, m2, &(prop->rng));
457
+        if (gMass.hasValue)
459 458
         {
460
-            acceptExchange(prop, gMass.first, r1, c1, r2, c2);
459
+            acceptExchange(prop, gMass.value, r1, c1, r2, c2);
461 460
             return;
462 461
         }
463 462
     }
464 463
 
465
-    float pUpper = gaps::p_gamma(m1 + m2, 2.f, 1.f / mLambda);
466
-    float newMass = prop->rng.inverseGammaSample(0.f, pUpper, 2.f, 1.f / mLambda);
464
+    float newMass = prop->rng.truncGammaUpper(m1 + m2, 2.f, 1.f / mLambda);
467 465
 
468 466
     float delta = m1 > m2 ? newMass - m1 : m2 - newMass; // change larger mass
469 467
     float pOldMass = 2.f * newMass > m1 + m2 ? gaps::max(m1, m2) : gaps::min(m1, m2);
... ...
@@ -537,7 +535,7 @@ float d1, unsigned r1, unsigned c1, unsigned r2, unsigned c2)
537 535
 }
538 536
 
539 537
 template <class T, class MatA, class MatB>
540
-std::pair<float, bool> GibbsSampler<T, MatA, MatB>::gibbsMass(AlphaParameters alpha,
538
+OptionalFloat GibbsSampler<T, MatA, MatB>::gibbsMass(AlphaParameters alpha,
541 539
 GapsRng *rng)
542 540
 {        
543 541
     alpha.s *= mAnnealingTemp;
... ...
@@ -553,14 +551,17 @@ GapsRng *rng)
553 551
         {
554 552
             float m = rng->inverseNormSample(pLower, 1.f, mean, sd);
555 553
             float gMass = gaps::min(m, mMaxGibbsMass / mLambda);
556
-            return std::pair<float, bool>(gMass, gMass >= gaps::epsilon);
554
+            if (gMass >= gaps::epsilon)
555
+            {
556
+                return OptionalFloat(gMass);
557
+            }
557 558
         }
558 559
     }
559
-    return std::pair<float, bool>(0.f, false);
560
+    return OptionalFloat();
560 561
 }
561 562
 
562 563
 template <class T, class MatA, class MatB>
563
-std::pair<float, bool> GibbsSampler<T, MatA, MatB>::gibbsMass(AlphaParameters alpha,
564
+OptionalFloat GibbsSampler<T, MatA, MatB>::gibbsMass(AlphaParameters alpha,
564 565
 float m1, float m2, GapsRng *rng)
565 566
 {
566 567
     alpha.s *= mAnnealingTemp;
... ...
@@ -576,11 +577,11 @@ float m1, float m2, GapsRng *rng)
576 577
         if (!(pLower >  0.95f || pUpper < 0.05f))
577 578
         {
578 579
             float delta = rng->inverseNormSample(pLower, pUpper, mean, sd);
579
-            float gibbsMass = gaps::min(gaps::max(-m1, delta), m2); // conserve mass
580
-            return std::pair<float, bool>(gibbsMass, true);
580
+            float gMass = gaps::min(gaps::max(-m1, delta), m2); // conserve mass
581
+            return OptionalFloat(gMass);
581 582
         }
582 583
     }
583
-    return std::pair<float, bool>(0.f, false);
584
+    return OptionalFloat();
584 585
 }
585 586
 
586 587
 #ifdef GAPS_DEBUG
... ...
@@ -8,8 +8,8 @@
8 8
 namespace gaps
9 9
 {
10 10
     const float epsilon = 1.0e-10f;
11
-    const float pi = 3.14159265358979323846264f;
12
-    const float pi_double = 3.14159265358979323846264;
11
+    const float pi = 3.1415926535897932384626433832795f;
12
+    const float pi_double = 3.1415926535897932384626433832795;
13 13
 
14 14
     float min(float a, float b);
15 15
     unsigned min(unsigned a, unsigned b);
... ...
@@ -237,14 +237,16 @@ float GapsRng::inverseNormSample(float a, float b, float mean, float sd)
237 237
     return gaps::q_norm(u, mean, sd);
238 238
 }
239 239
 
240
-float GapsRng::inverseGammaSample(float a, float b, float mean, float sd)
240
+float GapsRng::truncGammaUpper(float b, float shape, float scale)
241 241
 {
242
-    float u = uniform(a, b);
242
+    float upper = gaps::p_gamma(b, shape, scale);
243
+
244
+    float u = uniform(0.f, upper);
243 245
     while (u == 0.f || u == 1.f)
244 246
     {
245
-        u = uniform(a, b);
247
+        u = uniform(0.f, upper);
246 248
     }
247
-    return gaps::q_gamma(u, mean, sd);
249
+    return gaps::q_gamma(u, shape, scale);
248 250
 }
249 251
 
250 252
 Archive& operator<<(Archive &ar, GapsRng &gen)
... ...
@@ -303,3 +305,9 @@ double gaps::lgamma(double x)
303 305
 {
304 306
     return boost::math::lgamma(x);
305 307
 }
308
+
309
+float gaps::d_norm_fast(float d, float mean, float sd)
310
+{
311
+    return std::exp((d - mean) * (d - mean) / (-2.f * sd * sd))
312
+        / std::sqrt(2.f * gaps::pi * sd * sd);
313
+}
... ...
@@ -9,8 +9,8 @@
9 9
 
10 10
 struct OptionalFloat
11 11
 {
12
-    bool hasValue;
13 12
     float value;
13
+    bool hasValue;
14 14
 
15 15
     OptionalFloat() : hasValue(false), value(0.f) {}
16 16
     OptionalFloat(float f) : hasValue(true), value(f) {}
... ...
@@ -26,6 +26,13 @@ namespace gaps
26 26
     float d_norm(float d, float mean, float sd);
27 27
     float q_norm(float q, float mean, float sd);
28 28
     float p_norm(float p, float mean, float sd);
29
+
30
+    float d_gamma_fast(float d, float shape, float scale);
31
+    float p_gamma_fast(float p, float shape, float scale);
32
+    float q_gamma_fast(float q, float shape, float scale);
33
+    float d_norm_fast(float d, float mean, float sd);
34
+    float p_norm_fast(float p, float mean, float sd);
35
+    float q_norm_fast(float q, float mean, float sd);
29 36
 }
30 37
 
31 38
 // used for seeding individual rngs
... ...
@@ -66,7 +73,7 @@ public:
66 73
     float exponential(float lambda);
67 74
 
68 75
     float inverseNormSample(float a, float b, float mean, float sd);
69
-    float inverseGammaSample(float a, float b, float mean, float sd);
76
+    float truncGammaUpper(float b, float shape, float scale);
70 77
 
71 78
     static void setSeed(uint64_t seed);
72 79
     static void save(Archive &ar);