diff --git a/lib/splitting_tree.cpp b/lib/splitting_tree.cpp index 657e547..81dbeb0 100644 --- a/lib/splitting_tree.cpp +++ b/lib/splitting_tree.cpp @@ -15,7 +15,7 @@ splitting_tree::splitting_tree(size_t N, size_t d) : states(N), depth(d) { iota(begin(states), end(states), 0); } -result create_splitting_tree(const mealy & g, options opt) { +result create_splitting_tree(const mealy & g, options opt, uint_fast32_t random_seed) { const auto N = g.graph_size; const auto P = g.input_size; const auto Q = g.output_size; @@ -34,8 +34,7 @@ result create_splitting_tree(const mealy & g, options opt) { // List of inputs, will be shuffled in case of randomizations vector all_inputs(P); iota(begin(all_inputs), end(all_inputs), 0); - random_device rd; - mt19937 generator(rd()); + mt19937 generator(random_seed); size_t current_order = 0; bool split_in_current_order = false; diff --git a/lib/splitting_tree.hpp b/lib/splitting_tree.hpp index e34e21d..2f32583 100644 --- a/lib/splitting_tree.hpp +++ b/lib/splitting_tree.hpp @@ -111,4 +111,4 @@ struct result { /// \brief Creates a splitting tree by partition refinement. /// \returns a splitting tree and other calculated structures. -result create_splitting_tree(mealy const & m, options opt); +result create_splitting_tree(mealy const & m, options opt, uint_fast32_t random_seed); diff --git a/lib/test_suite.cpp b/lib/test_suite.cpp index fde1c29..a77a5ef 100644 --- a/lib/test_suite.cpp +++ b/lib/test_suite.cpp @@ -34,11 +34,10 @@ void test(const mealy & specification, const transfer_sequences & prefixes, void randomized_test(const mealy & specification, const transfer_sequences & prefixes, const separating_family & separating_family, size_t min_k, size_t rnd_length, - const writer & output) { + const writer & output, uint_fast32_t random_seed) { clog << "*** K >= " << min_k << endl; - std::random_device rd; - std::mt19937 generator(rd()); + std::mt19937 generator(random_seed); // https://en.wikipedia.org/wiki/Geometric_distribution we have the random variable Y here uniform_int_distribution<> unfair_coin(0, rnd_length); diff --git a/lib/test_suite.hpp b/lib/test_suite.hpp index 8c44681..d797b58 100644 --- a/lib/test_suite.hpp +++ b/lib/test_suite.hpp @@ -19,7 +19,7 @@ void test(mealy const & specification, transfer_sequences const & prefixes, /// \brief Performs random non-exhaustive tests for more states (harmonized, e.g. HSI / DS) void randomized_test(mealy const & specification, transfer_sequences const & prefixes, separating_family const & separating_family, size_t min_k, - size_t rnd_length, writer const & output); + size_t rnd_length, writer const & output, uint_fast32_t random_seed); /// \brief returns a writer which simply writes everything to cout (via inputs) writer default_writer(const std::vector & inputs); diff --git a/lib/transfer_sequences.cpp b/lib/transfer_sequences.cpp index 766fec6..a459be7 100644 --- a/lib/transfer_sequences.cpp +++ b/lib/transfer_sequences.cpp @@ -38,9 +38,8 @@ transfer_sequences create_transfer_sequences(const mealy& machine, state s){ return words; } -transfer_sequences create_randomized_transfer_sequences(const mealy & machine, state s){ - random_device rd; - mt19937 generator(rd()); +transfer_sequences create_randomized_transfer_sequences(const mealy & machine, state s, uint_fast32_t random_seed){ + mt19937 generator(random_seed); vector visited(machine.graph_size, false); vector words(machine.graph_size); diff --git a/lib/transfer_sequences.hpp b/lib/transfer_sequences.hpp index df346a5..40bf7f6 100644 --- a/lib/transfer_sequences.hpp +++ b/lib/transfer_sequences.hpp @@ -7,4 +7,4 @@ struct mealy; using transfer_sequences = std::vector; transfer_sequences create_transfer_sequences(mealy const & machine, state s); -transfer_sequences create_randomized_transfer_sequences(mealy const & machine, state s); +transfer_sequences create_randomized_transfer_sequences(mealy const & machine, state s, uint_fast32_t random_seed); diff --git a/src/main.cpp b/src/main.cpp index 18163ce..447a725 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,8 +18,8 @@ using namespace std; using time_logger = silent_timer; int main(int argc, char *argv[]) try { - if(argc != 5) { - cerr << "usage: main " << endl; + if(argc != 5 && argc != 6) { + cerr << "usage: main []" << endl; return 1; } const string filename = argv[1]; @@ -32,6 +32,9 @@ int main(int argc, char *argv[]) try { const bool streaming = mode == "all" || mode == "fixed"; const bool random_part = mode == "all" || mode == "random"; + const bool seed_provided = argc == 6; + const uint_fast32_t seed = seed_provided ? stoul(argv[5]) : 0; + const bool use_distinguishing_sequence = true; const bool randomize_prefixes = true; const bool randomize_hopcroft = true; @@ -57,10 +60,23 @@ int main(int argc, char *argv[]) try { const auto & machine = reachable_submachine(move(machine_and_translation.first), 0); const auto & translation = machine_and_translation.second; + // every thread gets its own seed + const auto random_seeds = [&] { + vector seeds(4); + if (seed_provided) { + seed_seq s{seed}; + s.generate(seeds.begin(), seeds.end()); + } else { + random_device rd; + generate(seeds.begin(), seeds.end(), ref(rd)); + } + return seeds; + }(); + auto all_pair_separating_sequences = [&]{ const auto splitting_tree_hopcroft = [&]{ time_logger t("creating hopcroft splitting tree"); - return create_splitting_tree(machine, randomize_hopcroft ? randomized_hopcroft_style : hopcroft_style); + return create_splitting_tree(machine, randomize_hopcroft ? randomized_hopcroft_style : hopcroft_style, random_seeds[0]); }(); return splitting_tree_hopcroft.root; @@ -70,7 +86,7 @@ int main(int argc, char *argv[]) try { const auto tree = [&]{ time_logger t("Lee & Yannakakis I"); if(use_distinguishing_sequence) - return create_splitting_tree(machine, randomize_lee_yannakakis ? randomized_lee_yannakakis_style : lee_yannakakis_style); + return create_splitting_tree(machine, randomize_lee_yannakakis ? randomized_lee_yannakakis_style : lee_yannakakis_style, random_seeds[1]); else return result(machine.graph_size); }(); @@ -86,7 +102,7 @@ int main(int argc, char *argv[]) try { auto transfer_sequences = [&]{ time_logger t("determining transfer sequences"); if(randomize_prefixes){ - return create_randomized_transfer_sequences(machine, 0); + return create_randomized_transfer_sequences(machine, 0, random_seeds[2]); } else { return create_transfer_sequences(machine, 0); } @@ -107,7 +123,7 @@ int main(int argc, char *argv[]) try { if(random_part){ time_logger t("outputting all random tests"); const auto k_max_ = streaming ? k_max + 1 : 0; - randomized_test(machine, transfer_sequences, separating_family, k_max_, rnd_length, default_writer(inputs)); + randomized_test(machine, transfer_sequences, separating_family, k_max_, rnd_length, default_writer(inputs), random_seeds[3]); } } catch (exception const & e) { diff --git a/src/methods.cpp b/src/methods.cpp index 5533304..da56325 100644 --- a/src/methods.cpp +++ b/src/methods.cpp @@ -6,8 +6,9 @@ #include #include -#include #include +#include +#include using namespace std; @@ -23,14 +24,16 @@ static Method parse_method(string const & s) { } int main(int argc, char * argv[]) { - if (argc != 4) { - cerr << "usage: methods \n"; + if (argc != 4 && argc != 5) { + cerr << "usage: methods []\n"; return 1; } const string filename = argv[1]; const Method method = parse_method(argv[2]); const size_t k_max = std::stoul(argv[3]); + const bool seed_provided = argc == 5; + const uint_fast32_t seed = seed_provided ? stoul(argv[5]) : 0; const auto machine = [&] { if (filename.find(".txt") != string::npos) { @@ -43,21 +46,33 @@ int main(int argc, char * argv[]) { return read_mealy_from_dot(filename).first; }(); + const auto random_seeds = [&] { + vector seeds(3); + if (seed_provided) { + seed_seq s{seed}; + s.generate(seeds.begin(), seeds.end()); + } else { + random_device rd; + generate(seeds.begin(), seeds.end(), ref(rd)); + } + return seeds; + }(); + auto sequence_fut = async([&] { if (method == hsi_method) { return create_adaptive_distinguishing_sequence(result(machine.graph_size)); } - const auto tree = create_splitting_tree(machine, randomized_lee_yannakakis_style); + const auto tree = create_splitting_tree(machine, randomized_lee_yannakakis_style, random_seeds[0]); return create_adaptive_distinguishing_sequence(tree); }); auto pairs_fut = async([&] { - const auto tree = create_splitting_tree(machine, randomized_min_hopcroft_style); + const auto tree = create_splitting_tree(machine, randomized_min_hopcroft_style, random_seeds[1]); return tree.root; }); auto prefixes_fut = async([&] { - return create_transfer_sequences(machine, 0); + return create_randomized_transfer_sequences(machine, 0, random_seeds[2]); }); auto middles_fut = async([&] { diff --git a/src/trees.cpp b/src/trees.cpp index cd91faa..54002c2 100644 --- a/src/trees.cpp +++ b/src/trees.cpp @@ -3,8 +3,9 @@ #include #include -#include #include +#include +#include using namespace std; @@ -20,7 +21,9 @@ int main(int argc, char * argv[]) { const auto & translation = machine_and_translation.second; const auto options = randomized ? randomized_lee_yannakakis_style : lee_yannakakis_style; - const auto tree = create_splitting_tree(machine, options); + + random_device rd; + const auto tree = create_splitting_tree(machine, options, rd()); const auto sequence = create_adaptive_distinguishing_sequence(tree); write_splitting_tree_to_dot(tree.root, filename + ".tree");