Vcsn  2.2
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  virtual bool
109  open(bool o) override final
110  {
111  return const_cast<labelset_t&>(*res_->context().labelset()).open(o);
112  }
113 
115  virtual void
116  add_state(string_t s) override final
117  {
118  state_(s);
119  }
120 
122  virtual void
123  add_pre(string_t s) override final
124  {
125  res_->state(s, res_->pre());
126  }
127 
129  virtual void
130  add_post(string_t s) override final
131  {
132  res_->state(s, res_->post());
133  }
134 
135  virtual 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  virtual 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  virtual 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  virtual 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 
203  virtual dyn::automaton
204  result() override final
205  {
206  const_cast<labelset_t&>(*res_->context().labelset()).open(false);
207  return dyn::make_automaton(res_);
208  }
209 
211  virtual 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::
#define VCSN_REQUIRE(Cond,...)
A macro similar to require.
Definition: raise.hh:89
bool weighted_
Whether we saw a non-empty weight.
automaton_editor::string_t string_t
A hash-cons'ed string type.
virtual void add_post(string_t s) override final
Register that state named s is postfinal.
typename polynomialset< context_t >::value_t entry_t
labelset_t_of< automaton_t > labelset_t
virtual void add_final(string_t s, string_t weight=string_t{}) override final
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:75
virtual void add_final(string_t s, string_t w)=0
std::vector< transition_t > transitions_
std::shared_ptr< const detail::weight_base > weight
Definition: fwd.hh:88
virtual void add_post(string_t s)=0
Declare that s denotes the postfinal state in entries.
automaton_editor * make_automaton_editor(const context &ctx)
Bridge.
state_t_of< automaton_t > state_t
Definition: a-star.hh:8
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:78
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.
virtual void add_pre(string_t s) override final
Register that state named s is preinitial.
bool open(bool o)
Whether unknown letters should be added, or rejected.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:55
label_t label_(string_t l)
Convert a label string to its value.
void set_separator(char c)
Set the label separator. Defaults to '+'.
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:14
Abstract Builder (the design pattern) for automata.
weight_t_of< automaton_t > weight_t
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
Build an automaton with unknown context.
virtual void add_initial(string_t s, string_t weight=string_t{}) override final
std::vector< std::pair< string_t, string_t > > final_states_
The collected final states: (State, Weight).
auto weight_of(const welement< Label, Weight > &m) -> decltype(m.weight())
The weight of a welement.
Definition: wet.hh:154
void weightset(weightset_type t)
Specify the weightset type.
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:58
std::unordered_map< string_t, weight_t > weight_map
Memoize weight conversion.
char sep_
The label separator.
virtual void add_state(string_t s) override final
Register the existence of state named s.
state_t state_(string_t k)
Convert a state name to a state handler.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:56
weightset_type weightset_type_
The weightset scale.
std::shared_ptr< const detail::label_base > label
Definition: fwd.hh:61
void reset()
Get ready to build another automaton.
dyn::automaton result(const std::string &ctx={})
Return the built automaton.
name_automaton< Aut > automaton_t
std::string result_context() const
Return the context that was inferred.
virtual bool open(bool o) override final
Whether unknown letters should be added, or rejected.
labelset_type
Labelset types, increasing generality.
std::shared_ptr< detail::name_automaton_impl< Aut >> name_automaton
Definition: fwd.hh:35
bool real_
Whether we saw a period in a the weight.
label_t_of< automaton_t > label_t
Concrete Builder (the design pattern) for automata.
super_t::string_t string_t
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
labelset_type input_type_
Labelset type for input tape.
std::shared_ptr< const detail::context_base > context
A dyn::context.
Definition: fwd.hh:43
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.
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
virtual void add_entry(string_t src, string_t dst, string_t entry) override final
Add transitions from src to dst, labeled by entry.
virtual void add_state(string_t s)=0
Register the existence of state named s.
polynomialset< context_t > ps_
Entries handler.
std::unordered_map< string_t, label_t > label_map
Memoize label conversion.
virtual void add_entry(string_t src, string_t dst, string_t entry)=0
Add an entry from src to dst, with value entry.
std::tuple< string_t, string_t, string_t, string_t > transition_t
The collected transitions: (Source, Destination, Label, Weight).
virtual dyn::automaton result() override final
Return the built automaton.
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:53
weight_t weight_(string_t w)
Convert a weight string to its value.
void register_weight_(string_t w)
Record that this weight was seen.
context_t_of< automaton_t > context_t
virtual void reset()=0
Forget about the current automaton, but do not free it.
auto label_of(const welement< Label, Weight > &m) -> decltype(m.label())
The label of a welement.
Definition: wet.hh:146
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
Definition: traits.hh:54
virtual void reset() override final
Detach the built automaton.
static dyn::context ctx(const driver &d)
Get the context of the driver.
Definition: parse.cc:82
weightset_type
Weightset types.
virtual bool open(bool o)=0
Whether unknown letters should be added, or rejected.
bool open_
Whether the labelset is open.
automaton_t res_
The automaton under construction.
labelset_type output_type_
Labelset type for output tape.
void add_final(string_t s, string_t w=string_t{})
Add s as a final state.
virtual 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.
std::unordered_map< string_t, entry_t > entry_map
Memoize entry conversion.
virtual dyn::automaton result()=0
The final result.
virtual void add_initial(string_t s, string_t w)=0
virtual void add_pre(string_t s)=0
Declare that s denotes the preinitial state in entries.
void add_initial(string_t s, string_t w=string_t{})
Add s as an initial state.
edit_automaton(const context_t &ctx)
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:28
std::vector< std::pair< string_t, string_t > > initial_states_
The collected initial states: (State, Weight).