300 likes | 403 Views
Lecture #4, Jan. 24, 2007. Homework 3 Representing sets as lists the cross product of two sets epsilon transitions epsilon - closure Interpreting an NFA NFA to DFA Labs scheduled: Thursday 4:00 pm, Friday at 9:00 am. Assignments.
E N D
Lecture #4, Jan. 24, 2007 • Homework 3 • Representing sets as lists • the cross product of two sets • epsilon transitions • epsilon - closure • Interpreting an NFA • NFA to DFA Labs scheduled: Thursday 4:00 pm, Friday at 9:00 am
Assignments • Read Chapter 2, pages 27-72 • There will be a 5 minute quiz next lecture • Programming exercise 4 is listed on the web page. It is due next Monday. • exercise writing accumulating parameter functions • a guided exercise to write the e-closure in 10 easy steps
Homework 3 fun reverse [] = [] | reverse (x::xs) = reverse xs @ [x]; fun reverse2 xs = let fun revonto [] ans = ans | revonto (x::xs) ans = revonto xs (x::ans) in revonto xs [] end; fun count n [] = 0 | count n (x::xs) = if n=x then 1 + count n xs else count n xs; fun concatenate [] = [] | concatenate (xs::xss) = xs @ concatenate xss;
Fully Parenthesized fun toStr Empty = "#" | toStr (C c) = implode [c] | toStr (Concat(x,y)) = toStrP x ^ toStrP y | toStr (Union(x,y)) = toStrP x ^"+"^toStrP y | toStr (Star x) = toStrP x ^ "*" and toStrP x = "("^toStr x^")"; - toStr re1; val it = "((+)+((-)+(#)))((D)((D)*))" : string
Not parenthesizing leaf REs fun toStr2 Empty = "#" | toStr2 (C c) = implode [c] | toStr2 (Concat(x,y)) = toStr2P x ^ toStr2P y | toStr2 (Union(x,y)) = toStr2P x ^"+"^toStr2P y | toStr2 (Star x) = toStr2P x ^ "*" and toStr2P (x as (C _)) = toStr2 x | toStr2P (x as Empty) = toStr2 x | toStr2P x = "("^toStr2 x^")"; - toStr2 re1; val it = "(++(-+#))(D(D*))" : string
Escaping special characters fun escape #"+" = "\\+" | escape #"*" = "\\*" | escape #"(" = "\\(" | escape #")" = "\\)" | escape c = implode [c]; fun toStr3 Empty = "#" | toStr3 (C c) = escape c | toStr3 (Concat(x,y)) = toStr3P x ^ toStr3P y | toStr3 (Union(x,y)) = toStr3P x ^"+"^toStr3P y | toStr3 (Star x) = toStr3P x ^ "*" and toStr3P (x as (C _)) = toStr3 x | toStr3P (x as Empty) = toStr3 x | toStr3P x = "("^toStr3 x^")"; - toStr3 re1; val it = "(\\++(-+#))(D(D*))" : string
A separate rule for each sub-RE fun toStr4 Empty = "#" | toStr4 (C c) = escape c | toStr4 (Concat(x,y)) = toStrC x ^ toStrC y | toStr4 (Union(x,y)) = toStrU x ^"+"^toStrU y | toStr4 (Star x) = toStrS x ^ "*" and toStrC (x as (C _)) = toStr4 x | toStrC (x as Empty) = toStr4 x | toStrC (x as (Concat _)) = toStr4 x | toStrC (x as (Star _)) = toStr4 x | toStrC x = "("^toStr4 x^")" and toStrU (x as (C _)) = toStr4 x | toStrU (x as Empty) = toStr4 x | toStrU (x as (Union _)) = toStr4 x | toStrU x = "("^toStr4 x^")" and toStrS (x as (C _)) = toStr4 x | toStrS (x as Empty) = toStr4 x | toStrS x = "("^toStr4 x^")"; - toStr4 re1; val it = "(\\++-+#)DD*" : string
Representing Sets in ML • We do it for ‘int’ others would be similar • Key – Represent a set as an ordered list without duplicates fun mem x [] = false | mem x (y::ys) = if x=y then true else mem x ys; fun setAdd x [] = [x] | setAdd x (y::ys) = case Int.compare (x,y) of EQUAL => (y::ys) | LESS => x::y::ys | GREATER => y :: setAdd x ys; datatype order = EQUAL | LESS | GREATER; Note the use of the Int library compare function.
Union of two sets • Take advantage of the fact that the lists are ordered, this allows union with time proportional to what? fun setUnion [] [] = [] | setUnion [] ys = ys | setUnion xs [] = xs | setUnion (x::xs) (y::ys) = case Int.compare (x,y) of EQUAL => setUnion xs (y::ys) | LESS => x:: setUnion xs (y::ys) | GREATER => y :: setUnion (x::xs) ys; fun setConcat [] = [] | setConcat (x::xs) = setUnion x (setConcat xs);
Can we turn a normal list into a set? (* Turn a list into a set *) (* sort and remove duplicates. *) fun sort [] = [] | sort (x::xs) = setAdd x (sort xs); fun remDupFromOrdered [] = [] | remDupFromOrdered [x] = [x] | remDupFromOrdered (x::y::zs) = if x=y then remDupFromOrdered (y::zs) else x:: remDupFromOrdered (y::zs); fun norm xs = remDupFromOrdered(sort xs);
Cross Product • Consider the two sets • [1,2,6] • [3,5] • The cross product is a set of pairs • all possible pairs (x,y) where x comes from [1,2,6] and y comes from [3,5] • [(1,3),(1,5),(2,3),(2,5),(6,3),(6,5)] • How could we compute this? In pseudo code ( ans := [ ] ; while not (null xs) do let val x = hd xs val ptr = y in while not (null ptr) do let val y = hd ptr in ans := (x,y)::ans ptr := tl ptr end; xs := tl xs end) This has the pattern of a nested set of accumulating parameter functions!
ML code fun innerWhile x [] ans = ans | innerWhile x (y::ys) ans = innerWhile x ys((x,y)::ans) ; fun outerWhile ys [] ans = ans | outerWhile ys (x::xs) ans = outerWhile ys xs (innerWhile x ys ans); fun cross xs ys = outerWhile ys xs []; ( ans := [ ] ; while not (null xs) do let val x = hd xs in while not (null ys) do let val y = hd ys in ans := (x,y)::ans xs := tl xs ys := tl ys end end)
The power of a set of strings if A = [“x”, “y”] what is AA, or AAA, or AAAA fun power 0 x = [""] | power n x = map (op ^) (cross x (power (n-1) x)); power 3 ["a","xy"]; Val it = ["xyaxy","xyaa","xyxyxy","xyxya“ ,"aaxy","aaa","axyxy","axya"]
Concat(Union(C #”+”,Union(C #”-”,Empty)) ,Concat(C #”D”,Star (C #”D”))) (+|-| ε)DD* + val ex6 = (8,15, [Edge (9,Epsilon,10) ,Edge (8,Epsilon,0) ,Edge (8,Epsilon,6) ,Edge (1,Epsilon,9) ,Edge (7,Epsilon,9) ,Edge (0,Char #"+",1) ,Edge (6,Epsilon,2) ,Edge (6,Epsilon,4) ,Edge (3,Epsilon,7) ,Edge (5,Epsilon,7) ,Edge (2,Char #"-",3) ,Edge (4,Epsilon,5) ,Edge (11,Epsilon,14) ,Edge (10,Char #"D",11) ,Edge (14,Epsilon,12) ,Edge (13,Epsilon,15) ,Edge (14,Epsilon,15) ,Edge (15,Epsilon,14) ,Edge (12,Char #"D",13)]) : Nfa 0 1 ε ε 8 ε 9 10 ε - ε 2 ε 3 D 6 7 ε ε 11 ε 4 5 ε 14 ε 12 ε D ε 13 ε 15
Epsilon transitions + • Note that in state 8, one can get to {0,6,2,4,5,7,9,10} by not consuming any characters. • We need only take epsilon transitions • This set is called the epsilon-closure • eclosure [8] = {0,6,2,4,5,7,9,10} • How do we compute this? 0 1 ε ε 8 ε 9 10 ε - ε 2 ε 3 D 6 7 ε ε 11 ε 4 5 ε 14 ε 12 ε D ε 13 ε 15
1-step epsilon + • Note that every state has a 1-step epsilon set. • oneStep 8 = [0,6] • oneStep 0 = [ ] • oneStep 4 = [5] • oneStep 6 = [2,4] • . . . 0 1 ε ε 8 ε 9 10 ε - ε 2 ε 3 D 6 7 ε ε 11 ε 4 5 ε 14 ε many states have empty epsilon sets 12 ε D ε 13 ε 15
Recall how an NFA is represented fun oneStep n (Edge(s,Epsilon,f)) = if n=s then [f] else [] | oneStep n (Edge(s,Char _,f)) = [] • Given a list of edges we apply this function to every edge. fun oneStepFromEdges es n = setConcat(map (oneStep n) es); • How does this work? val ex6 = (8,15, [Edge (9,Epsilon,10) ,Edge (8,Epsilon,0) ,Edge (8,Epsilon,6) ,Edge (1,Epsilon,9) ,Edge (7,Epsilon,9) ,Edge (0,Char #"+",1) ,Edge (6,Epsilon,2) ,Edge (6,Epsilon,4) ,Edge (3,Epsilon,7) ,Edge (5,Epsilon,7) ,Edge (2,Char #"-",3) ,Edge (4,Epsilon,5) ,Edge (11,Epsilon,14) ,Edge (10,Char #"D",11) ,Edge (14,Epsilon,12) ,Edge (13,Epsilon,15) ,Edge (14,Epsilon,15) ,Edge (15,Epsilon,14) ,Edge (12,Char #"D",13)])
Step – by - step - oneStep 8 (Edge(5,Epsilon,6)); val it = [ ] - oneStep 8 (Edge(8,Epsilon,6)); val it = [6] - map (oneStep 8) edges; val it = [[],[0],[6],[],[],[],[],[]] - setConcat [[],[0],[6],[],[],[],[],[]]; val it = [0,6] : int list val edges = [Edge (9,Epsilon,10) ,Edge (8,Epsilon,0) ,Edge (8,Epsilon,6) ,Edge (1,Epsilon,9) ,Edge (7,Epsilon,9) ,Edge (0,Char #"+",1) ,Edge (6,Epsilon,2) ,Edge (6,Epsilon,4)] fun oneStepFromEdges n es = List.concat (map (oneStep n) es); we only get output if the start state matches n
One step from a set of states • Note oneStepFromEdge only gives the e-states from a single starting state. • What if I wanted all the reachable states on epsilon from both 8 or 9? fun oneStepFromSet es states = setConcat (map (oneStepFromEdges es) states); 10 D + 0 1 ε 11 ε ε ε 8 14 9 ε - ε ε 2 ε 3 6 12 ε 7 ε ε ε D ε 4 5 13 ε 15
Iterate fun oneStepFromSet es states = setConcat (map (oneStepFromEdges es) states); - oneStepFromSet edges [8]; val it = [0,6] : int list - oneStepFromSet edges (setUnion [8] [0,6]); val it = [0,2,4,6] : int list - oneStepFromSet edges (setUnion [0,6,8] [0,2,4,6]); val it = [0,2,4,5,6] : int list - oneStepFromSet edges (setUnion [0,2,4,6,8] [0,2,4,5,6]); val it = [0,2,4,5,6,7] : int list - oneStepFromSet edges (setUnion [0,2,4,5,6,8] [0,2,4,5,6,7]); val it = [0,2,4,5,6,7,9] : int list - oneStepFromSet edges (setUnion [0,2,4,5,6,7,8] [0,2,4,5,6,7,9]); val it = [0,2,4,5,6,7,9,10] : int list - oneStepFromSet edges (setUnion [0,2,4,5,6,7,8,9] [0,2,4,5,6,7,9,10]); val it = [0,2,4,5,6,7,9,10] : int list
eclose - eclose edges [8]; [8] [0,6] [0,6,8] ----------------------- [0,6,8] [0,2,4,6] [0,2,4,6,8] ----------------------- [0,2,4,6,8] [0,2,4,5,6] [0,2,4,5,6,8] ----------------------- [0,2,4,5,6,8] [0,2,4,5,6,7] [0,2,4,5,6,7,8] ----------------------- [0,2,4,5,6,7,8] [0,2,4,5,6,7,9] [0,2,4,5,6,7,8,9] ----------------------- [0,2,4,5,6,7,8,9] [0,2,4,5,6,7,9,10] [0,2,4,5,6,7,8,9,10] ----------------------- val it = [0,2,4,5,6,7,8,9,10] fun eclose edges states = let val new = oneStepFromSet edges states val union = setUnion new states in if union = states then states else ( print (setToString states) ; print (setToString new) ; print (setToString union) ; print "-------------\n" ; eclose edges union ) end;
Fixed-point functions fun fix f init = let val new = f init in if new=init then new else fix f new end; fun eclose2 edges xs = let fun step x = setUnion x (oneStepFromSet edges x) in fix step xs end; - eclose2 edges [8]; val it = [0,2,4,5,6,7,8,9,10] : int list
ε a ε 2 3 ε ε b ε a b 6 0 9 10 8 7 1 b ε ε 4 5 ε Simulating an NFA • Given a string, say “ababb” use the NFA to determine if the NFA “accepts” the string. • ε -closure , All those states reachable from a given set on transitions via ε transitions only • Initial state is ε-closure of {0} • For character in the input string keep track of what set-of-states the machine could possibly be in.
ε a ε 2 3 ε ε b ε a b 6 0 9 10 8 7 1 b ε ε 4 5 ε Example: “ababb” Accepting Algorithm state input {0;1,2,4,7} “ababb” {3,8;6,7,0,1,2,4} “babb” {9,5;6,7,0,1,2,4} “abb” {3,8;6,7,0,1,2,4} “bb” {9,5;6,7,0,1,2,4} “b” {10,5;6,7,0,1,2,4} ““ Final state includes the accepting state, 10, so the string is accepted. S := S0; C := nextchar(); while C <> eof do { S := move(S,C); C := nextchar() }; if S is in F then return “yes” else return “no”
fun transitionOn c states edges = let fun good (Edge(s,Char x,f)) = (c=x) andalso (mem s states) | good _ = false fun finish (Edge(s,_,f)) = f in map finish (List.filter good edges) end; fun nfa edges final states [] = mem final states | nfa edges final states (c::cs) = let val _ = print ("State = "^setToString states) val _ = print ("Input = "^implode(c::cs)^"\n") val new = eclose2 edges (transitionOn c states edges) val _ = print ("On '"^implode [c]^ "' we can get to "^ setToString new) in if new = [] then false else nfa edges final new cs end;
Code fun accept (start,final,edges) input = nfa edges final (eclose2 edges [start]) (explode input) - accept ex6 "+DDD"; State = [0,2,4,5,6,7,8,9,10] Input = +DDD On '+' we can get to [1,9,10] State = [1,9,10] Input = DDD On 'D' we can get to [11,12,14,15] State = [11,12,14,15] Input = DD On 'D' we can get to [12,13,14,15] State = [12,13,14,15] Input = D On 'D' we can get to [12,13,14,15] val it = true : bool
A failing examples - accept ex6 "+DaD“; State = [0,2,4,5,6,7,8,9,10] Input = +DaD On '+' we can get to [1,9,10] State = [1,9,10] Input = DaD On 'D' we can get to [11,12,14,15] State = [11,12,14,15] Input = aD On 'a' we can get to [] val it = false : bool - accept ex6 "+"; State = [0,2,4,5,6,7,8,9,10] Input = + On '+' we can get to [1,9,10] val it = false : bool
ε a ε 2 3 ε ε b ε a b 6 0 9 10 8 7 1 b ε ε 4 5 ε Making a DFA To turn an NFA into a DFA Simulate all possible transitions simultaneously. Algorithm is a famous one and is called “the subset construction”. DStates := { (e-clos(S0),unmarked) }; while exists (T,unmarked) in DStates do { mark T; for-each input symbol a do { U := e-clos(move(T,a)); if U is not in DStates then add (U,unmarked) to Dstates Dtran[T,a] := U } }
ε a ε 2 3 ε ε b ε a b 6 0 9 10 8 7 1 b ε ε 4 5 ε • Initial state is 0 • ε –closure of 0 is {0;1,2,4,7} • From any of {0;1,2,4,7} • We can make a transition on “a” to {3,8} • We can make a transition on “b” to {5} • ε –closure of {3,8} is {3,8;6,7,0,1,2,4} • ε –closure of {5} is {5;6,7,0,1,2,4} • From any of {3,8;6,7,0,1,2,4} • We can make a transition on “a” to {3,8} -- which we’ve seen before • We can make a transition on “b” to {9,5} -- which is new • From any of {4;6,7,0,1,2,4} • We can make a transition on “a” to {3,8} -- which we’ve seen before • We can make a transition on “b” to {5} – which we’ve seen before ε –closure of {9,5} is {9;6,7,0,1,2,4} • From any of {9;6,7,0,1,2,4} • We can make a transition on “a” to {3,8} -- which we’ve seen before • We can make a transition on “b” to {10,5} – which is new
ε a ε 2 3 ε ε b ε a b 6 0 9 10 8 7 1 b ε ε 4 5 ε b C b b a b b A B D E a a a Example Algorithm use Dstates Dtran on a Dtran on b A{0;1,2,4,7} B {3,8;1,2,4,6,7} C{5;1,2,4,6,7} B{1,2,3,4,6,7,8} B{3,8;1,2,4,6,7} D{5,9;6,7,1,2,4} C{1,2,4,5,6,7} B{3,8;1,2,4,6,7} C{5;1,2,4,6,7} D{1,2,4,5,6,7,9} B{3,8;1,2,4,6,7} E{5,10;1,2,4,6,7} E{1,2,4,5,6,7,10} B{3,8;1,2,4,6,7} C{5;1,2,4,6,7}