Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
edit-automaton.hh
Go to the documentation of this file.
1 #ifndef VCSN_ALGOS_EDIT_AUTOMATON_HH
2 # define VCSN_ALGOS_EDIT_AUTOMATON_HH
3 
4 # include <set>
5 # include <tuple>
6 # include <unordered_map>
7 # include <utility>
8 # include <vector>
9 
11 # include <vcsn/ctx/context.hh>
12 # include <vcsn/ctx/fwd.hh>
13 # include <vcsn/dyn/algos.hh>
14 # include <vcsn/dyn/automaton.hh>
15 # include <vcsn/dyn/context.hh>
16 # include <vcsn/dyn/fwd.hh>
17 # include <vcsn/misc/symbol.hh>
18 # include <vcsn/misc/raise.hh>
19 # include <vcsn/misc/stream.hh>
21 
22 namespace vcsn
23 {
24 
25  /*----------------------.
26  | edit_automaton<Aut>. |
27  `----------------------*/
28 
31  {
32  public:
33  using string_t = symbol;
34 
35  virtual ~automaton_editor() {}
36  virtual void add_initial(string_t s, string_t w) = 0;
37  virtual void add_final(string_t s, string_t w) = 0;
38 
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 
56  virtual bool open(bool o) = 0;
57 
59  virtual dyn::automaton result() = 0;
60 
62  virtual void reset() = 0;
63 
65  void set_separator(char c)
66  {
67  sep_ = c;
68  }
69 
70  protected:
72  char sep_ = '+';
73  };
74 
75 
81  template <typename Aut>
83  {
84  public:
86  using automaton_t = Aut;
88 
89  private:
96 
97  public:
100  , ps_(ctx)
101  {}
102 
103  virtual bool
104  open(bool o) override final
105  {
106  return const_cast<labelset_t&>(*res_->context().labelset()).open(o);
107  }
108 
110  virtual void
111  add_state(string_t s) override final
112  {
113  state_(s);
114  }
115 
117  virtual void
118  add_pre(string_t s) override final
119  {
120  smap_.emplace(s, res_->pre());
121  }
122 
124  virtual void
125  add_post(string_t s) override final
126  {
127  smap_.emplace(s, res_->post());
128  }
129 
130  virtual void
131  add_initial(string_t s, string_t weight = string_t{}) override final
132  {
133  res_->add_initial(state_(s), weight_(weight));
134  }
135 
136  virtual void
137  add_final(string_t s, string_t weight = string_t{}) override final
138  {
139  res_->add_final(state_(s), weight_(weight));
140  }
141 
142  virtual void
144  string_t label,
145  string_t weight = string_t{}) override final
146  {
147  // In case of states we don't know, we'd like to register s
148  // first, then d, in an attempt to keep the order in which we
149  // discover states. Which is not guaranteed by plain argument
150  // evaluation.
151  auto s = state_(src);
152  auto d = state_(dst);
153  res_->add_transition(s, d, label_(label), weight_(weight));
154  }
155 
157  virtual void
158  add_entry(string_t src, string_t dst, string_t entry) override final
159  {
160  auto s = state_(src);
161  auto d = state_(dst);
162  require(s != res_->pre() || d != res_->post(),
163  "edit_automaton: invalid transition from pre to post: ",
164  src, " -> ", dst, " (", entry, ")");
165  if (s == res_->pre() || d == res_->post())
166  {
167  if (entry.get().empty())
168  res_->add_transition(s, d, res_->prepost_label());
169  else
170  {
171  // Adding a pre/post transition: be sure that it's only
172  // a weight. Entries see the special label as an empty
173  // one.
174  auto e = conv(ps_, entry, sep_);
175  if (e.size() == 1
176  && (res_->labelset()->is_special(begin(e)->first)
177  || res_->labelset()->is_one(begin(e)->first)))
178  {
179  auto w = begin(e)->second;
180  res_->add_transition(s, d, res_->prepost_label(), w);
181  }
182  else
183  raise("edit_automaton: invalid ",
184  s == res_->pre() ? "initial" : "final",
185  " entry: ", entry.get());
186  }
187  }
188  else
189  {
190  auto p = emap_.emplace(entry, entry_t{});
191  if (p.second)
192  p.first->second = conv(ps_, entry, sep_);
193  for (auto e: p.first->second)
194  res_->add_transition(s, d, e.first, e.second);
195  }
196  }
197 
199  virtual dyn::automaton
200  result() override final
201  {
202  const_cast<labelset_t&>(*res_->context().labelset()).open(false);
203  return dyn::make_automaton(res_);
204  }
205 
207  virtual void
208  reset() override final
209  {
210  res_ = nullptr;
211  }
212 
213  private:
215  label_t
217  {
218  const auto& ls = *res_->labelset();
219  auto p = lmap_.emplace(l, label_t{});
220  if (p.second)
221  p.first->second = conv(ls, l);
222  return p.first->second;
223  }
224 
226  weight_t
228  {
229  const auto& ws = *res_->weightset();
230  auto p = wmap_.emplace(w, weight_t{});
231  if (p.second)
232  p.first->second = w.get().empty() ? ws.one() : conv(ws, w);
233  return p.first->second;
234  }
235 
237  state_t
239  {
240  auto p = smap_.emplace(k, Aut::element_type::null_state());
241  if (p.second)
242  p.first->second = res_->new_state();
243  return p.first->second;
244  }
245 
250 
252  using state_map = std::unordered_map<string_t, state_t>;
255  using entry_map = std::unordered_map<string_t, entry_t>;
258  using label_map = std::unordered_map<string_t, label_t>;
261  using weight_map = std::unordered_map<string_t, weight_t>;
263  };
264 
271  {
272  public:
275 
277  enum class labelset_type { empty, lal, lan, law };
278 
280  void add_initial(string_t s, string_t w = string_t{});
281 
283  void add_final(string_t s, string_t w = string_t{});
284 
287  void add_transition(string_t src, string_t dst,
288  string_t lbl, string_t w = string_t{});
289 
292  void add_transition(string_t src, string_t dst,
293  string_t lbl1, string_t lbl2,
294  string_t w);
295 
298 
302  bool open(bool o);
303 
305  void reset();
306 
307  private:
309  std::vector<std::tuple<string_t, string_t, string_t, string_t>> transitions_;
311  std::vector<std::pair<string_t, string_t>> initial_states_;
313  std::vector<std::pair<string_t, string_t>> final_states_;
319  bool weighted_ = false;
321  bool real_ = false;
323  bool open_ = false;
324  };
325 
326  namespace dyn
327  {
328  namespace detail
329  {
331  template <typename Ctx>
334  {
335  const auto& c = ctx->as<Ctx>();
337  }
338 
340  (const context& ctx) -> automaton_editor*);
341  }
342  }
343 
344 } // vcsn::
345 
346 #endif // !VCSN_ALGOS_EDIT_AUTOMATON_HH
std::vector< std::pair< string_t, string_t > > initial_states_
The collected initial states: (State, Weight).
virtual bool open(bool o) overridefinal
Linear combination of labels: map labels to weights.
Definition: fwd.hh:32
bool open(bool o)
Whether unknown letters should be added, or rejected.
virtual dyn::automaton result()=0
The final result.
automaton_editor::string_t string_t
A hash-cons'ed string type.
std::unordered_map< string_t, entry_t > entry_map
Memoize entry conversion.
state_t state_(string_t k)
Convert a state name to a state handler.
REGISTER_DECLARE(accessible,(const automaton &) -> automaton)
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:71
bool real_
Whether we saw a period in a the weight.
virtual dyn::automaton result() overridefinal
Return the built automaton.
void reset()
Get ready to build another automaton.
labelset_t_of< automaton_t > labelset_t
std::unordered_map< string_t, weight_t > weight_map
Memoize weight conversion.
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.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:34
labelset_type input_type_
Labelset type for input tape.
virtual bool open(bool o)=0
weight_t weight_(string_t w)
Convert a weight string to its value.
Concrete Builder (the design pattern) for automata.
polynomialset< context_t > ps_
Entries handler.
super_t::string_t string_t
label_t label_(string_t l)
Convert a label string to its value.
virtual void add_final(string_t s, string_t weight=string_t{}) overridefinal
virtual void add_pre(string_t s)=0
Declare that s denotes the preinitial state in entries.
std::shared_ptr< const detail::weight_base > weight
Definition: fwd.hh:82
boost::flyweight< std::string, boost::flyweights::no_tracking > symbol
An internalized string.
Definition: symbol.hh:24
void add_initial(string_t s, string_t w=string_t{})
Add s as an initial state.
virtual void add_transition(string_t src, string_t dst, string_t label, string_t weight=string_t{}) overridefinal
Add a transition from src to dst.
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:77
context_t_of< automaton_t > context_t
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
virtual void add_final(string_t s, string_t w)=0
state_t_of< automaton_t > state_t
virtual void add_state(string_t s)=0
virtual void add_entry(string_t src, string_t dst, string_t entry)=0
Add an entry from src to dst, with value entry.
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:32
virtual void add_pre(string_t s) overridefinal
Register that state named s is preinitial.
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_post(string_t s) overridefinal
Register that state named s is postfinal.
void add_final(string_t s, string_t w=string_t{})
Add s as a final state.
labelset_type output_type_
Labelset type for output tape.
std::vector< std::pair< string_t, string_t > > final_states_
The collected final states: (State, Weight).
typename polynomialset< context_t >::value_t entry_t
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
Definition: traits.hh:33
std::unordered_map< string_t, state_t > state_map
State name -> state handle.
virtual void add_initial(string_t s, string_t w)=0
virtual void add_state(string_t s) overridefinal
Register the existence of state named s.
dyn::automaton result()
Return the built automaton.
automaton_t res_
The automaton under construction.
std::shared_ptr< const detail::label_base > label
Definition: fwd.hh:46
Abstract Builder (the design pattern) for automata.
bool weighted_
Whether we saw a non-empty weight.
edit_automaton(const context_t &ctx)
std::shared_ptr< const detail::context_base > context
Definition: context.hh:71
virtual void add_initial(string_t s, string_t weight=string_t{}) overridefinal
void set_separator(char c)
Set the label separator. Defaults to '+'.
virtual void add_post(string_t s)=0
Declare that s denotes the postfinal state in entries.
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:37
std::vector< std::tuple< string_t, string_t, string_t, string_t > > transitions_
The collected transitions: (Source, Destination, Label, Weight).
weight_t_of< automaton_t > weight_t
labelset_type
Labelset types, increasing generality.
std::unordered_map< string_t, label_t > label_map
Memoize label conversion.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:35
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:15
automaton_editor * make_automaton_editor(const context &ctx)
Bridge.
virtual void reset()=0
Forget about the current automaton, but do not free it.
virtual void add_entry(string_t src, string_t dst, string_t entry) overridefinal
Add transitions from src to dst, labeled by entry.
virtual void reset() overridefinal
Detach the built automaton.
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:39
label_t_of< automaton_t > label_t
bool open_
Whether the labelset is open.
Build an automaton with unknown context.
char sep_
The label separator.