home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / prog / graph / nfa.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  5.7 KB  |  285 lines

  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.  
  7. /* We use sets, stacks, and arrays of nodes */
  8.  
  9. declare(set,node)
  10. declare(stack,node)
  11. declare(array,node)
  12.  
  13.  
  14. // alphabeth: `a`,'b', ... , 'z','~'
  15.  
  16. // epsilon = '~'
  17.  
  18. const char EPSILON = '~';
  19.  
  20.  
  21. //------------------------------------------------------------------------------
  22. // NFA's are directed graphs with
  23. // node labels of type "int"  (states)
  24. // edge labels of type "char" 
  25. //------------------------------------------------------------------------------
  26.  
  27. declare2(GRAPH,int,char)
  28.  
  29. typedef GRAPH(int,char) NFA;
  30.  
  31.  
  32. /*------------------------------------------------------------------------------
  33.    DFA's are directed graphs with
  34.    node labels of type set(node)*  (pointers to set of nodes of an NFA)
  35.    edge labels of type "char"      
  36. ------------------------------------------------------------------------------*/
  37.  
  38. typedef set(node)* node_set_ptr;
  39.  
  40. declare2(GRAPH,node_set_ptr,char)
  41.  
  42. typedef GRAPH(node_set_ptr,char) DFA;
  43.  
  44.  
  45.  
  46. //------------------------------------------------------------------------------
  47. // We need a test for equality on sets of nodes 
  48. // This implementation is very inefficient!
  49. //------------------------------------------------------------------------------
  50.  
  51. bool EQ_NODE_SET(node_set_ptr S1, node_set_ptr S2)
  52. {
  53.   // input: two pointers S1 and S2 to sets of nodes
  54.   // ouput: true,  if node sets *S1 and *S2 are equal
  55.   //        false, otherwise
  56.  
  57.   node v;
  58.  
  59.   forall(v,*S1) 
  60.     if (! S2->member(v)) return false;
  61.  
  62.   forall(v,*S2) 
  63.     if (! S1->member(v)) return false;
  64.  
  65.   return true;
  66.  
  67.  }
  68.  
  69.  
  70.  
  71.  
  72. //------------------------------------------------------------------------------
  73. // Epsilon Closure
  74. //------------------------------------------------------------------------------
  75.  
  76. void E_CLOSURE(NFA& A, node_set_ptr T)
  77. {
  78.   /* expands node set *T by dfs on the epsilon edges */
  79.  
  80.   stack(node) S;
  81.  
  82.   node u,v;
  83.   edge e;
  84.  
  85.   forall(v,*T) S.push(v);
  86.  
  87.   while ( ! S.empty() )
  88.    { u = S.pop();
  89.  
  90.      // visit all neighbors v of u not in T and reachable by an epsilon-edge 
  91.  
  92.      forall_adj_edges(e,u)
  93.      { v = A.target(e);
  94.        if ( A.inf(e) == EPSILON && !T->member(v) ) 
  95.         { T->insert(v);
  96.           S.push(v);
  97.          }
  98.       }
  99.     }
  100.  
  101.  } // E_CLOSURE
  102.  
  103.  
  104. //------------------------------------------------------------------------------
  105. // Move
  106. //------------------------------------------------------------------------------
  107.  
  108. node_set_ptr MOVE(NFA& A, node_set_ptr T, char x)
  109. {
  110.   /* result is a pointer p to the set of nodes to which there 
  111.      is a transition on input symbol x from a node in *T
  112.   */
  113.  
  114.   node v;
  115.   edge e;
  116.  
  117.   node_set_ptr p = new set(node);  
  118.   /* now p is a pointer to an empty set  of nodes */
  119.  
  120.   forall(v,*T)
  121.     forall_adj_edges(e,v)
  122.       if ( A.inf(e) == x ) p->insert(A.target(e));
  123.  
  124.   return p;
  125.  
  126. } // MOVE
  127.  
  128.  
  129.  
  130. //------------------------------------------------------------------------------
  131. // Build a DFA from an NFA
  132. //------------------------------------------------------------------------------
  133.  
  134. DFA  BUILD_DFA_FROM_NFA(NFA& A, node s0)
  135. {
  136.   // result is a DFA B accepting the same language
  137.   // as NFA A with initial state s0
  138.  
  139.  
  140.   DFA B;
  141.  
  142.   stack(node) S;
  143.  
  144.   node v,w;
  145.   char c;
  146.   node_set_ptr p;
  147.  
  148.   /* First we create a DFA-node for epsilon-closure(s0)and push it 
  149.      on the stack S. S contains all nodes of DFA B whose transitions 
  150.      have not been examined so far.  
  151.   */
  152.  
  153.   p = new set(node);
  154.   p->insert(s0);
  155.   E_CLOSURE(A,p);
  156.   S.push(B.new_node(p));
  157.  
  158.   while ( ! S.empty() )
  159.   { v = S.pop();
  160.  
  161.     for(c = 'a'; c<='z'; c++)  // for each input symbol c do
  162.      {
  163.        p = MOVE(A,B.inf(v),c);
  164.  
  165.        // Is there any NFA-transisition from a node in B.inf(v) ?
  166.        // i.e.: Is p not empty ?
  167.  
  168.        if ( ! p->empty() )     
  169.         {
  170.           // compute the epsilon closure of *p
  171.  
  172.           E_CLOSURE(A,p);
  173.    
  174.  
  175.           /* search for a DFA-node w with B.inf(w) == *p */
  176.  
  177.           bool found = false;       
  178.           forall_nodes(w,B)
  179.             if (EQ_NODE_SET(B.inf(w),p))
  180.                { found = true;
  181.                  break;
  182.                 }
  183.  
  184.           /* if no such node exists create it */
  185.    
  186.           if ( !found )                     
  187.            { w = B.new_node(p);
  188.              S.push(w);
  189.             }
  190.    
  191.           /* insert edge [v] --(c)--> [w] */
  192.  
  193.           B.new_edge(v,w,c);               
  194.  
  195.          } // if p not empty
  196.    
  197.       }  // for c = 'a' ... 'z'
  198.  
  199.    } // while S not empty
  200.  
  201.  return B;
  202.   
  203. }
  204.  
  205.  
  206.   
  207.  
  208. main()
  209.  
  210.   // Build a NFA A
  211.  
  212.   NFA A;
  213.  
  214.   // States = {0,1,...,N-1}
  215.  
  216.   int N = read_int("number of states N = ");
  217.  
  218.   cout << "Start state = 0\n";
  219.  
  220.   array(node) state(0,N-1);
  221.  
  222.   int i,j;
  223.   char c;
  224.  
  225.   // create N nodes: state[0], ... , state[N-1]
  226.  
  227.   loop(i,0,N-1) state[i] = A.new_node(i);
  228.  
  229.  
  230.   // create edges (transistions)
  231.  
  232.   cout << "Enter Transitions of NFA (terminate input with   0 0 0)\n";
  233.   
  234.  
  235.   for(;;)
  236.   { cout << "state1  state2  label : ";
  237.     cin >> i >> j >> c;
  238.     if (i==0 && j==0 && c=='0') break;
  239.  
  240.     A.new_edge(state[i], state[j], c);
  241.    }
  242.  
  243.   node u,v;
  244.   edge e;
  245.  
  246.   // output  NFA A:
  247.  
  248.   newline;
  249.   cout << "NFA A: \n";
  250.  
  251.   forall_nodes(v,A)
  252.     { cout << form(" [%d] : ",A.inf(v));
  253.       forall_adj_edges(e,v) 
  254.         cout << form(" [%d]--%c-->[%d] ",A.inf(v),A.inf(e),A.inf(A.target(e)));
  255.       newline;
  256.      }
  257.  
  258.   DFA B = BUILD_DFA_FROM_NFA(A,state[0]);
  259.  
  260.  
  261.   // output  DFA B:
  262.  
  263.   node_array(int) name(B);
  264.  
  265.   newline;
  266.   cout << "DFA B:\n";
  267.   i=0;
  268.   forall_nodes(v,B)
  269.     { name[v] = i++;
  270.       cout << form(" [%d] = {",i);
  271.       forall(u,*B.inf(v)) cout << " " << A.inf(u);
  272.       cout << " }\n";
  273.      }
  274.   newline;
  275.  
  276.   forall_nodes(v,B)
  277.     { cout << form(" [%d] : ",name[v]);
  278.       forall_adj_edges(e,v) 
  279.         cout << form(" [%d]--%c-->[%d] ",name[v],B.inf(e),name[B.target(e)]);
  280.       newline;
  281.      }
  282.  
  283. }
  284.