mirror of
https://github.com/Jaxan/hybrid-ads.git
synced 2025-04-28 07:27:45 +02:00
Adds randomization
This commit is contained in:
parent
e4a7cf9933
commit
5512b57c75
6 changed files with 82 additions and 25 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@
|
||||||
*.pdf
|
*.pdf
|
||||||
*_seq
|
*_seq
|
||||||
*splitting_tree
|
*splitting_tree
|
||||||
|
*test_suite
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <random>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -41,6 +42,12 @@ result create_splitting_tree(const mealy& g, options opt){
|
||||||
queue<reference_wrapper<splitting_tree>> work;
|
queue<reference_wrapper<splitting_tree>> work;
|
||||||
size_t days_without_progress = 0;
|
size_t days_without_progress = 0;
|
||||||
|
|
||||||
|
/* List of inputs, will be shuffled in case of randomizations */
|
||||||
|
vector<input> all_inputs(g.input_size);
|
||||||
|
iota(begin(all_inputs), end(all_inputs), 0);
|
||||||
|
random_device rd;
|
||||||
|
mt19937 generator(rd());
|
||||||
|
|
||||||
// Some lambda functions capturing some state, makes the code a bit easier :)
|
// Some lambda functions capturing some state, makes the code a bit easier :)
|
||||||
const auto add_push_new_block = [&work](auto new_blocks, auto & boom) {
|
const auto add_push_new_block = [&work](auto new_blocks, auto & boom) {
|
||||||
boom.children.assign(new_blocks.size(), splitting_tree(0, boom.depth + 1));
|
boom.children.assign(new_blocks.size(), splitting_tree(0, boom.depth + 1));
|
||||||
|
@ -83,8 +90,12 @@ result create_splitting_tree(const mealy& g, options opt){
|
||||||
|
|
||||||
if(boom.states.size() == 1) continue;
|
if(boom.states.size() == 1) continue;
|
||||||
|
|
||||||
|
if(opt.randomized){
|
||||||
|
shuffle(begin(all_inputs), end(all_inputs), generator);
|
||||||
|
}
|
||||||
|
|
||||||
// First try to split on output
|
// First try to split on output
|
||||||
for(input symbol = 0; symbol < P; ++symbol){
|
for(input symbol : all_inputs){
|
||||||
const auto new_blocks = partition_(begin(boom.states), end(boom.states), [symbol, depth, &g, &update_succession](state state){
|
const auto new_blocks = partition_(begin(boom.states), end(boom.states), [symbol, depth, &g, &update_succession](state state){
|
||||||
const auto ret = apply(g, state, symbol);
|
const auto ret = apply(g, state, symbol);
|
||||||
update_succession(state, ret.to, depth);
|
update_succession(state, ret.to, depth);
|
||||||
|
@ -105,7 +116,7 @@ result create_splitting_tree(const mealy& g, options opt){
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then try to split on state
|
// Then try to split on state
|
||||||
for(input symbol = 0; symbol < P; ++symbol){
|
for(input symbol : all_inputs){
|
||||||
vector<bool> successor_states(N, false);
|
vector<bool> successor_states(N, false);
|
||||||
for(auto && state : boom.states){
|
for(auto && state : boom.states){
|
||||||
successor_states[apply(g, state, symbol).to.base()] = true;
|
successor_states[apply(g, state, symbol).to.base()] = true;
|
||||||
|
|
|
@ -58,11 +58,13 @@ const splitting_tree & lca(const splitting_tree & root, Fun && f){
|
||||||
struct options {
|
struct options {
|
||||||
bool check_validity = true;
|
bool check_validity = true;
|
||||||
bool cache_succesors = true;
|
bool cache_succesors = true;
|
||||||
|
bool randomized = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr options lee_yannakakis_style{true, true};
|
constexpr options lee_yannakakis_style{true, true, false};
|
||||||
constexpr options hopcroft_style{false, false};
|
constexpr options hopcroft_style{false, false, false};
|
||||||
|
constexpr options randomized_lee_yannakakis_style{true, true, true};
|
||||||
|
constexpr options randomized_hopcroft_style{false, false, true};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The algorithm to create a splitting tree also produces some other useful
|
* The algorithm to create a splitting tree also produces some other useful
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
#include "mealy.hpp"
|
#include "mealy.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -10,10 +13,12 @@ transfer_sequences create_transfer_sequences(const mealy& machine, state s){
|
||||||
vector<bool> visited(machine.graph_size, false);
|
vector<bool> visited(machine.graph_size, false);
|
||||||
vector<word> words(machine.graph_size);
|
vector<word> words(machine.graph_size);
|
||||||
|
|
||||||
queue<state> work;
|
priority_queue<pair<int, state>> work;
|
||||||
work.push(s);
|
work.push({0, s});
|
||||||
while(!work.empty()){
|
while(!work.empty()){
|
||||||
const auto u = work.front();
|
const auto p = work.top();
|
||||||
|
const auto u = p.second;
|
||||||
|
const auto d = p.first - 1;
|
||||||
work.pop();
|
work.pop();
|
||||||
|
|
||||||
if(visited[u.base()]) continue;
|
if(visited[u.base()]) continue;
|
||||||
|
@ -26,17 +31,44 @@ transfer_sequences create_transfer_sequences(const mealy& machine, state s){
|
||||||
|
|
||||||
words[v.base()] = words[u.base()];
|
words[v.base()] = words[u.base()];
|
||||||
words[v.base()].push_back(i);
|
words[v.base()].push_back(i);
|
||||||
work.push(v);
|
work.push({d, v});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return words;
|
return words;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<transfer_sequences> create_all_transfer_sequences(const mealy& machine){
|
transfer_sequences create_randomized_transfer_sequences(const mealy & machine, state s){
|
||||||
vector<transfer_sequences> transfer_sequences(machine.graph_size);
|
random_device rd;
|
||||||
for(state s = 0; s < machine.graph_size; ++s){
|
mt19937 generator(rd());
|
||||||
transfer_sequences[s.base()] = create_transfer_sequences(machine, s);
|
|
||||||
|
vector<bool> visited(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));
|
||||||
|
|
||||||
|
priority_queue<pair<int, state>> work;
|
||||||
|
work.push({0, s});
|
||||||
|
while(!work.empty()){
|
||||||
|
const auto p = work.top();
|
||||||
|
const auto u = p.second;
|
||||||
|
const auto d = p.first - 1;
|
||||||
|
work.pop();
|
||||||
|
|
||||||
|
if(visited[u.base()]) continue;
|
||||||
|
|
||||||
|
visited[u.base()] = true;
|
||||||
|
|
||||||
|
shuffle(begin(all_inputs), end(all_inputs), generator);
|
||||||
|
for(input i : all_inputs){
|
||||||
|
const auto v = apply(machine, u, i).to;
|
||||||
|
if(visited[v.base()]) continue;
|
||||||
|
|
||||||
|
words[v.base()] = words[u.base()];
|
||||||
|
words[v.base()].push_back(i);
|
||||||
|
work.push({d, v});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return transfer_sequences;
|
|
||||||
|
return words;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,4 +7,4 @@ struct mealy;
|
||||||
using transfer_sequences = std::vector<word>;
|
using transfer_sequences = std::vector<word>;
|
||||||
|
|
||||||
transfer_sequences create_transfer_sequences(mealy const & machine, state s);
|
transfer_sequences create_transfer_sequences(mealy const & machine, state s);
|
||||||
std::vector<transfer_sequences> create_all_transfer_sequences(mealy const & machine);
|
transfer_sequences create_randomized_transfer_sequences(mealy const & machine, state s);
|
||||||
|
|
31
src/main.cpp
31
src/main.cpp
|
@ -33,6 +33,11 @@ int main(int argc, char *argv[]){
|
||||||
const bool statistics = mode == "stats";
|
const bool statistics = mode == "stats";
|
||||||
const bool compress_suite = mode == "compr";
|
const bool compress_suite = mode == "compr";
|
||||||
|
|
||||||
|
const bool use_relevances = true;
|
||||||
|
const bool randomize_prefixes = true;
|
||||||
|
const bool randomize_hopcroft = true;
|
||||||
|
const bool randomize_lee_yannakakis = true;
|
||||||
|
|
||||||
const auto machine = [&]{
|
const auto machine = [&]{
|
||||||
time_logger t("reading file " + filename);
|
time_logger t("reading file " + filename);
|
||||||
if(use_stdio){
|
if(use_stdio){
|
||||||
|
@ -45,7 +50,7 @@ int main(int argc, char *argv[]){
|
||||||
auto all_pair_seperating_sequences_fut = async([&]{
|
auto all_pair_seperating_sequences_fut = async([&]{
|
||||||
const auto splitting_tree_hopcroft = [&]{
|
const auto splitting_tree_hopcroft = [&]{
|
||||||
time_logger t("creating hopcroft splitting tree");
|
time_logger t("creating hopcroft splitting tree");
|
||||||
return create_splitting_tree(machine, hopcroft_style);
|
return create_splitting_tree(machine, randomize_hopcroft ? randomized_hopcroft_style : hopcroft_style);
|
||||||
}();
|
}();
|
||||||
|
|
||||||
const auto all_pair_seperating_sequences = [&]{
|
const auto all_pair_seperating_sequences = [&]{
|
||||||
|
@ -59,7 +64,7 @@ int main(int argc, char *argv[]){
|
||||||
auto sequence_fut = async([&]{
|
auto sequence_fut = async([&]{
|
||||||
const auto splitting_tree = [&]{
|
const auto splitting_tree = [&]{
|
||||||
time_logger t("Lee & Yannakakis I");
|
time_logger t("Lee & Yannakakis I");
|
||||||
return create_splitting_tree(machine, lee_yannakakis_style);
|
return create_splitting_tree(machine, randomize_lee_yannakakis ? randomized_lee_yannakakis_style : lee_yannakakis_style);
|
||||||
}();
|
}();
|
||||||
|
|
||||||
const auto sequence = [&]{
|
const auto sequence = [&]{
|
||||||
|
@ -72,7 +77,11 @@ int main(int argc, char *argv[]){
|
||||||
|
|
||||||
auto transfer_sequences_fut = std::async([&]{
|
auto transfer_sequences_fut = std::async([&]{
|
||||||
time_logger t("determining transfer sequences");
|
time_logger t("determining transfer sequences");
|
||||||
return create_transfer_sequences(machine, 0);
|
if(randomize_prefixes){
|
||||||
|
return create_randomized_transfer_sequences(machine, 0);
|
||||||
|
} else {
|
||||||
|
return create_transfer_sequences(machine, 0);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
auto inputs_fut = std::async([&]{
|
auto inputs_fut = std::async([&]{
|
||||||
|
@ -84,11 +93,13 @@ int main(int argc, char *argv[]){
|
||||||
vector<discrete_distribution<input>> distributions(machine.graph_size);
|
vector<discrete_distribution<input>> distributions(machine.graph_size);
|
||||||
|
|
||||||
for(state s = 0; s < machine.graph_size; ++s){
|
for(state s = 0; s < machine.graph_size; ++s){
|
||||||
vector<double> r_cache(machine.input_size, 0);
|
vector<double> r_cache(machine.input_size, 1);
|
||||||
for(input i = 0; i < machine.input_size; ++i){
|
if(use_relevances){
|
||||||
const auto test1 = apply(machine, s, i).output != machine.output_indices.at("quiescence");
|
for(input i = 0; i < machine.input_size; ++i){
|
||||||
const auto test2 = apply(machine, s, i).to != s;
|
//const auto test1 = apply(machine, s, i).output != machine.output_indices.at("quiescence");
|
||||||
r_cache[i.base()] = test1 + test2;
|
const auto test2 = apply(machine, s, i).to != s;
|
||||||
|
r_cache[i.base()] = 0.1 + test2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
distributions[s.base()] = discrete_distribution<input>(begin(r_cache), end(r_cache));
|
distributions[s.base()] = discrete_distribution<input>(begin(r_cache), end(r_cache));
|
||||||
|
@ -185,7 +196,7 @@ int main(int argc, char *argv[]){
|
||||||
std::mt19937 generator(rd());
|
std::mt19937 generator(rd());
|
||||||
|
|
||||||
uniform_int_distribution<size_t> prefix_selection(0, transfer_sequences.size());
|
uniform_int_distribution<size_t> prefix_selection(0, transfer_sequences.size());
|
||||||
uniform_int_distribution<> fair_coin(0, 1);
|
uniform_int_distribution<> unfair_coin(0, 2); // expected flips is p / (p-1)^2, where p is succes probability
|
||||||
uniform_int_distribution<size_t> suffix_selection;
|
uniform_int_distribution<size_t> suffix_selection;
|
||||||
auto relevant_inputs = relevant_inputs_fut.get();
|
auto relevant_inputs = relevant_inputs_fut.get();
|
||||||
|
|
||||||
|
@ -200,7 +211,7 @@ int main(int argc, char *argv[]){
|
||||||
vector<input> m;
|
vector<input> m;
|
||||||
m.reserve(k_max + 2);
|
m.reserve(k_max + 2);
|
||||||
size_t minimal_size = k_max + 1;
|
size_t minimal_size = k_max + 1;
|
||||||
while(minimal_size || fair_coin(generator)){
|
while(minimal_size || unfair_coin(generator)){
|
||||||
input i = relevant_inputs[current_state.base()](generator);
|
input i = relevant_inputs[current_state.base()](generator);
|
||||||
m.push_back(i);
|
m.push_back(i);
|
||||||
current_state = apply(machine, current_state, i).to;
|
current_state = apply(machine, current_state, i).to;
|
||||||
|
|
Loading…
Add table
Reference in a new issue