Vcsn  2.2
Be Rational
are-equivalent.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vcsn/algos/accessible.hh> // is_useless
5 #include <vcsn/algos/complete.hh>
9 #include <vcsn/algos/letterize.hh> // rea
10 #include <vcsn/algos/conjunction.hh> // conjunction
11 #include <vcsn/algos/reduce.hh>
12 #include <vcsn/algos/strip.hh>
13 #include <vcsn/algos/sum.hh>
14 #include <vcsn/dyn/automaton.hh>
15 #include <vcsn/dyn/expression.hh>
16 
17 namespace vcsn
18 {
19 
20  /*---------------------------------------.
21  | are_equivalent(automaton, automaton). |
22  `---------------------------------------*/
23 
25  template <Automaton Aut1, Automaton Aut2>
26  auto
27  are_equivalent(const Aut1& a1, const Aut2& a2)
28  -> std::enable_if_t<(std::is_same<weightset_t_of<Aut1>, b>::value
29  && std::is_same<weightset_t_of<Aut2>, b>::value),
30  bool>
31  {
32  const auto& l = realtime(a1);
33  const auto& r = realtime(a2);
34  return (is_useless(difference(l, r))
35  && is_useless(difference(r, l)));
36  }
37 
38 
40  template <Automaton Aut1, Automaton Aut2>
41  auto
42  are_equivalent(const Aut1& a1, const Aut2& a2)
43  -> decltype((std::enable_if_t<!std::is_same<weightset_t_of<Aut1>, b>::value>(),
44  a2->weightset()->sub(a2->weightset()->zero(),
45  a2->weightset()->one()),
46  true))
47  {
48  const auto& ws2 = *a2->weightset();
49  const auto& l = realtime(a1);
50  const auto& r = realtime(a2);
51  // d = l + -r.
52  auto d = sum(l,
53  left_mult(ws2.sub(ws2.zero(), ws2.one()),
54  r));
55  return is_empty(reduce(d));
56  }
57 
58 
59  namespace dyn
60  {
61  namespace detail
62  {
64  template <Automaton Aut1, Automaton Aut2>
65  bool
66  are_equivalent(const automaton& aut1, const automaton& aut2)
67  {
68  const auto& a1 = aut1->as<Aut1>();
69  const auto& a2 = aut2->as<Aut2>();
71  }
72  }
73  }
74 
75 
76  /*-----------------------------------------.
77  | are_equivalent(expression, expression). |
78  `-----------------------------------------*/
79 
81  template <typename ExpSet1, typename ExpSet2>
82  auto
83  are_equivalent(const ExpSet1& rs1,
84  const typename ExpSet1::value_t r1,
85  const ExpSet2& rs2,
86  const typename ExpSet2::value_t r2)
87  -> bool
88  {
89  // We use derived-term because it supports all our operators.
90  // FIXME: bench to see if standard would not be a better bet in
91  // the other cases.
92  return are_equivalent(strip(derived_term(rs1, r1)),
93  strip(derived_term(rs2, r2)));
94  }
95 
96 
97  namespace dyn
98  {
99  namespace detail
100  {
102  template <typename ExpSet1, typename ExpSet2>
103  bool
105  {
106  const auto& l = r1->as<ExpSet1>();
107  const auto& r = r2->as<ExpSet2>();
108  return ::vcsn::are_equivalent(l.expressionset(), l.expression(),
109  r.expressionset(), r.expression());
110  }
111  }
112  }
113 
114 
115  /*-----------------------------------.
116  | difference(automaton, automaton). |
117  `-----------------------------------*/
118 
120  template <Automaton Lhs, Automaton Rhs>
121  fresh_automaton_t_of<Lhs>
122  difference(const Lhs& lhs, const Rhs& rhs)
123  {
124  // Meet complement()'s requirements.
125  auto r = strip(rhs);
126  if (!is_deterministic(r))
128  else if (!is_complete(r))
129  r = complete(r);
130  return strip(conjunction(lhs, complement(r)));
131  }
132 
133  namespace dyn
134  {
135  namespace detail
136  {
138  template <Automaton Lhs, Automaton Rhs>
139  automaton
140  difference(const automaton& lhs, const automaton& rhs)
141  {
142  const auto& l = lhs->as<Lhs>();
143  const auto& r = rhs->as<Rhs>();
144  return make_automaton(::vcsn::difference(l, r));
145  }
146  }
147  }
148 
149  /*--------------------------------------.
150  | difference(expression, expression). |
151  `--------------------------------------*/
152 
154  template <typename ExpSet>
155  inline
156  typename ExpSet::value_t
157  difference(const ExpSet& rs,
158  const typename ExpSet::value_t& lhs,
159  const typename ExpSet::value_t& rhs)
160  {
161  return rs.conjunction(lhs, rs.complement(rhs));
162  }
163 
164  namespace dyn
165  {
166  namespace detail
167  {
169  template <typename ExpSetLhs, typename ExpSetRhs>
170  expression
172  {
173  const auto& l = lhs->as<ExpSetLhs>();
174  const auto& r = rhs->as<ExpSetLhs>();
175  return make_expression(l.expressionset(),
176  ::vcsn::difference(l.expressionset(),
177  l.expression(),
178  r.expression()));
179  }
180  }
181  }
182 }
auto complete(const Aut &aut) -> decltype(::vcsn::copy(aut))
Definition: complete.hh:61
auto strip(const Aut &aut)
Remove (all) the decorations from a decorated automaton.
Definition: strip.hh:34
auto realtime(const Aut &aut) -> decltype(proper(::vcsn::letterize(aut)))
Split the word transitions in the input automaton into letter ones, and remove the spontaneous transi...
Definition: letterize.hh:220
auto are_equivalent(const Aut1 &a1, const Aut2 &a2) -> std::enable_if_t<(std::is_same< weightset_t_of< Aut1 >, b >::value &&std::is_same< weightset_t_of< Aut2 >, b >::value), bool >
Check equivalence between Boolean automata on a free labelset.
bool are_equivalent_expression(const expression &r1, const expression &r2)
Bridge (are_equivalent).
auto are_equivalent(const ExpSet1 &rs1, const typename ExpSet1::value_t r1, const ExpSet2 &rs2, const typename ExpSet2::value_t r2) -> bool
Check equivalence between two expressions.
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:75
auto conjunction(const Auts &...as) -> tuple_automaton< decltype(meet_automata(as...)), Auts... >
Build the (accessible part of the) conjunction.
Definition: conjunction.hh:448
auto sum(const Aut1 &lhs, const Aut2 &rhs, Tag tag={}) -> decltype(join_automata(lhs, rhs))
The sum of two automata.
Definition: sum.hh:95
automaton difference(const automaton &lhs, const automaton &rhs)
Bridge.
auto left_mult(const weight_t_of< Aut > &w, const Aut &aut, Tag tag={}) -> fresh_automaton_t_of< Aut >
Left-multiplication of an automaton by a weight.
Definition: left-mult.hh:128
Definition: a-star.hh:8
std::enable_if_t< labelset_t_of< ExpSet >::is_free(), expression_automaton< mutable_automaton< typename ExpSet::context_t > > > derived_term(const ExpSet &rs, const typename ExpSet::value_t &r, const std::string &algo="auto")
The derived-term automaton, for free labelsets.
expression difference_expression(const expression &lhs, const expression &rhs)
Bridge (difference).
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
auto determinize(const Aut &a, Tag={}, bool_constant< Lazy >={})
Definition: determinize.hh:246
bool is_empty(const Aut &a) ATTRIBUTE_PURE
Whether has no states.
Definition: accessible.hh:192
bool are_equivalent(const automaton &aut1, const automaton &aut2)
Bridge.
bool is_deterministic(const Aut &aut, state_t_of< Aut > s)
Whether state s is deterministic in aut.
auto complement(const Aut &aut) -> decltype(copy(aut))
Definition: complement.hh:48
auto reduce(const Aut &input) -> decltype(copy(input))
Definition: reduce.hh:608
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
auto rs
Definition: lift.hh:151
bool is_complete(const Aut &aut)
Whether aut is complete.
Definition: is-complete.hh:13
fresh_automaton_t_of< Lhs > difference(const Lhs &lhs, const Rhs &rhs)
An automaton that computes weights of lhs, but not by rhs.
bool is_useless(const Aut &a)
Whether all no state is useful.
Definition: accessible.hh:168
std::shared_ptr< detail::expression_base > expression
Definition: expression.hh:92
ExpSet::value_t difference(const ExpSet &rs, const typename ExpSet::value_t &lhs, const typename ExpSet::value_t &rhs)
Difference of expressions.
expression make_expression(const ExpSet &rs, const typename ExpSet::value_t &r)
Definition: expression.hh:97
weightset_mixin< detail::b_impl > b
Definition: fwd.hh:48