Commit 5e3f838e authored by Gijs van Cuyck's avatar Gijs van Cuyck

Created new readable version of the splitting tree that uses strings

instead of the internal integer labels.

Created a way to print the readable splitting tree to a file in an
organized way to compare it with expected results.
parent 95660fda
......@@ -42,3 +42,8 @@ com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
#project specific
outputs/
examples/
todos en vragen.txt
\ No newline at end of file
......@@ -3,6 +3,6 @@ project(complete_ads)
set(CMAKE_CXX_STANDARD 17)
set(SOURCE_FILES main.cpp src/main_test.cpp)
set(SOURCE_FILES main.cpp src/main_test.cpp reachability.cpp)
add_subdirectory("lib")
add_subdirectory("src")
\ No newline at end of file
......@@ -4,6 +4,6 @@ file(GLOB_RECURSE headers "*.hpp")
set(libs)
add_library(common ${headers} ${sources})
add_library(common ${headers} ${sources} vector_printing.hpp)
target_link_libraries(common ${libs})
target_include_directories(common PUBLIC ".")
......@@ -4,4 +4,4 @@
struct mealy;
mealy reachable_submachine(const mealy& in, state start);
mealy reachable_submachine(const mealy& in, std::uint16_t start);
......@@ -79,9 +79,6 @@ mealy read_mealy_from_txt(const std::string & filename, bool check) {
mealy read_mealy_from_dot(std::istream & in, translation & t, bool check){
mealy m;
std::unordered_map<std::string, state> state_indices;
state max_state = 0;
string line;
while(getline(in, line)){
const auto npos = std::string::npos;
......@@ -106,22 +103,22 @@ mealy read_mealy_from_dot(std::istream & in, translation & t, bool check){
const auto output = trim_copy(easy_substr(line, slash_pos+1, quote2_pos));
// make fresh indices, if needed
if(state_indices.count(lh) < 1) state_indices[lh] = max_state++;
if(state_indices.count(rh) < 1) state_indices[rh] = max_state++;
if(t.state_indices.count(lh) < 1) t.state_indices[lh] = t.max_state++;
if(t.state_indices.count(rh) < 1) t.state_indices[rh] = t.max_state++;
if(t.input_indices.count(input) < 1) t.input_indices[input] = t.max_input++;
if(t.output_indices.count(output) < 1) t.output_indices[output] = t.max_output++;
if(defined(m, state_indices[lh], t.input_indices[input]))
if(defined(m, t.state_indices[lh], t.input_indices[input]))
throw runtime_error("Nondeterministic machine");
// add edge
m.graph.resize(max_state);
auto & v = m.graph[state_indices[lh]];
m.graph.resize(t.max_state);
auto & v = m.graph[t.state_indices[lh]];
v.resize(t.max_input);
v[t.input_indices[input]] = mealy::edge(state_indices[rh], t.output_indices[output]);
v[t.input_indices[input]] = mealy::edge(t.state_indices[rh], t.output_indices[output]);
}
m.graph_size = max_state;
m.graph_size = t.max_state;
m.input_size = t.max_input;
m.output_size = t.max_output;
......@@ -142,14 +139,14 @@ mealy read_mealy_from_dot(const string & filename, translation & t, bool check){
std::pair<mealy, translation> read_mealy_from_dot(istream & in, bool check){
translation t;
const auto m = read_mealy_from_dot(in, t, check);
return {move(m), move(t)};
return std::make_pair(move(m), move(t));
}
std::pair<mealy, translation> read_mealy_from_dot(const string & filename, bool check){
translation t;
const auto m = read_mealy_from_dot(filename, t, check);
return {move(m), move(t)};
return std::make_pair(move(m), move(t));
}
......
......@@ -33,11 +33,35 @@ struct translation {
std::unordered_map<std::string, output> output_indices;
output max_output = 0;
std::unordered_map<std::string,state> state_indices;
state max_state = 0;
};
//todo: check of dit nog gebruikt wordt
/*
struct reverse_translation{
std::vector<std::string> inputs;
std::vector<std::string> outputs;
std::vector<std::string> states;
};
*/
/// \brief inverts the input_indices and output_indices maps
std::vector<std::string> create_reverse_map(std::unordered_map<std::string, input> const & indices);
std::vector<std::string> create_reverse_map(std::unordered_map<std::string, output> const & indices);
//todo: check of dit nog gebruikt wordt
/*
reverse_translation translate_translation(translation t)
{
reverse_translation return_value;
return_value.inputs = create_reverse_map(t.input_indices);
return_value.outputs = create_reverse_map(t.output_indices);
return_value.states = create_reverse_map(t.state_indices);
return return_value;
}
*/
/// \brief defines trivial translation (the string represent integers directly)
translation create_translation_for_mealy(mealy const & m);
#include "splitting_tree.hpp"
#include "partition.hpp"
#include "vector_printing.hpp"
#include <algorithm>
#include <cassert>
......@@ -15,6 +16,27 @@ splitting_tree::splitting_tree(size_t N, size_t d) : states(N), depth(d) {
iota(begin(states), end(states), 0);
}
readable_splitting_tree translate_splitting_tree(splitting_tree & tree, std::vector<std::string> & inputs, std::vector<std::string> & states) {
readable_splitting_tree translated_tree(tree.states.size(),tree.depth,tree.separator.size(),tree.children.size());
transform(tree.states.begin(),tree.states.end(),translated_tree.states.begin(),[&states](state s){return states[s];});
transform(tree.separator.begin(),tree.separator.end(),translated_tree.separator.begin(),[&inputs](input i){return inputs[i];});
transform(tree.children.begin(),tree.children.end(),translated_tree.children.begin(),
[&inputs,&states](splitting_tree & child){ return translate_splitting_tree(child,inputs,states);});
return translated_tree;
}
void rst_to_stream(readable_splitting_tree & tree, ostream & output, int ident){
string indentations(ident,'\t');
output << indentations << "{" << join(tree.states.begin(),tree.states.end(),",","}") << "\n";
if(tree.children.size()>0)
{
output << indentations << join(tree.separator.begin(),tree.separator.end()) << "\n" ;
for(auto & child : tree.children) {
rst_to_stream(child,output,ident+1);
}
}
}
result create_splitting_tree(const mealy & g, options opt, uint_fast32_t random_seed) {
const auto N = g.graph_size;
const auto P = g.input_size;
......
......@@ -13,6 +13,31 @@ struct splitting_tree {
word separator;
size_t depth = 0;
};
/// \brief used to turn a readable splitting tree into a string.
/// Not intended for direct use, instead call tree.to_string()
struct readable_splitting_tree {
/// \brief constructor that presets the internal vectors to the correct sizes for filling with iterators.
readable_splitting_tree (size_t state_amount, size_t depth_value, size_t seperator_size, size_t children_amount):
states(state_amount),depth(depth_value),separator(seperator_size),children(children_amount){}
readable_splitting_tree(){}
std::vector<std::string> states;
std::vector<readable_splitting_tree> children;
std::vector<std::string> separator;
size_t depth = 0;
};
void rst_to_stream(readable_splitting_tree & tree, std::ostream & output, int ident = 0);
/* todo: check of dit gebruikt wordt
std::ostream& operator<<(std::ostream& os, const readable_splitting_tree& tree);
*/
readable_splitting_tree translate_splitting_tree(splitting_tree & tree, std::vector<std::string> & inputs, std::vector<std::string> & states);
/// \brief the generic lca implementation.
/// It uses \p store to store the relevant nodes (in some bottom up order), the last store is the
......
//
// Created by Gijs van Cuyck on 18/10/2018.
//
#ifndef COMPLETE_ADS_PRINTING_H
#define COMPLETE_ADS_PRINTING_H
#include <string>
#include <sstream>
/// \brief turns a vector of printable objects into a string, putting a sepperator between every two elements and
/// a concluder after the last one.
///implementation taken from: https://codereview.stackexchange.com/questions/142902/simple-string-joiner-in-modern-c
template<typename InputIt>
std::string join(InputIt begin,
InputIt end,
const std::string & separator ="",
const std::string & concluder ="")
{
std::ostringstream ss;
if(begin != end)
{
ss << *begin++;
}
while(begin != end)
{
ss << separator;
ss << *begin++;
}
ss << concluder;
return ss.str();
}
#endif //COMPLETE_ADS_PRINTING_H
......@@ -7,11 +7,11 @@ int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
char *optarg; /* argument associated with option */
char empty[1] = {'\0'};
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
#define EMSG empty
/*
* getopt --
......@@ -22,7 +22,6 @@ int
{
static char *place = EMSG; /* option letter processing */
const char *oli; /* option letter list index */
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
......
......@@ -8,6 +8,7 @@
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <map>
#include <random>
#include <stdexcept>
......@@ -62,12 +63,12 @@ struct main_options {
PrefixMode prefix_mode = MIN;
SuffixMode suffix_mode = HADS;
unsigned long k_max = 3; // 3 means 2 extra states
unsigned long k_max = 1; // 3 means 2 extra states
unsigned long rnd_length = 8; // in addition to k_max
unsigned long seed = 0; // 0 for unset/noise
string input_filename; // empty for stdin
string output_filename; // empty for stdout
string input_filename = "../examples/coffe_machine.dot";
string output_filename = "../outputs/default_output_file.txt";
};
main_options parse_options(int argc, char ** argv) {
......@@ -112,7 +113,7 @@ main_options parse_options(int argc, char ** argv) {
opts.input_filename = optarg;
break;
case 'o': // output filename
opts.output_filename = optarg;
opts.output_filename += optarg;
break;
case ':': // some option without argument
throw runtime_error(string("No argument given to option -") + char(optopt));
......@@ -132,7 +133,7 @@ main_options parse_options(int argc, char ** argv) {
using time_logger = silent_timer;
int main(int argc, char * argv[]) try {
int main(int argc, char * argv[]){
/*
* First we parse the command line options.
* We quit when asked for help or version
......@@ -152,12 +153,8 @@ int main(int argc, char * argv[]) try {
const bool no_suffix = args.suffix_mode == NOSUFFIX;
const bool use_distinguishing_sequence = args.suffix_mode == HADS;
const bool randomize_hopcroft = true;
const bool randomize_lee_yannakakis = true;
if (args.output_filename != "" && args.output_filename != "-") {
throw runtime_error("File ouput is currently not supported");
}
const bool randomize_hopcroft = false;
const bool randomize_lee_yannakakis = false;
/*
* Then all the setup is done. Parsing the automaton,
......@@ -182,36 +179,23 @@ int main(int argc, char * argv[]) try {
return read_mealy_from_dot(filename);
}();
const auto & machine = reachable_submachine(move(machine_and_translation.first), 0);
const auto & machine = reachable_submachine(move(machine_and_translation.first), 0U);
const auto & translation = machine_and_translation.second;
// every thread gets its own seed
const auto random_seeds = [&] {
vector<uint_fast32_t> seeds(4);
if (args.seed != 0) {
seed_seq s{args.seed};
s.generate(seeds.begin(), seeds.end());
} else {
random_device rd;
generate(seeds.begin(), seeds.end(), ref(rd));
}
return seeds;
}();
auto all_pair_separating_sequences = [&] {
if (no_suffix) return splitting_tree(0, 0);
splitting_tree complete_splitting_tree = create_splitting_tree(machine,complete_ads,0).root;
vector<string> input_translation = create_reverse_map(translation.input_indices);
vector<string> state_translation = create_reverse_map(translation.state_indices);
readable_splitting_tree translated_tree = translate_splitting_tree(complete_splitting_tree,input_translation,state_translation);
ofstream out_file(args.output_filename);
rst_to_stream(translated_tree,out_file);
out_file.close();
cout << "finished!\n";
const auto splitting_tree_hopcroft = [&] {
time_logger t("creating hopcroft splitting tree");
return create_splitting_tree(
machine, randomize_hopcroft ? randomized_hopcroft_style : hopcroft_style,
random_seeds[0]);
}();
return splitting_tree_hopcroft.root;
}();
} catch (exception const & e) {
cerr << "Exception thrown: " << e.what() << endl;
return 1;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment