|
|
1.1 root 1: ### mindfa -- minimize a DFA
2:
3: record dfa(Q,S,d,q0,F) # a DFA
4:
5: procedure main()
6:
7: x := getdfa()
8: every 1 to 10 do
9: showdfa("Reduced",minimize(showdfa("Original",x)))
10:
11: end
12:
13: ## - getdfa() -- accept a dfa from input, return it
14: ##
15: procedure getdfa()
16: local Q,S,d,q0,F
17: local q,a
18:
19: Q := readset("Enter states (1 character names): ")
20: S := readset("Enter input alphabet: ")
21: F := readset("Enter Final states (subset of states): ")
22: writes("What is the start state? ")
23: q0 := read()
24: d := table()
25: every q := !Q & a := !S do {
26: writes("enter delta(",q,",",a,") = ")
27: d[q||":"||a] := read()
28: }
29: return dfa(Q,S,d,q0,F)
30:
31: end
32:
33:
34: ## readset(s) - get a set
35: #
36: procedure readset(s)
37: local t1
38:
39: writes(s)
40: t1 := []
41: every put(t1,!cset(read())) # the cset removes duplicates
42: return t1
43:
44: end
45:
46: ## showdfa(msg,D) -- show a dfa
47: #
48: procedure showdfa(msg,D)
49: local q,a
50:
51: every 1 to 3 do write()
52: write(msg," Deterministic Finite Automaton is:")
53: write()
54: write("\t(Q,S,delta,q0,F)")
55: write()
56: write("where:")
57: write()
58: writeset("Q",D.Q)
59: writeset("S",D.S)
60: writeset("F",D.F)
61: write("\tStart state is ",D.q0)
62: write("\tDelta: ")
63: every q := !D.Q do {
64: every writes("\td(",q,",",a := !D.S,") = ",D.d[q||":"||a])
65: write()
66: }
67: return D
68:
69: end
70:
71: ## writeset(msg,s) -- display a set
72: #
73: procedure writeset(msg,s)
74: local tmp
75: tmp := ""
76: every tmp ||:= !s || ","
77: write("\t",msg," = {",tmp[1:-1],"}")
78: return
79: end
80:
81: ## minimize(D) -- minimize a dfa
82: #
83: global distab, dlists
84:
85: procedure minimize(D)
86: local F,QF
87: local p,q,a,cs
88:
89: distab := table()
90: dlists := table()
91: F := D.F
92: QF := diff(D.Q,D.F)
93: every p := !F & q := !QF do
94: distab[cset(p||q)] := "X"
95: every ((p := !F & q := !F) |
96: (p := !QF & q := !QF)) & p ~== q do
97: if \distab[cset(D.d[p||":"||(a:=!D.S)]||D.d[q||":"||a])] then {
98: distab[cset(p||q)] := "X"
99: marklists(dlists[cset(p||q)])
100: }
101: else
102: every a := !D.S do
103: if D.d[p||":"||a] ~== D.d[q||":"||a] then {
104: cs := cset(D.d[p||":"||a]||D.d[q||":"||a])
105: if cs == cset(p||q) then next
106: /dlists[cs] := []
107: put(dlists[cs],cset(p||q))
108: }
109:
110: return makemdfa(D,distab)
111:
112: end
113:
114: ## marklists(l) -- recursively mark the pair of nodes
115: # on list l.
116: procedure marklists(l)
117: local e
118:
119: if /l then return
120: every e := !l do {
121: distab[e] := "X"
122: marklists(dlists[e])
123: }
124: return
125:
126: end
127:
128: ## makemdfa(D,DT) -- Use the table from the minimization
129: # to construct the minimal dfa
130: procedure makemdfa(D,DT)
131: local elist, etab, qset, tlist, echeck
132: local p, q, Delta, q0
133:
134: etab := table() # table of new states
135: qset := ''
136: every p := !D.Q do {
137: qset ++:= p
138: plike := equiv(p,etab) | cset(p)
139: every q := !diff(D.Q,qset) & p ~== q do
140: if /distab[cset(p||q)] then {
141: plike ++:= equiv(q,etab) | q
142: }
143: etab[plike] := plike
144: }
145: tlist := []
146: elist := []
147: Delta := table()
148: q0 := equiv(D.q0,etab) # start state of reduced machine
149: put(tlist,q0)
150: put(elist,q0) # only worry about states reachable
151: # from [q0]
152: echeck := table() # keep track of states
153: echeck[q0] := q0
154: while q := get(tlist) do
155: every a := !D.S do {
156: Delta[q||":"||a] := equivdelta(q,a,D,etab)
157: if /echeck[Delta[q||":"||a]] then {
158: echeck[Delta[q||":"||a]] := Delta[q||":"||a]
159: put(tlist,Delta[q||":"||a])
160: put(elist,Delta[q||":"||a])
161: }
162: }
163:
164: return dfa(elist,D.S,Delta,q0,finalstates(D,elist))
165: end
166:
167: ## equiv(q,el) -- return the equivalence class in el containing q
168: #
169: procedure equiv(q,el)
170: every p := !el do
171: if p++q == p then return p
172: end
173:
174: ## equivdelta(p,a,D,el) -- apply delta to equiv. classes
175: #
176: procedure equivdelta(p,a,D,el)
177: local q, r
178: q := !p # any state in equiv. class p
179: r := D.d[q||":"||a] # find state in original dfa
180:
181: return equiv(r,el) # return its equivalence class
182: end
183:
184:
185: ## finalstates(D,el) -- build the set of final states
186: #
187: procedure finalstates(D,el)
188: local flist, p, q
189:
190: ftab := table()
191: every p := !D.F do
192: ftab[q := equiv(p,el)] := q
193: flist := []
194: every put(flist,(!sort(ftab))[1])
195: return flist
196: end
197:
198:
199: ## diff(l1,l2) -- return the difference of two sets
200: #
201: procedure diff(l1,l2)
202: local l,t1,t2
203:
204: t1 := ''
205: every t1 ++:= !l1
206:
207: t2 := ''
208: every t2 ++:= !l2
209:
210: l := []
211: every put(l,!(t1--t2))
212: if *l = 0 then fail
213: return l
214: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.