Vcsn  2.8
Be Rational
dot.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <iostream>
4 #include <memory>
5 
6 #include <vcsn/algos/project.hh> // bad layering: should not be in algos.
8 #include <vcsn/misc/algorithm.hh> // transform
9 #include <vcsn/misc/format.hh>
10 #include <vcsn/misc/indent.hh>
11 
12 namespace vcsn
13 {
14  namespace rat
15  {
17  template <typename ExpSet>
19  : public ExpSet::const_visitor
20  {
21  public:
22  using expressionset_t = ExpSet;
23  using super_t = typename expressionset_t::const_visitor;
25 
27  using identities_t = typename expressionset_t::identities_t;
31 
33  using node_t = typename super_t::node_t;
35  using value_t = typename node_t::value_t;
36  template <type_t Type>
37  using constant_t = typename super_t::template constant_t<Type>;
38  template <type_t Type>
39  using unary_t = typename super_t::template unary_t<Type>;
40  template <type_t Type>
41  using variadic_t = typename super_t::template variadic_t<Type>;
42 
44  constexpr static const char* me() { return "dot_printer"; }
45 
52  dot_printer(const expressionset_t& rs, std::ostream& out,
53  bool physical = false)
54  : out_{out}
55  , rs_{rs}
56  , physical_{physical}
57  {
58  format(vcsn::format("utf8"));
59  }
60 
65  template <typename OtherExpSet>
68  : out_{other.out_}
69  , rs_{rs}
70  , physical_{other.physical_}
71  , names_{other.names_}
72  , count_{other.count_}
73  {
74  format(other.fmt_);
75  }
76 
79  template <typename OtherExpSet>
80  friend class dot_printer;
81 
83  void format(format fmt)
84  {
85  fmt_ = fmt;
86  if (fmt_ == format::latex)
87  {
88  add_ = (rs_.identities().is_distributive() ? " \\oplus "
89  : " + ");
90  complement_ = "^{c}";
91  compose_ = "@";
92  conjunction_ = " \\& ";
93  infiltrate_ = " \\uparrow ";
94  ldivide_ = " \\backslash ";
95  lweight_ = "\\,";
96  one_ = "\\varepsilon";
97  mul_ = " \\, ";
98  rweight_ = "\\,";
99  shuffle_ = " \\between ";
100  star_ = "^{*}";
101  transposition_ = "^{T}";
102  tuple_ = " \\mid ";
103  zero_ = "\\emptyset";
104  }
105  else if (fmt_ == format::text)
106  {
107  add_ = "+";
108  complement_ = "{c}";
109  compose_ = "@";
110  conjunction_ = "&";
111  infiltrate_ = "&:";
112  ldivide_ = "{\\}";
113  lweight_ = "<.>.";
114  one_ = "\\e";
115  mul_ = ".";
116  rweight_ = ".<.>";
117  shuffle_ = ":";
118  star_ = "*";
119  transposition_ = "{T}";
120  tuple_ = "|";
121  zero_ = "\\z";
122  }
123  else if (fmt_ == format::utf8)
124  {
125  add_ = "+";
126  complement_ = "ᶜ";
127  compose_ = "@";
128  conjunction_ = "&";
129  infiltrate_ = "&:";
130  ldivide_ = "{\\}";
131  lweight_ = "⟨.⟩.";
132  one_ = "ε";
133  mul_ = ".";
134  rweight_ = ".⟨.⟩";
135  shuffle_ = ":";
136  star_ = "*";
137  transposition_ = "ᵗ";
138  tuple_ = "|";
139  zero_ = "∅";
140  }
141  else
142  raise("expression: invalid format: ", fmt_);
143  }
144 
146  std::ostream& operator()(const value_t& v)
147  {
148  out_ << "digraph" << vcsn::iendl
149  << "{" << vcsn::incendl
150  << "edge [arrowhead = vee, arrowsize = .6]" << vcsn::iendl
151  << "node [shape = circle, style = rounded, width = 0.5]\n";
152  print_(v);
154  << "}";
155  return out_;
156  }
157 
158  private:
160  using id_t = unsigned;
161 
164  {
165  return print_(*v);
166  }
167 
169  id_t print_(const node_t& v)
170  {
171  v.accept(*this);
172  return last_name_;
173  }
174 
191 
192  using tuple_t = typename super_t::tuple_t;
193 
194  template <typename = void>
195  struct visit_tuple
196  {
198  template <size_t I>
199  void print_(const tuple_t& v)
200  {
201  auto rs = detail::project<I>(self_.rs_);
202  const auto& r = std::get<I>(v.sub());
204  auto name = printer.print_(r);
206  << name_ << " -> " << name;
207  }
208 
210  template <size_t... I>
212  {
213  using swallow = int[];
214  (void) swallow
215  {
216  (print_<I>(v),
217  0)...
218  };
219  }
220 
222  void operator()(const tuple_t& v)
223  {
224  auto name = self_.name_(v);
225  if (name.second)
226  {
227  name_ = name.first;
229  << name_
230  << " [label=\"" << self_.tuple_ << "\"]";
231  print_(v, labelset_t::indices);
232  }
233  self_.last_name_ = name.first;
234  }
237  id_t name_ = {};
238  };
239 
240  void visit(const tuple_t& v, std::true_type) override
241  {
242  detail::static_if<context_t::is_lat>
243  ([this](auto&& v){ visit_tuple<decltype(v)>{*this}(v); })
244  (v);
245  }
246 
249  template <typename Node>
250  std::pair<id_t, bool> name_(const Node& n)
251  {
252  if (physical_)
253  {
254  auto p = names_->emplace(&n, 0);
255  if (p.second)
256  p.first->second = names_->size();
257  return {p.first->second, p.second};
258  }
259  else
260  return {(*count_)++, true};
261  }
262 
264  void print_(const name_t& n)
265  {
266  auto name = name_(n);
267  if (name.second)
268  {
269  auto sub = print_(n.sub());
270  out_ << vcsn::iendl
271  << name.first << " [label=\"name=" << n.name_get() << "\"]"
272  << vcsn::iendl
273  << name.first << " -> " << sub;
274  }
275  last_name_ = name.first;
276  }
277 
279  template <rat::exp::type_t Type>
280  void print_(const constant_t<Type>& n, const char* op)
281  {
282  auto name = name_(n);
283  if (name.second)
284  out_ << vcsn::iendl
285  << name.first << " [label=\"" << op << "\"]";
286  last_name_ = name.first;
287  }
288 
290  template <rat::exp::type_t Type>
291  void print_(const unary_t<Type>& n, const char* op)
292  {
293  auto name = name_(n);
294  if (name.second)
295  {
296  auto sub = print_(n.sub());
297  out_ << vcsn::iendl
298  << name.first << " [label=\"" << op << "\"]"
299  << vcsn::iendl
300  << name.first << " -> " << sub;
301  }
302  last_name_ = name.first;
303  }
304 
306  template <rat::exp::type_t Type>
307  void print_(const variadic_t<Type>& n, const char* op)
308  {
309  auto name = name_(n);
310  if (name.second)
311  {
312  auto subs
314  [this](const auto& i)
315  {
316  return this->print_(i);
317  }) ;
318  out_<< vcsn::iendl
319  << name.first << " [label=\"" << op << "\"]";
320  for (auto s: subs)
321  out_ << vcsn::iendl
322  << name.first << " -> " << s;
323  }
324  last_name_ = name.first;
325  }
326 
328  id_t print_(const weight_t& w)
329  {
330  auto res = name_(w).first;
331  out_ << vcsn::iendl
332  << res << " [label=\"";
333  rs_.weightset()->print(w, out_, fmt_.for_weights());
334  out_ << "\"]";
335  return res;
336  }
337 
339  void print_(const lweight_t& n)
340  {
341  auto name = name_(n);
342  if (name.second)
343  {
344  auto weight = print_(n.weight());
345  auto sub = print_(n.sub());
346  out_
347  << vcsn::iendl
348  << name.first << " [label=\"" << lweight_ << "\"]" << vcsn::iendl
349  << name.first << " -> " << weight << vcsn::iendl
350  << name.first << " -> " << sub;
351  }
352  last_name_ = name.first;
353  }
354 
356  void print_(const rweight_t& n)
357  {
358  auto name = name_(n);
359  if (name.second)
360  {
361  auto sub = print_(n.sub());
362  auto weight = print_(n.weight());
363  out_
364  << vcsn::iendl
365  << name.first << " [label=\"" << rweight_ << "\"]" << vcsn::iendl
366  << name.first << " -> " << sub << vcsn::iendl
367  << name.first << " -> " << weight;
368  }
369  last_name_ = name.first;
370  }
371 
373  void print_(const atom_t& n)
374  {
375  auto name = name_(n);
376  if (name.second)
377  {
378  out_ << vcsn::iendl
379  << name.first << " [label=\"";
380  rs_.labelset()->print(n.value(), out_, fmt_.for_labels());
381  out_ << "\"]";
382  }
383  last_name_ = name.first;
384  }
385 
387  std::ostream& out_;
389  class format fmt_;
392 
395  bool physical_ = false;
396 
398  using names_t = std::unordered_map<const void*, id_t>;
400  std::shared_ptr<names_t> names_ = std::make_shared<names_t>();
401 
404  std::shared_ptr<unsigned> count_ = std::make_shared<unsigned>(0);
407 
409  const char* lweight_ = nullptr;
410  const char* rweight_ = nullptr;
412  const char* ldivide_ = nullptr;
414  const char* add_ = nullptr;
415  const char* complement_ = nullptr;
416  const char* compose_ = nullptr;
417  const char* conjunction_ = nullptr;
418  const char* infiltrate_ = nullptr;
419  const char* mul_ = nullptr;
420  const char* shuffle_ = nullptr;
421  const char* star_ = nullptr;
422  const char* transposition_ = nullptr;
423 
425  const char* tuple_ = nullptr;
426 
428  const char* zero_ = nullptr;
429  const char* one_ = nullptr;
430  };
431 
432  template <typename ExpSet>
434  make_dot_printer(const ExpSet& rs, std::ostream& out,
435  bool physical = false)
436  {
437  return {rs, out, physical};
438  }
439  } // namespace rat
440 } // namespace vcsn
dot_printer(const expressionset_t &rs, dot_printer< OtherExpSet > &other)
Construct from another dot_printer.
Definition: dot.hh:66
std::ostream & iendl(std::ostream &o)
Print an end of line, then set the indentation.
Definition: indent.cc:49
std::ostream & operator()(const value_t &v)
Entry point: print v as a complete Dot graph.
Definition: dot.hh:146
const char * mul_
Definition: dot.hh:419
VCSN_RAT_VISIT(add, v)
Definition: dot.hh:175
format for_labels() const
A copy of this format, but to print labels.
Definition: format.hh:42
VCSN_RAT_VISIT(shuffle, v)
Definition: dot.hh:187
const char * rweight_
Definition: dot.hh:410
dot_printer(const expressionset_t &rs, std::ostream &out, bool physical=false)
A printer.
Definition: dot.hh:52
typename super_t::template unary_t< Type > unary_t
Definition: dot.hh:39
const expressionset_t & rs_
The expressionset.
Definition: dot.hh:391
void print_(const atom_t &n)
Print a label.
Definition: dot.hh:373
const char * complement_
Definition: dot.hh:415
VCSN_RAT_VISIT(lweight, v)
Definition: dot.hh:182
An inner node with multiple children.
Definition: expression.hh:119
void print_(const constant_t< Type > &n, const char *op)
Print a nullary node.
Definition: dot.hh:280
typename super_t::tuple_t tuple_t
Definition: dot.hh:192
VCSN_RAT_VISIT(star, v)
Definition: dot.hh:188
typename super_t::node_t node_t
Actual node, without indirection.
Definition: dot.hh:33
unsigned id_t
A type to label the node.
Definition: dot.hh:160
void format(format fmt)
Set output format.
Definition: dot.hh:83
void print_(const variadic_t< Type > &n, const char *op)
Print a variadic node.
Definition: dot.hh:307
typename super_t::template variadic_t< Type > variadic_t
Definition: dot.hh:41
void operator()(const tuple_t &v)
Entry point.
Definition: dot.hh:222
class format fmt_
Output format.
Definition: dot.hh:389
id_t print_(const node_t &v)
Easy recursion: print an expression and return its ID.
Definition: dot.hh:169
const char * conjunction_
Definition: dot.hh:417
VCSN_RAT_VISIT(infiltrate, v)
Definition: dot.hh:180
const char * infiltrate_
Definition: dot.hh:418
std::ostream & out_
Output stream.
Definition: dot.hh:387
label_t_of< context_t > label_t
Definition: dot.hh:29
typename super_t::template constant_t< Type > constant_t
Definition: dot.hh:37
An inner node to name the subexpression.
Definition: expression.hh:290
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:211
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Definition: traits.hh:61
labelset_t_of< context_t > labelset_t
Definition: dot.hh:28
VCSN_RAT_VISIT(conjunction, v)
Definition: dot.hh:179
id_t name_
The name of the tuple node.
Definition: dot.hh:237
void print_(const lweight_t &n)
Print a left-weight.
Definition: dot.hh:339
Print as rich UTF-8 text, escaped.
Definition: format.hh:30
An input/output format for valuesets.
Definition: format.hh:13
VCSN_RAT_VISIT(atom, v)
Definition: dot.hh:176
ExpSet expressionset_t
Definition: dot.hh:22
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
VCSN_RAT_VISIT(ldivide, v)
Definition: dot.hh:181
id_t print_(const weight_t &w)
Print a weight.
Definition: dot.hh:328
weight_t_of< context_t > weight_t
Definition: dot.hh:30
const char * shuffle_
Definition: dot.hh:420
static constexpr const char * me()
Name of this algorithm, for error messages.
Definition: dot.hh:44
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
typename expressionset_t::identities_t identities_t
Definition: dot.hh:27
context_t_of< expressionset_t > context_t
Definition: dot.hh:26
void print_(const unary_t< Type > &n, const char *op)
Print a unary node.
Definition: dot.hh:291
Definition: a-star.hh:8
std::shared_ptr< names_t > names_
A shared_ptr, to support tuples.
Definition: dot.hh:400
std::ostream & incendl(std::ostream &o)
Increment the indentation, print an end of line, and set the indentation.
Definition: indent.cc:54
const char * compose_
Definition: dot.hh:416
std::ostream & decendl(std::ostream &o)
Decrement the indentation, print an end of line, and set the indentation.
Definition: indent.cc:59
std::pair< id_t, bool > name_(const Node &n)
The identifier for this node, and a Boolean stating whether we should traverse (again) this node...
Definition: dot.hh:250
typename detail::label_t_of_impl< base_t< ValueSet > >::type label_t_of
Definition: traits.hh:62
typename expressionset_t::const_visitor super_t
Definition: dot.hh:23
Print as plain (ASCII) text, escaped.
Definition: format.hh:28
Naming an expression.
const char * one_
Definition: dot.hh:429
VCSN_RAT_VISIT(transposition, v)
Definition: dot.hh:189
const char * star_
Definition: dot.hh:421
An inner node implementing a weight.
Definition: expression.hh:256
A static list of size_t.
Definition: tuple.hh:32
id_t last_name_
The name of the last visited node.
Definition: dot.hh:406
const char * lweight_
External product.
Definition: dot.hh:409
VCSN_RAT_VISIT(rweight, v)
Definition: dot.hh:186
typename node_t::value_t value_t
A shared_ptr to node_t.
Definition: dot.hh:35
Pretty-printer for rational expressions.
Definition: fwd.hh:32
const char * ldivide_
Quotient.
Definition: dot.hh:412
void print_(const name_t &n)
Print a name node.
Definition: dot.hh:264
const char * transposition_
Definition: dot.hh:422
return v
Definition: multiply.hh:362
Print for LaTeX.
Definition: format.hh:22
std::shared_ptr< unsigned > count_
The node counter, used to name the nodes.
Definition: dot.hh:404
const char * add_
The expression operators.
Definition: dot.hh:414
format for_weights() const
A copy of this format, but to print weights.
Definition: format.hh:50
const char * zero_
The constants.
Definition: dot.hh:428
const char * tuple_
Tuple tape separator.
Definition: dot.hh:425
friend class dot_printer
Make it possible to view members from dot_printer&#39;s with a different template parameter.
Definition: dot.hh:80
void visit(const tuple_t &v, std::true_type) override
Definition: dot.hh:240
VCSN_RAT_VISIT(zero, v)
Definition: dot.hh:190
VCSN_RAT_VISIT(mul, v)
Definition: dot.hh:183
VCSN_RAT_VISIT(complement, v)
Definition: dot.hh:177
bool physical_
Whether to display the physical DAG rather than the logical tree.
Definition: dot.hh:395
typename detail::weight_t_of_impl< base_t< ValueSet > >::type weight_t_of
Definition: traits.hh:66
Pretty-printer for rational expressions.
Definition: dot.hh:18
void print_(const tuple_t &v, detail::index_sequence< I... >)
Print all the tapes.
Definition: dot.hh:211
symbol name_get() const
Definition: expression.hxx:55
dot_printer< ExpSet > make_dot_printer(const ExpSet &rs, std::ostream &out, bool physical=false)
Definition: dot.hh:434
VCSN_RAT_VISIT(name, v)
Definition: dot.hh:184
Indentation relative functions.
value_impl< detail::weight_tag > weight
Definition: fwd.hh:34
void print_(const tuple_t &v)
Print one tape.
Definition: dot.hh:199
return res
Definition: multiply.hh:399
void print_(const rweight_t &n)
Print a right-weight.
Definition: dot.hh:356
VCSN_RAT_VISIT(one, v)
Definition: dot.hh:185
VCSN_RAT_VISIT(compose, v)
Definition: dot.hh:178
std::unordered_map< const void *, id_t > names_t
If physical_ is enabled, register the identifiers of the nodes.
Definition: dot.hh:398
id_t print_(const value_t &v)
Easy recursion: print an expression and return its ID.
Definition: dot.hh:163
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:86