Algorithms Library Toolkit
A toolkit for algorithms, especially for algorithms on formal languages
RandomAutomatonFactory3.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
17
18namespace automaton {
19
20namespace generate {
21
23public:
24 template < class SymbolType >
25 static automaton::MultiInitialStateNFA < SymbolType, unsigned > generate ( size_t statesMinimal, size_t statesDuplicates, size_t statesUnreachable, size_t statesUseless, size_t initialStates, size_t finalStates, ext::set < SymbolType> alphabet, double density, bool deterministic );
26 static automaton::MultiInitialStateNFA < std::string, unsigned > generate ( size_t statesMinimal, size_t statesDuplicates, size_t statesUnreachable, size_t statesUseless, size_t initialStates, size_t finalStates, size_t alphabetSize, bool randomizedAlphabet, double density, bool deterministic );
27
28private:
29 static ext::vector < unsigned > makeVector ( size_t begin, size_t end );
30 template < class SymbolType >
31 static size_t randomSymbol ( unsigned sourceState, const ext::deque < SymbolType > & alphabet, const automaton::MultiInitialStateNFA < SymbolType, unsigned > & automaton, bool deterministic );
32 template < class SymbolType>
33 static bool makeRelationElement ( automaton::MultiInitialStateNFA < SymbolType, unsigned > & automaton, const ext::deque < SymbolType> & alphabet, const ext::vector < unsigned > & sourceSet, const ext::vector < unsigned > & targetSet, const ext::deque < ext::vector < unsigned > > & duplicates, bool deterministic );
34 template < class SymbolType >
35 static void makeRelation ( automaton::MultiInitialStateNFA < SymbolType, unsigned > & automaton, const ext::deque < SymbolType> & alphabet, const ext::vector < unsigned > & sourceSet, const ext::vector < unsigned > & targetSet, const ext::deque < ext::vector < unsigned > > & duplicates, double density, bool deterministic );
36 template < class SymbolType >
37 static bool addTransition ( automaton::MultiInitialStateNFA < SymbolType, unsigned > & automaton, unsigned source, SymbolType symbol, unsigned target, const ext::deque < ext::vector < unsigned > > & duplicates );
38 template < class SymbolType >
39 static automaton::MultiInitialStateNFA < SymbolType, unsigned > run ( ext::vector < unsigned > statesMinimal, size_t statesDuplicates, ext::vector < unsigned > statesUnreachable, ext::vector < unsigned > statesUseless, size_t statesInitial, size_t statesFinal, const ext::deque < SymbolType > & alphabet, double density, bool deterministic );
40};
41
42template < class SymbolType >
43automaton::MultiInitialStateNFA < SymbolType, unsigned > RandomAutomatonFactory3::generate ( size_t statesMinimal, size_t statesDuplicates, size_t statesUnreachable, size_t statesUseless, size_t initialStates, size_t finalStates, ext::set < SymbolType > alphabet, double density, bool deterministic ) {
44 if ( deterministic && initialStates > 1 )
45 throw exception::CommonException("Deterministic automaton has to have a single initial state.");
46
47 if ( initialStates == 0 )
48 throw exception::CommonException("There has to be at least one initial state.");
49
51
52 for( const auto & s : alphabet )
53 alphabet2.push_back ( s );
54
55 return RandomAutomatonFactory3::run ( makeVector ( 0 , statesMinimal ),
56 statesDuplicates,
57 makeVector ( statesMinimal , statesMinimal + statesUnreachable ),
58 makeVector ( statesMinimal + statesUnreachable , statesMinimal + statesUnreachable + statesUseless ),
59 initialStates, finalStates, alphabet, density, deterministic );
60}
61
62template < class SymbolType >
63size_t RandomAutomatonFactory3::randomSymbol ( unsigned sourceState, const ext::deque < SymbolType > & alphabet, const automaton::MultiInitialStateNFA < SymbolType, unsigned > & automaton, bool deterministic ) {
64 if ( ! deterministic )
65 return ext::random_devices::semirandom ( ) % alphabet.size ( );
66
67 size_t modulo = alphabet.size ( ) - automaton.getTransitions ( ).count ( ext::slice_comp ( sourceState ) );
68 if ( modulo == 0 )
69 throw exception::CommonException("State does not have any remaining symbol available.");
70
71 size_t x = ext::random_devices::semirandom ( ) % modulo + 1; // the +1 to match the incrementation of cnt if the symbol is not used
72 for( size_t i = 0, cnt = 0; i < alphabet.size ( ); i++ ) {
73 if ( automaton.getTransitions ( ).find ( std::make_pair ( sourceState, alphabet [ i ] ) ) == automaton.getTransitions ( ).end ( ) )
74 cnt ++;
75
76 if( cnt == x )
77 return i;
78 }
79
80 throw exception::CommonException("Should not be reached.");
81}
82
83template < class SymbolType >
84bool RandomAutomatonFactory3::addTransition ( automaton::MultiInitialStateNFA < SymbolType, unsigned > & automaton, unsigned source, SymbolType symbol, unsigned target, const ext::deque < ext::vector < unsigned > > & duplicates ) {
85 bool res = false;
86 for ( unsigned duplicateSource : duplicates [ source ] ) {
87 unsigned duplicateTarget = duplicates [ target ] [ ext::random_devices::semirandom() % ( duplicates [ target ].size ( ) ) ];
88 res |= automaton.addTransition ( duplicateSource, symbol, duplicateTarget );
89 }
90 return res;
91}
92
93template < class SymbolType>
94bool RandomAutomatonFactory3::makeRelationElement ( automaton::MultiInitialStateNFA < SymbolType, unsigned > & automaton, const ext::deque < SymbolType> & alphabet, const ext::vector < unsigned > & sourceSet, const ext::vector < unsigned > & targetSet, const ext::deque < ext::vector < unsigned > > & duplicates, bool deterministic ) {
95 unsigned a = sourceSet [ ext::random_devices::semirandom ( ) % sourceSet.size ( ) ];
96
97 if ( deterministic && automaton.getTransitions ( ).count ( ext::slice_comp ( a ) ) == alphabet.size ( ) )
98 return false;
99
100 unsigned c = randomSymbol ( a, alphabet, automaton, deterministic );
101 unsigned b = targetSet [ ext::random_devices::semirandom ( ) % targetSet.size ( ) ];
102
103 return addTransition ( automaton, a, alphabet [ c ], b, duplicates );
104}
105
106template < class SymbolType >
107void RandomAutomatonFactory3::makeRelation ( automaton::MultiInitialStateNFA < SymbolType, unsigned > & automaton, const ext::deque < SymbolType> & alphabet, const ext::vector < unsigned > & sourceSet, const ext::vector < unsigned > & targetSet, const ext::deque < ext::vector < unsigned > > & duplicates, double density, bool deterministic ) {
108
109 ext::vector < unsigned > targetSetIncludingDuplicates;
110 for ( unsigned targetState : targetSet )
111 for ( unsigned duplicateTarget : duplicates [ targetState ] )
112 targetSetIncludingDuplicates.push_back ( duplicateTarget );
113
114 std::sort ( targetSetIncludingDuplicates.begin ( ), targetSetIncludingDuplicates.end ( ) );
115
116 if ( targetSet.empty ( ) )
117 return;
118
119 size_t entriesToCreate = sourceSet.size ( ) * alphabet.size ( );
120 if ( ! deterministic )
121 entriesToCreate *= targetSet.size ( );
122
123 if ( deterministic )
124 for ( size_t state : sourceSet )
125 entriesToCreate -= automaton.getTransitions ( ).count ( ext::slice_comp ( state ) );
126 else
127 for ( unsigned state : sourceSet )
128 for ( const std::pair < const ext::pair < unsigned, SymbolType >, unsigned > & transition : automaton.getTransitionsFromState ( state ) ) // transitions are not sorted by the target ...
129 if ( std::binary_search ( targetSetIncludingDuplicates.begin ( ), targetSetIncludingDuplicates.end ( ), transition.second ) )
130 -- entriesToCreate;
131
132 entriesToCreate *= density;
133
134 while ( entriesToCreate )
135 if ( makeRelationElement ( automaton, alphabet, sourceSet, targetSet, duplicates, deterministic ) )
136 -- entriesToCreate;
137}
138
139template < class Callback >
140void callbackOnRandom ( Callback callback, size_t states, const ext::vector < unsigned > & set1, const ext::vector < unsigned > & set2, const ext::deque < ext::vector < unsigned > > & duplicates ) {
141 while ( states ) {
142 size_t index = ext::random_devices::semirandom ( ) % ( set1.size ( ) + set2.size ( ) );
143
144 unsigned state;
145 if ( index < set1.size ( ) )
146 state = set1 [ index ];
147 else {
148 index -= set1.size ( );
149 state = set2 [ index ];
150 }
151
152 bool res = false;
153 for ( unsigned duplicateState : duplicates [ state ] ) {
154 res |= callback ( duplicateState );
155 }
156
157 if ( res )
158 -- states;
159 }
160}
161
162template < class SymbolType >
163automaton::MultiInitialStateNFA < SymbolType, unsigned > RandomAutomatonFactory3::run ( ext::vector < unsigned > statesMinimal, size_t statesDuplicates, ext::vector < unsigned > statesUnreachable, ext::vector < unsigned > statesUseless, size_t statesInitial, size_t statesFinal, const ext::deque < SymbolType > & alphabet, double density, bool deterministic ) {
165
166 for ( const auto & s : alphabet )
167 automaton.addInputSymbol( s );
168
170
171 for ( unsigned state : statesMinimal ) {
172 duplicates.push_back ( ext::vector < unsigned > { state } );
173 automaton.addState ( state );
174 }
175
176 for ( unsigned state : statesUnreachable ) {
177 duplicates.push_back ( ext::vector < unsigned > { state } );
178 automaton.addState ( state );
179 }
180
181 for ( unsigned state : statesUseless ) {
182 duplicates.push_back ( ext::vector < unsigned > { state } );
183 automaton.addState ( state );
184 }
185
186 size_t statesNow = automaton.getStates ( ).size ( );
187 for ( unsigned duplicate = 0; duplicate < statesDuplicates; ++ duplicate ) {
188 automaton.addState ( statesNow + duplicate );
189
190 size_t a = ext::random_devices::semirandom() % ( statesNow );
191 duplicates [ a ].push_back ( statesNow + duplicate );
192 }
193
194 callbackOnRandom ( [ & ] ( unsigned state ) {
195 return automaton.addFinalState ( state );
196 }, statesFinal, statesMinimal, statesUnreachable, duplicates );
197
198 unsigned initialState = ext::random_devices::semirandom ( ) % statesMinimal.size ( );
199 automaton.addInitialState ( initialState );
200 callbackOnRandom ( [ & ] ( unsigned state ) {
201 return automaton.addInitialState ( state );
202 }, statesInitial - 1, statesMinimal, statesUseless, duplicates );
203
204 ext::vector < unsigned > visited { initialState };
205 ext::vector < unsigned > unused = statesMinimal;
206 unused.erase ( std::find ( unused.begin ( ), unused.end ( ), initialState ) );
207
208 while ( visited.size ( ) != statesMinimal.size ( ) ) {
209 unsigned a = visited [ ext::random_devices::semirandom ( ) % visited.size ( ) ];
210
211 if ( automaton.getTransitions ( ).count ( ext::slice_comp ( a ) ) == alphabet.size ( ) )
212 continue;
213
214 size_t c = randomSymbol ( a, alphabet, automaton, deterministic );
215 size_t b = ext::random_devices::semirandom ( ) % unused.size ( );
216
217 addTransition( automaton, a, alphabet [ c ], unused [ b ], duplicates );
218 visited.push_back ( unused [ b ] );
219 unused.erase ( unused.begin ( ) + b );
220 }
221
222 makeRelation ( automaton, alphabet, statesMinimal, statesMinimal, duplicates, density, deterministic );
223 makeRelation ( automaton, alphabet, statesUnreachable, statesUnreachable, duplicates, density, deterministic );
224 makeRelation ( automaton, alphabet, statesUseless, statesUseless, duplicates, density, deterministic );
225
226 if ( ! statesUnreachable.empty ( ) && ! statesUseless.empty ( ) )
227 makeRelationElement ( automaton, alphabet, statesUnreachable, statesUseless, duplicates, deterministic );
228
229 makeRelation ( automaton, alphabet, statesMinimal, statesUseless, duplicates, density, deterministic );
230 makeRelation ( automaton, alphabet, statesUnreachable, statesMinimal, duplicates, density, deterministic );
231 makeRelation ( automaton, alphabet, statesUnreachable, statesUseless, duplicates, density, deterministic );
232
233 return automaton;
234}
235
236} /* namespace generate */
237
238} /* namespace automaton */
Nondeterministic finite automaton with multiple initial states. Accepts regular languages.
Definition: MultiInitialStateNFA.h:69
Definition: RandomAutomatonFactory3.h:22
static automaton::MultiInitialStateNFA< SymbolType, unsigned > generate(size_t statesMinimal, size_t statesDuplicates, size_t statesUnreachable, size_t statesUseless, size_t initialStates, size_t finalStates, ext::set< SymbolType > alphabet, double density, bool deterministic)
Definition: RandomAutomatonFactory3.h:43
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
Class extending the pair class from the standard library. Original reason is to allow printing of the...
Definition: pair.hpp:43
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
auto begin() &
Inherited behavior of begin for non-const instance.
Definition: vector.hpp:125
iterator erase(iterator pos)
Removes element from the container at position given by parameter pos.
Definition: vector.hpp:323
auto end() &
Inherited behavior of end for non-const instance.
Definition: vector.hpp:155
Definition: BarSymbol.cpp:12
void callbackOnRandom(Callback callback, size_t states, const ext::vector< unsigned > &set1, const ext::vector< unsigned > &set2, const ext::deque< ext::vector< unsigned > > &duplicates)
Definition: RandomAutomatonFactory3.h:140
int i
Definition: AllEpsilonClosure.h:118
typename T::SymbolType SymbolType
Definition: ReachableStates.h:176
return res
Definition: MinimizeByPartitioning.h:145
ext::set< ext::tuple< StateType, StateType, SymbolType > > visited
Definition: Compaction.h:81
Definition: ToGrammar.h:31
int callback(struct dl_phdr_info *info, size_t, void *data)
Definition: simpleStacktrace.cpp:25
SliceComp< Ts ... > slice_comp(const Ts &... inst)
Definition: functional.hpp:95
constexpr auto make_pair(T1 &&x, T2 &&y)
Definition: pair.hpp:79
auto begin(Container &&cont) -> decltype(std::forward(cont).begin())
Definition: iterator.hpp:900
void end()
Definition: measurements.cpp:19