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:
parent
e4a7cf9933
commit
5512b57c75
6 changed files with 82 additions and 25 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@
|
|||
*.pdf
|
||||
*_seq
|
||||
*splitting_tree
|
||||
*test_suite
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
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 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;
|
||||
|
|
Loading…
Add table
Reference in a new issue