Skip to content
Snippets Groups Projects
Commit 4388418d authored by Jan Trávníček's avatar Jan Trávníček
Browse files

compaction revised

parent 5700f6c3
No related branches found
No related tags found
No related merge requests found
...@@ -38,57 +38,43 @@ automaton::CompactNFA Compaction::convert(const automaton::DFA& automaton) ...@@ -38,57 +38,43 @@ automaton::CompactNFA Compaction::convert(const automaton::DFA& automaton)
automaton::CompactNFA res(automaton.getInitialState()); automaton::CompactNFA res(automaton.getInitialState());
res.setInputAlphabet(automaton.getInputAlphabet()); res.setInputAlphabet(automaton.getInputAlphabet());
   
string::LinearString path; std::set<automaton::State> visited;
path.setAlphabet(automaton.getInputAlphabet());
std::map<automaton::State, bool> visited;
for(const auto& state : automaton.getStates())
visited.insert(std::make_pair(state, automaton.getInitialState() == state));
   
std::stack<std::tuple<automaton::State, automaton::State, alphabet::Symbol>> stack; // state x lastFork x symbol we used to go to that state std::stack<std::tuple<automaton::State, automaton::State, alphabet::Symbol>> stack; // state x lastFork x symbol we used to go to that state
for(const auto& transition: automaton.getTransitionsFromState(automaton.getInitialState())) for(const auto& transition: automaton.getTransitionsFromState(automaton.getInitialState()))
{
stack.push(std::make_tuple(transition.second, automaton.getInitialState(), transition.first.second)); stack.push(std::make_tuple(transition.second, automaton.getInitialState(), transition.first.second));
}
   
if(automaton.getFinalStates().count(automaton.getInitialState()) > 0) if(automaton.getFinalStates().count(automaton.getInitialState()) > 0)
res.addFinalState(automaton.getInitialState()); res.addFinalState(automaton.getInitialState());
   
while(!stack.empty()) while(!stack.empty()) {
{ automaton::State q = std::move(std::get<0>(stack.top()));
const automaton::State q = std::get<0>(stack.top()); automaton::State lastFork = std::move(std::get<1>(stack.top()));
const automaton::State lastFork = std::get<1>(stack.top()); alphabet::Symbol symbol = std::move(std::get<2>(stack.top()));
const alphabet::Symbol symbol = std::get<2>(stack.top());
stack.pop(); stack.pop();
   
path.appendSymbol(symbol); string::LinearString path { automaton.getInputAlphabet(), { symbol } };
   
std::map<std::pair<automaton::State, alphabet::Symbol>, automaton::State> transitions;
// only 1 child and nonfinal // only 1 child and nonfinal
if(automaton.getTransitionsFromState(q).size() == 1 && automaton.getFinalStates().count(q) == 0 && automaton.getInitialState() != q) while((transitions = std::move(automaton.getTransitionsFromState(q))).size() == 1 && automaton.getFinalStates().count(q) == 0) {
{ const std::pair<std::pair<automaton::State, alphabet::Symbol>, automaton::State>& transition = * transitions.begin();
const auto& transition = * automaton.getTransitionsFromState(q).begin(); path.appendSymbol(transition.first.second);
q = transition.second;
stack.push(std::make_tuple(transition.second, lastFork, transition.first.second));
}
else // fork or final state
{
res.addState(q);
if(automaton.getFinalStates().count(q))
res.addFinalState(q);
res.addTransition(lastFork, path, q);
path.setContent({});
for(const auto& transition : automaton.getTransitionsFromState(q))
{
if(visited.find(transition.second)->second == false)
{
stack.push(std::make_tuple(transition.second, q, transition.first.second));
visited.find(transition.second)->second = true;
}
}
} }
// fork or final state
res.addState(q);
if(automaton.getFinalStates().count(q))
res.addFinalState(q);
res.addTransition(lastFork, path, q);
for(const std::pair<std::pair<automaton::State, alphabet::Symbol>, automaton::State>& transition : automaton.getTransitionsFromState(q))
if(visited.insert(transition.second).second)
stack.push(std::make_tuple(transition.second, q, transition.first.second));
} }
   
return res; return res;
......
#include <list>
#include "AutomataCompactionTest.h"
#include "automaton/transform/Compaction.h"
#include <alphabet/Symbol.h>
#include <automaton/FSM/DFA.h>
#include <automaton/FSM/CompactNFA.h>
#include <string/LinearString.h>
#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y))
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AutomataCompactionTest, "automaton" );
CPPUNIT_TEST_SUITE_REGISTRATION( AutomataCompactionTest );
void AutomataCompactionTest::setUp() {
}
void AutomataCompactionTest::tearDown() {
}
void AutomataCompactionTest::testAutomataCompaction1() {
automaton::State q0("0"), q1("1"), q2("2"), q3("3"), q4("4"), q5("5");
alphabet::Symbol a(alphabet::symbolFrom('a')), b(alphabet::symbolFrom('b'));
automaton::DFA m1(q0);
automaton::CompactNFA m2(q0);
m1.setInputAlphabet({a, b});
m1.setStates({q0, q1, q2, q3, q4, q5});
m1.addTransition(q0, a, q1);
m1.addTransition(q1, b, q2);
m1.addTransition(q2, a, q3);
m1.addTransition(q3, b, q4);
m1.addTransition(q4, a, q5);
m1.addFinalState(q5);
m2.setInputAlphabet({a, b});
m2.setStates({q0, q5});
m2.addTransition(q0, string::LinearString{ { a, b }, {a, b, a, b, a} }, q5);
m2.addFinalState(q5);
automaton::CompactNFA c1 = automaton::transform::Compaction::convert(m1);
CPPUNIT_ASSERT(c1 == m2);
}
void AutomataCompactionTest::testAutomataCompaction2() {
automaton::State q0("0"), q1("1"), q2("2"), q3("3"), q4("4"), q5("5");
alphabet::Symbol a(alphabet::symbolFrom('a')), b(alphabet::symbolFrom('b'));
automaton::DFA m1(q0);
automaton::CompactNFA m2(q0);
m1.setInputAlphabet({a, b});
m1.setStates({q0, q1, q2, q3, q4, q5});
m1.addTransition(q0, a, q1);
m1.addTransition(q1, b, q2);
m1.addTransition(q2, a, q3);
m1.addTransition(q3, b, q4);
m1.addTransition(q4, a, q5);
m1.addTransition(q5, a, q1);
m1.addFinalState(q5);
m2.setInputAlphabet({a, b});
m2.setStates({q0, q5});
m2.addTransition(q0, string::LinearString{ { a, b }, {a, b, a, b, a} }, q5);
m2.addTransition(q5, string::LinearString{ { a, b }, {a, b, a, b, a} }, q5);
m2.addFinalState(q5);
automaton::CompactNFA c1 = automaton::transform::Compaction::convert(m1);
CPPUNIT_ASSERT(c1 == m2);
}
void AutomataCompactionTest::testAutomataCompaction3() {
automaton::State q0("0"), q1("1"), q2("2"), q3("3"), q4("4"), q5("5"), q6("6");
alphabet::Symbol a(alphabet::symbolFrom('a')), b(alphabet::symbolFrom('b'));
automaton::DFA m1(q0);
automaton::CompactNFA m2(q0);
m1.setInputAlphabet({a, b});
m1.setStates({q0, q1, q2, q3, q4, q5, q6});
m1.addTransition(q0, a, q1);
m1.addTransition(q1, a, q2);
m1.addTransition(q2, a, q3);
m1.addTransition(q3, a, q4);
m1.addTransition(q4, a, q2);
m1.addTransition(q1, b, q5);
m1.addTransition(q5, b, q6);
m1.addTransition(q6, a, q0);
m1.addFinalState(q3);
m1.addFinalState(q5);
m2.setInputAlphabet({a, b});
m2.setStates({q0, q1, q3, q5});
m2.addTransition(q0, string::LinearString{ { a, b }, {a} }, q1);
m2.addTransition(q1, string::LinearString{ { a, b }, {a, a} }, q3);
m2.addTransition(q3, string::LinearString{ { a, b }, {a, a, a} }, q3);
m2.addTransition(q1, string::LinearString{ { a, b }, {b} }, q5);
m2.addTransition(q5, string::LinearString{ { a, b }, {b, a, a} }, q1);
m2.addFinalState(q3);
m2.addFinalState(q5);
automaton::CompactNFA c1 = automaton::transform::Compaction::convert(m1);
CPPUNIT_ASSERT(c1 == m2);
}
#ifndef AUTOMATA_COMPACTION_TEST_H_
#define AUTOMATA_COMPACTION_TEST_H_
#include <cppunit/extensions/HelperMacros.h>
class AutomataCompactionTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE( AutomataCompactionTest );
CPPUNIT_TEST( testAutomataCompaction1 );
CPPUNIT_TEST( testAutomataCompaction2 );
CPPUNIT_TEST( testAutomataCompaction3 );
CPPUNIT_TEST_SUITE_END();
public:
void setUp();
void tearDown();
void testAutomataCompaction1();
void testAutomataCompaction2();
void testAutomataCompaction3();
};
#endif /* AUTOMATA_COMPACTION_TEST_H_ */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment