From 9cd08197ed84ec72dacb528cad16e77170913410 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Sat, 12 Oct 2019 20:52:35 +0200
Subject: [PATCH] construction algos for some AAG automata

---
 .../generate/NumberModuloAutomaton.cpp        | 59 +++++++++++
 .../generate/NumberModuloAutomaton.h          | 52 ++++++++++
 .../generate/NumberOfSymbolsAutomaton.cpp     | 65 ++++++++++++
 .../generate/NumberOfSymbolsAutomaton.h       | 98 +++++++++++++++++++
 4 files changed, 274 insertions(+)
 create mode 100644 alib2algo/src/automaton/generate/NumberModuloAutomaton.cpp
 create mode 100644 alib2algo/src/automaton/generate/NumberModuloAutomaton.h
 create mode 100644 alib2algo/src/automaton/generate/NumberOfSymbolsAutomaton.cpp
 create mode 100644 alib2algo/src/automaton/generate/NumberOfSymbolsAutomaton.h

diff --git a/alib2algo/src/automaton/generate/NumberModuloAutomaton.cpp b/alib2algo/src/automaton/generate/NumberModuloAutomaton.cpp
new file mode 100644
index 0000000000..d909be6110
--- /dev/null
+++ b/alib2algo/src/automaton/generate/NumberModuloAutomaton.cpp
@@ -0,0 +1,59 @@
+/*
+ * NumberModuloAutomaton.cpp
+ *
+ *  Created on: 9. 2. 2017
+ *	  Author: Jan Travnicek
+ */
+
+#include "NumberModuloAutomaton.h"
+#include <exception/CommonException.h>
+#include <registration/AlgoRegistration.hpp>
+
+namespace automaton::generate {
+
+automaton::DFA < std::string, unsigned > NumberModuloAutomaton::generate ( unsigned base, unsigned modulo, unsigned result_modulo ) {
+	if ( modulo == 0 )
+		throw exception::CommonException ( "Modulo is zero." );
+
+	if ( base > 36 )
+		throw exception::CommonException ( "Number base " + ext::to_string ( base ) + " not handled." );
+
+	if ( result_modulo >= modulo )
+		throw exception::CommonException ( "Result modulo bigger than modulo limit." );
+
+	std::vector < std::string > base_map;
+	for ( unsigned i = 0; i < std::min ( 10u, base ); ++ i )
+		base_map.push_back ( ext::to_string ( i ) );
+
+	for ( unsigned i = 10; i < base; ++ i )
+		base_map.push_back ( std::string ( 'A' + i, 1 ) );
+
+	automaton::DFA < std::string, unsigned > res ( 0 );
+
+	for ( const std::string & input : base_map )
+		res.addInputSymbol ( input );
+
+	for ( unsigned modulo_state = 0; modulo_state < modulo; ++ modulo_state )
+		res.addState ( modulo_state );
+
+	for ( unsigned modulo_state = 0; modulo_state < modulo; ++ modulo_state )
+		for ( unsigned input = 0; input < base; ++ input )
+			res.addTransition ( modulo_state, base_map.at ( input ), ( modulo_state * base + input ) % modulo );
+
+	res.addFinalState ( result_modulo );
+
+	return res;
+}
+
+} /* automaton::generate */
+
+namespace {
+
+auto NumberModuloAutomatonDFA = registration::AbstractRegister < automaton::generate::NumberModuloAutomaton, automaton::DFA < std::string, unsigned >, unsigned, unsigned, unsigned > ( automaton::generate::NumberModuloAutomaton::generate, "base", "modulo", "result_modulo" ).setDocumentation (
+"Generates an automaton recognising numbers in given base that have modulo equal to a concrete value.\n\
+\n\
+@param base the base of read number\n\
+@param modulo the requested modulo\n\
+@param result_modulo the final modulo" );
+
+} /* namespace */
diff --git a/alib2algo/src/automaton/generate/NumberModuloAutomaton.h b/alib2algo/src/automaton/generate/NumberModuloAutomaton.h
new file mode 100644
index 0000000000..0bb8140208
--- /dev/null
+++ b/alib2algo/src/automaton/generate/NumberModuloAutomaton.h
@@ -0,0 +1,52 @@
+/*
+ * NumberModuloAutomaton.h
+ *
+ * This file is part of Algorithms library toolkit.
+ * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz)
+
+ * Algorithms library toolkit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * Algorithms library toolkit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with Algorithms library toolkit.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Created on: 9. 2. 2017
+ *	  Author: Jan Travnicek
+ */
+
+#ifndef NUMBER_MODULO_AUTOMATON_H_
+#define NUMBER_MODULO_AUTOMATON_H_
+
+#include <automaton/FSM/DFA.h>
+
+namespace automaton {
+
+namespace generate {
+
+/**
+ * Algorithm to generate an automaton recognising numbers in given base that have modulo equal to a concrete value.
+ */
+class NumberModuloAutomaton {
+public:
+	/**
+	 * Generates an automaton recognising numbers in given base that have modulo equal to a concrete value.
+	 *
+	 * @param base the base of read number
+	 * @param modulo the requested modulo
+	 * @param result_modulo the final modulo
+	 */
+	static automaton::DFA < std::string, unsigned > generate ( unsigned base, unsigned modulo, unsigned result_modulo );
+};
+
+} /* namespace generate */
+
+} /* namespace automaton */
+
+#endif /* NUMBER_MODULO_AUTOMATON_H_ */
diff --git a/alib2algo/src/automaton/generate/NumberOfSymbolsAutomaton.cpp b/alib2algo/src/automaton/generate/NumberOfSymbolsAutomaton.cpp
new file mode 100644
index 0000000000..a2d28f0b54
--- /dev/null
+++ b/alib2algo/src/automaton/generate/NumberOfSymbolsAutomaton.cpp
@@ -0,0 +1,65 @@
+/*
+ * NumberOfSymbolsAutomaton.cpp
+ *
+ *  Created on: 27. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "NumberOfSymbolsAutomaton.h"
+#include <registration/AlgoRegistration.hpp>
+
+#include <alib/deque>
+#include <alib/algorithm>
+#include <alib/random>
+
+namespace automaton::generate {
+
+automaton::NFA < std::string, unsigned > NumberOfSymbolsAutomaton::generateNFA ( size_t modulo, size_t alphabetSize, bool randomizedAlphabet, char symbol, size_t final_modulo ) {
+	if ( alphabetSize > 26 )
+		throw exception::CommonException("Too big alphabet.");
+
+	if ( alphabetSize < 1 )
+		throw exception::CommonException("Too small alphabet.");
+
+	if ( symbol < 'a' || symbol > 'z' )
+		throw exception::CommonException("Invalid symbol " + ext::to_string ( symbol ) + ".");
+
+	ext::deque < std::string > alphabet;
+	alphabet.push_back ( std::string ( 1, symbol ) );
+
+	for ( char i = 'a'; i <= 'z'; ++ i )
+		if ( i != symbol )
+			alphabet.push_back ( std::string ( 1, i ) );
+
+	if ( randomizedAlphabet )
+		shuffle ( std::next ( alphabet.begin ( ) ), alphabet.end ( ), ext::random_devices::semirandom );
+
+	alphabet.resize ( alphabetSize );
+
+	return automaton::generate::NumberOfSymbolsAutomaton::generateNFA ( modulo, ext::set < std::string > ( alphabet.begin ( ), alphabet.end ( ) ), std::string ( 1, symbol ), final_modulo );
+}
+
+} /* namespace automaton::generate */
+
+namespace {
+
+auto GenerateNFA1 = registration::AbstractRegister < automaton::generate::NumberOfSymbolsAutomaton, automaton::NFA < DefaultSymbolType, unsigned >, size_t, const ext::set < DefaultSymbolType > &, DefaultSymbolType, size_t > ( automaton::generate::NumberOfSymbolsAutomaton::generateNFA, abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT, "modulo", "alphabet", "symbol", "final_modulo" ).setDocumentation (
+"Generates automaton accepting strings over alphabet where the number of symbol given by @p symbol is modulo @p modulo equal to @p final_modulo.\n\
+\n\
+@param modulo number of symbols to modulo by\n\
+@param alphabet Input alphabet of the automaton\n\
+@param symbol the counted symbol\n\
+@param final_modulo number of symbols to recognise mod modulo\n\
+@return random nondeterministic finite automaton" );
+
+auto GenerateNFA2 = registration::AbstractRegister < automaton::generate::NumberOfSymbolsAutomaton, automaton::NFA < std::string, unsigned >, size_t, size_t, bool, char, size_t > ( automaton::generate::NumberOfSymbolsAutomaton::generateNFA, abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT, "statesCount", "alphabetSize", "randomizedAlphabet", "symbol", "final_modulo" ).setDocumentation (
+"Generates automaton accepting strings over alphabet where the number of symbol given by @p symbol is modulo @p modulo equal to @p final_modulo.\n\
+\n\
+@param modulo number of symbols to modulo by\n\
+@param alphabetSize size of the alphabet (1-26)\n\
+@param randomizedAlphabet selects random symbols from a-z range if true\n\
+@param symbol the counted symbol\n\
+@param final_modulo number of symbols to recognise mod modulo\n\
+@return random nondeterministic finite automaton" );
+
+} /* namespace */
diff --git a/alib2algo/src/automaton/generate/NumberOfSymbolsAutomaton.h b/alib2algo/src/automaton/generate/NumberOfSymbolsAutomaton.h
new file mode 100644
index 0000000000..23c0c95f78
--- /dev/null
+++ b/alib2algo/src/automaton/generate/NumberOfSymbolsAutomaton.h
@@ -0,0 +1,98 @@
+/*
+ * NumberOfSymbolsAutomaton.h
+ *
+ * This file is part of Algorithms library toolkit.
+ * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz)
+
+ * Algorithms library toolkit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * Algorithms library toolkit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with Algorithms library toolkit.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Created on: 27. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef RANDOM_AUTOMATON_FACTORY_H_
+#define RANDOM_AUTOMATON_FACTORY_H_
+
+#include <alib/set>
+#include <alib/string>
+
+#include <exception/CommonException.h>
+
+#include <automaton/FSM/NFA.h>
+
+namespace automaton::generate {
+
+/**
+ * Algorithm NFA accepting strings with given number of symbols A modulo N.
+ */
+class NumberOfSymbolsAutomaton {
+public:
+	/**
+	 * Generates automaton accepting strings over alphabet where the number of symbol given by @p symbol is modulo @p modulo equal to @p final_modulo.
+	 * @tparam SymbolType the type of terminal symbols of the random automaton
+	 *
+	 * @param modulo number of symbols to modulo by
+	 * @param alphabet Input alphabet of the automaton
+	 * @param symbol the counted symbol
+	 * @param final_modulo number of symbols to recognise mod modulo
+	 *
+	 * @return nondeterministic finite automaton
+	 */
+	template < class SymbolType >
+	static automaton::NFA < SymbolType, unsigned > generateNFA ( size_t modulo, const ext::set < SymbolType > & alphabet, SymbolType symbol, size_t final_modulo );
+
+	/**
+	 * \overload
+	 *
+	 * Generates automaton accepting strings over alphabet where the number of symbol given by @p symbol is modulo @p modulo equal to @p final_modulo.
+	 *
+	 * @param modulo number of symbols to modulo by
+	 * @param alphabetSize size of the alphabet (1-26)
+	 * @param randomizedAlphabet selects random symbols from a-z range if true
+	 * @param symbol the counted symbol
+	 * @param final_modulo number of symbols to recognise mod modulo
+	 *
+	 * @return nondeterministic finite automaton
+	 */
+	static automaton::NFA < std::string, unsigned > generateNFA ( size_t modulo, size_t alphabetSize, bool randomizedAlphabet, char symbol, size_t final_modulo );
+};
+
+template < class SymbolType >
+automaton::NFA < SymbolType, unsigned > NumberOfSymbolsAutomaton::generateNFA ( size_t modulo, const ext::set < SymbolType > & alphabet, SymbolType symbol, size_t final_modulo ) {
+	if ( ! alphabet.contains ( symbol ) )
+		throw exception::CommonException ( "Symbol is not in the alphabet." );
+
+	automaton::NFA < SymbolType, unsigned > automaton ( 0 );
+
+	automaton.setInputAlphabet ( alphabet );
+
+	for ( size_t i = 1; i < modulo; ++ i )
+		automaton.addState ( i );
+
+	for ( size_t i = 0; i < modulo; ++ i )
+		automaton.addTransition ( i, symbol, ( i + 1 ) % modulo );
+
+	for ( size_t i = 0; i < modulo; ++ i )
+		for ( const SymbolType & alphabet_symbol : alphabet )
+			if ( alphabet_symbol != symbol )
+				automaton.addTransition ( i, alphabet_symbol, i );
+
+	automaton.addFinalState ( final_modulo );
+
+	return automaton;
+}
+
+} /* namespace automaton::generate */
+
+#endif /* RANDOM_AUTOMATON_FACTORY_H_ */
-- 
GitLab