From 0ab23f5ec2a0a6e99274792759658148036b067b Mon Sep 17 00:00:00 2001 From: Joshua Moerman Date: Wed, 20 May 2015 12:07:41 +0200 Subject: [PATCH] Moves test suite generation to separate files --- lib/test_suite.cpp | 79 +++++++++++++++++++++++++++++++++++++++ lib/test_suite.hpp | 25 +++++++++++++ src/main.cpp | 93 +++++----------------------------------------- 3 files changed, 113 insertions(+), 84 deletions(-) create mode 100644 lib/test_suite.cpp create mode 100644 lib/test_suite.hpp diff --git a/lib/test_suite.cpp b/lib/test_suite.cpp new file mode 100644 index 0000000..5e99559 --- /dev/null +++ b/lib/test_suite.cpp @@ -0,0 +1,79 @@ +#include "test_suite.hpp" + +#include +#include + + +using namespace std; + +void test(const mealy & specification, const transfer_sequences & prefixes, + const characterization_family & separating_family, size_t k_max, const writer & output) { + vector all_sequences(1); + + for (size_t k = 0; k <= k_max; ++k) { + clog << "*** K = " << k << endl; + + for (state s = 0; s < specification.graph_size; ++s) { + const auto prefix = prefixes[s]; + + for (auto && middle : all_sequences) { + const auto t = apply(specification, s, middle.begin(), middle.end()).to; + + for (auto && suffix : separating_family[t].local_suffixes) { + output.apply(prefix); + output.apply(middle); + output.apply(suffix); + output.reset(); + } + } + } + + all_sequences = all_seqs(0, specification.input_size, all_sequences); + } +} + +void randomized_test(const mealy & specification, const transfer_sequences & prefixes, + const characterization_family & separating_family, size_t min_k, + const writer & output) { + clog << "*** K >= " << min_k << endl; + + std::random_device rd; + std::mt19937 generator(rd()); + + uniform_int_distribution<> unfair_coin(0, 2); + uniform_int_distribution prefix_selection(0, prefixes.size() - 1); + uniform_int_distribution suffix_selection; + uniform_int_distribution input_selection(0, specification.input_size - 1); + + while (true) { + state current_state = 0; + + const auto & prefix = prefixes[prefix_selection(generator)]; + current_state = apply(specification, current_state, begin(prefix), end(prefix)).to; + + vector middle; + middle.reserve(min_k + 1); + size_t minimal_size = min_k; + while (minimal_size || unfair_coin(generator)) { + input i = input_selection(generator); + middle.push_back(i); + current_state = apply(specification, current_state, i).to; + if (minimal_size) minimal_size--; + } + + using params = decltype(suffix_selection)::param_type; + const auto & suffixes = separating_family[current_state].local_suffixes; + const auto & suffix = suffixes[suffix_selection(generator, params{0, suffixes.size() - 1})]; + + output.apply(prefix); + output.apply(middle); + output.apply(suffix); + output.reset(); + } +} + +writer default_writer(std::vector const & inputs) { + static const auto print_word = [&](word w) { for (auto && x : w) cout << inputs[x] << ' '; }; + static const auto reset = [&] { cout << endl; }; + return {print_word, reset}; +} diff --git a/lib/test_suite.hpp b/lib/test_suite.hpp new file mode 100644 index 0000000..0205576 --- /dev/null +++ b/lib/test_suite.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "characterization_family.hpp" +#include "mealy.hpp" +#include "transfer_sequences.hpp" +#include "types.hpp" + +#include + +struct writer { + std::function apply; // store a part of a word + std::function reset; // flush +}; + +/// \brief Performs exhaustive tests with \p k_max extra states (harmonized, e.g. HSI / DS) +void test(mealy const & specification, transfer_sequences const & prefixes, + characterization_family const & separating_family, size_t k_max, writer const & output); + +/// \brief Performs random non-exhaustive tests for more states (harmonized, e.g. HSI / DS) +[[noreturn]] void randomized_test(mealy const & specification, transfer_sequences const & prefixes, + characterization_family const & separating_family, size_t min_k, + writer const & output); + +/// \brief returns a writer which simply writes everything to cout (via inputs) +writer default_writer(const std::vector & inputs); diff --git a/src/main.cpp b/src/main.cpp index 4923059..1a20d6c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -34,13 +35,12 @@ int main(int argc, char *argv[]) try { const bool random_part = streaming && mode != "stop"; const bool use_distinguishing_sequence = true; - const bool use_relevances = false; const bool randomize_prefixes = true; const bool randomize_hopcroft = true; const bool randomize_lee_yannakakis = true; const auto machine_and_translation = [&]{ - time_logger t("reading file " + filename); + time_logger t_("reading file " + filename); if(use_stdio){ return read_mealy_from_dot(cin); } @@ -65,12 +65,12 @@ int main(int argc, char *argv[]) try { return create_splitting_tree(machine, randomize_hopcroft ? randomized_hopcroft_style : hopcroft_style); }(); - const auto all_pair_seperating_sequences = [&]{ + const auto all_pair_seperating_sequences_ = [&]{ time_logger t("gathering all seperating sequences"); return create_all_pair_seperating_sequences(splitting_tree_hopcroft.root); }(); - return all_pair_seperating_sequences; + return all_pair_seperating_sequences_; }(); auto sequence = [&]{ @@ -82,12 +82,12 @@ int main(int argc, char *argv[]) try { return result(machine.graph_size); }(); - const auto sequence = [&]{ + const auto sequence_ = [&]{ time_logger t("Lee & Yannakakis II"); return create_adaptive_distinguishing_sequence(tree); }(); - return sequence; + return sequence_; }(); auto transfer_sequences = [&]{ @@ -103,26 +103,6 @@ int main(int argc, char *argv[]) try { return create_reverse_map(translation.input_indices); }(); - auto relevant_inputs = [&]{ - time_logger t("determining relevance of inputs"); - vector> distributions(machine.graph_size); - - for(state s = 0; s < machine.graph_size; ++s){ - vector r_cache(machine.input_size, 1); - if(use_relevances){ - for(input i = 0; i < machine.input_size; ++i){ - //const auto test1 = apply(machine, s, i).output != machine.output_indices.at("quiescence"); - const auto test2 = apply(machine, s, i).to != s; - r_cache[i] = 0.1 + test2; - } - } - - // VS 2013 is missing some c++11 support: http://stackoverflow.com/questions/21959404/initialising-stddiscrete-distribution-in-vs2013 - size_t i = 0; - distributions[s] = discrete_distribution(r_cache.size(), r_cache.front(), r_cache.back(), [&r_cache, &i](double) { return r_cache[i++]; }); - } - return distributions; - }(); // const auto all_pair_seperating_sequences = all_pair_seperating_sequences_fut.get(); // const auto sequence = sequence_fut.get(); @@ -135,71 +115,16 @@ int main(int argc, char *argv[]) try { // const auto transfer_sequences = transfer_sequences_fut.get(); // const auto inputs = inputs_fut.get(); - const auto print_word = [&](vector w){ - for(auto && x : w) cout << inputs[x] << ' '; - }; - if(streaming){ time_logger t("outputting all preset tests"); - - vector all_sequences(1); - for(size_t k = 0; k <= k_max; ++k){ - clog << "*** K = " << k << endl; - for(state s = 0; s < machine.graph_size; ++s){ - const auto prefix = transfer_sequences[s]; - - for(auto && suffix : seperating_family[s].local_suffixes){ - for(auto && r : all_sequences){ - print_word(prefix); - print_word(r); - print_word(suffix); - cout << endl; - } - } - } - - all_sequences = all_seqs(0, machine.input_size, all_sequences); - } + test(machine, transfer_sequences, seperating_family, k_max, default_writer(inputs)); } if(random_part){ time_logger t("outputting all random tests"); - clog << "*** K > " << k_max << endl; - - std::random_device rd; - std::mt19937 generator(rd()); - - uniform_int_distribution prefix_selection(0, transfer_sequences.size()-1); - uniform_int_distribution<> unfair_coin(0, 2); // expected flips is p / (p-1)^2, where p is succes probability - uniform_int_distribution suffix_selection; - // auto relevant_inputs = relevant_inputs_fut.get(); - - while(true){ - state current_state = 0; - - const auto & p = transfer_sequences[prefix_selection(generator)]; - current_state = apply(machine, current_state, begin(p), end(p)).to; - - vector m; - m.reserve(k_max + 2); - size_t minimal_size = k_max + 1; - while(minimal_size || unfair_coin(generator)){ - input i = relevant_inputs[current_state](generator); - m.push_back(i); - current_state = apply(machine, current_state, i).to; - if(minimal_size) minimal_size--; - } - - using params = uniform_int_distribution::param_type; - const auto & suffixes = seperating_family[current_state].local_suffixes; - const auto & s = suffixes[suffix_selection(generator, params{0, suffixes.size()-1})]; - - print_word(p); - print_word(m); - print_word(s); - cout << endl; - } + randomized_test(machine, transfer_sequences, seperating_family, k_max+1, default_writer(inputs)); } + } catch (exception const & e) { cerr << "Exception thrown: " << e.what() << endl; return 1;