diff --git a/lib/transfer_sequences.cpp b/lib/transfer_sequences.cpp index 25da8d8129a8cfc4c3176fe796f7ccec39f099e4..4cc17a2fad24b1c73e59fdb40cb04ab8d9559995 100644 --- a/lib/transfer_sequences.cpp +++ b/lib/transfer_sequences.cpp @@ -4,28 +4,45 @@ #include <algorithm> #include <numeric> -#include <queue> +#include <deque> #include <random> #include <tuple> using namespace std; +namespace { +static size_t clamp_to_size_t(double x, size_t min, size_t max) { + if (x >= max) return max; + if (x <= min) return min; + return x; +} +} + transfer_sequences create_transfer_sequences(transfer_options const & opt, const mealy & machine, state s, uint_fast32_t random_seed) { mt19937 generator(random_seed); + uniform_int_distribution<double> dist(opt.q_min, opt.q_max); vector<bool> added(machine.graph_size, false); vector<word> words(machine.graph_size); vector<input> all_inputs(machine.input_size); iota(begin(all_inputs), end(all_inputs), input(0)); - // state - queue<state> work; - work.push(s); + deque<state> work(1, s); added[s] = true; while (!work.empty()) { - const auto u = work.front(); - work.pop(); + const auto u = [&] { + // get the place in the array to pop a state + const auto sample = dist(generator); + const auto scaled_sample = clamp_to_size_t(floor(work.size() * sample), 0, work.size()-1); + const auto it = work.begin() + scaled_sample; + // get the element + const auto ret = *it; + // pop it + work.erase(it); + // return it + return ret; + }(); // NOTE: we could also shuffle work, but we would need to do this per distance // the current shuffle is an approximation of real randomization, but easier to implement. @@ -34,7 +51,7 @@ transfer_sequences create_transfer_sequences(transfer_options const & opt, const const auto v = apply(machine, u, i).to; if (added[v]) continue; - work.push(v); + work.push_back(v); added[v] = true; words[v] = words[u]; words[v].push_back(i); diff --git a/lib/transfer_sequences.hpp b/lib/transfer_sequences.hpp index 285efa370551e2935e9828d86af17d7c830ffec5..4e1200d2105add2d0163983793c709882514dff4 100644 --- a/lib/transfer_sequences.hpp +++ b/lib/transfer_sequences.hpp @@ -8,11 +8,20 @@ struct mealy; using transfer_sequences = std::vector<word>; struct transfer_options { + // range used to sample the work-queue. [0,0] is a bfs (minimal), [1,1] is a dfs (dumb). + // q_min should be smaller than q_max. + double q_min; + double q_max; + + // indicates whether to randomly iterate over the alphabet + // and to randomly select in [q_min, q_max] instead of taking the center bool randomized; }; -const transfer_options randomized_transfer_sequences{true}; -const transfer_options canonical_transfer_sequences{false}; +const transfer_options canonical_transfer_sequences{0.0, 0.0, false}; +const transfer_options minimal_transfer_sequences{0.0, 0.0, true}; +const transfer_options buggy_transfer_sequences{0.0, 1.0, true}; +const transfer_options longest_transfer_sequences{1.0, 1.0, true}; // longest, forming a tree transfer_sequences create_transfer_sequences(transfer_options const & opt, mealy const & machine, state s, uint_fast32_t random_seed); diff --git a/src/main.cpp b/src/main.cpp index ba0705dd77130690201e60540f51512fe4bf62db..e0408aef4a86cba8d498e18052db30b43dcc288d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,6 +32,7 @@ R"(Generate a test suite --random-ds Choose randomly between the ds method or hsi method --no-suffix Dont calculate anything smart, just do the random stuff --suffix-based Only applies in random mode. Chooses suffix first, and not prefix first + --prefix <type> Chooses the kind of prefix: canonical, minimal, buggy, longest )"; using time_logger = silent_timer; @@ -60,7 +61,7 @@ int main(int argc, char *argv[]) try { } return !args.at("--no-ds").asBool(); }(); - const bool randomize_prefixes = true; + const string prefix_type = args.at("--prefix") ? args.at("--prefix").asString() : "minimal"; const bool randomize_hopcroft = true; const bool randomize_lee_yannakakis = true; @@ -129,9 +130,13 @@ int main(int argc, char *argv[]) try { auto transfer_sequences = [&] { time_logger t("determining transfer sequences"); - return create_transfer_sequences(randomize_prefixes ? randomized_transfer_sequences - : canonical_transfer_sequences, - machine, 0, random_seeds[2]); + if(prefix_type == "canonical") return create_transfer_sequences(canonical_transfer_sequences, machine, 0, random_seeds[2]); + if(prefix_type == "minimal") return create_transfer_sequences(minimal_transfer_sequences, machine, 0, random_seeds[2]); + if(prefix_type == "buggy") return create_transfer_sequences(buggy_transfer_sequences, machine, 0, random_seeds[2]); + if(prefix_type == "longest") return create_transfer_sequences(longest_transfer_sequences, machine, 0, random_seeds[2]); + + cerr << "Warning: no valid prefix type specified. Assuming minimal.\n"; + return create_transfer_sequences(minimal_transfer_sequences, machine, 0, random_seeds[2]); }(); auto inputs = create_reverse_map(translation.input_indices); diff --git a/src/methods.cpp b/src/methods.cpp index be75b379643b62438baa15933a70ba4e4c7df2d9..c9579934c8040d905f3377ee5096dff656705449 100644 --- a/src/methods.cpp +++ b/src/methods.cpp @@ -81,7 +81,7 @@ int main(int argc, char * argv[]) { auto prefixes_fut = async([&] { return create_transfer_sequences(args.at("--non-random").asBool() ? canonical_transfer_sequences - : randomized_transfer_sequences, + : minimal_transfer_sequences, machine, 0, random_seeds[2]); });