1
Fork 0
mirror of https://github.com/Jaxan/hybrid-ads.git synced 2025-04-27 23:17:44 +02:00

Adds randomization

This commit is contained in:
Joshua Moerman 2015-03-18 09:57:08 +01:00
parent e4a7cf9933
commit 5512b57c75
6 changed files with 82 additions and 25 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@
*.pdf *.pdf
*_seq *_seq
*splitting_tree *splitting_tree
*test_suite

View file

@ -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;

View file

@ -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

View file

@ -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;
} }

View file

@ -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);

View file

@ -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;