diff --git a/alib2algo/src/automaton/simplify/MinimizeBrzozowski.cpp b/alib2algo/src/automaton/simplify/MinimizeBrzozowski.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e6352dee80f445ea6609ee03bf5965ed6c6c3f15 --- /dev/null +++ b/alib2algo/src/automaton/simplify/MinimizeBrzozowski.cpp @@ -0,0 +1,67 @@ +/* + * MinimizeBrzozowski.cpp + * + * Created on: 18. 11. 2014 + * Author: Tomas Pecka + */ + +#include "MinimizeBrzozowski.h" + +#include <exception/AlibException.h> +#include <automaton/Automaton.h> +#include <automaton/FSM/MultiInitialStateNFA.h> + +#include "../transform/ReverseFSM.h" +#include "../determinize/Determinize.h" + +namespace automaton { + +namespace simplify { + +automaton::Automaton MinimizeBrzozowski::minimize(const automaton::Automaton& automaton) { + automaton::Automaton* out = NULL; + automaton.getData().Accept((void*) &out, MinimizeBrzozowski::MINIMIZE_BRZOZOWSKI); + automaton::Automaton res = std::move(*out); + delete out; + return res; +} + +automaton::DFA MinimizeBrzozowski::minimize(const automaton::DFA& dfa) { + return automaton::determinize::Determinize::determinize(automaton::transform::ReverseFSM::convert(automaton::determinize::Determinize::determinize(automaton::transform::ReverseFSM::convert(dfa)))); +} + +automaton::DFA MinimizeBrzozowski::minimize(const automaton::NFA& nfa) { + return automaton::determinize::Determinize::determinize(automaton::transform::ReverseFSM::convert(automaton::determinize::Determinize::determinize(automaton::transform::ReverseFSM::convert(nfa)))); +} + +void MinimizeBrzozowski::Visit(void*, const automaton::EpsilonNFA&) const { + throw exception::AlibException("Unsupported automaton type EpsilonNFA"); +} + +void MinimizeBrzozowski::Visit(void* data, const automaton::DFA& automaton) const { + automaton::Automaton* & out = *((automaton::Automaton**) data); + out = new automaton::Automaton(this->minimize(automaton)); +} + +void MinimizeBrzozowski::Visit(void*, const automaton::MultiInitialStateNFA&) const { + throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA"); +} + +void MinimizeBrzozowski::Visit(void* data, const automaton::NFA& automaton) const { + automaton::Automaton* & out = *((automaton::Automaton**) data); + out = new automaton::Automaton(this->minimize(automaton)); +} + +void MinimizeBrzozowski::Visit(void*, const automaton::ExtendedNFA& ) const { + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void MinimizeBrzozowski::Visit(void*, const automaton::CompactNFA& ) const { + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +const MinimizeBrzozowski MinimizeBrzozowski::MINIMIZE_BRZOZOWSKI; + +} /* namespace simplify */ + +} /* namespace automaton */ diff --git a/alib2algo/src/automaton/simplify/MinimizeBrzozowski.h b/alib2algo/src/automaton/simplify/MinimizeBrzozowski.h new file mode 100644 index 0000000000000000000000000000000000000000..c21dc2d49b4ea58cac444d820cf6535943f6c319 --- /dev/null +++ b/alib2algo/src/automaton/simplify/MinimizeBrzozowski.h @@ -0,0 +1,43 @@ +/* + * MinimizeBrzozowski.cpp + * + * Created on: 18. 11. 2014 + * Author: Tomas Pecka + */ + +#ifndef MINIMIZE_BRZOZOWSKI_H_ +#define MINIMIZE_BRZOZOWSKI_H_ + +#include <automaton/Automaton.h> +#include <automaton/FSM/DFA.h> + +namespace automaton { + +namespace simplify { + +class MinimizeBrzozowski : public automaton::VisitableConstFSMBase { +public: + /** + * @param dfa automaton to minimize + */ + static automaton::Automaton minimize(const automaton::Automaton& dfa); + + static automaton::DFA minimize(const automaton::DFA& dfa); + static automaton::DFA minimize(const automaton::NFA& nfa); + +protected: + void Visit(void*, const automaton::EpsilonNFA& automaton) const; + void Visit(void*, const automaton::MultiInitialStateNFA& automaton) const; + void Visit(void*, const automaton::NFA& automaton) const; + void Visit(void*, const automaton::DFA& automaton) const; + void Visit(void*, const automaton::ExtendedNFA& automaton) const; + void Visit(void*, const automaton::CompactNFA& automaton) const; + + static const MinimizeBrzozowski MINIMIZE_BRZOZOWSKI; +}; + +} /* namespace simplify */ + +} /* namespace automaton */ + +#endif /* MINIMIZE_BRZOZOWSKI_H_ */ diff --git a/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.cpp b/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef1daf2b4080d49f85ff999a68f7576f902d94ad --- /dev/null +++ b/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.cpp @@ -0,0 +1,38 @@ +#include <list> +#include "minimizeBrzozowskiTest.h" + +#include "automaton/simplify/MinimizeBrzozowski.h" +#include "automaton/simplify/Minimize.h" +#include "automaton/simplify/Trim.h" +#include "automaton/simplify/Normalize.h" + +#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y)) + +CPPUNIT_TEST_SUITE_REGISTRATION( minimizeBrzozowskiTest ); + +void minimizeBrzozowskiTest::setUp() { +} + +void minimizeBrzozowskiTest::tearDown() { +} + +void minimizeBrzozowskiTest::testMinimizeBrzozowski() { + automaton::DFA automaton(automaton::State(1)); + + automaton.addState(automaton::State(1)); + automaton.addState(automaton::State(2)); + automaton.addState(automaton::State(3)); + automaton.addInputSymbol(alphabet::symbolFrom("a")); + automaton.addInputSymbol(alphabet::symbolFrom("b")); + + automaton.addTransition(automaton::State(1), alphabet::symbolFrom("a"), automaton::State(2)); + automaton.addTransition(automaton::State(2), alphabet::symbolFrom("b"), automaton::State(1)); + + automaton.addFinalState(automaton::State(3)); + + automaton::DFA minimizedHopcroft = automaton::simplify::Minimize::minimize(automaton); + automaton::DFA minimizedBrzozowski = automaton::simplify::MinimizeBrzozowski::minimize(automaton); + + CPPUNIT_ASSERT(minimizedHopcroft.getStates().size() == 3); + CPPUNIT_ASSERT(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(minimizedHopcroft)) == automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(minimizedBrzozowski))); +} diff --git a/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.h b/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.h new file mode 100644 index 0000000000000000000000000000000000000000..0039075c8bd7e0694a142f36f6ee72a73709e47c --- /dev/null +++ b/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.h @@ -0,0 +1,19 @@ +#ifndef MINIMIZE_BRZOZOWSKI_TEST_H_ +#define MINIMIZE_BRZOZOWSKI_TEST_H_ + +#include <cppunit/extensions/HelperMacros.h> + +class minimizeBrzozowskiTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( minimizeBrzozowskiTest ); + CPPUNIT_TEST( testMinimizeBrzozowski ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testMinimizeBrzozowski(); +}; + +#endif // MINIMIZE_BRZOZOWSKI_TEST_H_ diff --git a/aminimize2/src/aminimize.cpp b/aminimize2/src/aminimize.cpp index 3a6c226ecf3bbdcd479255e24d5a6e8fcaf39446..bc1790abd07195fdd849470b0d96b62a1f036226 100644 --- a/aminimize2/src/aminimize.cpp +++ b/aminimize2/src/aminimize.cpp @@ -11,6 +11,7 @@ #include <factory/DataFactory.hpp> #include "automaton/simplify/Minimize.h" +#include "automaton/simplify/MinimizeBrzozowski.h" int main(int argc, char** argv) { @@ -20,6 +21,11 @@ int main(int argc, char** argv) { TCLAP::ValueArg<std::string> input( "a", "automaton", "Automaton to minimize", false, "-", "file"); cmd.add( input ); + std::vector<std::string> algorithms {"Hopcroft", "Brzozowski" }; + TCLAP::ValuesConstraint<std::string> algorithmVals( algorithms ); + TCLAP::ValueArg<std::string> algorithm( "g", "algorithm", "Use specific algorithm. Hopcroft default.", false, "Hopcroft", &algorithmVals); + cmd.add( algorithm ); + cmd.parse(argc, argv); std::list<sax::Token> tokens; @@ -33,7 +39,15 @@ int main(int argc, char** argv) { sax::SaxParseInterface::parseStdin(tokens); } - alib::DataFactory::toStdout(automaton::simplify::Minimize::minimize(alib::DataFactory::fromTokens<automaton::Automaton>(tokens))); + if(algorithm.getValue() == "Hopcroft") { + alib::DataFactory::toStdout(automaton::simplify::Minimize::minimize(alib::DataFactory::fromTokens<automaton::Automaton>(tokens))); + } + else if(algorithm.getValue() == "Brzozowski") { + alib::DataFactory::toStdout(automaton::simplify::MinimizeBrzozowski::minimize(alib::DataFactory::fromTokens<automaton::Automaton>(tokens))); + } else { + throw exception::AlibException("Unknown algorithm selected."); + } + return 0; } catch (const exception::AlibException& exception) {