nfa.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:6k
开发平台:

MultiPlatform

  1. #include <LEDA/graph.h>
  2. #include <LEDA/graph_alg.h>
  3. #include <LEDA/set.h>
  4. #include <LEDA/stack.h>
  5. #include <LEDA/array.h>
  6. /* We use sets, stacks, and arrays of nodes */
  7. // alphabeth: `a`,'b', ... , 'z','~'
  8. // epsilon = '~'
  9. const char EPSILON = '~';
  10. //------------------------------------------------------------------------------
  11. // NFA's are directed graphs with
  12. // node labels of type "int"  (states)
  13. // edge labels of type "char" 
  14. //------------------------------------------------------------------------------
  15. typedef GRAPH<int,char> NFA;
  16. int compare(node x, node y) { return x-y; }
  17. /*------------------------------------------------------------------------------
  18.    DFA's are directed graphs with
  19.    node labels of type set<node>*  (pointers to set of nodes of an NFA)
  20.    edge labels of type "char"      
  21. ------------------------------------------------------------------------------*/
  22. typedef set<node>* node_set_ptr;
  23. typedef GRAPH<node_set_ptr,char> DFA;
  24. //------------------------------------------------------------------------------
  25. // We need a test for equality on sets of nodes 
  26. // This implementation is very inefficient!
  27. //------------------------------------------------------------------------------
  28. bool EQ_NODE_SET(node_set_ptr S1, node_set_ptr S2)
  29. {
  30.   // input: two pointers S1 and S2 to sets of nodes
  31.   // ouput: true,  if node sets *S1 and *S2 are equal
  32.   //        false, otherwise
  33.   node v;
  34.   forall(v,*S1) 
  35.     if (! S2->member(v)) return false;
  36.   forall(v,*S2) 
  37.     if (! S1->member(v)) return false;
  38.   return true;
  39.  }
  40. //------------------------------------------------------------------------------
  41. // Epsilon Closure
  42. //------------------------------------------------------------------------------
  43. void E_CLOSURE(NFA& A, node_set_ptr T)
  44. {
  45.   /* expands node set *T by dfs on the epsilon edges */
  46.   stack<node> S;
  47.   node u,v;
  48.   edge e;
  49.   forall(v,*T) S.push(v);
  50.   while ( ! S.empty() )
  51.    { u = S.pop();
  52.      // visit all neighbors v of u not in T and reachable by an epsilon-edge 
  53.      forall_adj_edges(e,u)
  54.      { v = A.target(e);
  55.        if ( A.inf(e) == EPSILON && !T->member(v) ) 
  56.         { T->insert(v);
  57.           S.push(v);
  58.          }
  59.       }
  60.     }
  61.  } // E_CLOSURE
  62. //------------------------------------------------------------------------------
  63. // Move
  64. //------------------------------------------------------------------------------
  65. node_set_ptr MOVE(NFA& A, node_set_ptr T, char x)
  66. {
  67.   /* result is a pointer p to the set of nodes to which there 
  68.      is a transition on input symbol x from a node in *T
  69.   */
  70.   node v;
  71.   edge e;
  72.   node_set_ptr p = new set<node>;  
  73.   /* now p is a pointer to an empty set  of nodes */
  74.   forall(v,*T)
  75.     forall_adj_edges(e,v)
  76.       if ( A.inf(e) == x ) p->insert(A.target(e));
  77.   return p;
  78. } // MOVE
  79. //------------------------------------------------------------------------------
  80. // Build a DFA from an NFA
  81. //------------------------------------------------------------------------------
  82. DFA  BUILD_DFA_FROM_NFA(NFA& A, node s0)
  83. {
  84.   // result is a DFA B accepting the same language
  85.   // as NFA A with initial state s0
  86.   DFA B;
  87.   stack<node> S;
  88.   node v,w;
  89.   char c;
  90.   node_set_ptr p;
  91.   /* First we create a DFA-node for epsilon-closure(s0)and push it 
  92.      on the stack S. S contains all nodes of DFA B whose transitions 
  93.      have not been examined so far.  
  94.   */
  95.   p = new set<node>;
  96.   p->insert(s0);
  97.   E_CLOSURE(A,p);
  98.   S.push(B.new_node(p));
  99.   while ( ! S.empty() )
  100.   { v = S.pop();
  101.     for(c = 'a'; c<='z'; c++)  // for each input symbol c do
  102.      {
  103.        p = MOVE(A,B.inf(v),c);
  104.        // Is there any NFA-transisition from a node in B.inf(v) ?
  105.        // i.e.: Is p not empty ?
  106.        if ( ! p->empty() )     
  107.         {
  108.           // compute the epsilon closure of *p
  109.           E_CLOSURE(A,p);
  110.    
  111.           /* search for a DFA-node w with B.inf(w) == *p */
  112.           bool found = false;       
  113.           forall_nodes(w,B)
  114.             if (EQ_NODE_SET(B.inf(w),p))
  115.                { found = true;
  116.                  break;
  117.                 }
  118.           /* if no such node exists create it */
  119.    
  120.           if ( !found )                     
  121.            { w = B.new_node(p);
  122.              S.push(w);
  123.             }
  124.    
  125.           /* insert edge [v] --(c)--> [w] */
  126.           B.new_edge(v,w,c);               
  127.          } // if p not empty
  128.    
  129.       }  // for c = 'a' ... 'z'
  130.    } // while S not empty
  131.  return B;
  132.   
  133. }
  134.   
  135. main()
  136.   // Build a NFA A
  137.   NFA A;
  138.   // States = {0,1,...,N-1}
  139.   int N = read_int("number of states N = ");
  140.   cout << "Start state = 0n";
  141.   array<node> state(0,N-1);
  142.   int i,j;
  143.   char c;
  144.   // create N nodes: state[0], ... , state[N-1]
  145.   loop(i,0,N-1) state[i] = A.new_node(i);
  146.   // create edges (transistions)
  147.   cout << "Enter Transitions of NFA (terminate input with   0 0 0)n";
  148.   
  149.   for(;;)
  150.   { cout << "state1  state2  label : ";
  151.     cin >> i >> j >> c;
  152.     if (i==0 && j==0 && c=='0') break;
  153.     A.new_edge(state[i], state[j], c);
  154.    }
  155.   node u,v;
  156.   edge e;
  157.   // output  NFA A:
  158.   newline;
  159.   cout << "NFA A: n";
  160.   forall_nodes(v,A)
  161.     { cout << string(" [%d] : ",A.inf(v));
  162.       forall_adj_edges(e,v) 
  163.         cout << string(" [%d]--%c-->[%d] ",A.inf(v),A.inf(e),A.inf(A.target(e)));
  164.       newline;
  165.      }
  166.   DFA B = BUILD_DFA_FROM_NFA(A,state[0]);
  167.   // output  DFA B:
  168.   node_array<int> name(B);
  169.   newline;
  170.   cout << "DFA B:n";
  171.   i=0;
  172.   forall_nodes(v,B)
  173.     { name[v] = i++;
  174.       cout << string(" [%d] = {",i);
  175.       forall(u,*B.inf(v)) cout << " " << A.inf(u);
  176.       cout << " }n";
  177.      }
  178.   newline;
  179.   forall_nodes(v,B)
  180.     { cout << string(" [%d] : ",name[v]);
  181.       forall_adj_edges(e,v) 
  182.         cout << string(" [%d]--%c-->[%d] ",name[v],B.inf(e),name[B.target(e)]);
  183.       newline;
  184.      }
  185.   return 0;
  186. }