mirror of
https://github.com/Jaxan/hybrid-ads.git
synced 2025-04-27 23:17:44 +02:00
Adds a test method without suffixes. Rewrites methods.cpp to use these functions.
This commit is contained in:
parent
e9ffbd3be8
commit
09c65377e7
4 changed files with 139 additions and 42 deletions
|
@ -23,7 +23,7 @@ void test(const mealy & specification, const transfer_sequences & prefixes,
|
||||||
output.apply(prefix);
|
output.apply(prefix);
|
||||||
output.apply(middle);
|
output.apply(middle);
|
||||||
output.apply(suffix);
|
output.apply(suffix);
|
||||||
output.reset();
|
if(!output.reset()) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ void randomized_test(const mealy & specification, const transfer_sequences & pre
|
||||||
const auto & prefix = prefixes[prefix_selection(generator)];
|
const auto & prefix = prefixes[prefix_selection(generator)];
|
||||||
current_state = apply(specification, current_state, begin(prefix), end(prefix)).to;
|
current_state = apply(specification, current_state, begin(prefix), end(prefix)).to;
|
||||||
|
|
||||||
vector<input> middle;
|
word middle;
|
||||||
middle.reserve(min_k + 1);
|
middle.reserve(min_k + 1);
|
||||||
size_t minimal_size = min_k;
|
size_t minimal_size = min_k;
|
||||||
while (minimal_size || unfair_coin(generator)) {
|
while (minimal_size || unfair_coin(generator)) {
|
||||||
|
@ -68,12 +68,77 @@ void randomized_test(const mealy & specification, const transfer_sequences & pre
|
||||||
output.apply(prefix);
|
output.apply(prefix);
|
||||||
output.apply(middle);
|
output.apply(middle);
|
||||||
output.apply(suffix);
|
output.apply(suffix);
|
||||||
output.reset();
|
if(!output.reset()) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void randomized_test_suffix(const mealy & specification, const transfer_sequences & prefixes,
|
||||||
|
const separating_family & separating_family, size_t min_k,
|
||||||
|
size_t rnd_length, const writer & output, uint_fast32_t random_seed) {
|
||||||
|
vector<pair<state, word>> all_suffixes;
|
||||||
|
for (state s = 0; s < separating_family.size(); ++s) {
|
||||||
|
for (auto const & w : separating_family[s].local_suffixes) {
|
||||||
|
all_suffixes.emplace_back(s, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// state -> [(input, state)]
|
||||||
|
vector<vector<pair<input, state>>> reverse_machine(specification.graph_size);
|
||||||
|
for (state s = 0; s < specification.graph_size; ++s) {
|
||||||
|
for (input i = 0; i < specification.input_size; ++i) {
|
||||||
|
const auto t = apply(specification, s, i).to;
|
||||||
|
reverse_machine[t].emplace_back(i, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
uniform_int_distribution<state> suffix_selection(0, all_suffixes.size() - 1);
|
||||||
|
uniform_int_distribution<size_t> input_selection;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const auto & state_suffix = all_suffixes[suffix_selection(generator)];
|
||||||
|
const auto & suffix = state_suffix.second;
|
||||||
|
state current_state = state_suffix.first;
|
||||||
|
|
||||||
|
word middle;
|
||||||
|
middle.reserve(min_k + 1);
|
||||||
|
size_t minimal_size = min_k;
|
||||||
|
while (minimal_size || unfair_coin(generator)) {
|
||||||
|
const auto & preds = reverse_machine[current_state];
|
||||||
|
if(preds.empty()) {
|
||||||
|
cerr << "ERROR: no predecessors for this state!\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
using params = decltype(input_selection)::param_type;
|
||||||
|
const auto & input_state
|
||||||
|
= preds[input_selection(generator, params{0, preds.size() - 1})];
|
||||||
|
|
||||||
|
current_state = input_state.second;
|
||||||
|
middle.insert(middle.begin(), input_state.first);
|
||||||
|
|
||||||
|
if (minimal_size) minimal_size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto & prefix = prefixes[current_state];
|
||||||
|
|
||||||
|
output.apply(prefix);
|
||||||
|
output.apply(middle);
|
||||||
|
output.apply(suffix);
|
||||||
|
if(!output.reset()) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writer default_writer(std::vector<std::string> const & inputs) {
|
writer default_writer(std::vector<std::string> const & inputs) {
|
||||||
static const auto print_word = [&](word w) { for (auto && x : w) cout << inputs[x] << ' '; };
|
static const auto print_word = [&](word w) {
|
||||||
static const auto reset = [&] { cout << endl; };
|
for (auto && x : w) cout << inputs[x] << ' ';
|
||||||
|
};
|
||||||
|
static const auto reset = [&] {
|
||||||
|
cout << endl;
|
||||||
|
return bool(cout);
|
||||||
|
};
|
||||||
return {print_word, reset};
|
return {print_word, reset};
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
struct writer {
|
struct writer {
|
||||||
std::function<void(word)> apply; // store a part of a word
|
std::function<void(word)> apply; // store a part of a word
|
||||||
std::function<void(void)> reset; // flush
|
std::function<bool(void)> reset; // flush, if flase is returned, testing is stopped
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Performs exhaustive tests with \p k_max extra states (harmonized, e.g. HSI / DS)
|
/// \brief Performs exhaustive tests with \p k_max extra states (harmonized, e.g. HSI / DS)
|
||||||
|
@ -18,6 +18,10 @@ void test(mealy const & specification, transfer_sequences const & prefixes,
|
||||||
|
|
||||||
/// \brief Performs random non-exhaustive tests for more states (harmonized, e.g. HSI / DS)
|
/// \brief Performs random non-exhaustive tests for more states (harmonized, e.g. HSI / DS)
|
||||||
void randomized_test(mealy const & specification, transfer_sequences const & prefixes,
|
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, uint_fast32_t random_seed);
|
||||||
|
|
||||||
|
void randomized_test_suffix(mealy const & specification, transfer_sequences const & prefixes,
|
||||||
separating_family const & separating_family, size_t min_k,
|
separating_family const & separating_family, size_t min_k,
|
||||||
size_t rnd_length, writer const & output, uint_fast32_t random_seed);
|
size_t rnd_length, writer const & output, uint_fast32_t random_seed);
|
||||||
|
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -31,6 +31,7 @@ R"(Generate a test suite
|
||||||
--no-ds Only use the classical algorithm (hsi)
|
--no-ds Only use the classical algorithm (hsi)
|
||||||
--random-ds Choose randomly between the ds method or hsi method
|
--random-ds Choose randomly between the ds method or hsi method
|
||||||
--no-suffix Dont calculate anything smart, just do the random stuff
|
--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
|
||||||
)";
|
)";
|
||||||
|
|
||||||
using time_logger = silent_timer;
|
using time_logger = silent_timer;
|
||||||
|
@ -47,6 +48,7 @@ int main(int argc, char *argv[]) try {
|
||||||
const bool streaming = args.at("all").asBool() || args.at("fixed").asBool();
|
const bool streaming = args.at("all").asBool() || args.at("fixed").asBool();
|
||||||
const bool random_part = args.at("all").asBool() || args.at("random").asBool();
|
const bool random_part = args.at("all").asBool() || args.at("random").asBool();
|
||||||
const bool no_suffix = args.at("--no-suffix").asBool();
|
const bool no_suffix = args.at("--no-suffix").asBool();
|
||||||
|
const bool suffix_based = args.at("--suffix-based").asBool();
|
||||||
|
|
||||||
const bool seed_provided = bool(args.at("--seed"));
|
const bool seed_provided = bool(args.at("--seed"));
|
||||||
const uint_fast32_t seed = seed_provided ? args.at("--seed").asLong() : 0;
|
const uint_fast32_t seed = seed_provided ? args.at("--seed").asLong() : 0;
|
||||||
|
@ -153,7 +155,14 @@ int main(int argc, char *argv[]) try {
|
||||||
if(random_part){
|
if(random_part){
|
||||||
time_logger t("outputting all random tests");
|
time_logger t("outputting all random tests");
|
||||||
const auto k_max_ = streaming ? k_max + 1 : 0;
|
const auto k_max_ = streaming ? k_max + 1 : 0;
|
||||||
randomized_test(machine, transfer_sequences, separating_family, k_max_, rnd_length, default_writer(inputs), random_seeds[3]);
|
|
||||||
|
if (suffix_based) {
|
||||||
|
randomized_test_suffix(machine, transfer_sequences, separating_family, k_max_,
|
||||||
|
rnd_length, default_writer(inputs), random_seeds[3]);
|
||||||
|
} else {
|
||||||
|
randomized_test(machine, transfer_sequences, separating_family, k_max_, rnd_length,
|
||||||
|
default_writer(inputs), random_seeds[3]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (exception const & e) {
|
} catch (exception const & e) {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <read_mealy.hpp>
|
#include <read_mealy.hpp>
|
||||||
#include <separating_family.hpp>
|
#include <separating_family.hpp>
|
||||||
#include <splitting_tree.hpp>
|
#include <splitting_tree.hpp>
|
||||||
|
#include <test_suite.hpp>
|
||||||
#include <transfer_sequences.hpp>
|
#include <transfer_sequences.hpp>
|
||||||
#include <trie.hpp>
|
#include <trie.hpp>
|
||||||
|
|
||||||
|
@ -25,14 +26,15 @@ R"(FSM-based test methods
|
||||||
--version Show version
|
--version Show version
|
||||||
-s <seed>, --seed <seed> Specify a seed
|
-s <seed>, --seed <seed> Specify a seed
|
||||||
--non-random Iterate inputs in specified order (as occurring in input file)
|
--non-random Iterate inputs in specified order (as occurring in input file)
|
||||||
-k <states> Testing extra states [default: 0]
|
-k <states> Testing extra states [default: 1]
|
||||||
|
--print-suite Prints the whole test suite
|
||||||
)";
|
)";
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
const auto args = docopt::docopt(USAGE, {argv + 1, argv + argc}, true, __DATE__ __TIME__);
|
const auto args = docopt::docopt(USAGE, {argv + 1, argv + argc}, true, __DATE__ __TIME__);
|
||||||
|
|
||||||
const string filename = args.at("<file>").asString();
|
const string filename = args.at("<file>").asString();
|
||||||
const size_t k_max = args.at("-k").asLong() + 1;
|
const size_t k_max = args.at("-k").asLong();
|
||||||
|
|
||||||
const auto machine = [&] {
|
const auto machine = [&] {
|
||||||
if (filename.find(".txt") != string::npos) {
|
if (filename.find(".txt") != string::npos) {
|
||||||
|
@ -61,54 +63,71 @@ int main(int argc, char * argv[]) {
|
||||||
if (args.at("hsi").asBool()) {
|
if (args.at("hsi").asBool()) {
|
||||||
return create_adaptive_distinguishing_sequence(result(machine.graph_size));
|
return create_adaptive_distinguishing_sequence(result(machine.graph_size));
|
||||||
}
|
}
|
||||||
const auto tree
|
const auto tree = create_splitting_tree(machine, args.at("--non-random").asBool()
|
||||||
= create_splitting_tree(machine, args.at("--non-random").asBool() ? lee_yannakakis_style : randomized_lee_yannakakis_style, random_seeds[0]);
|
? lee_yannakakis_style
|
||||||
|
: randomized_lee_yannakakis_style,
|
||||||
|
random_seeds[0]);
|
||||||
return create_adaptive_distinguishing_sequence(tree);
|
return create_adaptive_distinguishing_sequence(tree);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto pairs_fut = async([&] {
|
auto pairs_fut = async([&] {
|
||||||
const auto tree
|
const auto tree = create_splitting_tree(machine, args.at("--non-random").asBool()
|
||||||
= create_splitting_tree(machine, args.at("--non-random").asBool() ? min_hopcroft_style : randomized_min_hopcroft_style, random_seeds[1]);
|
? min_hopcroft_style
|
||||||
|
: randomized_min_hopcroft_style,
|
||||||
|
random_seeds[1]);
|
||||||
return tree.root;
|
return tree.root;
|
||||||
});
|
});
|
||||||
|
|
||||||
auto prefixes_fut
|
auto prefixes_fut = async([&] {
|
||||||
= async([&] { return create_randomized_transfer_sequences(machine, 0, random_seeds[2]); });
|
return create_transfer_sequences(args.at("--non-random").asBool()
|
||||||
|
? canonical_transfer_sequences
|
||||||
auto middles_fut = async([&] {
|
: randomized_transfer_sequences,
|
||||||
vector<word> all_sequences(1);
|
machine, 0, random_seeds[2]);
|
||||||
for (size_t k = 0; k < k_max; ++k) {
|
|
||||||
const auto new_sequences = all_seqs(0, machine.input_size, all_sequences);
|
|
||||||
all_sequences.reserve(all_sequences.size() + new_sequences.size());
|
|
||||||
copy(begin(new_sequences), end(new_sequences), back_inserter(all_sequences));
|
|
||||||
}
|
|
||||||
return all_sequences;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto suffixes_fut
|
auto suffixes_fut
|
||||||
= async([&] { return create_separating_family(sequence_fut.get(), pairs_fut.get()); });
|
= async([&] { return create_separating_family(sequence_fut.get(), pairs_fut.get()); });
|
||||||
|
|
||||||
const auto prefixes = prefixes_fut.get();
|
|
||||||
const auto middles = middles_fut.get();
|
|
||||||
const auto suffixes = suffixes_fut.get();
|
|
||||||
trie<input> test_suite;
|
trie<input> test_suite;
|
||||||
|
word buffer;
|
||||||
|
|
||||||
const state start = 0;
|
const auto suffixes = suffixes_fut.get();
|
||||||
const word empty = {};
|
for(state s = 0; s < suffixes.size(); ++s){
|
||||||
for (auto && p : prefixes) {
|
clog << "suffixes for " << s << endl;
|
||||||
const state s1 = apply(machine, start, begin(p), end(p)).to;
|
for(auto s : suffixes[s].local_suffixes) {
|
||||||
const word w1 = concat(empty, p);
|
for(auto x : s){
|
||||||
for (auto && m : middles) {
|
clog << x;
|
||||||
const state s2 = apply(machine, s1, begin(m), end(m)).to;
|
}
|
||||||
const word w2 = concat(w1, m);
|
clog << endl;
|
||||||
const auto & suffixes_for_state = suffixes[s2].local_suffixes;
|
|
||||||
for (auto && s : suffixes_for_state) {
|
|
||||||
word test = concat(w2, s);
|
|
||||||
test_suite.insert(test);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto prefixes = prefixes_fut.get();
|
||||||
|
for(state s = 0; s < prefixes.size(); ++s) {
|
||||||
|
clog << "prefix for " << s << endl;
|
||||||
|
for(auto x : prefixes[s]) {
|
||||||
|
clog << x;
|
||||||
}
|
}
|
||||||
|
clog << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
test(machine, prefixes, suffixes, k_max,
|
||||||
|
{[&buffer](auto const & w) { buffer.insert(buffer.end(), w.begin(), w.end()); },
|
||||||
|
[&buffer, &test_suite]() {
|
||||||
|
test_suite.insert(buffer);
|
||||||
|
buffer.clear();
|
||||||
|
return true;
|
||||||
|
}});
|
||||||
|
|
||||||
const auto p = total_size(test_suite);
|
const auto p = total_size(test_suite);
|
||||||
cout << p.first << '\t' << p.second << '\t' << p.first + p.second << endl;
|
cout << p.first << '\t' << p.second << '\t' << p.first + p.second << endl;
|
||||||
|
|
||||||
|
if(args.at("--print-suite").asBool()){
|
||||||
|
test_suite.for_each([](const auto & w){
|
||||||
|
for(const auto & x : w) {
|
||||||
|
cout << x;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue