7 #include <boost/heap/binomial_heap.hpp> 8 #include <boost/optional.hpp> 14 #include <vcsn/dyn/fwd.hh> 28 template <Automaton Aut>
48 using profile_t = std::tuple<state_t, word_t, weight_t>;
54 if (labelset_t::less(std::get<1>(l), std::get<1>(r)))
56 else if (labelset_t::less(std::get<1>(r), std::get<1>(l)))
59 return std::get<0>(l) < std::get<0>(r);
75 boost::optional<unsigned> len)
78 num = !len ? 1 : std::numeric_limits<unsigned>::max();
80 len = std::numeric_limits<unsigned>::max();
92 return shortest_(1, std::numeric_limits<unsigned>::max(), src, dst);
105 template <
typename LabelSet = labelset_t_of<context_t>>
109 -> std::enable_if_t<LabelSet::is_free(), polynomial_t>
113 if (len != std::numeric_limits<unsigned>::max())
116 using queue_t = std::deque<profile_t>;
120 auto output =
ps_.zero();
122 !queue.empty() && i < len && output.size() < num;
126 for (
const auto& sm: queue)
129 std::tie(s, l, w) = sm;
132 auto t_dst =
aut_->dst_of(t);
133 auto nw =
ws_.mul(w,
aut_->weight_of(t));
134 if (t_dst ==
aut_->post() && t_dst == dst)
135 ps_.add_here(output, l, std::move(nw));
136 else if (
aut_->src_of(t) ==
aut_->pre()
137 || t_dst ==
aut_->post())
138 q2.emplace_back(t_dst, l, std::move(nw));
139 else if (t_dst == dst)
140 ps_.add_here(output,
ls_.mul(l,
aut_->label_of(t)),
143 q2.emplace_back(t_dst,
153 for (
const auto& m: output)
166 template <
typename LabelSet = labelset_t_of<context_t>>
170 -> std::enable_if_t<!LabelSet::is_free(), polynomial_t>
176 boost::heap::compare<profile_less>>;
178 auto queue = queue_t{};
179 queue.emplace(src,
ls_.one(),
ws_.one());
183 while (!queue.empty())
186 std::tie(s, l, w) = queue.top();
198 while (!queue.empty()
199 && std::get<0>(queue.top()) == s
200 &&
ls_.equal(std::get<1>(queue.top()), l))
202 w =
ws_.add(w, std::get<2>(queue.top()));
208 auto t_dst =
aut_->dst_of(t);
209 auto nw =
ws_.mul(w,
aut_->weight_of(t));
210 if (t_dst ==
aut_->post() && t_dst == dst)
211 ps_.add_here(
res, l, std::move(nw));
212 else if (
aut_->src_of(t) ==
aut_->pre()
213 || t_dst ==
aut_->post())
214 queue.emplace(t_dst, l, std::move(nw));
215 else if (t_dst == dst)
217 auto nl =
ls_.mul(l,
aut_->label_of(t));
219 if (
ls_.size(nl) <= len)
220 ps_.add_here(
res, std::move(nl), std::move(nw));
224 auto nl =
ls_.mul(l,
aut_->label_of(t));
226 if (
ls_.size(nl) <= len)
227 queue.emplace(t_dst, std::move(nl), std::move(nw));
235 || (num ==
res.size()
236 && !
ls_.equal(std::get<1>(queue.top()), l)))
245 template <
typename Queue>
248 const char* sep =
"";
249 for (
auto i = q.ordered_begin(), end = q.ordered_end();
254 aut_->print_state_name(std::get<0>(*i),
os) <<
":<";
255 ws_.print(std::get<2>(*i),
os) <<
'>';
256 ls_.print(std::get<1>(*i),
os);
277 template <Automaton Aut>
280 boost::optional<unsigned> num = {},
281 boost::optional<unsigned> len = {})
293 template <Automaton Aut>
306 template <Automaton Aut>
310 return shortest(aut, boost::none, len);
319 template <Automaton Aut,
typename Num,
typename Len>
322 boost::optional<unsigned> num,
323 boost::optional<unsigned> len)
325 const auto& a = aut->
as<Aut>();
typename detail::weightset_t_of_impl< base_t< ValueSet > >::type weightset_t_of
void show_heap_(const Queue &q, std::ostream &os=std::cerr) const
Show the heap, for debugging.
auto shortest_(unsigned num, unsigned len, state_t_of< Aut > src=Aut::element_type::pre(), state_t_of< Aut > dst=Aut::element_type::post()) -> std::enable_if_t<!LabelSet::is_free(), polynomial_t >
Case of non free labelsets (e.g., law, lan x lan).
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
bool operator()(const profile_t &r, const profile_t &l) const
Whether l < r (as this is a max heap).
state_t_of< automaton_t > state_t
labelset_t_of< polynomialset_t > labelset_t
Wordset.
polynomial_t operator()(state_t src, state_t dst)
The approximated behavior of a part of the automaton (looks for one word of unspecified length)...
polynomial_t operator()(boost::optional< unsigned > num, boost::optional< unsigned > len)
The approximated behavior of the automaton.
value_impl< detail::polynomial_tag > polynomial
auto all_out(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions leaving state s.
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Provide a variadic mul on top of a binary mul(), and one().
word_t_of< automaton_t > word_t
const labelset_t & ls_
Shorthand to the (word) labelset.
std::ostringstream os
The output stream: the corresponding C++ snippet to compile.
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
std::tuple< state_t, word_t, weight_t > profile_t
Used in the case of non-free labelsets.
enumerater(const automaton_t &aut)
Prepare to compute an approximation of the behavior.
const polynomialset_t ps_
Shorthand to the polynomialset of words.
detail::enumerater< Aut >::polynomial_t enumerate(const Aut &aut, unsigned len)
The approximated behavior of an automaton.
detail::enumerater< Aut >::polynomial_t shortest(const Aut &aut, boost::optional< unsigned > num={}, boost::optional< unsigned > len={})
The approximated behavior of an automaton.
weightset_t_of< automaton_t > weightset_t
Compute the shortest words accepted by an automaton.
context_t_of< Aut > context_t
auto & as()
Extract wrapped typed automaton.
auto make_word_polynomialset(const Ctx &ctx) -> word_polynomialset_t< Ctx >
The polynomialset of words of a labelset (not necessarily on words itself).
const weightset_t & ws_
Shorthand to the weightset.
weight_t_of< automaton_t > weight_t
automaton_t aut_
The automaton whose behavior to approximate.
typename polynomialset_t::value_t polynomial_t
auto shortest_(unsigned num, unsigned len, state_t_of< Aut > src=Aut::element_type::pre(), state_t_of< Aut > dst=Aut::element_type::post()) -> std::enable_if_t< LabelSet::is_free(), polynomial_t >
Case of free labelsets (e.g., lal or lal x lal).
typename labelset_t_of< base_t< ValueSet > >::word_t word_t_of
typename detail::weight_t_of_impl< base_t< ValueSet > >::type weight_t_of