From 13a53699098d5687e306c51f1e849d1eb21fd16f 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: Sat, 5 Mar 2022 20:16:59 +0100 Subject: [PATCH] algo: introduces ranked alphabet generator and addapts tree automaton generator --- .../alphabet/generate/AsRankedAlphabet.cpp | 28 ++++++++ .../src/alphabet/generate/AsRankedAlphabet.h | 72 +++++++++++++++++++ .../generate/RandomTreeAutomatonFactory.cpp | 49 ------------- .../generate/RandomTreeAutomatonFactory.h | 15 ---- tests/cppaql/conversionsTest2.cpp | 2 +- 5 files changed, 101 insertions(+), 65 deletions(-) create mode 100644 alib2algo/src/alphabet/generate/AsRankedAlphabet.cpp create mode 100644 alib2algo/src/alphabet/generate/AsRankedAlphabet.h diff --git a/alib2algo/src/alphabet/generate/AsRankedAlphabet.cpp b/alib2algo/src/alphabet/generate/AsRankedAlphabet.cpp new file mode 100644 index 0000000000..e4413580dd --- /dev/null +++ b/alib2algo/src/alphabet/generate/AsRankedAlphabet.cpp @@ -0,0 +1,28 @@ +#include "AsRankedAlphabet.h" + +#include <registration/AlgoRegistration.hpp> + +namespace { + +auto AsRankedAlphabet = registration::AbstractRegister < alphabet::generate::AsFullRankedAlphabet, ext::set < common::ranked_symbol < object::Object > >, const ext::set < object::Object > &, size_t > ( alphabet::generate::AsFullRankedAlphabet::asRankedAlphabet < object::Object >, "alphabet", "maxRank" ).setDocumentation ( +"Generates ranked alphabet from unranked alphabet so that all symbols are put into the result with all ranks.\n\ +\n\ +@param alphabet the converted alphabet\n\ +@param maxRank the maximal rank used\n\ +@return the generated ranked alphabet" ); + +auto AsRandomRankedAlphabet = registration::AbstractRegister < alphabet::generate::AsRandomRankedAlphabet, ext::set < common::ranked_symbol < object::Object > >, const ext::set < object::Object > &, size_t > ( alphabet::generate::AsRandomRankedAlphabet::asRankedAlphabet < object::Object >, "alphabet", "maxRank" ).setDocumentation ( +"Generates ranked alphabet from unranked alphabet so that at least one symbol is assigned rank 0 and other are random.\n\ +\n\ +@param alphabet the converted alphabet\n\ +@param maxRank the maximal rank used\n\ +@return the generated ranked alphabet" ); + +auto AsSequencedRankedAlphabet = registration::AbstractRegister < alphabet::generate::AsSequencedRankedAlphabet, ext::set < common::ranked_symbol < object::Object > >, const ext::set < object::Object > &, size_t > ( alphabet::generate::AsSequencedRankedAlphabet::asRankedAlphabet < object::Object >, "alphabet", "maxRank" ).setDocumentation ( +"Generates ranked alphabet from unranked alphabet so that first symbol is assigned rank 0, second rank 1 up to maxRank-th symbol rank maxRank when the assigned ranks assigned also reset to 0 and are increases again.\n\ +\n\ +@param alphabet the converted alphabet\n\ +@param maxRank the maximal rank used\n\ +@return the generated ranked alphabet" ); + +} /* namespace */ diff --git a/alib2algo/src/alphabet/generate/AsRankedAlphabet.h b/alib2algo/src/alphabet/generate/AsRankedAlphabet.h new file mode 100644 index 0000000000..a097462a99 --- /dev/null +++ b/alib2algo/src/alphabet/generate/AsRankedAlphabet.h @@ -0,0 +1,72 @@ +#pragma once + +#include <ext/random> + +#include <alib/set> + +#include <common/ranked_symbol.hpp> + +namespace alphabet::generate { + +class AsFullRankedAlphabet { +public: +template < class T > +static ext::set < common::ranked_symbol < T > > asRankedAlphabet ( const ext::set < T > & alphabet, size_t maxRank ) { + ext::set < common::ranked_symbol < T > > res; + + if ( alphabet.size ( ) == 0 ) + throw std::invalid_argument ( "There needs to be at least one symbol for nullary symbol." ); + + for ( size_t i = 0; i <= maxRank; ++ i ) { + for ( const T & symbol : alphabet ) { + res.insert ( common::ranked_symbol < T > ( symbol, i ) ); + } + } + return res; +} + +}; + +class AsRandomRankedAlphabet { +public: +template < class T > +static ext::set < common::ranked_symbol < T > > asRankedAlphabet ( const ext::set < T > & alphabet, size_t maxRank ) { + ext::set < common::ranked_symbol < T > > res; + + if ( alphabet.size ( ) == 0 ) + throw std::invalid_argument ( "There needs to be at least one symbol for nullary symbol." ); + + size_t nullaryIndex = static_cast < size_t > ( ext::random_devices::semirandom ( ) % ( alphabet.size ( ) ) ); + + for ( auto iter = alphabet.begin ( ); iter != alphabet.end ( ); ++ iter ) { + if ( res.size ( ) == nullaryIndex ) + res.insert ( common::ranked_symbol < T > ( * iter, 0 ) ); + else + res.insert ( common::ranked_symbol < T > ( * iter, static_cast < size_t > ( ext::random_devices::semirandom ( ) % ( maxRank + 1 ) ) ) ); + } + + return res; +} + +}; + +class AsSequencedRankedAlphabet { +public: +template < class T > +static ext::set < common::ranked_symbol < T > > asRankedAlphabet ( const ext::set < T > & alphabet, size_t maxRank ) { + ext::set < common::ranked_symbol < T > > res; + + if ( alphabet.size ( ) <= maxRank ) + throw std::invalid_argument ( "Not enough symbols were provided to fulfill the max rank request." ); + + auto iter = alphabet.begin ( ); + for ( size_t i = 0; iter != alphabet.end ( ); i = ( i + 1 ) % ( maxRank + 1 ) ) { + res.insert ( common::ranked_symbol < T > ( * iter ++, i ) ); + } + + return res; +} + +}; + +} /* namespace alphabet::generate */ diff --git a/alib2algo/src/automaton/generate/RandomTreeAutomatonFactory.cpp b/alib2algo/src/automaton/generate/RandomTreeAutomatonFactory.cpp index 38f56b280b..5013bbfd3f 100644 --- a/alib2algo/src/automaton/generate/RandomTreeAutomatonFactory.cpp +++ b/alib2algo/src/automaton/generate/RandomTreeAutomatonFactory.cpp @@ -3,45 +3,6 @@ namespace automaton::generate { -namespace { - constexpr unsigned ENGLISH_ALPHABET_SIZE = 26; -} - -automaton::NFTA < std::string, unsigned > RandomTreeAutomatonFactory::generateNFTA( size_t statesCount, size_t alphabetSize, size_t maxRank, bool randomizedAlphabet, double density ) { - if ( alphabetSize > ENGLISH_ALPHABET_SIZE ) - throw exception::CommonException("Too big alphabet."); - - if(alphabetSize < 1) - throw exception::CommonException("Too small alphabet."); - - ext::deque < std::string > alphabet; - for(char i = 'a'; i <= 'z'; i++) - alphabet.push_back ( std::string ( 1, i ) ); - - if(randomizedAlphabet) - shuffle(alphabet.begin(), alphabet.end(), ext::random_devices::semirandom); - - alphabet.resize ( alphabetSize ); - - ext::deque < common::ranked_symbol < std::string > > rankedAlphabet; - - for ( std::string && symbol : ext::make_mover ( alphabet ) ) { - rankedAlphabet.push_back ( common::ranked_symbol < std::string > ( std::move ( symbol ), ext::random_devices::semirandom() % ( maxRank + 1 ) ) ); - } - - bool containsNullary = false; - for ( common::ranked_symbol < std::string > & rankedSymbol : rankedAlphabet ) { - containsNullary |= rankedSymbol.getRank ( ) == 0; - } - - if ( ! containsNullary ) { - int c = ext::random_devices::semirandom() % rankedAlphabet.size ( ); - rankedAlphabet [ c ] = common::ranked_symbol ( rankedAlphabet [ c ].getSymbol ( ), 0u ); - } - - return automaton::generate::RandomTreeAutomatonFactory::LeslieConnectedNFTA( statesCount, rankedAlphabet, density ); -} - unsigned RandomTreeAutomatonFactory::ithAccessibleState ( const ext::deque < bool > & VStates, size_t i ) { i ++; for( size_t j = 0; j < VStates.size ( ); j++ ) { @@ -77,14 +38,4 @@ auto GenerateNFTA1 = registration::AbstractRegister < automaton::generate::Rando @param density density of the transition function\n\ @return random nondeterministic finite automaton" ); -auto GenerateNFTA2 = registration::AbstractRegister < automaton::generate::RandomTreeAutomatonFactory, automaton::NFTA < std::string, unsigned >, size_t, size_t, size_t, bool, double > ( automaton::generate::RandomTreeAutomatonFactory::generateNFTA, abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT, "statesCount", "alphabetSize", "maxRank", "randomizedAlphabet", "density" ).setDocumentation ( -"Generates a random finite automaton.\n\ -\n\ -@param statesCount number of states in the generated automaton\n\ -@param alphabetSize size of the alphabet (1-26)\n\ -@param maxRank the maximum rank in the randomly generated alphabet\n\ -@param randomizedAlphabet selects random symbols from a-z range if true\n\ -@param density density of the transition function (0-100). 100 means every possible transition is created\n\ -@return random nondeterministic finite automaton" ); - } /* namespace */ diff --git a/alib2algo/src/automaton/generate/RandomTreeAutomatonFactory.h b/alib2algo/src/automaton/generate/RandomTreeAutomatonFactory.h index de5b907d57..d58ac16660 100644 --- a/alib2algo/src/automaton/generate/RandomTreeAutomatonFactory.h +++ b/alib2algo/src/automaton/generate/RandomTreeAutomatonFactory.h @@ -54,21 +54,6 @@ public: template < class SymbolType > static automaton::NFTA < SymbolType, unsigned > generateNFTA ( size_t statesCount, const ext::set < common::ranked_symbol < SymbolType > > & alphabet, double density ); - /** - * \overload - * - * Generates a random finite automaton. - * - * \param statesCount number of states in the generated automaton - * \param alphabetSize size of the alphabet (1-26) - * \param maxRank the maximum rank in the randomly generated alphabet - * \param randomizedAlphabet selects random symbols from a-z range if true - * \param density density of the transition function (0-100). 100 means every possible transition is created - * - * \return random nondeterministic finite automaton - */ - static automaton::NFTA < std::string, unsigned > generateNFTA ( size_t statesCount, size_t alphabetSize, size_t maxRank, bool randomizedAlphabet, double density ); - private: /** * Selects ith accessible state form \p VStates. diff --git a/tests/cppaql/conversionsTest2.cpp b/tests/cppaql/conversionsTest2.cpp index 4d0c0c0ed1..b61bad0456 100644 --- a/tests/cppaql/conversionsTest2.cpp +++ b/tests/cppaql/conversionsTest2.cpp @@ -12,7 +12,7 @@ const double RAND_DENSITY = 5; const size_t ITERATIONS = 50; std::string qGenNFTA ( ) { - return ext::concat ( "execute automaton::generate::RandomTreeAutomatonFactory (size_t)", rand ( ) % RAND_STATES + 1, " (size_t)", rand ( ) % RAND_ALPHABET + 1, " (size_t)", rand ( ) % RAND_RANK, " (bool)true (double)\"", RAND_DENSITY, "\"" ); + return ext::concat ( "execute automaton::generate::RandomTreeAutomatonFactory (size_t)", rand ( ) % RAND_STATES + 1, " <(alphabet::generate::AsFullRankedAlphabet <(alphabet::generate::GenerateAlphabet (size_t)", rand ( ) % RAND_ALPHABET + 1, " true true)" " (size_t)", rand ( ) % RAND_RANK, ") (double)\"", RAND_DENSITY, "\"" ); } TEST_CASE ( "FTA-RTE conversions test", "[integration]" ) { -- GitLab