1
Fork 0
mirror of https://github.com/Jaxan/hybrid-ads.git synced 2025-04-27 15:07:45 +02:00

Simplifies code by removing phantom typing.

Also removes other unused tools.
This commit is contained in:
Joshua Moerman 2015-04-07 08:50:18 +02:00
parent 3de4f29a87
commit 598e72b880
18 changed files with 71 additions and 293 deletions

View file

@ -33,11 +33,11 @@ adaptive_distinguishing_sequence create_adaptive_distinguishing_sequence(const r
vector<bool> states(N, false);
for(auto && state : node.CI){
states[state.first.base()] = true;
states[state.first] = true;
}
const auto & oboom = lca(root, [&states](state state) -> bool{
return states[state.base()];
return states[state];
});
if(oboom.children.empty()) continue;
@ -55,7 +55,7 @@ adaptive_distinguishing_sequence create_adaptive_distinguishing_sequence(const r
} else if(node.CI[i].first > c.states[j]) {
j++;
} else {
const auto curr = succession[oboom.depth][node.CI[i].first.base()];
const auto curr = succession[oboom.depth][node.CI[i].first];
const auto init = node.CI[i].second;
new_c.CI.push_back({curr, init});
i++;

View file

@ -1,31 +0,0 @@
#pragma once
#include "phantom.hpp"
#include "mealy.hpp"
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <iostream>
#include <fstream>
namespace boost {
namespace serialization {
template<class Archive, typename B, typename T>
void serialize(Archive & ar, phantom<B, T> & value, const unsigned int /*version*/){
ar & value.x;
}
} // namespace serialization
} // namespace boost

View file

@ -31,22 +31,22 @@ struct mealy {
inline auto is_complete(const mealy & m){
for(state n = 0; n < m.graph_size; ++n){
if(m.graph[n.base()].size() != m.input_size) return false;
for(auto && e : m.graph[n.base()]) if(e.to == -1 || e.output == -1) return false;
if(m.graph[n].size() != m.input_size) return false;
for(auto && e : m.graph[n]) if(e.to == -1 || e.output == -1) return false;
}
return true;
}
inline auto apply(mealy const & m, state state, input input){
return m.graph[state.base()][input.base()];
return m.graph[state][input];
}
template <typename Iterator>
auto apply(mealy const & m, state state, Iterator b, Iterator e){
mealy::edge ret{state, -1};
mealy::edge ret;
ret.to = state;
while(b != e){
ret = apply(m, state, *b++);
state = ret.to;
ret = apply(m, ret.to, *b++);
}
return ret;
}

View file

@ -1,50 +0,0 @@
#pragma once
#include <boost/operators.hpp>
#include <iosfwd>
template <typename Base, typename T>
struct phantom : boost::operators<phantom<Base, T>>, boost::shiftable<phantom<Base, T>> {
phantom() = default;
phantom(Base y) : x(y) {}
phantom(phantom const &) = default;
phantom& operator=(phantom const &) = default;
phantom(phantom &&) = default;
phantom& operator=(phantom &&) = default;
explicit operator Base() const { return x; }
Base base() const { return x; }
Base x;
#define IMPL(op) \
phantom & operator op (phantom rh) { \
x op rh.x; \
return *this; \
}
IMPL(+=)
IMPL(-=)
IMPL(*=)
IMPL(/=)
IMPL(%=)
IMPL(|=)
IMPL(&=)
IMPL(^=)
IMPL(<<=)
IMPL(>>=)
#undef IMPL
phantom & operator++() { ++x; return *this; }
phantom & operator--() { --x; return *this; }
bool operator<(phantom rh) const { return x < rh.x; }
bool operator==(phantom rh) const { return x == rh.x; }
};
template <typename B, typename T>
std::ostream & operator<<(std::ostream & out, phantom<B, T> p){ return out << p.x; }
template <typename B, typename T>
std::istream & operator>>(std::istream & in, phantom<B, T> & p){ return in >> p.x; }

View file

@ -54,15 +54,15 @@ mealy read_mealy_from_dot(std::istream & in, translation & t){
if(t.output_indices.count(output) < 1) t.output_indices[output] = t.max_output++;
// add edge
m.graph.resize(max_state.base());
auto & v = m.graph[state_indices[lh].base()];
v.resize(t.max_input.base());
v[t.input_indices[input].base()] = {state_indices[rh], t.output_indices[output]};
m.graph.resize(max_state);
auto & v = m.graph[state_indices[lh]];
v.resize(t.max_input);
v[t.input_indices[input]] = {state_indices[rh], t.output_indices[output]};
}
m.graph_size = max_state.base();
m.input_size = t.max_input.base();
m.output_size = t.max_output.base();
m.graph_size = max_state;
m.input_size = t.max_input;
m.output_size = t.max_output;
if(m.graph_size == 0) throw runtime_error("Empty state set");
if(m.input_size == 0) throw runtime_error("Empty input set");

View file

@ -32,7 +32,7 @@ template <typename T>
std::vector<std::string> create_reverse_map(std::map<std::string, T> const & indices){
std::vector<std::string> ret(indices.size());
for(auto&& p : indices){
ret[p.second.base()] = p.first;
ret[p.second] = p.first;
}
return ret;
}

View file

@ -24,7 +24,7 @@ seperating_family create_seperating_family(const adaptive_distinguishing_sequenc
// add sequence to this leave
for(auto && p : node.CI){
const auto state = p.second;
seperating_family[state.base()].push_back(word);
seperating_family[state].push_back(word);
}
// if the leaf is not a singleton, we need the all_pair seperating seqs
@ -33,7 +33,7 @@ seperating_family create_seperating_family(const adaptive_distinguishing_sequenc
const auto s = p.second;
const auto t = q.second;
if(s == t) continue;
seperating_family[s.base()].push_back(all_pair_seperating_sequences[s.base()][t.base()]);
seperating_family[s].push_back(all_pair_seperating_sequences[s][t]);
}
}

View file

@ -26,10 +26,10 @@ seperating_matrix create_all_pair_seperating_sequences(const splitting_tree & ro
while(jt != ed){
for(auto && s : it->states){
for(auto && t : jt->states){
assert(all_pair_seperating_sequences[t.base()][s.base()].empty());
assert(all_pair_seperating_sequences[s.base()][t.base()].empty());
all_pair_seperating_sequences[t.base()][s.base()] = node.seperator;
all_pair_seperating_sequences[s.base()][t.base()] = node.seperator;
assert(all_pair_seperating_sequences[t][s].empty());
assert(all_pair_seperating_sequences[s][t].empty());
all_pair_seperating_sequences[t][s] = node.seperator;
all_pair_seperating_sequences[s][t] = node.seperator;
}
}
jt++;

View file

@ -68,7 +68,7 @@ result create_splitting_tree(const mealy& g, options opt){
for(auto && block : blocks) {
const auto new_blocks = partition_(begin(block), end(block), [symbol, &g](state state){
return apply(g, state, symbol).to.base();
return apply(g, state, symbol).to;
}, N);
for(auto && new_block : new_blocks){
if(new_block.size() != 1) return false;
@ -78,7 +78,7 @@ result create_splitting_tree(const mealy& g, options opt){
};
const auto update_succession = [N, &succession](state s, state t, size_t depth){
if(succession.size() < depth+1) succession.resize(depth+1, vector<state>(N, -1));
succession[depth][s.base()] = t;
succession[depth][s] = t;
};
// We'll start with the root, obviously
@ -99,7 +99,7 @@ result create_splitting_tree(const mealy& g, options opt){
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);
return ret.output.base();
return ret.output;
}, Q);
// no split -> continue with other input symbols
@ -119,11 +119,11 @@ result create_splitting_tree(const mealy& g, options opt){
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;
successor_states[apply(g, state, symbol).to] = true;
}
const auto & oboom = lca(root, [&successor_states](state state) -> bool{
return successor_states[state.base()];
return successor_states[state];
});
// a leaf, hence not a split -> try other symbols
@ -134,7 +134,7 @@ result create_splitting_tree(const mealy& g, options opt){
const auto new_blocks = partition_(begin(boom.states), end(boom.states), [word, depth, &g, &update_succession](state state){
const auto ret = apply(g, state, begin(word), end(word));
update_succession(state, ret.to, depth);
return ret.output.base();
return ret.output;
}, Q);
// not a valid split -> continue

View file

@ -21,16 +21,16 @@ transfer_sequences create_transfer_sequences(const mealy& machine, state s){
const auto d = p.first - 1;
work.pop();
if(visited[u.base()]) continue;
if(visited[u]) continue;
visited[u.base()] = true;
visited[u] = true;
for(input i = 0; i < machine.input_size; ++i){
const auto v = apply(machine, u, i).to;
if(visited[v.base()]) continue;
if(visited[v]) continue;
words[v.base()] = words[u.base()];
words[v.base()].push_back(i);
words[v] = words[u];
words[v].push_back(i);
work.push({d, v});
}
}
@ -55,17 +55,17 @@ transfer_sequences create_randomized_transfer_sequences(const mealy & machine, s
const auto d = p.first - 1;
work.pop();
if(visited[u.base()]) continue;
if(visited[u]) continue;
visited[u.base()] = true;
visited[u] = 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;
if(visited[v]) continue;
words[v.base()] = words[u.base()];
words[v.base()].push_back(i);
words[v] = words[u];
words[v].push_back(i);
work.push({d, v});
}
}

View file

@ -1,15 +1,11 @@
#pragma once
#include "phantom.hpp"
#include <vector>
/* We use size_t's for easy indexing. But we do not want to mix states and
* inputs. We use phantom typing to "generate" distinguished types :).
*/
using state = phantom<size_t, struct state_tag>;
using input = phantom<size_t, struct input_tag>;
using output = phantom<size_t, struct output_tag>;
// We use size_ts for fast indexing. Note that there is little type safety here
using state = size_t;
using input = size_t;
using output = size_t;
using word = std::vector<input>;
@ -24,7 +20,7 @@ std::vector<T> concat(std::vector<T> const & l, std::vector<T> const & r){
// extends all words in seqs by all input symbols. Used to generate *all* strings
inline std::vector<word> all_seqs(input min, input max, std::vector<word> const & seqs){
std::vector<word> ret((max.base() - min.base()) * seqs.size());
std::vector<word> ret((max - min) * seqs.size());
auto it = begin(ret);
for(auto const & x : seqs){
for(input i = min; i < max; ++i){

View file

@ -1,82 +0,0 @@
#include <mealy.hpp>
#include <read_mealy_from_dot.hpp>
#include <io.hpp>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
using namespace std;
template <typename T>
vector<T> resize_new(vector<T> const & in, size_t N){
vector<T> ret(N);
copy_n(in.begin(), N, ret.begin());
return ret;
}
struct mealy_with_maps {
mealy machine;
map<string, input> inputs;
vector<string> outputs;
};
vector<string> conform(mealy_with_maps const & spec, mealy_with_maps const & impl, vector<vector<string>> const & suite){
for(auto && test : suite){
state s = 0;
state t = 0;
size_t count = 0;
for(auto && i : test){
const auto i1 = spec.inputs.at(i);
const auto r1 = apply(spec.machine, s, i1);
const auto o1 = spec.outputs[r1.output.base()];
s = r1.to;
const auto i2 = impl.inputs.at(i);
const auto r2 = apply(impl.machine, t, i2);
const auto o2 = impl.outputs[r2.output.base()];
t = r2.to;
if(o1 != o2){
return resize_new(test, count+1);
}
count++;
}
}
return {};
}
vector<vector<string>> open_suite(string suite_filename){
boost::iostreams::filtering_istream suite_file;
suite_file.push(boost::iostreams::gzip_decompressor());
suite_file.push(boost::iostreams::file_descriptor_source(suite_filename));
boost::archive::text_iarchive archive(suite_file);
vector<vector<string>> suite;
archive >> suite;
return suite;
}
int main(int argc, char *argv[]){
if(argc != 3) return 1;
const auto spec = read_mealy_from_dot(argv[1]);
const auto spec_o_map = create_reverse_map(spec.second.output_indices);
const auto impl = read_mealy_from_dot(argv[2]);
const auto impl_o_map = create_reverse_map(impl.second.output_indices);
const auto suite = open_suite(argv[1] + string("test_suite"));
const auto counter_example = conform({spec.first, spec.second.input_indices, spec_o_map}, {impl.first, impl.second.input_indices, impl_o_map}, suite);
if(counter_example.empty()){
cerr << "No counter example found" << endl;
}
for(auto && i : counter_example) cout << i << ' ';
cout << endl;
}

View file

@ -101,11 +101,11 @@ int main(int argc, char *argv[]) try {
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;
r_cache[i] = 0.1 + test2;
}
}
distributions[s.base()] = discrete_distribution<input>(begin(r_cache), end(r_cache));
distributions[s] = discrete_distribution<input>(begin(r_cache), end(r_cache));
}
return distributions;
});
@ -122,7 +122,7 @@ int main(int argc, char *argv[]) try {
const auto inputs = inputs_fut.get();
const auto print_word = [&](auto w){
for(auto && x : w) cout << inputs[x.base()] << ' ';
for(auto && x : w) cout << inputs[x] << ' ';
};
if(statistics){
@ -176,9 +176,9 @@ int main(int argc, char *argv[]) try {
for(int k = 0; k <= k_max; ++k){
cerr << "*** K = " << k << endl;
for(state s = 0; s < machine.graph_size; ++s){
const auto prefix = transfer_sequences[s.base()];
const auto prefix = transfer_sequences[s];
for(auto && suffix : seperating_family[s.base()]){
for(auto && suffix : seperating_family[s]){
for(auto && r : all_sequences){
print_word(prefix);
print_word(r);
@ -214,14 +214,14 @@ int main(int argc, char *argv[]) try {
m.reserve(k_max + 2);
size_t minimal_size = k_max + 1;
while(minimal_size || unfair_coin(generator)){
input i = relevant_inputs[current_state.base()](generator);
input i = relevant_inputs[current_state](generator);
m.push_back(i);
current_state = apply(machine, current_state, i).to;
if(minimal_size) minimal_size--;
}
using params = uniform_int_distribution<size_t>::param_type;
const auto & suffixes = seperating_family[current_state.base()];
const auto & suffixes = seperating_family[current_state];
const auto & s = suffixes[suffix_selection(generator, params{0, suffixes.size()-1})];
print_word(p);

View file

@ -16,13 +16,13 @@ auto create_transfer_sequences(const mealy& machine, const state s, const input
const auto u = work.front();
work.pop();
if(visited[u.base()]) continue;
visited[u.base()] = true;
if(visited[u]) continue;
visited[u] = true;
for(input i = 0; i < machine.input_size; ++i){
if(i == ignore) continue;
const auto v = apply(machine, u, i).to;
if(visited[v.base()]) continue;
if(visited[v]) continue;
work.push(v);
}
}
@ -40,7 +40,7 @@ int main(int argc, char *argv[]){
// vector<vector<bool>> table(machine.input_size);
// for(input i = 0; i < machine.input_size; ++i){
// table[i.base()] = create_transfer_sequences(machine, 0, i);
// table[i] = create_transfer_sequences(machine, 0, i);
// }
// note the wrong iteration ;D

View file

@ -1,30 +0,0 @@
#include <phantom.hpp>
#include <iostream>
template <typename T>
using phantom_int = phantom<int, T>;
struct state_tag;
using state = phantom_int<state_tag>;
struct input_tag;
using input = phantom_int<input_tag>;
int main(int argc, char *argv[]){
state x = 5;
x += 5;
input y = 9;
y -= 9;
y++;
std::cout << (x - 1) << std::endl;
std::cout << (y << 1) << std::endl;
// std::cout << x+y << std::endl; // does not compile
for(input i = 0; i < 10; ++i){
std::cout << i << ", ";
}
std::cout << std::endl;
}

View file

@ -54,10 +54,10 @@ int main(int argc, char *argv[]){
for(auto && p : state_cover){
state s = 0;
for(auto && inp : p){
if(!visited[s.base()]) visited[s.base()] = i;
if(!visited[s]) visited[s] = i;
s = apply(machine, s, inp).to;
}
if(!visited[s.base()]) visited[s.base()] = i;
if(!visited[s]) visited[s] = i;
}
}
@ -72,21 +72,21 @@ int main(int argc, char *argv[]){
out << "digraph {\n";
for(state s = 0; s < machine.graph_size; ++s){
bool is_visited = visited[s.base()] ? (visited[s.base()].value() <= i) : false;
bool is_visited = visited[s] ? (visited[s].value() <= i) : false;
out << "\t" << "s" << s << " [";
out << "color=\"" << (is_visited ? "green" : "red") << "\"" << ", ";
out << "pos=\"" << positions[s.base()].first << "," << positions[s.base()].second << "\"";
out << "pos=\"" << positions[s].first << "," << positions[s].second << "\"";
out << "]\n";
}
for(state s = 0; s < machine.graph_size; ++s){
vector<bool> visited(machine.graph_size, false);
visited[s.base()] = true;
visited[s] = true;
for(input i = 0; i < machine.input_size; ++i){
const auto t = apply(machine, s, i).to;
if(visited[t.base()]) continue;
if(visited[t]) continue;
out << "\t" << "s" << s << " -> " << "s" << t << "\n";
visited[t.base()] = true;
visited[t] = true;
}
}

View file

@ -42,12 +42,12 @@ int main(int argc, char *argv[]){
const state s = work.front();
work.pop();
if(visited[s.base()]) continue;
visited[s.base()] = true;
if(visited[s]) continue;
visited[s] = true;
for(auto x : subalphabet){
const state t = apply(machine, s, x).to;
if(!visited[t.base()]) work.push(t);
if(!visited[t]) work.push(t);
}
}
@ -56,21 +56,21 @@ int main(int argc, char *argv[]){
out << "digraph {\n";
for(state s = 0; s < machine.graph_size; ++s){
bool is_visited = visited[s.base()];
bool is_visited = visited[s];
out << "\t" << "s" << s << " [";
out << "color=\"" << (is_visited ? "green" : "red") << "\"" << ", ";
out << "pos=\"" << positions[s.base()].first << "," << positions[s.base()].second << "\"";
out << "pos=\"" << positions[s].first << "," << positions[s].second << "\"";
out << "]\n";
}
for(state s = 0; s < machine.graph_size; ++s){
vector<bool> visited(machine.graph_size, false);
visited[s.base()] = true;
visited[s] = true;
for(input i = 0; i < machine.input_size; ++i){
const auto t = apply(machine, s, i).to;
if(visited[t.base()]) continue;
if(visited[t]) continue;
out << "\t" << "s" << s << " -> " << "s" << t << "\n";
visited[t.base()] = true;
visited[t] = true;
}
}

View file

@ -1,4 +1,3 @@
#include <io.hpp>
#include <mealy.hpp>
#include <read_mealy_from_dot.hpp>
@ -18,33 +17,9 @@ void print_stats_for_machine(string filename){
cout << '\t' << machine.output_size << " outputs\n";
}
void print_stats_for_suite(string filename){
boost::iostreams::filtering_istream suite_file;
suite_file.push(boost::iostreams::gzip_decompressor());
suite_file.push(boost::iostreams::file_descriptor_source(filename));
boost::archive::text_iarchive archive(suite_file);
vector<vector<string>> suite;
archive >> suite;
const auto & longest = *max_element(suite.begin(), suite.end(), [](const auto & x, const auto & y){ return x.size() < y.size(); });
const auto total_length = accumulate(suite.begin(), suite.end(), 0, [](const auto & x, const auto & y){ return x + y.size(); });
cout << "suite " << filename << " has\n";
cout << '\t' << suite.size() << " sequences\n";
cout << '\t' << total_length << " input symbols in total\n";
cout << '\t' << double(total_length) / suite.size() << " input symbols on average per test\n";
cout << '\t' << longest.size() << " inputs symbols in the longest test\n";
}
int main(int argc, char *argv[]){
if(argc != 2) return 37;
const string filename = argv[1];
if(filename.find("test_suite") == string::npos){
print_stats_for_machine(filename);
} else {
print_stats_for_suite(filename);
}
print_stats_for_machine(filename);
}