diff --git a/src/generator.cpp b/src/generator.cpp index 97d2e2f12b39d1a05e6ed0831fafc5d273f37017..d2e6d101afb1422178390497fd87338ba71a8fcc 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -11,10 +11,12 @@ using namespace std; static const char USAGE[] = - R"(Random Mealy machine generator +R"(Random Mealy machine generator Usage: generator random [-mc] <states> <inputs> <outputs> <machines> [<seed>] + generator hopcroft a <states> + generator hopcroft b <states> Options: -h, --help Show this screen @@ -51,8 +53,8 @@ static mealy generate_random_machine(size_t N, size_t P, size_t Q, mt19937 & gen return m; } -static void print_machine(mealy const & m, size_t count) { - ofstream file("machine_" + to_string(m.graph_size) + "_" + to_string(m.input_size) + "_" +static void print_machine(string const & prefix, mealy const & m, size_t count) { + ofstream file(prefix + "_" + 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) { @@ -64,38 +66,73 @@ static void print_machine(mealy const & m, size_t count) { int main(int argc, char * argv[]) { 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; - } - auto gen = [&] { - if (args.at("<seed>")) { - auto seed = args.at("<seed>").asLong(); - return mt19937(seed); + if (args.at("random").asBool()) { + auto gen = [&] { + if (args.at("<seed>")) { + auto seed = args.at("<seed>").asLong(); + return mt19937(seed); + } + random_device rd; + return mt19937(rd()); + }(); + + size_t number_of_machines = args.at("<machines>").asLong(); + size_t constructed = 0; + + while (constructed < number_of_machines) { + auto const m = generate_random_machine(args.at("<states>").asLong(), + args.at("<inputs>").asLong(), + args.at("<outputs>").asLong(), gen); + + if (args.at("--connected").asBool()) { + auto const m2 = reachable_submachine(m, 0); + if (m2.graph_size != m.graph_size) continue; + } + + 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; + } + + constructed++; + print_machine("machine", m, constructed); } - random_device rd; - return mt19937(rd()); - }(); - - size_t number_of_machines = args.at("<machines>").asLong(); - size_t constructed = 0; + } else if (args.at("hopcroft").asBool() && args.at("a").asBool()) { + mealy m; - while (constructed < number_of_machines) { - auto const m - = generate_random_machine(args.at("<states>").asLong(), args.at("<inputs>").asLong(), - args.at("<outputs>").asLong(), gen); + m.graph_size = args.at("<states>").asLong(); + m.input_size = m.output_size = 2; + m.graph.assign(m.graph_size, vector<mealy::edge>(m.input_size)); - if (args.at("--connected").asBool()) { - auto const m2 = reachable_submachine(m, 0); - if (m2.graph_size != m.graph_size) continue; + for (state s = 0; s < m.graph_size; ++s) { + m.graph[s][0] = mealy::edge(s + 1, 0); + m.graph[s][1] = mealy::edge(s, 0); } - 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; + // "accepting state" + m.graph[m.graph_size - 1][0] = mealy::edge(m.graph_size - 1, 1); + m.graph[m.graph_size - 1][1] = mealy::edge(m.graph_size - 1, 1); + + print_machine("hopcroft_a", m, 1); + } else if (args.at("hopcroft").asBool() && args.at("b").asBool()) { + // In the original paper, the machine is not well defined... + // So I don't know what Hopcroft had in mind exactly... + mealy m; + + auto n = m.graph_size = args.at("<states>").asLong(); + m.input_size = m.output_size = 2; + m.graph.assign(m.graph_size, vector<mealy::edge>(m.input_size)); + + for (state s = 0; s < n; ++s) { + m.graph[s][0] = mealy::edge(s ? s - 1 : 0, s < n / 2 ? 0 : 1); + if (s < n / 2) { + m.graph[s][1] = mealy::edge(2 * s + 1, 0); + } else { + m.graph[s][1] = mealy::edge(s + (n - s) / 2, 0); + } } - constructed++; - print_machine(m, constructed); + print_machine("hopcroft_b", m, 1); } }