1- package DFA
1+ package dfa
22
3+ // HopcroftDFAMin Given A DFA returns a new DFA with minimum states
34func HopcroftDFAMin (A DFA ) DFA {
45 var pi []Partition
56 pi = append (pi , A .FinalStates )
67 pi = append (pi , A .States )
78 pi [1 ].Extract (pi [0 ])
89
9- var worklist []Splitter
10+ var worklist []splitter
1011
1112 for _ , symb := range A .Alphabet { // Step 4
12- var a0 = pi [0 ].StatesWithIncomingTransitionWith (symb , & A )
13+ var a0 = pi [0 ].StatesWithIncomingTransitionWith (symb , & A )
1314 var a1 = pi [1 ].StatesWithIncomingTransitionWith (symb , & A )
1415 if a0 .Size () < a1 .Size () {
1516 // Use partition with finals states
16- worklist = append (worklist , Splitter { Partition : pi [0 ], Symbol : symb })
17+ worklist = append (worklist , splitter { partition : pi [0 ], input : symb })
1718 } else {
1819 // Use partition with non finals states
19- worklist = append (worklist , Splitter { Partition : pi [1 ], Symbol : symb })
20+ worklist = append (worklist , splitter { partition : pi [1 ], input : symb })
2021 }
2122 }
2223 for len (worklist ) > 0 {
2324 // Pick a splitter <Partition P, Symbol a> from the splitter set (and delete it)
24- currentSplitter := PickOneAndRemove (& worklist )
25+ currentSplitter := pickOneAndRemove (& worklist )
2526 for i , R := range pi { //Step 7
2627 R1 , R2 , splitted := R .SplitBy (& currentSplitter , & A )
2728 if splitted { // Hay refinamiento
@@ -30,17 +31,17 @@ func HopcroftDFAMin(A DFA) DFA {
3031 // R2 == B''j ==> Bk
3132 pi = append (pi , R2 )
3233 for _ , c := range A .Alphabet {
33- spR := Splitter { Partition : R , Symbol : c }
34- spR1 := Splitter { Partition : R1 , Symbol : c }
35- spR2 := Splitter { Partition : R2 , Symbol : c }
36- if ! ReplaceInWorklistIfSplitterExists (& worklist , spR , spR1 , spR2 ) {
37- ar1 := R1 .StatesWithIncomingTransitionWith (c , & A )
38- ar2 := R2 .StatesWithIncomingTransitionWith (c , & A )
39- if ( ( ar1 .Size () < ar2 .Size ())) {
40- worklist = append (worklist , Splitter { Partition : R1 , Symbol : c })
41- } else {
42- worklist = append (worklist , Splitter { Partition : R2 , Symbol : c })
43- }
34+ spR := splitter { partition : R , input : c }
35+ spR1 := splitter { partition : R1 , input : c }
36+ spR2 := splitter { partition : R2 , input : c }
37+ if ! RefinedPartitionReplacedInWorklist (& worklist , spR , spR1 , spR2 ) {
38+ ar1 := R1 .StatesWithIncomingTransitionWith (c , & A )
39+ ar2 := R2 .StatesWithIncomingTransitionWith (c , & A )
40+ if ar1 .Size () < ar2 .Size () {
41+ worklist = append (worklist , splitter { partition : R1 , input : c })
42+ } else {
43+ worklist = append (worklist , splitter { partition : R2 , input : c })
44+ }
4445 }
4546 }
4647 pi = append (pi , R1 )
@@ -54,40 +55,40 @@ func HopcroftDFAMin(A DFA) DFA {
5455 var initialStateMinim State
5556 DeltaMin := make (map [State ]map [int ]State )
5657 for i , part := range pi {
57- statesMinim .Add (i )
58- AddTransitions (& DeltaMin , & A , pi , i )
59- partitionHasFinalStates := false
60- partitionHasInitialState := false
61- for _ , s := range part {
62- if A .FinalStates .Includes (s ) {
63- partitionHasFinalStates = true
64- }
65- if (A .InitialState == s ) {
66- partitionHasInitialState = true
67- continue
68- }
58+ statesMinim .Add (i )
59+ addTransitions (& DeltaMin , & A , pi , i )
60+ partitionHasFinalStates := false
61+ partitionHasInitialState := false
62+ for _ , s := range part {
63+ if A .FinalStates .Includes (s ) {
64+ partitionHasFinalStates = true
6965 }
70- if partitionHasFinalStates {
71- finalStatesMinim .Add (i )
66+ if A .InitialState == s {
67+ partitionHasInitialState = true
68+ continue
7269 }
73- if partitionHasInitialState {
74- initialStateMinim = i
75- }
70+ }
71+ if partitionHasFinalStates {
72+ finalStatesMinim .Add (i )
73+ }
74+ if partitionHasInitialState {
75+ initialStateMinim = i
76+ }
7677 }
7778 Ar := DFA {States : * statesMinim , Alphabet : A .Alphabet , InitialState : initialStateMinim , FinalStates : * finalStatesMinim , Delta : DeltaMin }
7879 return Ar
7980}
8081
81- func AddTransitions (DeltaMin * map [State ]map [int ]State , A * DFA , pi []Partition , i int ) {
82+ func addTransitions (DeltaMin * map [State ]map [int ]State , A * DFA , pi []Partition , i int ) {
8283 for _ , c := range A .Alphabet {
8384 transitionState , ok := A .Delta [pi [i ][0 ]][c ]
8485 if ! ok {
8586 continue
8687 }
8788 partitionOfState := getPartitionOfState (& pi , transitionState )
8889 if (* DeltaMin )[i ] == nil {
89- (* DeltaMin )[i ] = map [int ]State {c : partitionOfState }
90- }else {
90+ (* DeltaMin )[i ] = map [int ]State {c : partitionOfState }
91+ } else {
9192 (* DeltaMin )[i ][c ] = partitionOfState
9293 }
9394 }
@@ -103,11 +104,13 @@ func getPartitionOfState(pi *[]Partition, q State) int {
103104 return 0
104105}
105106
106- func ReplaceInWorklistIfSplitterExists (worklist * []Splitter , spR Splitter , spR1 Splitter , spR2 Splitter ) bool {
107+ // RefinedPartitionReplacedInWorklist if the splitted partition was in the worklist it has to be replaced.
108+ // If did not exist in the worklist return false
109+ func RefinedPartitionReplacedInWorklist (worklist * []splitter , spR splitter , spR1 splitter , spR2 splitter ) bool {
107110 newWorklist := * worklist
108111 worklistSize := len (* worklist )
109- for i , w := range ( * worklist ) {
110- if w .Partition .Equals (spR .Partition ) && w .Symbol == spR .Symbol {
112+ for i , w := range * worklist {
113+ if w .partition .Equals (spR .partition ) && w .input == spR .input {
111114 newWorklist [i ] = (* worklist )[worklistSize - 1 ]
112115 newWorklist = append (newWorklist , spR1 )
113116 newWorklist = append (newWorklist , spR2 )
@@ -118,10 +121,10 @@ func ReplaceInWorklistIfSplitterExists(worklist *[]Splitter, spR Splitter, spR1
118121 return false
119122}
120123
121- func PickOneAndRemove (worklist * []Splitter ) Splitter {
124+ func pickOneAndRemove (worklist * []splitter ) splitter {
122125 worklistSize := len (* worklist )
123126 newWorklist := * worklist
124- sp := (* worklist )[worklistSize - 1 ]
127+ sp := (* worklist )[worklistSize - 1 ]
125128 newWorklist = (* worklist )[:worklistSize - 1 ]
126129 * worklist = newWorklist
127130 return sp
0 commit comments