Vcsn  2.8
Be Rational
edit-automaton.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <tuple>
4 #include <unordered_map>
5 #include <utility>
6 #include <vector>
7 
9 #include <vcsn/ctx/context.hh>
10 #include <vcsn/ctx/fwd.hh>
11 #include <vcsn/dyn/algos.hh>
12 #include <vcsn/dyn/automaton.hh>
13 #include <vcsn/dyn/context.hh>
14 #include <vcsn/dyn/fwd.hh>
15 #include <vcsn/misc/symbol.hh>
16 #include <vcsn/misc/raise.hh>
17 #include <vcsn/misc/static-if.hh>
18 #include <vcsn/misc/stream.hh>
20 
21 namespace vcsn
22 {
23 
24  /*----------------------.
25  | edit_automaton<Aut>. |
26  `----------------------*/
27 
30  {
31  public:
32  using string_t = symbol;
33 
34  virtual ~automaton_editor() {}
35  virtual void add_initial(string_t s, string_t w) = 0;
36  virtual void add_final(string_t s, string_t w) = 0;
37 
39  virtual void add_state(string_t s) = 0;
40 
42  virtual void add_pre(string_t s) = 0;
43 
45  virtual void add_post(string_t s) = 0;
46 
48  virtual void add_entry(string_t src, string_t dst,
49  string_t entry) = 0;
50 
52  virtual void add_transition(string_t src, string_t dst,
54  string_t weight = string_t{}) = 0;
55 
59  virtual bool open(bool o) = 0;
60 
62  virtual dyn::automaton result() = 0;
63 
65  virtual void reset() = 0;
66 
68  void set_separator(char c)
69  {
70  sep_ = c;
71  }
72 
73  protected:
75  char sep_ = '+';
76  };
77 
78 
84  template <Automaton Aut>
86  {
87  public:
91 
92  private:
99 
100  public:
102  : res_(make_shared_ptr<automaton_t>(ctx))
103  , ps_(ctx)
104  {}
105 
109  bool
110  open(bool o) override final
111  {
112  return const_cast<labelset_t&>(*res_->context().labelset()).open(o);
113  }
114 
116  void
117  add_state(string_t s) override final
118  {
119  state_(s);
120  }
121 
123  void
124  add_pre(string_t s) override final
125  {
126  res_->state(s, res_->pre());
127  }
128 
130  void
131  add_post(string_t s) override final
132  {
133  res_->state(s, res_->post());
134  }
135 
136  void
137  add_initial(string_t s, string_t weight = string_t{}) override final
138  {
139  res_->add_initial(state_(s), weight_(weight));
140  }
141 
142  void
143  add_final(string_t s, string_t weight = string_t{}) override final
144  {
145  res_->add_final(state_(s), weight_(weight));
146  }
147 
148  void
150  string_t label,
151  string_t weight = string_t{}) override final
152  {
153  // In case of states we don't know, we'd like to register s
154  // first, then d, in an attempt to keep the order in which we
155  // discover states. Which is not guaranteed by plain argument
156  // evaluation.
157  auto s = state_(src);
158  auto d = state_(dst);
159  res_->add_transition(s, d, label_(label), weight_(weight));
160  }
161 
163  void
164  add_entry(string_t src, string_t dst, string_t entry) override final
165  {
166  const auto s = state_(src);
167  const auto d = state_(dst);
168  require(s != res_->pre() || d != res_->post(),
169  "edit_automaton: invalid transition from pre to post: ",
170  src, " -> ", dst, " (", entry, ")");
171  const auto& ls = *res_->labelset();
172  if (s == res_->pre() || d == res_->post())
173  {
174  if (entry.get().empty())
175  res_->add_transition(s, d, res_->prepost_label());
176  else
177  {
178  using std::begin;
179  // Adding a pre/post transition: be sure that it's only
180  // a weight.
181  const auto p = conv(ps_, entry, sep_);
182  const auto m = *begin(p);
183  VCSN_REQUIRE(p.size() == 1
184  && ls.is_special(label_of(m)),
185  "edit_automaton: invalid ",
186  s == res_->pre() ? "initial" : "final",
187  " entry: ", entry.get());
188  res_->add_transition(s, d,
189  res_->prepost_label(), weight_of(m));
190  }
191  }
192  else
193  {
194  auto p = emap_.emplace(entry, entry_t{});
195  if (p.second)
196  p.first->second = conv(ps_, entry, sep_);
197  for (auto m: p.first->second)
198  {
199  detail::static_if<labelset_t::has_one()>
200  ([&](const auto& ls)
201  {
202  res_->add_transition
203  (s, d,
204  ls.is_special(label_of(m)) ? ls.one() : label_of(m),
205  weight_of(m));
206  },
207  [&](const auto& ls)
208  {
209  VCSN_REQUIRE(!ls.is_special(label_of(m)),
210  "edit_automaton: invalid entry: ",
211  entry.get());
212  res_->add_transition(s, d,
213  label_of(m), weight_of(m));
214  })
215  (ls);
216  }
217  }
218  }
219 
222  result() override final
223  {
224  const_cast<labelset_t&>(*res_->context().labelset()).open(false);
225  return res_;
226  }
227 
229  void
230  reset() override final
231  {
232  res_ = nullptr;
233  }
234 
235  private:
237  label_t
239  {
240  const auto& ls = *res_->labelset();
241  auto p = lmap_.emplace(l, label_t{});
242  if (p.second)
243  p.first->second = conv(ls, l);
244  return p.first->second;
245  }
246 
248  weight_t
250  {
251  const auto& ws = *res_->weightset();
252  auto p = wmap_.emplace(w, weight_t{});
253  if (p.second)
254  p.first->second = w.get().empty() ? ws.one() : conv(ws, w);
255  return p.first->second;
256  }
257 
259  state_t
261  {
262  return res_->state(k);
263  }
264 
269 
271  using entry_map = std::unordered_map<string_t, entry_t>;
274  using label_map = std::unordered_map<string_t, label_t>;
277  using weight_map = std::unordered_map<string_t, weight_t>;
279  };
280 
287  {
288  public:
291 
293  enum class labelset_type { empty, lal, lan, law };
294 
296  enum class weightset_type { logarithmic, numerical, tropical };
297 
299  void add_initial(string_t s, string_t w = string_t{});
300 
302  void add_final(string_t s, string_t w = string_t{});
303 
306  void add_transition(string_t src, string_t dst,
307  string_t lbl, string_t w = string_t{});
308 
311  void add_transition(string_t src, string_t dst,
312  string_t lbl1, string_t lbl2,
313  string_t w);
314 
316  std::string result_context() const;
317 
321  dyn::automaton result(const std::string& ctx = {});
322 
326  bool open(bool o);
327 
329  void reset();
330 
332  void weightset(weightset_type t) { weightset_type_ = t; };
333 
334  private:
337  void register_weight_(string_t w);
338 
340  using transition_t = std::tuple<string_t, string_t, string_t, string_t>;
341  std::vector<transition_t> transitions_;
343  std::vector<std::pair<string_t, string_t>> initial_states_;
345  std::vector<std::pair<string_t, string_t>> final_states_;
347  labelset_type input_type_ = labelset_type::empty;
349  labelset_type output_type_ = labelset_type::empty;
351  bool weighted_ = false;
353  bool real_ = false;
355  bool open_ = false;
357  weightset_type weightset_type_ = weightset_type::numerical;
358  };
359 
360  namespace dyn
361  {
362  namespace detail
363  {
365  template <typename Ctx>
368  {
369  const auto& c = ctx->as<Ctx>();
371  }
372  }
373  }
374 } // vcsn::
A dyn automaton.
Definition: automaton.hh:17
std::tuple< string_t, string_t, string_t, string_t > transition_t
The collected transitions: (Source, Destination, Label, Weight).
automaton_editor * make_automaton_editor(const context &ctx)
Bridge.
typename polynomialset< context_t >::value_t entry_t
automaton_t res_
The automaton under construction.
void reset() override final
Detach the built automaton.
std::vector< transition_t > transitions_
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
Definition: traits.hh:64
virtual bool open(bool o)=0
Whether unknown letters should be added, or rejected.
super_t::string_t string_t
SharedPtr make_shared_ptr(Args &&... args)
Same as std::make_shared, but parameterized by the shared_ptr type, not the (pointed to) element_type...
Definition: memory.hh:13
void add_final(string_t s, string_t weight=string_t{}) override final
std::vector< std::pair< string_t, string_t > > initial_states_
The collected initial states: (State, Weight).
Concrete Builder (the design pattern) for automata.
weight_t_of< automaton_t > weight_t
dyn::automaton result() override final
Return the built automaton.
bool open(bool o) override final
Whether unknown letters should be added, or rejected.
char sep_
The label separator.
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:21
virtual void add_post(string_t s)=0
Declare that s denotes the postfinal state in entries.
virtual void add_pre(string_t s)=0
Declare that s denotes the preinitial state in entries.
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
symbol string_t
Definition: parse.hh:66
virtual void reset()=0
Forget about the current automaton, but do not free it.
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Definition: traits.hh:61
context_t_of< automaton_t > context_t
labelset_type
Labelset types, increasing generality.
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
state_t_of< automaton_t > state_t
Abstract Builder (the design pattern) for automata.
void weightset(weightset_type t)
Specify the weightset type.
weight_t weight_(string_t w)
Convert a weight string to its value.
void set_separator(char c)
Set the label separator. Defaults to &#39;+&#39;.
Template-less root for contexts.
Definition: context.hh:16
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
virtual void add_initial(string_t s, string_t w)=0
void add_initial(string_t s, string_t weight=string_t{}) override final
Definition: a-star.hh:8
label_t_of< automaton_t > label_t
std::shared_ptr< detail::name_automaton_impl< Aut > > name_automaton
Definition: fwd.hh:35
auto & as()
Downcast to the exact type.
Definition: context.hh:36
std::vector< std::pair< string_t, string_t > > final_states_
The collected final states: (State, Weight).
typename detail::label_t_of_impl< base_t< ValueSet > >::type label_t_of
Definition: traits.hh:62
Build an automaton with unknown context.
void add_entry(string_t src, string_t dst, string_t entry) override final
Add transitions from src to dst, labeled by entry.
std::unordered_map< string_t, label_t > label_map
Memoize label conversion.
name_automaton< Aut > automaton_t
void add_pre(string_t s) override final
Register that state named s is preinitial.
virtual void add_entry(string_t src, string_t dst, string_t entry)=0
Add an entry from src to dst, with value entry.
polynomialset< context_t > ps_
Entries handler.
virtual void add_transition(string_t src, string_t dst, string_t label, string_t weight=string_t{})=0
Add a transition from src to dst.
void add_state(string_t s) override final
Register the existence of state named s.
auto weight_of(const welement< Label, Weight > &m) -> decltype(m.weight())
The weight of a welement.
Definition: wet.hh:154
label_t label_(string_t l)
Convert a label string to its value.
auto label_of(const welement< Label, Weight > &m) -> decltype(m.label())
The label of a welement.
Definition: wet.hh:146
virtual void add_state(string_t s)=0
Register the existence of state named s.
value_impl< detail::label_tag > label
Definition: fwd.hh:32
virtual dyn::automaton result()=0
The final result.
virtual void add_final(string_t s, string_t w)=0
std::unordered_map< string_t, entry_t > entry_map
Memoize entry conversion.
automaton_editor::string_t string_t
A hash-cons&#39;ed string type.
std::unordered_map< string_t, weight_t > weight_map
Memoize weight conversion.
void require(Bool b, Args &&... args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:87
typename detail::weight_t_of_impl< base_t< ValueSet > >::type weight_t_of
Definition: traits.hh:66
weightset_type
Weightset types.
void add_transition(string_t src, string_t dst, string_t label, string_t weight=string_t{}) override final
Add a transition from src to dst.
#define VCSN_REQUIRE(Cond,...)
A macro similar to require.
Definition: raise.hh:98
edit_automaton(const context_t &ctx)
labelset_t_of< automaton_t > labelset_t
state_t state_(string_t k)
Convert a state name to a state handler.
void add_post(string_t s) override final
Register that state named s is postfinal.
value_impl< detail::weight_tag > weight
Definition: fwd.hh:34