1 #ifndef BAYES_CLASSIFIER_HPP
2 #define BAYES_CLASSIFIER_HPP
3 
4 #include <cmath>
5 
6 #include <utility>
7 #include <vector>
8 
9 #include <boost/math/constants/constants.hpp>
10 
11 namespace osrm
12 {
13 namespace engine
14 {
15 namespace map_matching
16 {
17 
18 struct NormalDistribution
19 {
NormalDistributionosrm::engine::map_matching::NormalDistribution20     NormalDistribution(const double mean, const double standard_deviation)
21         : mean(mean), standard_deviation(standard_deviation)
22     {
23     }
24 
25     // FIXME implement log-probability version since it's faster
Densityosrm::engine::map_matching::NormalDistribution26     double Density(const double val) const
27     {
28         using namespace boost::math::constants;
29 
30         const double x = val - mean;
31         return 1.0 / (std::sqrt(two_pi<double>()) * standard_deviation) *
32                std::exp(-x * x / (standard_deviation * standard_deviation));
33     }
34 
35     double mean;
36     double standard_deviation;
37 };
38 
39 struct LaplaceDistribution
40 {
LaplaceDistributionosrm::engine::map_matching::LaplaceDistribution41     LaplaceDistribution(const double location, const double scale)
42         : location(location), scale(scale)
43     {
44     }
45 
46     // FIXME implement log-probability version since it's faster
Densityosrm::engine::map_matching::LaplaceDistribution47     double Density(const double val) const
48     {
49         const double x = std::abs(val - location);
50         return 1.0 / (2. * scale) * std::exp(-x / scale);
51     }
52 
53     double location;
54     double scale;
55 };
56 
57 template <typename PositiveDistributionT, typename NegativeDistributionT, typename ValueT>
58 class BayesClassifier
59 {
60   public:
61     enum class ClassLabel : unsigned
62     {
63         NEGATIVE,
64         POSITIVE
65     };
66     using ClassificationT = std::pair<ClassLabel, double>;
67 
BayesClassifier(PositiveDistributionT positive_distribution,NegativeDistributionT negative_distribution,const double positive_apriori_probability)68     BayesClassifier(PositiveDistributionT positive_distribution,
69                     NegativeDistributionT negative_distribution,
70                     const double positive_apriori_probability)
71         : positive_distribution(std::move(positive_distribution)),
72           negative_distribution(std::move(negative_distribution)),
73           positive_apriori_probability(positive_apriori_probability),
74           negative_apriori_probability(1. - positive_apriori_probability)
75     {
76     }
77 
78     // Returns label and the probability of the label.
classify(const ValueT & v) const79     ClassificationT classify(const ValueT &v) const
80     {
81         const double positive_postpriori =
82             positive_apriori_probability * positive_distribution.Density(v);
83         const double negative_postpriori =
84             negative_apriori_probability * negative_distribution.Density(v);
85         const double norm = positive_postpriori + negative_postpriori;
86 
87         if (positive_postpriori > negative_postpriori)
88         {
89             return std::make_pair(ClassLabel::POSITIVE, positive_postpriori / norm);
90         }
91 
92         return std::make_pair(ClassLabel::NEGATIVE, negative_postpriori / norm);
93     }
94 
95   private:
96     PositiveDistributionT positive_distribution;
97     NegativeDistributionT negative_distribution;
98     double positive_apriori_probability;
99     double negative_apriori_probability;
100 };
101 } // namespace map_matching
102 } // namespace engine
103 } // namespace osrm
104 
105 #endif // BAYES_CLASSIFIER_HPP
106