diff --git a/CMakeLists.txt b/CMakeLists.txt index c9c940540f8216ced054cfb8bf755a6117a76603..36bd70f05a78d8ac61dc7c5f1035b697e4b3c6ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ endif() set(CMAKE_CXX_FLAGS "-Wall -Wextra -std=c++11") set(CMAKE_CXX_FLAGS_DEBUG "-g3 -Ofast") -set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -march=native") +set(CMAKE_CXX_FLAGS_RELEASE "-Ofast") include_directories(maca_common/include) include_directories(transition_machine/include) diff --git a/maca_common/include/LimitedStack.hpp b/maca_common/include/LimitedStack.hpp index 7e45414cbf5ffdd6cc9d2310a57e414ef73be776..8521d3eb914bfc7c7d40c81cce447413eeb388dd 100644 --- a/maca_common/include/LimitedStack.hpp +++ b/maca_common/include/LimitedStack.hpp @@ -76,6 +76,22 @@ class LimitedStack { return nbElements == 0; } + + bool contains(const T & element) + { + int currentIndex = lastElementIndex; + for (unsigned int i = 0; i < nbElements; i++) + { + if (data[currentIndex] == element) + return true; + + currentIndex--; + if (currentIndex < 0) + currentIndex = data.size()-1; + } + + return false; + } }; #endif diff --git a/transition_machine/include/Config.hpp b/transition_machine/include/Config.hpp index 83f4831fe1d39b3f98d5b77f871df032a842a53d..015337b1d6ddf29398cafe355f310e9fc15d6fd0 100644 --- a/transition_machine/include/Config.hpp +++ b/transition_machine/include/Config.hpp @@ -67,6 +67,8 @@ class Config std::string inputFilename; /// @brief The sequence of Actions that made that Config. LimitedStack< std::pair<std::string, Action> > pastActions; + /// @brief An history of hashes, can be used to detect loops. + LimitedStack<std::size_t> hashHistory; public : @@ -183,6 +185,18 @@ class Config /// /// @param entropy The entropy value. void addToEntropyHistory(float entropy); + // ////////////////////////////////////////////////////////////////////////// + /// \brief Compute a hash of this Config. + /// + /// \return The computed hash. + // + //////////////////////////////////////////////////////////////////////////// + std::size_t computeHash(); + // ////////////////////////////////////////////////////////////////////////// + /// \brief Compute and add current hash to the history of hash. + // + //////////////////////////////////////////////////////////////////////////// + void addHashToHistory(); }; #endif diff --git a/transition_machine/src/Action.cpp b/transition_machine/src/Action.cpp index 6c5973f950c518a1818d931dabb6b5be89e6f633..9d64573765e294b65644f1dbd579619cdd333af5 100644 --- a/transition_machine/src/Action.cpp +++ b/transition_machine/src/Action.cpp @@ -4,6 +4,8 @@ void Action::apply(Config & config) { + config.addHashToHistory(); + for(auto & basicAction : sequence) basicAction.apply(config, basicAction); diff --git a/transition_machine/src/ActionBank.cpp b/transition_machine/src/ActionBank.cpp index 0e2d98a0bd0b4e9c44596e7fefe2cc93753044c3..7946d1fa74ef33da9a9c7e0a2043036adc2b05c8 100644 --- a/transition_machine/src/ActionBank.cpp +++ b/transition_machine/src/ActionBank.cpp @@ -503,29 +503,39 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na auto apply = [dist](Config & c, Action::BasicAction &) { - static auto undoOneTime = [](Config & c) + std::string classifierName = c.pastActions.top().first; + if (ProgramParameters::debug) + fprintf(stderr, "classifierName = <%s>\n", classifierName.c_str()); + + static auto undoOneTime = [classifierName](Config & c) { + if (ProgramParameters::debug) + fprintf(stderr, "classifierName = <%s>\n", classifierName.c_str()); + while (true) { auto a = c.pastActions.pop(); if (ProgramParameters::debug) - fprintf(stderr, "Undoing... <%s>\n", a.second.name.c_str()); + fprintf(stderr, "Undoing... <%s><%s>\n", a.first.c_str(), a.second.name.c_str()); a.second.undoOnlyStack(c); - if (a.first == "tagger") + if (a.first == classifierName) return; } }; - static auto undoForReal = [](Config & c) + static auto undoForReal = [classifierName](Config & c) { + if (ProgramParameters::debug) + fprintf(stderr, "classifierName = <%s>\n", classifierName.c_str()); + while (true) { auto a = c.pastActions.pop(); if (ProgramParameters::debug) - fprintf(stderr, "Undoing... <%s>\n", a.second.name.c_str()); + fprintf(stderr, "Undoing... <%s><%s>\n", a.first.c_str(), a.second.name.c_str()); - if (a.first == "tagger") + if (a.first == classifierName) { a.second.undo(c); return; diff --git a/transition_machine/src/Config.cpp b/transition_machine/src/Config.cpp index 25477a74041ab5e9847f92d5c39aee5f2055d85a..c75a000c31539ec27a84d71a147d2649bfcd8f5d 100644 --- a/transition_machine/src/Config.cpp +++ b/transition_machine/src/Config.cpp @@ -4,7 +4,7 @@ #include "ProgramParameters.hpp" #include "Action.hpp" -Config::Config(BD & bd) : bd(bd), tapes(bd.getNbLines()), pastActions(100) +Config::Config(BD & bd) : bd(bd), hashHistory(10), tapes(bd.getNbLines()), pastActions(100) { this->stackHistory = -1; this->currentStateName = nullptr; @@ -215,6 +215,7 @@ void Config::reset() actionHistory.clear(); pastActions.clear(); + hashHistory.clear(); stack.clear(); stackHistory = -1; @@ -499,3 +500,25 @@ void Config::addToEntropyHistory(float entropy) entropyHistory[*currentStateName].emplace_back(entropy); } +std::size_t Config::computeHash() +{ + static int window = 3; + + unsigned int start = std::max(0, head-window); + unsigned int end = std::min((unsigned int)tapes[0].ref.size()-1, (unsigned int)head+window); + + std::hash<std::string> hasher; + std::size_t result = 0; + + for (unsigned int i = start; i < end; i++) + for (auto & tape : tapes) + result ^= (hasher(tape[i])*0x9e3779b9+(result << 6)+(result >>2)); + + return result; +} + +void Config::addHashToHistory() +{ + hashHistory.push(computeHash()); +} + diff --git a/transition_machine/src/Oracle.cpp b/transition_machine/src/Oracle.cpp index 6a4d618922999991bd98e463f86ad44632660386..f0246c6654bcb0d4392092d418f17681562b0955 100644 --- a/transition_machine/src/Oracle.cpp +++ b/transition_machine/src/Oracle.cpp @@ -106,6 +106,9 @@ void Oracle::createDatabase() if (c.getCurrentStateHistory().size() < 2) return std::string("EPSILON"); + if (c.hashHistory.contains(c.computeHash())) + return std::string("EPSILON"); + //return std::string("BACK 1"); auto & pos = c.getTape("POS"); @@ -135,12 +138,22 @@ void Oracle::createDatabase() }, [](Config & c, Oracle *) { + //fprintf(stderr, "HistorySize = %lu\n", c.getCurrentStateHistory().size()); + //if (c.getCurrentStateHistory().size() >= 2) + //fprintf(stderr, "<%s> <%s>\n", c.getCurrentStateHistory()[c.getCurrentStateHistory().size()-2].c_str(), c.getCurrentStateHistory()[c.getCurrentStateHistory().size()-1].c_str()); + if (c.getCurrentStateHistory().size() >= 2 && (c.getCurrentStateHistory().back() == "BACK" || c.getCurrentStateHistory()[c.getCurrentStateHistory().size()-2] == "BACK")) + { +// fprintf(stderr, "Avoiding loop\n"); return std::string("EPSILON"); + } if (c.getCurrentStateHistory().size() < 2) return std::string("EPSILON"); + if (c.hashHistory.contains(c.computeHash())) + return std::string("EPSILON"); + //return std::string("BACK 1"); auto & morpho = c.getTape("MORPHO"); @@ -155,8 +168,8 @@ void Oracle::createDatabase() if (morpho0 == morphoRef) return std::string("EPSILON"); - auto & genre0 = split(morpho0, '|')[0]; - auto & genre1 = split(morpho1, '|')[0]; + auto genre0 = split(morpho0, '|')[0]; + auto genre1 = split(morpho1, '|')[0]; if (genre0 == "g=f" && genre1 == "g=m") return std::string("BACK 1");