1
Fork 0
mirror of https://github.com/Jaxan/hybrid-ads.git synced 2025-04-27 15:07:45 +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
*_seq
*splitting_tree
*test_suite

View file

@ -5,6 +5,7 @@
#include <functional>
#include <numeric>
#include <queue>
#include <random>
#include <utility>
using namespace std;
@ -41,6 +42,12 @@ result create_splitting_tree(const mealy& g, options opt){
queue<reference_wrapper<splitting_tree>> work;
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 :)
const auto add_push_new_block = [&work](auto new_blocks, auto & boom) {
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(opt.randomized){
shuffle(begin(all_inputs), end(all_inputs), generator);
}
// 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 ret = apply(g, state, symbol);
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
for(input symbol = 0; symbol < P; ++symbol){
for(input symbol : all_inputs){
vector<bool> successor_states(N, false);
for(auto && state : boom.states){
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 {
bool check_validity = true;
bool cache_succesors = true;
bool randomized = false;
};
constexpr options lee_yannakakis_style{true, true};
constexpr options hopcroft_style{false, false};
constexpr options lee_yannakakis_style{true, true, 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

View file

@ -2,7 +2,10 @@
#include "mealy.hpp"
#include <algorithm>
#include <numeric>
#include <queue>
#include <random>
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<word> words(machine.graph_size);
queue<state> work;
work.push(s);
priority_queue<pair<int, state>> work;
work.push({0, s});
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();
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()].push_back(i);
work.push(v);
work.push({d, v});
}
}
return words;
}
std::vector<transfer_sequences> create_all_transfer_sequences(const mealy& machine){
vector<transfer_sequences> transfer_sequences(machine.graph_size);
for(state s = 0; s < machine.graph_size; ++s){
transfer_sequences[s.base()] = create_transfer_sequences(machine, s);
transfer_sequences create_randomized_transfer_sequences(const mealy & machine, state s){
random_device rd;
mt19937 generator(rd());
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>;
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 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 = [&]{
time_logger t("reading file " + filename);
if(use_stdio){
@ -45,7 +50,7 @@ int main(int argc, char *argv[]){
auto all_pair_seperating_sequences_fut = async([&]{
const auto splitting_tree_hopcroft = [&]{
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 = [&]{
@ -59,7 +64,7 @@ int main(int argc, char *argv[]){
auto sequence_fut = async([&]{
const auto splitting_tree = [&]{
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 = [&]{
@ -72,7 +77,11 @@ int main(int argc, char *argv[]){
auto transfer_sequences_fut = std::async([&]{
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([&]{
@ -84,11 +93,13 @@ int main(int argc, char *argv[]){
vector<discrete_distribution<input>> distributions(machine.graph_size);
for(state s = 0; s < machine.graph_size; ++s){
vector<double> r_cache(machine.input_size, 0);
for(input i = 0; i < machine.input_size; ++i){
const auto test1 = apply(machine, s, i).output != machine.output_indices.at("quiescence");
const auto test2 = apply(machine, s, i).to != s;
r_cache[i.base()] = test1 + test2;
vector<double> r_cache(machine.input_size, 1);
if(use_relevances){
for(input i = 0; i < machine.input_size; ++i){
//const auto test1 = apply(machine, s, i).output != machine.output_indices.at("quiescence");
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));
@ -185,7 +196,7 @@ int main(int argc, char *argv[]){
std::mt19937 generator(rd());
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;
auto relevant_inputs = relevant_inputs_fut.get();
@ -200,7 +211,7 @@ int main(int argc, char *argv[]){
vector<input> m;
m.reserve(k_max + 2);
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);
m.push_back(i);
current_state = apply(machine, current_state, i).to;