#include #include #include "graph.hpp" #include "heuristic.hpp" #include "tree.hpp" using namespace std; void usage(char *name) { cout << "Usage: " << name << " [OPTIONS] " << endl << endl; cout << name << " is a heuristic for the Steiner tree problem. It reads the input from\ stdin. By default, " << name << " takes a graph as input and run a deterministic\ heuristic on it and outputs a Steiner tree." << endl; cout << name << " can be stopped by a SIGINT or SIGTERM signal." << endl << endl; cout << "OPTIONS:\n\ -r, --random\n\ After running a deterministic heuristic to construct a reasonable initial Steiner tree,\n\ a randomized improvement procedure will be initiated. This procedure does not terminate by \n\ itself and needs to be explicitly stopped by a SIGINT or SIGTERM signal.\n\ -i, --improve\n\ With this option, the program will take a graph and a Steiner tree as input and will \n\ try to construct a lighter Steiner tree. This is a deterministic procedure. With this option,\n\ the flags --random and --seed have no effect.\n\ -s SEED, --seed SEED\n\ Initializes the random number generator with SEED. SEED must be an integer.\n\ Useful with the --random option.\ " << endl; } int main(int argc, char **argv) { // register signal SIGINT and signal handler signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); bool improve = false; bool random_init = false; for (auto count = 1; count < argc; ++count) { string arg(argv[count]); if (arg == "-h" || arg == "--help") { usage(argv[0]); return 0; } if (arg == "-s" || arg == "--seed") { try { ++count; if (count >= argc) throw invalid_argument("Missing seed"); srand(stoi(argv[count])); } catch (const invalid_argument &e) { cerr << "Invalid argument: seed must be an integer." << endl; usage(argv[0]); return 1; } continue; } if (arg == "-i" || arg == "--improve") { improve = true; continue; } if (arg == "-r" || arg == "--random") { random_init = true; continue; } cerr << "Invalid argument: " << arg << endl; usage(argv[0]); return 1; } Graph G(cin); if (not improve) { map, vector> hash = G.contract(); pair p = complet_heuristic(G, G.terminalsMap, G.terminals, random_init); cout << "VALUE " << p.second << endl; p.first.print(hash); } else { Tree T(G, cin); Weight w, oldw; w = T.pruneLeaves(G.terminalsMap); do { if (tle) break; oldw = w; apply_opt(T, G); w = T.pruneLeaves(G.terminalsMap); } while (oldw != w); do { if (tle) break; oldw = w; full_d3(T, G); w = T.pruneLeaves(G.terminalsMap); } while (oldw != w); cout << "VALUE " << w << endl; T.print(); } return 0; }