Algorithms Library Toolkit
A toolkit for algorithms, especially for algorithms on formal languages
RandomAutomatonFactory2.h
Go to the documentation of this file.
1
6#pragma once
7
8#include <ext/algorithm>
9#include <ext/random>
10
11#include <alib/deque>
12#include <alib/set>
13
15
16#include <automaton/FSM/DFA.h>
17
18namespace automaton {
19
20namespace generate {
21
23public:
24 template < class SymbolType >
25 static automaton::DFA < SymbolType, unsigned > generateDFA ( size_t statesMinimal, size_t statesDuplicates, size_t statesUnreachable, size_t statesUseless, ext::set < SymbolType> alphabet, double density );
26 static automaton::DFA < std::string, unsigned > generateDFA ( size_t statesMinimal, size_t statesDuplicates, size_t statesUnreachable, size_t statesUseless, size_t alphabetSize, bool randomizedAlphabet, double density );
27
28private:
29 static size_t randomSourceState ( size_t statesMinimal, size_t visited, size_t depleted, const ext::deque < bool > & VStates, const ext::deque < bool > & DStates );
30 static size_t randomTargetState ( size_t statesMinimal, size_t visited, const ext::deque < bool > & VStates );
31 template < class SymbolType >
32 static size_t randomSymbol ( unsigned sourceState, const ext::deque < SymbolType > & alphabet, const automaton::DFA < SymbolType, unsigned > & automaton );
33 template < class SymbolType >
34 static void addTransition ( automaton::DFA < SymbolType, unsigned > & automaton, unsigned source, SymbolType symbol, unsigned target, const ext::deque < ext::vector < unsigned > > & duplicates );
35 template < class SymbolType >
36 static automaton::DFA < SymbolType, unsigned > NonminimalDFA( size_t statesMinimal, size_t statesDuplicates, size_t statesUnreachable, size_t statesUseless, const ext::deque < SymbolType > & alphabet, double density );
37};
38
39template < class SymbolType >
40automaton::DFA < SymbolType, unsigned > RandomAutomatonFactory2::generateDFA( size_t statesMinimal, size_t statesDuplicates, size_t statesUnreachable, size_t statesUseless, ext::set < SymbolType > alphabet, double density ) {
42
43 for( const auto & s : alphabet )
44 alphabet2.push_back ( s );
45
46 return RandomAutomatonFactory2::NonminimalDFA ( statesMinimal, statesDuplicates, statesUnreachable, statesUseless, alphabet, density );
47}
48
49template < class SymbolType >
50size_t RandomAutomatonFactory2::randomSymbol ( unsigned sourceState, const ext::deque < SymbolType > & alphabet, const automaton::DFA < SymbolType, unsigned > & automaton ) {
51 size_t x = ext::random_devices::semirandom() % ( alphabet.size( ) - automaton.getTransitionsFromState ( sourceState ).size ( ) ) + 1;
52 for( size_t i = 0, cnt = 0; i < alphabet.size ( ); i++ ) {
53 if ( automaton.getTransitions ( ).find ( std::make_pair ( sourceState, alphabet [ i ] ) ) == automaton.getTransitions ( ).end ( ) )
54 cnt ++;
55
56 if( cnt == x )
57 return i;
58 }
59
60 return -1;
61}
62
63template < class SymbolType >
64void RandomAutomatonFactory2::addTransition ( automaton::DFA < SymbolType, unsigned > & automaton, unsigned source, SymbolType symbol, unsigned target, const ext::deque < ext::vector < unsigned > > & duplicates ) {
65 for ( unsigned duplicateSource : duplicates [ source ] ) {
66 unsigned duplicateTarget = duplicates [ target ] [ ext::random_devices::semirandom() % ( duplicates [ target ].size ( ) ) ];
67 automaton.addTransition( duplicateSource, symbol, duplicateTarget );
68 }
69}
70
71template < class SymbolType >
72automaton::DFA < SymbolType, unsigned > RandomAutomatonFactory2::NonminimalDFA( size_t statesMinimal, size_t statesDuplicates, size_t statesUnreachable, size_t statesUseless, const ext::deque < SymbolType > & alphabet, double density ) {
73 // TODO make the same transition function on one of final states and one of the nonfinal ones.
74 // unreachable states accesible from each other atleast a bit
75 if( alphabet.empty ( ) )
76 throw exception::CommonException( "Alphabet size must be greater than 0." );
77
78 ext::deque < bool > VStates;
79 ext::deque < bool > FStates;
80 ext::deque < bool > DStates;
81 // to represent states that will merge
83
84 size_t visited;
85 size_t finals = 0;
86 size_t depleted = 0;
87
89
90 for( const auto & s : alphabet )
91 automaton.addInputSymbol( s );
92
93 /* states partitioning -- | statesMinimal | statesUseless | statesUnreachable | statesDuplicates | */
94
95 for( unsigned i = 0; i < statesMinimal + statesUseless + statesUnreachable + statesDuplicates; i ++ ) {
96 VStates.push_back( false );
97 DStates.push_back( false );
98 FStates.push_back( false );
99 duplicates.push_back ( ext::vector < unsigned > { i } );
100 automaton.addState( i );
101 }
102
103 for ( unsigned i = 0; i < statesDuplicates; ++ i ) {
104 size_t a = ext::random_devices::semirandom() % ( statesMinimal );
105 duplicates [ a ].push_back ( i + statesMinimal + statesUseless + statesUnreachable );
106 }
107
108 // ---- base
109 if( statesMinimal == 0 ) {
110 return automaton;
111 } else if( statesMinimal == 1 ) {
112 addTransition( automaton, 0, alphabet[ ext::random_devices::semirandom() % alphabet.size( ) ], 0, duplicates );
113
114 visited = 1;
115 VStates[ 0 ] = true;
116 DStates[ 0 ] = automaton.getTransitionsFromState ( 0 ).size ( ) == alphabet.size ( );
117 if ( DStates[ 0 ] )
118 depleted ++;
119 } else {
120 size_t x = ( ext::random_devices::semirandom() % ( statesMinimal - 1 ) ) + 1;
121 addTransition( automaton, 0, alphabet[ ext::random_devices::semirandom() % alphabet.size( ) ], x, duplicates );
122 visited = 2;
123
124 VStates[ 0 ] = true;
125 VStates[ x ] = true;
126
127 DStates[ 0 ] = automaton.getTransitionsFromState ( 0 ).size ( ) == alphabet.size ( );
128 if ( DStates[ 0 ] )
129 depleted ++;
130 }
131
132 // ---- make statesMinimal reachable
133 while( visited != statesMinimal ) {
134 size_t a = randomSourceState ( statesMinimal, visited, depleted, VStates, DStates );
135 size_t b = randomTargetState ( statesMinimal, visited, VStates );
136 size_t c = randomSymbol ( a, alphabet, automaton );
137
138 addTransition( automaton, a, alphabet[ c ], b, duplicates );
139
140 visited ++;
141 VStates[ b ] = true;
142 DStates[ a ] = automaton.getTransitionsFromState ( a ).size ( ) == alphabet.size ( );
143 if ( DStates[ a ] )
144 depleted ++;
145 }
146
147 // ---- make statesUseless reachable
148 while( visited != statesMinimal + statesUseless ) {
149 size_t a = randomSourceState ( statesMinimal + statesUseless, visited, depleted, VStates, DStates );
150 size_t b = randomTargetState ( statesMinimal + statesUseless, visited, VStates );
151 size_t c = randomSymbol ( a, alphabet, automaton );
152
153 addTransition( automaton, a, alphabet[ c ], b, duplicates );
154
155 visited ++;
156 VStates[ b ] = true;
157 DStates[ a ] = automaton.getTransitionsFromState ( a ).size ( ) == alphabet.size ( );
158 if ( DStates[ a ] )
159 depleted ++;
160 }
161
162 // ---- make 0 state and leaf states connected by path
163 unsigned last = 0;
164 for ( unsigned i = 0; i < statesMinimal; ++ i ) {
165 if ( automaton.getTransitionsFromState ( i ).empty ( ) ) {
166 size_t c = randomSymbol ( i, alphabet, automaton );
167 addTransition ( automaton, i, alphabet [ c ], last, duplicates );
168 last = i;
169 }
170 }
171
172 // ---- make 1/3 to 2/3 of base states final
173 for ( unsigned i = 0; i < statesMinimal * 2 / 3; ++ i ) {
174 if ( i > statesMinimal / 3 && ext::random_devices::semirandom() % 2 == 0 )
175 continue;
176
177 size_t a = randomSourceState ( statesMinimal, visited - statesUseless, finals, VStates, FStates );
178 FStates [ a ] = true;
179 finals ++;
180
181 for ( unsigned s : duplicates [ a ] )
182 automaton.addFinalState ( s );
183 }
184
185 // ---- make 1/3 to 2/3 of unreachable states final
186 for ( unsigned i = 0; i < statesUnreachable * 2 / 3; ++ i ) {
187 if ( i > statesUnreachable / 3 && ext::random_devices::semirandom() % 2 == 0 )
188 continue;
189
190 size_t a = ext::random_devices::semirandom() % statesUnreachable + statesMinimal + statesUseless;
191 FStates [ a ] = true;
192 finals ++;
193
194 for ( unsigned s : duplicates [ a ] )
195 automaton.addFinalState ( s );
196 }
197
198 visited += statesUnreachable;
199 for ( unsigned i = 0; i < statesUnreachable; ++ i ) {
200 VStates [ statesMinimal + statesUseless + i ] = true;
201 }
202
203 // ---- fill in the rest of transition function randomly
204 double mnn100 = 100.0 / alphabet.size( ) / ( statesMinimal + statesUseless + statesUnreachable + statesDuplicates );
205 while( automaton.getTransitions ( ).size( ) * mnn100 < density ) {
206 size_t a = randomSourceState ( statesMinimal + statesUseless + statesUnreachable, visited, depleted, VStates, DStates );
207 size_t b;
208 if ( a < statesMinimal )
209 b = ext::random_devices::semirandom() % ( statesMinimal );
210 else if ( a < statesMinimal + statesUseless )
211 b = ext::random_devices::semirandom() % ( statesUseless ) + statesMinimal;
212 else
213 b = ext::random_devices::semirandom() % ( statesMinimal + statesUseless + statesUnreachable );
214
215 size_t c = randomSymbol ( a, alphabet, automaton );
216
217 addTransition( automaton, a, alphabet [ c ], b, duplicates );
218 DStates[ a ] = automaton.getTransitionsFromState ( a ).size ( ) == alphabet.size ( );
219 if ( DStates[ a ] )
220 depleted ++;
221 }
222
223 return automaton;
224}
225
226} /* namespace generate */
227
228} /* namespace automaton */
229
Deterministic finite automaton. Accepts regular languages.
Definition: DFA.h:71
Definition: RandomAutomatonFactory2.h:22
static automaton::DFA< SymbolType, unsigned > generateDFA(size_t statesMinimal, size_t statesDuplicates, size_t statesUnreachable, size_t statesUseless, ext::set< SymbolType > alphabet, double density)
Definition: RandomAutomatonFactory2.h:40
Basic exception from which all other exceptions are derived.
Definition: CommonException.h:21
Class extending the deque class from the standard library. Original reason is to allow printing of th...
Definition: deque.hpp:44
static semirandom_device & semirandom
The reference to singleton semirandom device.
Definition: random.hpp:147
Definition: set.hpp:44
Class extending the vector class from the standard library. Original reason is to allow printing of t...
Definition: vector.hpp:45
Definition: BarSymbol.cpp:12
int i
Definition: AllEpsilonClosure.h:118
typename T::SymbolType SymbolType
Definition: ReachableStates.h:176
ext::set< ext::tuple< StateType, StateType, SymbolType > > visited
Definition: Compaction.h:81
Definition: ToGrammar.h:31
constexpr auto make_pair(T1 &&x, T2 &&y)
Definition: pair.hpp:79