diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..d1221a932504335fca69084307ab126d2678a3b9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "contrib/docopt.cpp"] + path = contrib/docopt.cpp + url = git@github.com:docopt/docopt.cpp.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 64247ab708a12b1afe9dd9b665bdc6695ddf30c0..e649e79d18bbf48ed2439998d9ee2fe6aa9fe581 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,10 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") find_package(Boost REQUIRED COMPONENTS iostreams program_options filesystem system serialization) include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) -set(libs ${libs} ${Boost_LIBRARIES}) +include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/contrib/docopt.cpp") +set(libs ${libs} ${Boost_LIBRARIES} docopt_s) -# add_subdirectory("contrib") +add_subdirectory("contrib/docopt.cpp") add_subdirectory("lib") add_subdirectory("src") diff --git a/contrib/docopt.cpp b/contrib/docopt.cpp new file mode 160000 index 0000000000000000000000000000000000000000..ef2ba2a929ae5fd3a7740d15c891bbb7bb1f9b99 --- /dev/null +++ b/contrib/docopt.cpp @@ -0,0 +1 @@ +Subproject commit ef2ba2a929ae5fd3a7740d15c891bbb7bb1f9b99 diff --git a/src/generator.cpp b/src/generator.cpp index 5153a53c76e4cfe42debea3d207ebe1803486149..97d2e2f12b39d1a05e6ed0831fafc5d273f37017 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -2,12 +2,27 @@ #include <reachability.hpp> #include <splitting_tree.hpp> +#include <docopt.h> + #include <iostream> #include <random> #include <fstream> using namespace std; +static const char USAGE[] = + R"(Random Mealy machine generator + + Usage: + generator random [-mc] <states> <inputs> <outputs> <machines> [<seed>] + + Options: + -h, --help Show this screen + --version Show version + -m, --minimal Only generate minimal machines + -c, --connected Only generate reachable machines +)"; + static size_t number_of_leaves(splitting_tree const & root) { if (root.children.empty()) return 1; @@ -37,7 +52,8 @@ static mealy generate_random_machine(size_t N, size_t P, size_t Q, mt19937 & gen } static void print_machine(mealy const & m, size_t count) { - ofstream file("machine_" + to_string(m.graph_size) + "_" + to_string(m.input_size) + "_" + to_string(m.output_size) + "_" + to_string(count) + ".txt"); + ofstream file("machine_" + to_string(m.graph_size) + "_" + to_string(m.input_size) + "_" + + to_string(m.output_size) + "_" + to_string(count) + ".txt"); for (state s = 0; s < m.graph_size; ++s) { for (input i = 0; i < m.input_size; ++i) { auto e = m.graph[s][i]; @@ -47,44 +63,39 @@ static void print_machine(mealy const & m, size_t count) { } int main(int argc, char * argv[]) { - if (argc != 5 && argc != 6) { - cerr << "usage: generator <N> <P> <Q> <number of machines> [<seed>]" << endl; - return 1; + const auto args = docopt::docopt(USAGE, {argv + 1, argv + argc}, true, __DATE__ __TIME__); + for (auto const & arg : args) { + std::cout << arg.first << arg.second << std::endl; } - const auto N = stoul(argv[1]); - const auto P = stoul(argv[2]); - const auto Q = stoul(argv[3]); - const auto number_of_machines = stoul(argv[4]); - auto gen = [&] { - if (argc == 6) { - auto seed = stoul(argv[5]); + if (args.at("<seed>")) { + auto seed = args.at("<seed>").asLong(); return mt19937(seed); } random_device rd; return mt19937(rd()); }(); - size_t count = 0; - size_t connected = 0; - size_t minimal = 0; + size_t number_of_machines = args.at("<machines>").asLong(); + size_t constructed = 0; - while (true) { - auto const m = generate_random_machine(N, P, Q, gen); - auto const m2 = reachable_submachine(m, 0); - auto const tree = create_splitting_tree(m2, min_hopcroft_style, 0).root; + while (constructed < number_of_machines) { + auto const m + = generate_random_machine(args.at("<states>").asLong(), args.at("<inputs>").asLong(), + args.at("<outputs>").asLong(), gen); - count++; - if (m.graph_size == m2.graph_size) connected++; - if (number_of_leaves(tree) == m.graph_size) minimal++; + if (args.at("--connected").asBool()) { + auto const m2 = reachable_submachine(m, 0); + if (m2.graph_size != m.graph_size) continue; + } - if (number_of_leaves(tree) == m.graph_size) { - print_machine(m2, minimal); + if (args.at("--minimal").asBool()) { + auto const tree = create_splitting_tree(m, min_hopcroft_style, 0).root; + if (number_of_leaves(tree) != m.graph_size) continue; } - if (minimal >= number_of_machines) break; + constructed++; + print_machine(m, constructed); } - - clog << minimal << " / " << connected << " / " << count << endl; }