Generated on Wed Nov 1 15:04:38 2006 for Gecode by doxygen 1.4.5

dfa.cc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *
00005  *  Copyright:
00006  *     Christian Schulte, 2004
00007  *
00008  *  Last modified:
00009  *     $Date: 2006-08-04 16:03:26 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $
00010  *     $Revision: 3512 $
00011  *
00012  *  This file is part of Gecode, the generic constraint
00013  *  development environment:
00014  *     http://www.gecode.org
00015  *
00016  *  See the file "LICENSE" for information on usage and
00017  *  redistribution of this file, and for a
00018  *     DISCLAIMER OF ALL WARRANTIES.
00019  *
00020  */
00021 
00022 #include "gecode/int.hh"
00023 #include "gecode/support/sort.hh"
00024 #include "gecode/support/static-stack.hh"
00025 
00026 
00027 namespace Gecode { namespace Int { namespace Regular {
00028 
00032   class TransByI_State {
00033   public:
00034     forceinline bool
00035     operator()(const DFA::Transition& x, const DFA::Transition& y) {
00036       return x.i_state < y.i_state;
00037     }
00038     forceinline static void
00039     sort(DFA::Transition t[], int n) {
00040       TransByI_State tbis;
00041       Support::quicksort<DFA::Transition,TransByI_State>(t,n,tbis);
00042     }
00043   };
00044 
00048   class TransBySymbol {
00049   public:
00050     forceinline bool
00051     operator()(const DFA::Transition& x, const DFA::Transition& y) {
00052       return x.symbol < y.symbol;
00053     }
00054     forceinline static void
00055     sort(DFA::Transition t[], int n) {
00056       TransBySymbol tbs;
00057       Support::quicksort<DFA::Transition,TransBySymbol>(t,n,tbs);
00058     }
00059   };
00060 
00064   class TransBySymbolI_State {
00065   public:
00066     forceinline bool
00067     operator()(const DFA::Transition& x, const DFA::Transition& y) {
00068       return ((x.symbol < y.symbol) ||
00069               (x.symbol == y.symbol) && (x.i_state < y.i_state));
00070     }
00071     forceinline static void
00072     sort(DFA::Transition t[], int n) {
00073       TransBySymbolI_State tbsi;
00074       Support::quicksort<DFA::Transition,TransBySymbolI_State>(t,n,tbsi);
00075     }
00076   };
00077 
00081   class TransByO_State {
00082   public:
00083     forceinline bool
00084     operator()(const DFA::Transition& x, const DFA::Transition& y) {
00085       return x.o_state < y.o_state;
00086     }
00087     forceinline static void
00088     sort(DFA::Transition t[], int n) {
00089       TransByO_State tbos;
00090       Support::quicksort<DFA::Transition,TransByO_State>(t,n,tbos);
00091     }
00092   };
00093 
00094 
00098   class StateGroup {
00099   public:
00100     int state;
00101     int group;
00102   };
00103 
00107   class StateGroupByGroup {
00108   public:
00109     forceinline bool
00110     operator()(const StateGroup& x, const StateGroup& y) {
00111       return ((x.group < y.group) ||
00112               (x.group == y.group) && (x.state < y.state));
00113     }
00114     static void
00115     sort(StateGroup sg[], int n) {
00116       StateGroupByGroup o;
00117       Support::quicksort<StateGroup,StateGroupByGroup>(sg,n,o);
00118     }
00119   };
00120 
00124   class GroupStates {
00125   public:
00126     StateGroup* fst;
00127     StateGroup* lst;
00128   };
00129 
00131   enum StateInfo {
00132     SI_NONE       = 0, 
00133     SI_FROM_START = 1, 
00134     SI_TO_FINAL   = 2, 
00135     SI_FINAL      = 4, 
00136   };
00137 
00138 }}}
00139 
00140 namespace Gecode {
00141 
00142   void
00143   DFA::init(int start, Transition t_spec[], int f_spec[], bool minimize) {
00144     using namespace Int;
00145     using namespace Regular;
00146     // Compute number of states and transitions
00147     int n_states = start;
00148     int n_trans  = 0;
00149     for (Transition* t = &t_spec[0]; t->i_state >= 0; t++) {
00150       n_states = std::max(n_states,t->i_state);
00151       n_states = std::max(n_states,t->o_state);
00152       n_trans++;
00153     }
00154     for (int* f = &f_spec[0]; *f >= 0; f++)
00155       n_states = std::max(n_states,*f);
00156     n_states++;
00157 
00158     // Temporary structure for transitions
00159     GECODE_AUTOARRAY(Transition, trans, n_trans);
00160     for (int i = n_trans; i--; )
00161       trans[i] = t_spec[i];
00162     // Temporary structures for finals
00163     GECODE_AUTOARRAY(int,  final,    n_states+1);
00164     GECODE_AUTOARRAY(bool, is_final, n_states+1);
00165     int n_finals = 0;
00166     for (int i = n_states+1; i--; )
00167       is_final[i] = false;
00168     for (int* f = &f_spec[0]; *f != -1; f++) {
00169       is_final[*f]      = true;
00170       final[n_finals++] = *f;
00171     }
00172 
00173     if (minimize) {
00174       // Sort transitions by symbol and i_state
00175       TransBySymbolI_State::sort(trans, n_trans);
00176       GECODE_AUTOARRAY(Transition*, idx, n_trans+1);
00177       //  idx[i]...idx[i+1]-1 gives where transitions for symbol i start
00178       int n_symbols = 0;
00179       {
00180         int j = 0;
00181         while (j < n_trans) {
00182           idx[n_symbols++] = &trans[j];
00183           int s = trans[j].symbol;
00184           while ((j < n_trans) && (s == trans[j].symbol))
00185             j++;
00186         }
00187         idx[n_symbols] = &trans[j];
00188         assert(j == n_trans);
00189       }
00190       // Map states to groups
00191       GECODE_AUTOARRAY(int,         s2g,  n_states+1);
00192       GECODE_AUTOARRAY(StateGroup,  part, n_states+1);
00193       GECODE_AUTOARRAY(GroupStates, g2s,  n_states+1);
00194       // Initialize: final states is group one, all other group zero
00195       for (int i = n_states+1; i--; ) {
00196         part[i].state = i;
00197         part[i].group = is_final[i] ? 1 : 0;
00198         s2g[i]        = part[i].group;
00199       }
00200       // Important: the state n_state is the dead state, conceptually
00201       // if there is no transition for a symbol and input state, it is
00202       // assumed that there is an implicit transition to n_state
00203 
00204       // Set up the indexing data structure, sort by group
00205       StateGroupByGroup::sort(part,n_states+1);
00206       int n_groups;
00207       if (part[0].group == part[n_states].group) {
00208         // No final states, just one group
00209         g2s[0].fst = &part[0]; g2s[0].lst = &part[n_states+1];
00210         n_groups = 1;
00211       } else  {
00212         int i = 0;
00213         assert(part[0].group == 0);
00214         do i++; while (part[i].group == 0);
00215         g2s[0].fst = &part[0]; g2s[0].lst = &part[i];
00216         g2s[1].fst = &part[i]; g2s[1].lst = &part[n_states+1];
00217         n_groups = 2;
00218       }
00219 
00220       // Do the refinement
00221       {
00222         int m_groups;
00223         do {
00224           m_groups = n_groups;
00225           // Iterate over symbols
00226           for (int sidx = n_symbols; sidx--; ) {
00227             // Iterate over groups
00228             for (int g = n_groups; g--; ) {
00229               // Ignore singleton groups
00230               if (g2s[g].lst-g2s[g].fst > 1) {
00231                 // Apply transitions to group states
00232                 // This exploits that both transitions as well as
00233                 // stategroups are sorted by (input) state
00234                 Transition* t     = idx[sidx];
00235                 Transition* t_lst = idx[sidx+1];
00236                 for (StateGroup* sg = g2s[g].fst; sg<g2s[g].lst; sg++) {
00237                   while ((t < t_lst) && (t->i_state < sg->state))
00238                     t++;
00239                   // Compute group resulting from transition
00240                   if ((t < t_lst) && (t->i_state == sg->state))
00241                     sg->group = s2g[t->o_state];
00242                   else
00243                     sg->group = s2g[n_states]; // Go to dead state
00244                 }
00245                 // Sort group by groups from transitions
00246                 StateGroupByGroup::sort(g2s[g].fst,
00247                                         static_cast<int>(g2s[g].lst-g2s[g].fst));
00248                 // Group must be split?
00249                 if (g2s[g].fst->group != (g2s[g].lst-1)->group) {
00250                   // Skip first group
00251                   StateGroup* sg = g2s[g].fst+1;
00252                   while ((sg-1)->group == sg->group)
00253                     sg++;
00254                   // Start splitting
00255                   StateGroup* lst = g2s[g].lst;
00256                   g2s[g].lst = sg;
00257                   while (sg < lst) {
00258                     s2g[sg->state] = n_groups;
00259                     g2s[n_groups].fst  = sg++;
00260                     while ((sg < lst) && ((sg-1)->group == sg->group)) {
00261                       s2g[sg->state] = n_groups; sg++;
00262                     }
00263                     g2s[n_groups++].lst = sg;
00264                   }
00265                 }
00266               }
00267             }
00268           }
00269         } while (n_groups != m_groups);
00270         // New start state
00271         start = s2g[start];
00272         // Compute new final states
00273         n_finals = 0;
00274         for (int g = n_groups; g--; )
00275           for (StateGroup* sg = g2s[g].fst; sg < g2s[g].lst; sg++)
00276             if (is_final[sg->state]) {
00277               final[n_finals++] = g;
00278               break;
00279             }
00280         // Compute representatives
00281         GECODE_AUTOARRAY(int, s2r, n_states+1);
00282         for (int i = n_states+1; i--; )
00283           s2r[i] = -1;
00284         for (int g = n_groups; g--; )
00285           s2r[g2s[g].fst->state] = g;
00286         // Clean transitions
00287         int j = 0;
00288         for (int i = 0; i<n_trans; i++)
00289           if (s2r[trans[i].i_state] != -1) {
00290             trans[j].i_state = s2g[trans[i].i_state];
00291             trans[j].symbol  = trans[i].symbol;
00292             trans[j].o_state = s2g[trans[i].o_state];
00293             j++;
00294           }
00295         n_trans  = j;
00296         n_states = n_groups;
00297       }
00298     }
00299 
00300     // Do a reachability analysis for all states starting from start state
00301     Support::StaticStack<int> visit(n_states);
00302     GECODE_AUTOARRAY(int, state, n_states);
00303     for (int i=n_states; i--; )
00304       state[i] = SI_NONE;
00305 
00306     {
00307       // Sort all transitions according to i_state and create index structure
00308       //  idx[i]...idx[i+1]-1 gives where transitions for state i start
00309       TransByI_State::sort(trans, n_trans);
00310       GECODE_AUTOARRAY(Transition*, idx, n_states+1);
00311       {
00312         int j = 0;
00313         for (int i=0; i<n_states; i++) {
00314           idx[i] = &trans[j];
00315           while ((j < n_trans) && (i == trans[j].i_state))
00316             j++;
00317         }
00318         idx[n_states] = &trans[j];
00319         assert(j == n_trans);
00320       }
00321 
00322       state[start] = SI_FROM_START;
00323       visit.push(start);
00324       while (!visit.empty()) {
00325         int s = visit.pop();
00326         for (Transition* t = idx[s]; t < idx[s+1]; t++)
00327           if (!(state[t->o_state] & SI_FROM_START)) {
00328             state[t->o_state] |= SI_FROM_START;
00329             visit.push(t->o_state);
00330           }
00331       }
00332     }
00333 
00334     // Do a reachability analysis for all states to a final state
00335     {
00336       // Sort all transitions according to o_state and create index structure
00337       //  idx[i]...idx[i+1]-1 gives where transitions for state i start
00338       TransByO_State::sort(trans, n_trans);
00339       GECODE_AUTOARRAY(Transition*, idx, n_states+1);
00340       {
00341         int j = 0;
00342         for (int i=0; i<n_states; i++) {
00343           idx[i] = &trans[j];
00344           while ((j < n_trans) && (i == trans[j].o_state))
00345             j++;
00346         }
00347         idx[n_states] = &trans[j];
00348         assert(j == n_trans);
00349       }
00350 
00351       for (int i = n_finals; i--; ) {
00352         state[final[i]] |= (SI_TO_FINAL | SI_FINAL);
00353         visit.push(final[i]);
00354       }
00355       while (!visit.empty()) {
00356         int s = visit.pop();
00357         for (Transition* t = idx[s]; t < idx[s+1]; t++)
00358           if (!(state[t->i_state] & SI_TO_FINAL)) {
00359             state[t->i_state] |= SI_TO_FINAL;
00360             visit.push(t->i_state);
00361           }
00362       }
00363     }
00364 
00365     // Now all reachable states are known (also the final ones)
00366     GECODE_AUTOARRAY(int, re, n_states);
00367     for (int i = n_states; i--; )
00368       re[i] = -1;
00369 
00370     // Renumber states
00371     int m_states = 0;
00372     // Start state gets zero
00373     re[start] = m_states++;
00374 
00375     // Renumber final states
00376     for (int i = n_states; i--; )
00377       if ((state[i] == (SI_FINAL | SI_FROM_START | SI_TO_FINAL)) && (re[i] < 0))
00378         re[i] = m_states++;
00379     // If start state is final, final states start from zero, otherwise from one
00380     int final_fst = (state[start] & SI_FINAL) ? 0 : 1;
00381     int final_lst = m_states;
00382     // final_fst...final_lst-1 are the final states
00383 
00384     // Renumber remaining states
00385     for (int i = n_states; i--; )
00386       if ((state[i] == (SI_FROM_START | SI_TO_FINAL)) && (re[i] < 0))
00387         re[i] = m_states++;
00388 
00389     // Count number of remaining transitions
00390     int m_trans = 0;
00391     for (int i = n_trans; i--; )
00392       if ((re[trans[i].i_state] >= 0) && (re[trans[i].o_state] >= 0))
00393         m_trans++;
00394 
00395     // All done... Construct the automaton
00396     DFAI* d = reinterpret_cast<DFAI*>
00397       (Memory::malloc(sizeof(DFAI) + sizeof(Transition)*(m_trans-1)));
00398     d->use_cnt   = 1;
00399     d->n_states  = m_states;
00400     d->n_trans   = m_trans;
00401     d->final_fst = final_fst;
00402     d->final_lst = final_lst;
00403     {
00404       int j = 0;
00405       Transition* r = &d->trans[0];
00406       for (int i = 0; i<n_trans; i++)
00407         if ((re[trans[i].i_state] >= 0) && (re[trans[i].o_state] >= 0)) {
00408           r[j].symbol  = trans[i].symbol;
00409           r[j].i_state = re[trans[i].i_state];
00410           r[j].o_state = re[trans[i].o_state];
00411           j++;
00412         }
00413       TransBySymbol::sort(r,m_trans);
00414     }
00415     dfai = d;
00416   }
00417 
00418 }
00419 
00420 std::ostream&
00421 operator<<(std::ostream& os, const Gecode::DFA& dfa) {
00422   os << "Start state: 0" << std::endl
00423      << "States:      0..." << dfa.n_states()-1 << std::endl
00424      << "Transitions:";
00425   for (int s = 0; s < static_cast<int>(dfa.n_states()); s++) {
00426     Gecode::DFA::Transitions t(dfa);
00427     int n = 0;
00428     while (t()) {
00429       if (t.transition()->i_state == s) {
00430         if ((n % 4) == 0)
00431           os << std::endl << "\t";
00432         os << "[" << t.transition()->i_state << "]"
00433            << "- " << t.transition()->symbol << " >"
00434            << "[" << t.transition()->o_state << "]  ";
00435         ++n;
00436       }
00437       ++t;
00438     }
00439   }
00440   os << std::endl << "Final states: "
00441      << std::endl
00442      << "\t[" << dfa.final_fst() << "] ... ["
00443      << dfa.final_lst()-1 << "]"
00444      << std::endl;
00445   return os;
00446 }
00447 
00448 namespace Gecode {
00449 
00450   DFA::DFAI*
00451   DFA::DFAI::copy(void) {
00452     DFAI* d = reinterpret_cast<DFAI*>
00453       (Memory::malloc(sizeof(DFAI) + sizeof(Transition)*(n_trans-1)));
00454     d->use_cnt   = 1;
00455     d->n_states  = n_states;
00456     d->n_trans   = n_trans;
00457     d->final_fst = final_fst;
00458     d->final_lst = final_lst;
00459     memcpy(&d->trans[0], &trans[0], sizeof(Transition)*n_trans);
00460     return d;
00461   }
00462 
00463 }
00464 
00465 // STATISTICS: int-prop
00466