diff --git a/lib/adaptive_distinguishing_sequence.hpp b/lib/adaptive_distinguishing_sequence.hpp deleted file mode 100644 index 5738009..0000000 --- a/lib/adaptive_distinguishing_sequence.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "mealy.hpp" - -#include -#include - -struct dist_seq { - dist_seq(size_t N, size_t depth) - : CI(N) - , depth(depth) - { - for(size_t i = 0; i < N; ++i) - CI[i] = {i, i}; - } - - // current, initial - std::vector> CI; - std::vector word; - std::vector children; - size_t depth; -}; - diff --git a/lib/create_adaptive_distinguishing_sequence.cpp b/lib/create_adaptive_distinguishing_sequence.cpp index 72f7a69..4aebc3b 100644 --- a/lib/create_adaptive_distinguishing_sequence.cpp +++ b/lib/create_adaptive_distinguishing_sequence.cpp @@ -1,79 +1,75 @@ #include "create_adaptive_distinguishing_sequence.hpp" -#include "splitting_tree.hpp" +#include "create_splitting_tree.hpp" #include #include #include #include -#include using namespace std; -result2 create_adaptive_distinguishing_sequence(const result & splitting_tree){ +distinguishing_sequence create_adaptive_distinguishing_sequence(const result & splitting_tree){ const auto & root = splitting_tree.root; const auto & succession = splitting_tree.successor_cache; const auto N = root.states.size(); - result2 r(N); - auto & root_seq = r.sequence; + distinguishing_sequence sequence(N, 0); - { - queue> work2; - work2.push(root_seq); + queue> work; + work.push(sequence); - while(!work2.empty()){ - dist_seq & node = work2.front(); - work2.pop(); + while(!work.empty()){ + distinguishing_sequence & node = work.front(); + work.pop(); - if(node.CI.size() < 2) continue; + if(node.CI.size() < 2) continue; - vector states(N, false); - for(auto && state : node.CI){ - states[state.first.base()] = true; - } + vector states(N, false); + for(auto && state : node.CI){ + states[state.first.base()] = true; + } - const auto & oboom = lca(root, [&states](state state) -> bool{ - return states[state.base()]; - }); + const auto & oboom = lca(root, [&states](state state) -> bool{ + return states[state.base()]; + }); - if(oboom.children.empty()) continue; + if(oboom.children.empty()) continue; - node.word = oboom.seperator; - for(auto && c : oboom.children){ - dist_seq new_c(0, node.depth + 1); + node.word = oboom.seperator; + for(auto && c : oboom.children){ + distinguishing_sequence new_c(0, node.depth + 1); - size_t i = 0; - size_t j = 0; + size_t i = 0; + size_t j = 0; - while(i < node.CI.size() && j < c.states.size()){ - if(node.CI[i].first < c.states[j]) { - i++; - } else if(node.CI[i].first > c.states[j]) { - j++; - } else { - const auto curr = succession[oboom.depth][node.CI[i].first.base()]; - const auto init = node.CI[i].second; - new_c.CI.push_back({curr, init}); - i++; - j++; - } - } - - // FIXME: this should/could be done without sorting... - sort(begin(new_c.CI), end(new_c.CI)); - - if(!new_c.CI.empty()){ - node.children.push_back(move(new_c)); + while(i < node.CI.size() && j < c.states.size()){ + if(node.CI[i].first < c.states[j]) { + i++; + } else if(node.CI[i].first > c.states[j]) { + j++; + } else { + const auto curr = succession[oboom.depth][node.CI[i].first.base()]; + const auto init = node.CI[i].second; + new_c.CI.push_back({curr, init}); + i++; + j++; } } - assert(node.children.size() > 1); + // FIXME: this should/could be done without sorting... + sort(begin(new_c.CI), end(new_c.CI)); - for(auto & c : node.children) { - work2.push(c); + if(!new_c.CI.empty()){ + node.children.push_back(move(new_c)); } } + + assert(node.children.size() > 1); + + for(auto & c : node.children) { + work.push(c); + } } - return r; + return sequence; } diff --git a/lib/create_adaptive_distinguishing_sequence.hpp b/lib/create_adaptive_distinguishing_sequence.hpp index 47e52e4..ee60740 100644 --- a/lib/create_adaptive_distinguishing_sequence.hpp +++ b/lib/create_adaptive_distinguishing_sequence.hpp @@ -1,16 +1,32 @@ #pragma once -#include "adaptive_distinguishing_sequence.hpp" -#include "create_splitting_tree.hpp" +#include "mealy.hpp" -struct result2 { - result2(size_t N) - : sequence(N, 0) - {} +#include +#include - // The adaptive distinguishing sequence as described in Lee & Yannakakis - // This is really a tree! - dist_seq sequence; +struct result; +struct distinguishing_sequence; + + +// Creates a distinguishing sequence based on the output of the first algorithm +distinguishing_sequence create_adaptive_distinguishing_sequence(result const & splitting_tree); + + +// The adaptive distinguishing sequence as described in Lee & Yannakakis +// This is really a tree! +struct distinguishing_sequence { + distinguishing_sequence(size_t N, size_t depth) + : CI(N) + , depth(depth) + { + for(size_t i = 0; i < N; ++i) + CI[i] = {i, i}; + } + + // current, initial + std::vector> CI; + std::vector word; + std::vector children; + size_t depth; }; - -result2 create_adaptive_distinguishing_sequence(result const & splitting_tree); diff --git a/lib/create_splitting_tree.cpp b/lib/create_splitting_tree.cpp index 211ab11..95526b4 100644 --- a/lib/create_splitting_tree.cpp +++ b/lib/create_splitting_tree.cpp @@ -1,4 +1,5 @@ #include "create_splitting_tree.hpp" +#include "partition.hpp" #include #include diff --git a/lib/create_splitting_tree.hpp b/lib/create_splitting_tree.hpp index 213393a..782324b 100644 --- a/lib/create_splitting_tree.hpp +++ b/lib/create_splitting_tree.hpp @@ -1,11 +1,31 @@ #pragma once #include "mealy.hpp" -#include "partition.hpp" #include "splitting_tree.hpp" #include +struct options; +struct result; + + +// Creates a Lee & Yannakakis style splitting tree +// Depending on the options it can also create the classical Hopcroft splitting tree +result create_splitting_tree(Mealy const & m, options opt); + + +// The algorithm can be altered in some ways. This struct provides options +// to the algorithm +struct options { + bool check_validity = true; +}; + +constexpr options with_validity_check{true}; +constexpr options without_validity_check{false}; + + +// The algorithm constructs more than the splitting tree +// We capture the other information as well struct result { result(size_t N) : root(N, 0) @@ -22,12 +42,3 @@ struct result { // false <-> no adaptive distinguishing sequence bool is_complete; }; - -struct options { - bool check_validity = true; -}; - -constexpr options with_validity_check{true}; -constexpr options without_validity_check{false}; - -result create_splitting_tree(Mealy const & m, options opt); diff --git a/lib/write_tree_to_dot.cpp b/lib/write_tree_to_dot.cpp index 9352221..fe586ae 100644 --- a/lib/write_tree_to_dot.cpp +++ b/lib/write_tree_to_dot.cpp @@ -1,5 +1,5 @@ #include "write_tree_to_dot.hpp" -#include "adaptive_distinguishing_sequence.hpp" +#include "create_adaptive_distinguishing_sequence.hpp" #include "splitting_tree.hpp" #include @@ -31,8 +31,8 @@ void write_splitting_tree_to_dot(const splijtboom& root, const string& filename) write_splitting_tree_to_dot(root, file); } -void write_adaptive_distinguishing_sequence_to_dot(const dist_seq & root, ostream & out){ - write_tree_to_dot(root, [](const dist_seq & node, ostream& out){ +void write_adaptive_distinguishing_sequence_to_dot(const distinguishing_sequence & root, ostream & out){ + write_tree_to_dot(root, [](const distinguishing_sequence & node, ostream& out){ if(!node.word.empty()){ out << node.word; } else { @@ -43,7 +43,7 @@ void write_adaptive_distinguishing_sequence_to_dot(const dist_seq & root, ostrea }, out); } -void write_adaptive_distinguishing_sequence_to_dot(const dist_seq & root, string const & filename){ +void write_adaptive_distinguishing_sequence_to_dot(const distinguishing_sequence & root, string const & filename){ ofstream file(filename); write_adaptive_distinguishing_sequence_to_dot(root, file); } diff --git a/lib/write_tree_to_dot.hpp b/lib/write_tree_to_dot.hpp index 1e7fc7b..2c957fc 100644 --- a/lib/write_tree_to_dot.hpp +++ b/lib/write_tree_to_dot.hpp @@ -40,6 +40,6 @@ struct splijtboom; void write_splitting_tree_to_dot(const splijtboom & root, std::ostream & out); void write_splitting_tree_to_dot(const splijtboom & root, std::string const & filename); -struct dist_seq; -void write_adaptive_distinguishing_sequence_to_dot(const dist_seq & root, std::ostream & out); -void write_adaptive_distinguishing_sequence_to_dot(const dist_seq & root, std::string const & filename); +struct distinguishing_sequence; +void write_adaptive_distinguishing_sequence_to_dot(const distinguishing_sequence & root, std::ostream & out); +void write_adaptive_distinguishing_sequence_to_dot(const distinguishing_sequence & root, std::string const & filename); diff --git a/src/main.cpp b/src/main.cpp index 1983c5f..dc29e4b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,21 +1,20 @@ #include #include +#include #include #include -#include #include -#include #include +#include #include -#include - -#include -#include -#include -#include #include +#include +#include +#include +#include +#include using namespace std; @@ -127,7 +126,7 @@ int main(int argc, char *argv[]){ write_splitting_tree_to_dot(splitting_tree.root, tree_filename); } - const auto distinguishing_sequence = [&]{ + const auto sequence = [&]{ timer t("Lee & Yannakakis II"); return create_adaptive_distinguishing_sequence(splitting_tree); }(); @@ -135,7 +134,7 @@ int main(int argc, char *argv[]){ if(false){ timer t("writing dist sequence"); const string dseq_filename = splitting_tree.is_complete ? (filename + ".dist_seq") : (filename + ".incomplete_dist_seq"); - write_adaptive_distinguishing_sequence_to_dot(distinguishing_sequence.sequence, dseq_filename); + write_adaptive_distinguishing_sequence_to_dot(sequence, dseq_filename); } const auto seperating_family = [&]{ @@ -144,12 +143,12 @@ int main(int argc, char *argv[]){ using SepSet = vector; vector seperating_family(machine.graph_size); - stack, reference_wrapper>> work; - work.push({{}, distinguishing_sequence.sequence}); + stack, reference_wrapper>> work; + work.push({{}, sequence}); while(!work.empty()){ auto word = work.top().first; - const dist_seq & node = work.top().second; + const distinguishing_sequence & node = work.top().second; work.pop(); if(node.children.empty()){