Vcsn  2.4
Be Rational
weightset.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <iostream>
4 #include <map>
5 #include <memory> // std::make_shared
6 #include <string>
7 #include <type_traits>
8 #include <vector>
9 
10 #include <boost/algorithm/string/erase.hpp>
11 #include <boost/tokenizer.hpp>
12 
13 #include <vcsn/misc/algorithm.hh>
14 #include <vcsn/misc/cast.hh>
15 #include <vcsn/misc/functional.hh>
16 #include <vcsn/misc/random.hh>
17 #include <vcsn/misc/type_traits.hh> // detect
18 
19 // It is much simpler and saner in C++ to put types and functions on
20 // these types in the same namespace. Since "using q =
21 // detail::weightset_mixin<q_impl>" would just create an alias of
22 // q, its original namespace, detail::, would still be the namespace
23 // used in ADL.
24 //
25 // This is really troublesome to implement free-functions such as join.
26 //
27 // Therefore, although this wrapper should be hidden as a detail::, it
28 // will remain in vcsn::, where join and the like will find it.
29 
30 namespace vcsn
31 {
32  namespace detail
33  {
35  template <typename T>
36  using power_mem_fn_t
37  = decltype(std::declval<T>()
38  .power(std::declval<typename T::value_t>(), 0));
39 
41  template <typename T>
43  }
44 
46  template <typename WeightSet>
47  struct weightset_mixin : WeightSet
48  {
49  using super_t = WeightSet;
50  using typename super_t::value_t;
51 
53  using super_t::super_t;
54 
56  using super_t::mul;
57 
59  template <typename... Ts>
60  value_t mul(const Ts&... ts) const
61  {
62  value_t res = this->one();
63  // FIXME: Remove once GCC is fixed.
64  using swallow = int[];
65  (void) swallow
66  {
67  ((res = super_t::mul(res, ts)), 0)...
68  };
69  return res;
70  }
71 
72  private:
75  template <typename WS = super_t>
76  auto power_(value_t e, unsigned n) const
77  -> std::enable_if_t<detail::has_power_mem_fn<WS>{}, value_t>
78  {
79  return super_t::power(e, n);
80  }
81 
84  template <typename WS = super_t>
85  auto power_(value_t e, unsigned n) const
86  -> std::enable_if_t<!detail::has_power_mem_fn<WS>{}, value_t>
87  {
89  if (!super_t::is_one(e))
90  while (n--)
91  res = mul(res, e);
92  return res;
93  }
94 
95  public:
96 
98  value_t power(value_t e, unsigned n) const
99  {
100  return power_<WeightSet>(e, n);
101  }
102  };
103 
104 
105  namespace detail
106  {
110  template <typename WeightSet,
111  typename RandomGenerator = std::default_random_engine>
113  {
114  public:
115  using weight_weight_t = std::vector<float>;
116  using weight_map_t = std::map<typename WeightSet::value_t, float,
118  using randomGenerator_t = RandomGenerator;
119  using weight_t = typename WeightSet::value_t;
120 
121  random_weight_base(RandomGenerator& gen, const WeightSet& ws)
122  : gen_{gen}
123  , ws_{ws}
124  , min_{ws.min()}
125  , max_{ws.max()}
126  {}
127 
128  void parse_param(const std::string& param)
129  {
130  if (!param.empty())
131  parse_param_(param);
132  }
133 
135  {
136  return print_random_weight_();
137  }
138 
139  protected:
140  virtual void parse_param_(const std::string& weights)
141  {
142  using tokenizer = boost::tokenizer<boost::char_separator<char>>;
143  auto sep = boost::char_separator<char>{","};
144  auto tok = tokenizer(weights, sep);
145  for (auto it = tok.begin(); it != tok.end(); ++it)
146  {
147  auto tok_arg = std::string{*it};
148  auto eq = tok_arg.find_first_of('=');
149  auto weight = tok_arg.substr(0, eq);
150  boost::algorithm::erase_all(weight, " ");
151  if (weight == "min")
152  min_ = conv(ws_, tok_arg.substr(eq + 1));
153  else if (weight == "max")
154  max_ = conv(ws_, tok_arg.substr(eq + 1));
155  else
156  {
157  float value = (eq != std::string::npos)
158  ? value = detail::lexical_cast<float>(tok_arg.substr(eq + 1))
159  : 1;
160  auto w = conv(ws_, weight);
161  weight_[w] = value;
162  }
163  }
164 
166  = detail::transform(weight_, [](const auto& v){ return v.second; });
167  }
168 
169  virtual weight_t pick_value_() const = 0;
170 
173  {
177  {
178  auto it = chooser_it_(weight_weight_, weight_);
179  return it->first;
180  }
182  else
183  {
184  return pick_value_();
185  }
186  }
187 
194  RandomGenerator& gen_;
200  };
201 
204  template <typename WeightSet, typename RandomGenerator>
206  }
207 
208 
209  // FIXME: find generic implementation for min-plus.
210  template <typename T>
211  struct is_tropical : std::false_type
212  {};
213 }
constant< type_t::one, Context > one
Definition: fwd.hh:113
Generic declaration of the class which is specialized in each weightset.
Definition: weightset.hh:205
discrete_chooser< RandomGenerator > chooser_it_
Definition: weightset.hh:199
virtual void parse_param_(const std::string &weights)
Definition: weightset.hh:140
value_impl< detail::weight_tag > weight
Definition: fwd.hh:28
Functor to compare Values of ValueSets.
Definition: functional.hh:76
decltype(std::declval< T >().power(std::declval< typename T::value_t >(), 0)) power_mem_fn_t
The signature of power.
Definition: weightset.hh:38
random_weight_base(RandomGenerator &gen, const WeightSet &ws)
Definition: weightset.hh:121
value_t mul(const Ts &...ts) const
A variadic multiplication.
Definition: weightset.hh:60
Abstract class for random weight generation.
Definition: weightset.hh:112
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
auto power_(value_t e, unsigned n) const -> std::enable_if_t<!detail::has_power_mem_fn< WS >
Case where the weightset T does not feature a power(value_t, unsigned) member function.
Definition: weightset.hh:85
weight_t print_random_weight_() const
A random weight.
Definition: weightset.hh:172
value_t power(value_t e, unsigned n) const
Repeated multiplication.
Definition: weightset.hh:98
Request the map implementation.
Definition: a-star.hh:8
void parse_param(const std::string &param)
Definition: weightset.hh:128
auto transform(const Container &c, Fun &&fun)
Map a unary function on a container of values, and return the vector the results. ...
Definition: algorithm.hh:157
static bool choose_map(const std::vector< float > &map, RandomGenerator &gen=RandomGenerator())
Choose whether to pick an element from a map or not.
Definition: random.hh:17
weight_map_t weight_
Elements given by the user and their associated probabilities (weight_weight_).
Definition: weightset.hh:197
variadic< type_t::mul, Context > mul
Definition: fwd.hh:151
auto power_(value_t e, unsigned n) const -> std::enable_if_t< detail::has_power_mem_fn< WS >
Case where the weightset T features a power(value_t, unsigned) member function.
Definition: weightset.hh:76
virtual weight_t pick_value_() const =0
std::map< typename zmin::value_t, float, vcsn::less< zmin >> weight_map_t
Definition: weightset.hh:117
auto conv(const ValueSet &vs, const std::string &str, Args &&...args) -> decltype(vs.conv(std::declval< std::istream & >(), std::forward< Args >(args)...))
Parse str via vs.conv.
Definition: stream.hh:29
weight_t min_
The min and the max given by the user.
Definition: weightset.hh:192
weight_t generate_random_weight() const
Definition: weightset.hh:134
Random selector on container, using discrete distribution.
Definition: random.hh:27