5 #include <unordered_map>
6 #include <unordered_set>
9 #include <boost/lexical_cast.hpp>
10 #include <boost/heap/fibonacci_heap.hpp>
14 #include <vcsn/algos/fwd.hh>
33 bool has_one = labelset_t_of<Aut>::has_one()>
39 using weight_t =
typename weightset_t::value_t;
92 auto res = make_shared_ptr<aut_proper_t>(proper_ctx);
121 for (
auto s:
aut_->states())
126 auto ins =
in(
aut_, s).size();
130 {s, in_sp, ins, out_sp,
out});
138 const char* sep =
"";
139 for (
auto i =
todo_.ordered_begin(), end =
todo_.ordered_end();
142 std::cerr << sep << *i;
153 std::cerr <<
"update heap (" << s <<
" : ";
158 todo_.update(i->second);
161 std::cerr <<
") => ";
200 using state_weight_t = std::pair<state_t, weight_t>;
201 std::vector<state_weight_t> closure;
207 star =
ws_.star(weight);
209 closure.emplace_back(src, weight);
211 aut_->del_transition(t);
234 aut_->set_weight(t, blow);
238 for (
auto pair: closure)
242 aut_->add_transition(src, dst, label, w);
246 unsigned added =
all_out(
aut_, s).size() * closure.size();
247 unsigned removed = transitions.size();
260 std::cerr <<
" -" << removed <<
"+" << added
261 <<
" (-" << removed_ <<
"+" << added_ <<
")";
287 std::unordered_set<state_t> neighbors;
288 while (!
todo_.empty())
292 std::cerr <<
"Before: ";
296 auto p =
todo_.top();
299 std::cerr <<
"Remove: " << p;
308 neighbors.emplace(n);
314 neighbors.emplace(n);
320 for (
auto n: neighbors)
322 for (
auto n: neighbors)
325 std::cerr <<
" #tr: "
327 <<
"/" <<
aut_->num_transitions() <<
'\n';
330 std::cerr <<
"After: ";
341 std::cerr <<
"Total transitions -" << removed_
342 <<
"+" << added_ <<
'\n';
354 res +=
aut_->labelset()->is_one(
aut_->label_of(t));
369 using heap_t = boost::heap::fibonacci_heap<epsilon_profile<state_t>>;
372 std::unordered_map<state_t, typename heap_t::handle_type>
handles_;
383 template <Automaton Aut>
386 using automaton_t = Aut;
aut_proper_t operator()()
std::vector< typename Cont::value_type > make_vector(const Cont &cont)
The content of cont as a vector.
automaton_t aut_
The automaton we work on.
auto transitions(const Aut &aut) -> decltype(all_transitions(aut, is_special_t< Aut >
All the transition indexes between visible states.
aut_proper_t operator()()
Just a copy of the automata in the proper context, since there aren't any transitions to remove...
static int debug_level()
Debug level set in the user's environment.
void copy_into(const AutIn &in, AutOut &out, KeepState keep_state, KeepTrans keep_trans)
Copy selected states and transitions of an automaton.
void show_heap_() const
Show the heap, for debugging.
int debug_
Debug level. The higher, the more details are reported.
value_impl< detail::weight_tag > weight
weightset_t_of< automaton_t > weightset_t
fresh_automaton_t_of< automaton_t, detail::proper_context< context_t_of< automaton_t >>> aut_proper_t
transition_t_of< automaton_t > transition_t
void in_situ_remover()
Nothing to do to remove the transitions in place.
This is used by some epsilon removal algorithms.
labelset_t_of< automaton_t > labelset_t
typename weightset_t::value_t weight_t
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
size_t num_spontaneous_transitions_() const
The number of spontaneous transitions in aut_.
typename Aut::element_type::template fresh_automaton_t< Context > fresh_automaton_t_of
Given an automaton type, the type of its copies.
epsilon_remover(automaton_t &aut, bool prune=true)
The core of the (backward) epsilon-removal.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
state_t_of< automaton_t > state_t
bool prune_
Whether to prune states that become inaccessible.
bool is_proper(const Aut &aut)
Test whether an automaton is proper.
void in_situ_remover_()
Remove all the states with incoming spontaneous transitions.
label_t_of< automaton_t > label_t
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
auto in(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions arriving to state s.
size_t size(const ExpSet &rs, const typename ExpSet::value_t &r)
auto all_out(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions leaving state s.
epsilon_profile< state_t > * profile(state_t s)
void update_heap_(state_t s)
Update the heap for s.
pair_automaton< Aut > pair(const Aut &aut, bool keep_initials=false)
boost::heap::fibonacci_heap< epsilon_profile< state_t >> heap_t
Max-heap to decide the order of state-elimination.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
void build_heap_()
Build the profiles and the heap for states with incoming spontaneous transitions. ...
void update_profile_(state_t s)
Update the profile of s.
std::ostream & dot(const Aut &aut, std::ostream &out=std::cout, format fmt={}, bool mathjax=false)
Print an automaton in Graphviz's Dot format.
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
fresh_automaton_t_of< automaton_t > aut_proper_t
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
label_t empty_word_
Shorthand to the empty word.
auto copy(const AutIn &input, KeepState keep_state, KeepTrans keep_trans) -> decltype(keep_state(input->null_state()), keep_trans(input->null_transition()), make_fresh_automaton< AutIn, AutOut >(input))
A copy of input keeping only its states that are accepted by keep_state, and transitions accepted by ...
std::unordered_map< state_t, typename heap_t::handle_type > handles_
Map: state -> heap-handle.
value_impl< detail::label_tag > label
void in_situ_remover_(state_t s)
For each state (s), for each incoming epsilon-transitions (t), if (t) is a loop, the star of its weig...
auto all_in(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions entering state s.
auto make_proper_context(const context< LabelSet, WeightSet > &ctx) -> proper_context< context< LabelSet, WeightSet >>
From a context, its non-nullable context.
This class contains the core of the proper algorithm.
const weightset_t & ws_
Shorthand to the weightset.
epsilon_remover(automaton_t &aut, bool=true)