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;
60 auto res = make_shared_ptr<aut_proper_t>(proper_ctx);
120 for (
auto s:
aut_->states())
125 auto ins =
in(
aut_, s).size();
129 {s, in_sp, ins, out_sp,
out});
137 const char* sep =
"";
138 for (
auto i =
todo_.ordered_begin(), end =
todo_.ordered_end();
141 std::cerr << sep << *i;
152 std::cerr <<
"update heap (" << s <<
" : ";
157 todo_.update(i->second);
160 std::cerr <<
") => ";
199 using state_weight_t = std::pair<state_t, weight_t>;
200 std::vector<state_weight_t> closure;
206 star =
ws_.star(weight);
208 closure.emplace_back(src, weight);
210 aut_->del_transition(t);
233 aut_->set_weight(t, blow);
237 for (
auto pair: closure)
241 aut_->add_transition(src, dst, label, w);
245 unsigned added =
all_out(
aut_, s).size() * closure.size();
246 unsigned removed = transitions.size();
259 std::cerr <<
" -" << removed <<
"+" << added
260 <<
" (-" << removed_ <<
"+" << added_ <<
")";
286 std::unordered_set<state_t> neighbors;
287 while (!
todo_.empty())
291 std::cerr <<
"Before: ";
295 auto p =
todo_.top();
298 std::cerr <<
"Remove: " << p;
307 neighbors.emplace(n);
313 neighbors.emplace(n);
319 for (
auto n: neighbors)
321 for (
auto n: neighbors)
324 std::cerr <<
" #tr: "
326 <<
"/" <<
aut_->num_transitions() <<
'\n';
329 std::cerr <<
"After: ";
340 std::cerr <<
"Total transitions -" << removed_
341 <<
"+" << added_ <<
'\n';
353 res +=
aut_->labelset()->is_one(
aut_->label_of(t));
368 using heap_t = boost::heap::fibonacci_heap<epsilon_profile<state_t>>;
371 std::unordered_map<state_t, typename heap_t::handle_type>
handles_;
382 template <Automaton Aut>
385 using automaton_t = Aut;
value_impl< detail::weight_tag > weight
void show_heap_() const
Show the heap, for debugging.
labelset_t_of< automaton_t > labelset_t
int debug_
Debug level. The higher, the more details are reported.
weightset_t_of< automaton_t > weightset_t
std::vector< typename Cont::value_type > make_vector(const Cont &cont)
The content of cont as a vector.
auto transitions(const Aut &aut) -> decltype(all_transitions(aut, is_special_t< Aut >
All the transition indexes between visible states.
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
transition_t_of< automaton_t > transition_t
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
size_t size(const ExpSet &rs, const typename ExpSet::value_t &r)
auto in(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions arriving to state s.
typename weightset_t::value_t weight_t
aut_proper_t operator()()
Just a copy of the automata in the proper context, since there aren't any transitions to remove...
This class contains the core of the proper algorithm.
epsilon_profile< state_t > * profile(state_t s)
size_t num_spontaneous_transitions_() const
The number of spontaneous transitions in aut_.
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
state_t_of< automaton_t > state_t
void in_situ_remover_()
Remove all the states with incoming spontaneous transitions.
static int debug_level()
Debug level set in the user's environment.
bool prune_
Whether to prune states that become inaccessible.
void update_heap_(state_t s)
Update the heap for s.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
value_impl< detail::label_tag > label
void in_situ_remover()
Nothing to do to remove the transitions in place.
This is used by some epsilon removal algorithms.
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 ...
boost::heap::fibonacci_heap< epsilon_profile< state_t >> heap_t
Max-heap to decide the order of state-elimination.
epsilon_remover(automaton_t &aut, bool=true)
std::unordered_map< state_t, typename heap_t::handle_type > handles_
Map: state -> heap-handle.
epsilon_remover(automaton_t &aut, bool prune=true)
Get ready to eliminate spontaneous transitions.
void build_heap_()
Build the profiles and the heap for states with incoming spontaneous transitions. ...
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
typename Aut::element_type::template fresh_automaton_t< Context > fresh_automaton_t_of
Given an automaton type, the type of its copies.
pair_automaton< Aut > pair(const Aut &aut, bool keep_initials=false)
void copy_into(const AutIn &in, AutOut &out, KeepState keep_state, KeepTrans keep_trans)
Copy selected states and transitions of an automaton.
fresh_automaton_t_of< automaton_t > aut_proper_t
label_t_of< automaton_t > label_t
void update_profile_(state_t s)
The core of the (backward) epsilon-removal.
auto all_in(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions entering state s.
const weightset_t & ws_
Shorthand to the weightset.
label_t empty_word_
Shorthand to the empty word.
bool is_proper(const Aut &aut)
Test whether an automaton is proper.
automaton_t aut_
The automaton we work on.
std::ostream & dot(const Aut &aut, std::ostream &out=std::cout, format fmt={})
Print an automaton in Graphviz's Dot format.
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...
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
auto all_out(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions leaving state s.
aut_proper_t operator()()
fresh_automaton_t_of< automaton_t, detail::proper_context< context_t_of< automaton_t >>> aut_proper_t
auto make_proper_context(const context< LabelSet, WeightSet > &ctx) -> proper_context< context< LabelSet, WeightSet >>
From a context, its non-nullable context.