diff --git a/alib2algo_experimental/src/automaton/RandomAutomatonFactory3.h b/alib2algo_experimental/src/automaton/RandomAutomatonFactory3.h index 6b883dcfcb39a657405d04475252227887a99e14..e41ec2032a8b4b1a08acce3e37f875a8ad2a4437 100644 --- a/alib2algo_experimental/src/automaton/RandomAutomatonFactory3.h +++ b/alib2algo_experimental/src/automaton/RandomAutomatonFactory3.h @@ -200,18 +200,17 @@ automaton::MultiInitialStateNFA < SymbolType, unsigned > RandomAutomatonFactory3 ext::vector < unsigned > unused = statesMinimal; unused.erase ( std::find ( unused.begin ( ), unused.end ( ), initialState ) ); - while ( visited.size ( ) != statesMinimal.size ( ) ) { - unsigned a = visited [ ext::random_devices::semirandom ( ) % visited.size ( ) ]; + std::shuffle ( unused.begin ( ), unused.end ( ), ext::random_devices::semirandom ); - if ( automaton.getTransitions ( ).count ( ext::slice_comp ( a ) ) == alphabet.size ( ) ) - continue; + for ( unsigned b : unused ) { + unsigned a = * ext::randomValue ( visited.begin ( ), visited.end ( ), ext::random_devices::semirandom, [ & ] ( unsigned candidateState ) { + return automaton.getTransitions ( ).count ( ext::slice_comp ( candidateState ) ) != alphabet.size ( ); + } ); size_t c = randomSymbol ( a, alphabet, automaton, deterministic ); - size_t b = ext::random_devices::semirandom ( ) % unused.size ( ); - addTransition( automaton, a, alphabet [ c ], unused [ b ], duplicates ); - visited.push_back ( unused [ b ] ); - unused.erase ( unused.begin ( ) + b ); + addTransition( automaton, a, alphabet [ c ], b, duplicates ); + visited.push_back ( b ); } makeRelation ( automaton, alphabet, statesMinimal, statesMinimal, duplicates, density, deterministic ); diff --git a/alib2std/src/extensions/algorithm.hpp b/alib2std/src/extensions/algorithm.hpp index b883e7e4777ed495ba57dc792b5559ce00f4a086..af56da78eceadf437e1e29bf539d7a22a5355ad8 100644 --- a/alib2std/src/extensions/algorithm.hpp +++ b/alib2std/src/extensions/algorithm.hpp @@ -416,5 +416,25 @@ inline bool range_contains_iterator ( ForwardIteratorBegin from, const ForwardIt return false; } +template < class Iterator, class RandomDevice > +Iterator randomValue ( Iterator begin, Iterator end, RandomDevice && r ) { + if ( begin == end ) + throw std::invalid_argument ( "Empty range to pick random value from." ); + std::advance ( begin, r ( ) % std::distance ( begin, end ) ); + return begin; +} + +template < class Iterator, class RandomDevice, class Predicate > +Iterator randomValue ( Iterator begin, Iterator end, RandomDevice r, Predicate p ) { + Iterator value = end; + size_t incidency = 0; + + for ( ; begin != end; ++ begin ) + if ( p ( * begin ) && ( r ( ) % ( ++ incidency ) ) < 1 ) + value = begin; + + return value; +} + } /* namespace ext */