Vcsn  2.4
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/stream.hh>
19 
20 namespace vcsn
21 {
22 
23  /*----------------------.
24  | edit_automaton<Aut>. |
25  `----------------------*/
26 
29  {
30  public:
31  using string_t = symbol;
32 
33  virtual ~automaton_editor() {}
34  virtual void add_initial(string_t s, string_t w) = 0;
35  virtual void add_final(string_t s, string_t w) = 0;
36 
38  virtual void add_state(string_t s) = 0;
39 
41  virtual void add_pre(string_t s) = 0;
42 
44  virtual void add_post(string_t s) = 0;
45 
47  virtual void add_entry(string_t src, string_t dst,
48  string_t entry) = 0;
49 
51  virtual void add_transition(string_t src, string_t dst,
53  string_t weight = string_t{}) = 0;
54 
58  virtual bool open(bool o) = 0;
59 
61  virtual dyn::automaton result() = 0;
62 
64  virtual void reset() = 0;
65 
67  void set_separator(char c)
68  {
69  sep_ = c;
70  }
71 
72  protected:
74  char sep_ = '+';
75  };
76 
77 
83  template <Automaton Aut>
85  {
86  public:
90 
91  private:
98 
99  public:
102  , ps_(ctx)
103  {}
104 
108  bool
109  open(bool o) override final
110  {
111  return const_cast<labelset_t&>(*res_->context().labelset()).open(o);
112  }
113 
115  void
116  add_state(string_t s) override final
117  {
118  state_(s);
119  }
120 
122  void
123  add_pre(string_t s) override final
124  {
125  res_->state(s, res_->pre());
126  }
127 
129  void
130  add_post(string_t s) override final
131  {
132  res_->state(s, res_->post());
133  }
134 
135  void
136  add_initial(string_t s, string_t weight = string_t{}) override final
137  {
138  res_->add_initial(state_(s), weight_(weight));
139  }
140 
141  void
142  add_final(string_t s, string_t weight = string_t{}) override final
143  {
144  res_->add_final(state_(s), weight_(weight));
145  }
146 
147  void
149  string_t label,
150  string_t weight = string_t{}) override final
151  {
152  // In case of states we don't know, we'd like to register s
153  // first, then d, in an attempt to keep the order in which we
154  // discover states. Which is not guaranteed by plain argument
155  // evaluation.
156  auto s = state_(src);
157  auto d = state_(dst);
158  res_->add_transition(s, d, label_(label), weight_(weight));
159  }
160 
162  void
163  add_entry(string_t src, string_t dst, string_t entry) override final
164  {
165  auto s = state_(src);
166  auto d = state_(dst);
167  require(s != res_->pre() || d != res_->post(),
168  "edit_automaton: invalid transition from pre to post: ",
169  src, " -> ", dst, " (", entry, ")");
170  if (s == res_->pre() || d == res_->post())
171  {
172  if (entry.get().empty())
173  res_->add_transition(s, d, res_->prepost_label());
174  else
175  {
176  using std::begin;
177  // Adding a pre/post transition: be sure that it's only
178  // a weight. Entries see the special label as an empty
179  // one.
180  auto e = conv(ps_, entry, sep_);
181  auto i = begin(e);
182  VCSN_REQUIRE(e.size() == 1
183  && (res_->labelset()->is_special(label_of(*i))
184  || res_->labelset()->is_one(label_of(*i))),
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(*i));
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 e: p.first->second)
198  res_->add_transition(s, d, label_of(e), weight_of(e));
199  }
200  }
201 
204  result() override final
205  {
206  const_cast<labelset_t&>(*res_->context().labelset()).open(false);
207  return res_;
208  }
209 
211  void
212  reset() override final
213  {
214  res_ = nullptr;
215  }
216 
217  private:
219  label_t
221  {
222  const auto& ls = *res_->labelset();
223  auto p = lmap_.emplace(l, label_t{});
224  if (p.second)
225  p.first->second = conv(ls, l);
226  return p.first->second;
227  }
228 
230  weight_t
232  {
233  const auto& ws = *res_->weightset();
234  auto p = wmap_.emplace(w, weight_t{});
235  if (p.second)
236  p.first->second = w.get().empty() ? ws.one() : conv(ws, w);
237  return p.first->second;
238  }
239 
241  state_t
243  {
244  return res_->state(k);
245  }
246 
251 
253  using entry_map = std::unordered_map<string_t, entry_t>;
256  using label_map = std::unordered_map<string_t, label_t>;
259  using weight_map = std::unordered_map<string_t, weight_t>;
261  };
262 
269  {
270  public:
273 
275  enum class labelset_type { empty, lal, lan, law };
276 
279 
281  void add_initial(string_t s, string_t w = string_t{});
282 
284  void add_final(string_t s, string_t w = string_t{});
285 
288  void add_transition(string_t src, string_t dst,
289  string_t lbl, string_t w = string_t{});
290 
293  void add_transition(string_t src, string_t dst,
294  string_t lbl1, string_t lbl2,
295  string_t w);
296 
298  std::string result_context() const;
299 
303  dyn::automaton result(const std::string& ctx = {});
304 
308  bool open(bool o);
309 
311  void reset();
312 
315 
316  private:
319  void register_weight_(string_t w);
320 
322  using transition_t = std::tuple<string_t, string_t, string_t, string_t>;
323  std::vector<transition_t> transitions_;
325  std::vector<std::pair<string_t, string_t>> initial_states_;
327  std::vector<std::pair<string_t, string_t>> final_states_;
333  bool weighted_ = false;
335  bool real_ = false;
337  bool open_ = false;
340  };
341 
342  namespace dyn
343  {
344  namespace detail
345  {
347  template <typename Ctx>
350  {
351  const auto& c = ctx->as<Ctx>();
353  }
354  }
355  }
356 } // vcsn::
bool weighted_
Whether we saw a non-empty weight.
Abstract Builder (the design pattern) for automata.
automaton_editor * make_automaton_editor(const context &ctx)
Bridge.
void reset()
Get ready to build another automaton.
std::unordered_map< string_t, weight_t > weight_map
Memoize weight conversion.
virtual void add_state(string_t s)=0
Register the existence of state named s.
dyn::automaton result(const std::string &ctx={})
Return the built automaton.
weight_t weight_(string_t w)
Convert a weight string to its value.
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_transition(string_t src, string_t dst, string_t lbl, string_t w=string_t{})
Add an acceptor transition from src to dst, labeled by lbl.
void add_post(string_t s) override final
Register that state named s is postfinal.
std::vector< transition_t > transitions_
virtual void add_initial(string_t s, string_t w)=0
value_impl< detail::weight_tag > weight
Definition: fwd.hh:28
label_t label_(string_t l)
Convert a label string to its value.
void add_state(string_t s) override final
Register the existence of state named s.
void weightset(weightset_type t)
Specify the weightset type.
bool open(bool o) override final
Whether unknown letters should be added, or rejected.
virtual void add_final(string_t s, string_t w)=0
virtual void add_pre(string_t s)=0
Declare that s denotes the preinitial state in entries.
auto weight_of(const welement< Label, Weight > &m) -> decltype(m.weight())
The weight of a welement.
Definition: wet.hh:154
typename polynomialset< context_t >::value_t entry_t
std::shared_ptr< detail::name_automaton_impl< Aut >> name_automaton
Definition: fwd.hh:35
context_t_of< automaton_t > context_t
label_t_of< automaton_t > label_t
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:91
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
polynomialset< context_t > ps_
Entries handler.
virtual dyn::automaton result()=0
The final result.
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
Definition: traits.hh:62
name_automaton< Aut > automaton_t
labelset_type
Labelset types, increasing generality.
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:63
void register_weight_(string_t w)
Record that this weight was seen.
bool open_
Whether the labelset is open.
auto & as()
Downcast to the exact type.
Definition: context.hh:36
edit_automaton(const context_t &ctx)
virtual void reset()=0
Forget about the current automaton, but do not free it.
weightset_type
Weightset types.
virtual void add_entry(string_t src, string_t dst, string_t entry)=0
Add an entry from src to dst, with value entry.
Definition: a-star.hh:8
labelset_type output_type_
Labelset type for output tape.
state_t_of< automaton_t > state_t
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:111
void add_final(string_t s, string_t w=string_t{})
Add s as a final state.
void set_separator(char c)
Set the label separator. Defaults to '+'.
Template-less root for contexts.
Definition: context.hh:16
weightset_type weightset_type_
The weightset scale.
std::vector< std::pair< string_t, string_t > > initial_states_
The collected initial states: (State, Weight).
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:66
automaton_t res_
The automaton under construction.
virtual void add_post(string_t s)=0
Declare that s denotes the postfinal state in entries.
virtual bool open(bool o)=0
Whether unknown letters should be added, or rejected.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:64
void reset() override final
Detach the built automaton.
A dyn automaton.
Definition: automaton.hh:17
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_pre(string_t s) override final
Register that state named s is preinitial.
labelset_type input_type_
Labelset type for input tape.
std::unordered_map< string_t, label_t > label_map
Memoize label conversion.
void add_initial(string_t s, string_t w=string_t{})
Add s as an initial state.
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
value_impl< detail::label_tag > label
Definition: fwd.hh:26
automaton_editor::string_t string_t
A hash-cons'ed string type.
std::unordered_map< string_t, entry_t > entry_map
Memoize entry conversion.
void add_initial(string_t s, string_t weight=string_t{}) override final
labelset_t_of< automaton_t > labelset_t
weight_t_of< automaton_t > weight_t
Concrete Builder (the design pattern) for automata.
char sep_
The label separator.
Build an automaton with unknown context.
void add_final(string_t s, string_t weight=string_t{}) override final
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:61
auto label_of(const welement< Label, Weight > &m) -> decltype(m.label())
The label of a welement.
Definition: wet.hh:146
void add_entry(string_t src, string_t dst, string_t entry) override final
Add transitions from src to dst, labeled by entry.
bool real_
Whether we saw a period in a the weight.
std::string result_context() const
Return the context that was inferred.
super_t::string_t string_t
std::vector< std::pair< string_t, string_t > > final_states_
The collected final states: (State, Weight).
std::tuple< string_t, string_t, string_t, string_t > transition_t
The collected transitions: (Source, Destination, Label, Weight).
bool open(bool o)
Whether unknown letters should be added, or rejected.
dyn::automaton result() override final
Return the built automaton.
state_t state_(string_t k)
Convert a state name to a state handler.