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)
automaton::CompactNFA res(automaton.getInitialState());
res.setInputAlphabet(automaton.getInputAlphabet());
 
string::LinearString path;
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::set<automaton::State> visited;
 
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()))
{
stack.push(std::make_tuple(transition.second, automaton.getInitialState(), transition.first.second));
}
 
if(automaton.getFinalStates().count(automaton.getInitialState()) > 0)
res.addFinalState(automaton.getInitialState());
 
while(!stack.empty())
{
const automaton::State q = std::get<0>(stack.top());
const automaton::State lastFork = std::get<1>(stack.top());
const alphabet::Symbol symbol = std::get<2>(stack.top());
while(!stack.empty()) {
automaton::State q = std::move(std::get<0>(stack.top()));
automaton::State lastFork = std::move(std::get<1>(stack.top()));
alphabet::Symbol symbol = std::move(std::get<2>(stack.top()));
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
if(automaton.getTransitionsFromState(q).size() == 1 && automaton.getFinalStates().count(q) == 0 && automaton.getInitialState() != q)
{
const auto& transition = * automaton.getTransitionsFromState(q).begin();
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;
}
}
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();
path.appendSymbol(transition.first.second);
q = transition.second;
}
// 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;
......
#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