From db165dc641cd157ded5d2c410c85888e42b13362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Tr=C3=A1vn=C3=AD=C4=8Dek?= <jan.travnicek@fit.cvut.cz> Date: Wed, 29 Dec 2021 12:04:57 +0100 Subject: [PATCH] algo: make random automaton factory 3 more efficient --- .../src/automaton/RandomAutomatonFactory3.h | 15 +++++++------- alib2std/src/extensions/algorithm.hpp | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/alib2algo_experimental/src/automaton/RandomAutomatonFactory3.h b/alib2algo_experimental/src/automaton/RandomAutomatonFactory3.h index 6b883dcfcb..e41ec2032a 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 b883e7e477..af56da78ec 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 */ -- GitLab