diff --git a/alib2algo/src/automaton/properties/DistinguishableStates.cpp b/alib2algo/src/automaton/properties/DistinguishableStates.cpp index 7997a70f39105f3be90faf56c19067f97a831b70..21e96d86d3d83302de0c71bffbe4855eac9e6467 100644 --- a/alib2algo/src/automaton/properties/DistinguishableStates.cpp +++ b/alib2algo/src/automaton/properties/DistinguishableStates.cpp @@ -12,12 +12,18 @@ namespace automaton { namespace properties { -auto DistinguishableStatesDFA = registration::AbstractRegister < DistinguishableStates, ext::set < ext::pair < DefaultStateType, DefaultStateType > >, const automaton::DFA < > & > ( DistinguishableStates::distinguishableStates, "fsm" ).setDocumentation ( +auto DistinguishableStatesDFA = registration::AbstractRegister < DistinguishableStates, ext::set < ext::pair < DefaultStateType, DefaultStateType > >, const automaton::DFA < > & > ( DistinguishableStates::distinguishable, "fsm" ).setDocumentation ( "Computes the pairs of distinguishable states in given DFA.\n\ \n\ @param dfa finite automaton.\n\ @return set of pairs of distinguishable states" ); +auto DistinguishableStatesDFTA = registration::AbstractRegister < DistinguishableStates, ext::set < ext::pair < DefaultStateType, DefaultStateType > >, const automaton::DFTA < > & > ( DistinguishableStates::distinguishable, "fta" ).setDocumentation ( +"Computes the pairs of distinguishable states in given DFTA.\n\ +\n\ +@param dfta finite tree automaton.\n\ +@return set of pairs of distinguishable states" ); + } /* namespace properties */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/properties/DistinguishableStates.h b/alib2algo/src/automaton/properties/DistinguishableStates.h index 09ff344be96b58216759a7750f276f02817b2ff6..49512684ec839fc239dc471825219fa7a45354cc 100644 --- a/alib2algo/src/automaton/properties/DistinguishableStates.h +++ b/alib2algo/src/automaton/properties/DistinguishableStates.h @@ -28,6 +28,7 @@ #include <alib/map> #include <automaton/FSM/DFA.h> +#include <automaton/TA/DFTA.h> namespace automaton { @@ -38,6 +39,22 @@ namespace properties { * Implements table-filling algorithm, Hopcroft 2nd edition, 4.4.1 */ class DistinguishableStates { + template < class StateType > + static ext::set < ext::pair < StateType, StateType > > initial ( const ext::set < StateType > & states, const ext::set < StateType > & finals ) { + ext::set < ext::pair < StateType, StateType > > init; + + for ( const StateType & a : states ) { + for ( const StateType & b : states ) { + if ( finals.count ( a ) != finals.count ( b ) ) { + init.insert ( ext::make_pair ( a, b ) ); + init.insert ( ext::make_pair ( b, a ) ); + } + } + } + + return init; + } + public: /** * Find all distinguishable pairs of states of DFA. @@ -48,21 +65,15 @@ public: * @return set of pairs of distinguishable states of @p fsm */ template < class SymbolType, class StateType > - static ext::set < ext::pair < StateType, StateType > > distinguishableStates ( const automaton::DFA < SymbolType, StateType > & fsm ); + static ext::set < ext::pair < StateType, StateType > > distinguishable ( const automaton::DFA < SymbolType, StateType > & fsm ); + + template < class SymbolType, class RankType, class StateType > + static ext::set < ext::pair < StateType, StateType > > distinguishable ( const automaton::DFTA < SymbolType, RankType, StateType > & fta ); }; template < class SymbolType, class StateType > -ext::set < ext::pair < StateType, StateType > > DistinguishableStates::distinguishableStates ( const automaton::DFA < SymbolType, StateType > & fsm ) { - ext::set < ext::pair < StateType, StateType > > distinguishable; - - for ( const StateType & a : fsm.getStates ( ) ) { - for ( const StateType & b : fsm.getStates ( ) ) { - if ( ( fsm.getFinalStates ( ).count ( a ) == 0 ) ^ ( fsm.getFinalStates ( ).count ( b ) == 0 ) ) { - distinguishable.insert ( ext::make_pair ( a, b ) ); - distinguishable.insert ( ext::make_pair ( b, a ) ); - } - } - } +ext::set < ext::pair < StateType, StateType > > DistinguishableStates::distinguishable ( const automaton::DFA < SymbolType, StateType > & fsm ) { + ext::set < ext::pair < StateType, StateType > > distinguishable = initial ( fsm.getStates ( ), fsm.getFinalStates ( ) ); bool changed; do { @@ -70,6 +81,9 @@ ext::set < ext::pair < StateType, StateType > > DistinguishableStates::distingui for ( const StateType & a : fsm.getStates ( ) ) { for ( const StateType & b : fsm.getStates ( ) ) { + if ( distinguishable.count ( ext::make_pair ( a, b ) ) ) // we have not yet found this + continue; + for ( const SymbolType & symb : fsm.getInputAlphabet ( ) ) { auto trA = fsm.getTransitions ( ).find ( ext::make_pair ( a, symb ) ); auto trB = fsm.getTransitions ( ).find ( ext::make_pair ( b, symb ) ); @@ -79,11 +93,9 @@ ext::set < ext::pair < StateType, StateType > > DistinguishableStates::distingui } else if ( trA == fsm.getTransitions ( ).end ( ) || trB == fsm.getTransitions ( ).end ( ) || distinguishable.count ( ext::make_pair ( trA -> second, trB -> second ) ) ) { // end up in dead state - dead state is be distinguishable from every other state OR // end up in distinguishable states - if ( ! distinguishable.count ( ext::make_pair ( a, b ) ) ) { // we have not yet found this - distinguishable.insert ( ext::make_pair ( a, b ) ); - distinguishable.insert ( ext::make_pair ( b, a ) ); - changed = true; - } + distinguishable.insert ( ext::make_pair ( a, b ) ); + distinguishable.insert ( ext::make_pair ( b, a ) ); + changed = true; } } } @@ -94,6 +106,45 @@ ext::set < ext::pair < StateType, StateType > > DistinguishableStates::distingui return distinguishable; } +template < class SymbolType, class RankType, class StateType > +ext::set < ext::pair < StateType, StateType > > DistinguishableStates::distinguishable ( const automaton::DFTA < SymbolType, RankType, StateType > & fta ) { + ext::set < ext::pair < StateType, StateType > > distinguishable = initial ( fta.getStates ( ), fta.getFinalStates ( ) ); + + do { + ext::set < ext::pair < StateType, StateType > > distinguishable2 = distinguishable; + + for ( const StateType & a : fta.getStates ( ) ) { + for ( const StateType & b : fta.getStates ( ) ) { + if ( distinguishable.count ( ext::make_pair ( a, b ) ) ) + continue; + + for ( const std::pair < ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, StateType > & transition : fta.getTransitions ( ) ) { + for ( size_t i = 0; i < transition.first.second.size ( ); ++ i ) { + if ( transition.first.second [ i ] == a ) { + ext::vector < StateType > copy = transition.first.second; + copy [ i ] = b; + + const auto & transition2 = fta.getTransitions ( ).find ( std::make_pair ( transition.first.first, std::move ( copy ) ) ); + + if ( transition2 == fta.getTransitions ( ).end ( ) || distinguishable2.count ( ext::make_pair ( transition.second, transition2->second ) ) ) { + // end up in dead state - dead state is be distinguishable from every other state OR + // end up in distinguishable states + distinguishable.insert ( ext::make_pair ( a, b ) ); + distinguishable.insert ( ext::make_pair ( b, a ) ); + } + } + } + } + } + } + if ( distinguishable == distinguishable2 ) + break; + + } while ( true ); + + return distinguishable; +} + } /* namespace properties */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/properties/UndistinguishableStates.cpp b/alib2algo/src/automaton/properties/UndistinguishableStates.cpp index bff0d7afa0d65e977fe7a8bfa5da2ba030c01314..3a49e74a64294f2b6481475dbeb49caf7e39adda 100644 --- a/alib2algo/src/automaton/properties/UndistinguishableStates.cpp +++ b/alib2algo/src/automaton/properties/UndistinguishableStates.cpp @@ -18,6 +18,12 @@ auto UndistinguishableStatesDFA = registration::AbstractRegister < Undistinguish @param dfa finite automaton.\n\ @return set of blocks of undistinguishable states" ); +auto UndistinguishableStatesDFTA = registration::AbstractRegister < UndistinguishableStates, ext::set < ext::set < DefaultStateType > >, const automaton::DFTA < > & > ( UndistinguishableStates::undistinguishable, "fta" ).setDocumentation ( +"Computes the partitions of undistinguishable states states in given DFTA.\n\ +\n\ +@param dfta finite tree automaton.\n\ +@return set of blocks of undistinguishable states" ); + } /* namespace properties */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/properties/UndistinguishableStates.h b/alib2algo/src/automaton/properties/UndistinguishableStates.h index dcff4145ae668c2f5058df78083d31ec0b979ff0..75fe11d8c8a399a0f95d96f3f866dc9802727b03 100644 --- a/alib2algo/src/automaton/properties/UndistinguishableStates.h +++ b/alib2algo/src/automaton/properties/UndistinguishableStates.h @@ -28,6 +28,7 @@ #include <alib/map> #include <automaton/FSM/DFA.h> +#include <automaton/TA/DFTA.h> #include <automaton/properties/DistinguishableStates.h> @@ -41,39 +42,126 @@ namespace properties { * @sa DistinguishableStates */ class UndistinguishableStates { + template < class StateType > + static ext::set < ext::set < StateType > > convertUndistinguishable ( const ext::set < ext::pair < StateType, StateType > > & undistinguishable, const ext::set < StateType > & states ) { + ext::set < ext::set < StateType > > res; + for ( const StateType & state : states ) { + ext::set < StateType > partition; + + for ( const StateType & other : states ) + if ( undistinguishable.count ( ext::make_pair ( state, other ) ) != 0 ) + partition.insert ( other ); + + res.insert ( partition ); + } + return res; + } + + template < class StateType > + static ext::set < ext::pair < StateType, StateType > > initial ( const ext::set < StateType > & states, const ext::set < StateType > & finals ) { + ext::set < ext::pair < StateType, StateType > > init; + + for ( const StateType & a : states ) { + for ( const StateType & b : states ) { + if ( finals.count ( a ) == finals.count ( b ) ) { + init.insert ( ext::make_pair ( a, b ) ); + init.insert ( ext::make_pair ( b, a ) ); + } + } + } + + return init; + } + public: /** - * Creates state partitioning of undistinguishable states using DistinguishableStates algorithm + * Creates state partitioning of undistinguishable states. * * @tparam SymbolType Type for input symbols. * @tparam StateType Type for states. * @param dfa automaton which states are to be partitioned * - * @sa DistinguishableStates - * * @return state partitioning of undistinguishable states */ - template < class SymbolType, class StateType > - static ext::set < ext::set < StateType > > undistinguishable ( const automaton::DFA < SymbolType, StateType > & fsm ); + static ext::set < ext::set < StateType > > undistinguishable ( const automaton::DFA < SymbolType, StateType > & dft ); + + /** + * Creates state partitioning of undistinguishable states- + * + * @tparam SymbolType Type for input symbols. + * @tparam RankType Type of ranks of input symbols. + * @tparam StateType Type for states. + * @param dfta automaton which states are to be partitioned + * + * @return state partitioning of undistinguishable states + */ + template < class SymbolType, class RankType, class StateType > + static ext::set < ext::set < StateType > > undistinguishable ( const automaton::DFTA < SymbolType, RankType, StateType > & fta ); }; template < class SymbolType, class StateType > -ext::set < ext::set < StateType > > UndistinguishableStates::undistinguishable ( const automaton::DFA < SymbolType, StateType > & fsm ) { - const ext::set < ext::pair < StateType, StateType > > distinguishable = automaton::properties::DistinguishableStates::distinguishableStates ( fsm ); - ext::set < ext::set < StateType > > res; +ext::set < ext::set < StateType > > UndistinguishableStates::undistinguishable ( const automaton::DFA < SymbolType, StateType > & dfa ) { + ext::set < ext::pair < StateType, StateType > > undistinguishable = initial ( dfa.getStates ( ), dfa.getFinalStates ( ) ); - for ( const StateType & state : fsm.getStates ( ) ) { - ext::set < StateType > partition; + do { + ext::set < ext::pair < StateType, StateType > > undistinguishable2 = undistinguishable; - for ( const StateType & other : fsm.getStates ( ) ) - if ( distinguishable.count ( ext::make_pair ( state, other ) ) == 0 ) - partition.insert ( other ); + for ( const ext::pair < StateType, StateType > & iter : undistinguishable2 ) { + for ( const std::pair < ext::pair < StateType, SymbolType >, StateType > & transition : dfa.getTransitions ( ) ) { + if ( transition.first.first == iter . first ) { - res.insert ( partition ); - } + const auto & transition2 = dfa.getTransitions ( ).find ( std::make_pair ( iter.second, transition.first.second ) ); + + if ( transition2 == dfa.getTransitions ( ).end ( ) || ! undistinguishable2.count ( ext::make_pair ( transition.second, transition2->second ) ) ) { + // end up in dead state - dead state is be distinguishable from every other state OR + // end up in distinguishable states + undistinguishable.erase ( ext::make_pair ( iter.first, iter.second ) ); + undistinguishable.erase ( ext::make_pair ( iter.second, iter.first ) ); + } + } + } + } + if ( undistinguishable == undistinguishable2 ) + break; + + } while ( true ); + + return convertUndistinguishable ( undistinguishable, dfa.getStates ( ) ); +} - return res; +template < class SymbolType, class RankType, class StateType > +ext::set < ext::set < StateType > > UndistinguishableStates::undistinguishable ( const automaton::DFTA < SymbolType, RankType, StateType > & fta ) { + ext::set < ext::pair < StateType, StateType > > undistinguishable = initial ( fta.getStates ( ), fta.getFinalStates ( ) ); + + do { + ext::set < ext::pair < StateType, StateType > > undistinguishable2 = undistinguishable; + + for ( const ext::pair < StateType, StateType > & iter : undistinguishable2 ) { + for ( const std::pair < ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, StateType > & transition : fta.getTransitions ( ) ) { + for ( size_t i = 0; i < transition.first.second.size ( ); ++ i ) { + if ( transition.first.second [ i ] == iter . first ) { + ext::vector < StateType > copy = transition.first.second; + copy [ i ] = iter.second; + + const auto & transition2 = fta.getTransitions ( ).find ( std::make_pair ( transition.first.first, std::move ( copy ) ) ); + + if ( transition2 == fta.getTransitions ( ).end ( ) || ! undistinguishable2.count ( ext::make_pair ( transition.second, transition2->second ) ) ) { + // end up in dead state - dead state is be distinguishable from every other state OR + // end up in distinguishable states + undistinguishable.erase ( ext::make_pair ( iter.first, iter.second ) ); + undistinguishable.erase ( ext::make_pair ( iter.second, iter.first ) ); + } + } + } + } + } + if ( undistinguishable == undistinguishable2 ) + break; + + } while ( true ); + + return convertUndistinguishable ( undistinguishable, fta.getStates ( ) ); } } /* namespace properties */ diff --git a/alib2algo/src/automaton/properties/UndistinguishableStates2.cpp b/alib2algo/src/automaton/properties/UndistinguishableStates2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e13fa4428230032d6263ec0ddf1003ac36c67cb2 --- /dev/null +++ b/alib2algo/src/automaton/properties/UndistinguishableStates2.cpp @@ -0,0 +1,30 @@ +/* +* UndistinguishableStates2.cpp + * + * Created on: 27. 3. 2019 + * Author: Tomas Pecka + */ + +#include "UndistinguishableStates2.h" +#include <registration/AlgoRegistration.hpp> + +namespace automaton { + +namespace properties { + +auto UndistinguishableStates2DFA = registration::AbstractRegister < UndistinguishableStates2, ext::set < ext::set < DefaultStateType > >, const automaton::DFA < > & > ( UndistinguishableStates2::undistinguishable, "fsm" ).setDocumentation ( +"Computes the partitions of undistinguishable states states in given DFA.\n\ +\n\ +@param dfa finite automaton.\n\ +@return set of blocks of undistinguishable states" ); + +auto UndistinguishableStates2DFTA = registration::AbstractRegister < UndistinguishableStates2, ext::set < ext::set < DefaultStateType > >, const automaton::DFTA < > & > ( UndistinguishableStates2::undistinguishable, "fta" ).setDocumentation ( +"Computes the partitions of undistinguishable states states in given DFTA.\n\ +\n\ +@param dfta finite tree automaton.\n\ +@return set of blocks of undistinguishable states" ); + +} /* namespace properties */ + +} /* namespace automaton */ + diff --git a/alib2algo/src/automaton/properties/UndistinguishableStates2.h b/alib2algo/src/automaton/properties/UndistinguishableStates2.h new file mode 100644 index 0000000000000000000000000000000000000000..7775afe1eb79f67781234ab8faa2346f8f93bc99 --- /dev/null +++ b/alib2algo/src/automaton/properties/UndistinguishableStates2.h @@ -0,0 +1,84 @@ +/* + * UndistinguishableStates2.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. 2019 + * Author: Tomas Pecka + */ + +#ifndef DISTINGUISHABLE_STATES_PARTITIONING_H_ +#define DISTINGUISHABLE_STATES_PARTITIONING_H_ + +#include <alib/set> +#include <alib/map> + +#include <automaton/FSM/DFA.h> +#include <automaton/TA/DFTA.h> + +#include <automaton/properties/DistinguishableStates.h> + +namespace automaton { + +namespace properties { + +/** + * Partition undistinguishable states in automata + * + * @sa DistinguishableStates + */ +class UndistinguishableStates2 { +public: + /** + * Creates state partitioning of undistinguishable states using DistinguishableStates algorithm + * + * @tparam T Type of the parameter automaton. + * @param dfta automaton which states are to be partitioned + * + * @sa DistinguishableStates + * + * @return state partitioning of undistinguishable states + */ + template < class T > + static ext::set < ext::set < typename T::StateType > > undistinguishable ( const T & fsm ); +}; + +template < class T > +ext::set < ext::set < typename T::StateType > > UndistinguishableStates2::undistinguishable ( const T & fsm ) { + using StateType = typename T::StateType; + + const ext::set < ext::pair < StateType, StateType > > distinguishable = automaton::properties::DistinguishableStates::distinguishable ( fsm ); + ext::set < ext::set < StateType > > res; + + for ( const StateType & state : fsm.getStates ( ) ) { + ext::set < StateType > partition; + + for ( const StateType & other : fsm.getStates ( ) ) + if ( distinguishable.count ( ext::make_pair ( state, other ) ) == 0 ) + partition.insert ( other ); + + res.insert ( partition ); + } + + return res; +} + +} /* namespace properties */ + +} /* namespace automaton */ + +#endif /* DISTINGUISHABLE_STATES_H_ */ diff --git a/alib2algo/test-src/automaton/properties/DistinguishableStatesTest.cpp b/alib2algo/test-src/automaton/properties/DistinguishableStatesTest.cpp index 9d241c5e434b76073164f1ae4d2e1d2bdcf29c25..c32442ede6489463b29d5a47e7faac0ee19d181b 100644 --- a/alib2algo/test-src/automaton/properties/DistinguishableStatesTest.cpp +++ b/alib2algo/test-src/automaton/properties/DistinguishableStatesTest.cpp @@ -39,7 +39,7 @@ TEST_CASE ( "Distringuishable States Test", "[unit][algo][automaton]" ) { automaton.addTransition(qH, DefaultSymbolType ( 1 ), qC); ext::set < ext::pair < DefaultStateType, DefaultStateType > > exp; - const ext::set < ext::pair < DefaultStateType, DefaultStateType > > res = automaton::properties::DistinguishableStates::distinguishableStates ( automaton ); + const ext::set < ext::pair < DefaultStateType, DefaultStateType > > res = automaton::properties::DistinguishableStates::distinguishable ( automaton ); const ext::set < ext::pair < DefaultStateType, DefaultStateType > > exp_ ( { ext::make_pair ( qA, qB ), ext::make_pair ( qA, qC ), ext::make_pair ( qA, qD ), ext::make_pair ( qA, qF ), ext::make_pair ( qA, qG ), ext::make_pair ( qA, qH ), ext::make_pair ( qB, qC ), ext::make_pair ( qB, qD ), ext::make_pair ( qB, qE ), ext::make_pair ( qB, qF ), ext::make_pair ( qB, qG ), @@ -77,7 +77,7 @@ TEST_CASE ( "Distringuishable States Test", "[unit][algo][automaton]" ) { automaton.addTransition(qE, DefaultSymbolType ( 0 ), qF); ext::set < ext::pair < DefaultStateType, DefaultStateType > > exp; - const ext::set < ext::pair < DefaultStateType, DefaultStateType > > res = automaton::properties::DistinguishableStates::distinguishableStates ( automaton ); + const ext::set < ext::pair < DefaultStateType, DefaultStateType > > res = automaton::properties::DistinguishableStates::distinguishable ( automaton ); const ext::set < ext::pair < DefaultStateType, DefaultStateType > > exp_ ( { ext::make_pair ( qA, qB ), ext::make_pair ( qA, qC ), ext::make_pair ( qA, qD ), ext::make_pair ( qA, qE ), ext::make_pair ( qA, qF ), ext::make_pair ( qB, qC ), ext::make_pair ( qB, qD ), ext::make_pair ( qB, qF ), diff --git a/alib2common/src/PrimitiveRegistrator.cpp b/alib2common/src/PrimitiveRegistrator.cpp index 1ad32cb673ce8fa0900bfa1145311da7d2074e35..5f17732b71e1665da8a8b4f22ada7d7b2aa4baf4 100644 --- a/alib2common/src/PrimitiveRegistrator.cpp +++ b/alib2common/src/PrimitiveRegistrator.cpp @@ -68,6 +68,8 @@ public: abstraction::ValuePrinterRegistry::registerValuePrinter < object::Object > ( ); abstraction::ValuePrinterRegistry::registerValuePrinter < ext::set < object::Object > > ( ); + abstraction::ValuePrinterRegistry::registerValuePrinter < ext::set < ext::pair < object::Object, object::Object > > > ( ); + abstraction::ValuePrinterRegistry::registerValuePrinter < ext::set < ext::set < object::Object > > > ( ); abstraction::ValuePrinterRegistry::registerValuePrinter < ext::trie < object::Object, bool > > ( ); abstraction::ValuePrinterRegistry::registerValuePrinter < ext::set < unsigned > > ( ); @@ -123,6 +125,8 @@ public: abstraction::ValuePrinterRegistry::unregisterValuePrinter < object::Object > ( ); abstraction::ValuePrinterRegistry::unregisterValuePrinter < ext::set < object::Object > > ( ); + abstraction::ValuePrinterRegistry::unregisterValuePrinter < ext::set < ext::pair < object::Object, object::Object > > > ( ); + abstraction::ValuePrinterRegistry::unregisterValuePrinter < ext::set < ext::set < object::Object > > > ( ); abstraction::ValuePrinterRegistry::unregisterValuePrinter < ext::trie < object::Object, bool > > ( ); abstraction::ValuePrinterRegistry::unregisterValuePrinter < ext::set < unsigned > > ( );