Vaucanson 1.4
complete.hxx
00001 // complete.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The Vaucanson Group.
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 //
00012 // The complete GNU General Public Licence Notice can be found as the
00013 // `COPYING' file in the root directory.
00014 //
00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00016 //
00017 #ifndef VCSN_ALGORITHMS_COMPLETE_HXX
00018 # define VCSN_ALGORITHMS_COMPLETE_HXX
00019 
00020 # include <vaucanson/algorithms/complete.hh>
00021 
00022 # ifndef VCSN_NDEBUG
00023 #  include <vaucanson/algorithms/realtime.hh>
00024 # endif // ! VCSN_NDEBUG
00025 
00026 # include <vaucanson/automata/concept/automata_base.hh>
00027 # include <vaucanson/misc/usual_macros.hh>
00028 
00029 # include <list>
00030 # include <set>
00031 
00032 namespace vcsn {
00033 
00034   /*--------------.
00035   | complete_here |
00036   `--------------*/
00037 
00038   template <typename A, typename AI>
00039   void
00040   complete_here(Element<A, AI>& work)
00041   {
00042     // Note that this algorithm may be used on non-deterministic
00043     // automata.
00044     precondition(is_realtime(work));
00045     BENCH_TASK_SCOPED("complete");
00046     typedef Element<A, AI> automaton_t;
00047     AUTOMATON_TYPES(automaton_t);
00048     AUTOMATON_FREEMONOID_TYPES(automaton_t);
00049 
00050     hstate_t sink_state = work.add_state();
00051     bool sink_needed = false;
00052 
00053     // If the sink states is the only state of the automaton, we want
00054     // to keep it as an initial state.  This is meant!  The empty
00055     // automaton is deterministic, but a complete deterministic
00056     // automata has at least one state (it is then easier to
00057     // complement it).
00058     if (work.states().size() ==  1)
00059     {
00060       sink_needed = true;
00061       work.set_initial(sink_state);
00062     }
00063 
00064     for_all_const_states(s, work)
00065       for_all_const_letters(l, work.structure().series().monoid().alphabet())
00066       {
00067         bool empty = true;
00068         for (delta_iterator t(work.value(), *s); ! t.done(); t.next())
00069         {
00070           monoid_elt_t w(work.series_of(*t).structure().monoid(), *l);
00071           if (work.series_of(*t).get(w) != work.series().semiring().wzero_)
00072           {
00073             empty = false;
00074             break;
00075           }
00076         }
00077         if (empty)
00078         {
00079           sink_needed = true;
00080           work.add_letter_transition(*s, sink_state, *l);
00081         }
00082       }
00083 
00084     if (!sink_needed)
00085       work.del_state(sink_state);
00086   }
00087 
00088   /*---------.
00089   | complete |
00090   `---------*/
00091 
00092   template <typename A, typename AI>
00093   Element<A, AI>
00094   complete(const Element<A, AI>& e)
00095   {
00096     Element<A, AI> res(e);
00097     complete_here(res);
00098     return res;
00099   }
00100 
00101   /*------------.
00102   | is_complete |
00103   `------------*/
00104 
00105   template <typename A, typename AI>
00106   bool
00107   is_complete(const Element<A, AI>& e)
00108   {
00109     precondition(is_realtime(e));
00110     BENCH_TASK_SCOPED("is_complete");
00111     if (e.states().size() ==  0)
00112       return false;
00113     typedef Element<A, AI> automaton_t;
00114     AUTOMATON_TYPES(automaton_t);
00115     AUTOMATON_FREEMONOID_TYPES(automaton_t);
00116     const alphabet_t& alpha = e.structure().series().monoid().alphabet();
00117     for_all_const_states(i, e)
00118     {
00119       for_all_const_letters(j, alpha)
00120       {
00121         bool empty = true;
00122         for (delta_iterator t(e.value(), *i);
00123              ! t.done() && empty;
00124              t.next())
00125         {
00126           monoid_elt_t w(e.series_of(*t).structure().monoid(), *j);
00127           if (e.series_of(*t).get(w) != e.series().semiring().wzero_)
00128           {
00129             empty = false;
00130             break;
00131           }
00132         }
00133 
00134         if (empty)
00135           return false;
00136       }
00137     }
00138     return true;
00139   }
00140 
00141 } // vcsn
00142 
00143 #endif // ! VCSN_ALGORITHMS_COMPLETE_HXX