Skip to content
Snippets Groups Projects
Commit 1e30f909 authored by Jaime Arias's avatar Jaime Arias
Browse files

refactor: method to print statistics

parent 5999fc1a
No related branches found
No related tags found
No related merge requests found
Pipeline #8762 passed with stages
in 4 minutes and 34 seconds
......@@ -12,21 +12,73 @@
using namespace std;
/**
* Print the statistics of the optimal paths
* @param output_file - the output file
* @param optimal_paths - the optimal paths
* @param generated_paths - the generated paths
* @param random_graphs - whether the input is random graphs
*/
void print_statistics(const std::filesystem::path &output_file,
const std::vector<std::string> &optimal_paths,
const vector<string> &generated_paths,
bool random_graphs) {
if (random_graphs) {
size_t avg_opt_size = 0;
for (const string &path : optimal_paths) {
avg_opt_size += path.size();
}
const size_t nb_paths = optimal_paths.size();
cout << " # of generated paths: " << generated_paths.size() << "\n";
cout << " # of optimal paths: " << nb_paths << "\n";
cout << " Average optimal paths size: " << avg_opt_size / nb_paths << endl;
} else {
ofstream file(output_file);
if (!file) {
std::runtime_error("Unable to open file!");
}
int index = 0;
std::stringstream log;
size_t avg_opt_size = 0;
for (const string &path : optimal_paths) {
index++;
avg_opt_size += path.size();
log << "Optimal path (" << index << "):" << "\n - path: " << path
<< "\n - lenght: " << std::count(path.begin(), path.end(), '_')
<< "\n\n";
}
log << "# of observed paths: " << index << "";
log << "\nAverage optimal paths size: " << avg_opt_size << "\n";
cout << log.str();
file << log.str();
}
}
int main(int argc, char *argv[]) {
CLI::App app{
"OptLP: A tool to find the minimum number of shortest paths "
"that cover all system actions"};
auto *random = app.add_subcommand("random", "Generate a random LTS");
bool random_graphs_used = false;
auto *random_graphs = app.add_subcommand("random", "Generate a random LTS");
random_graphs->callback([&]() { random_graphs_used = true; });
int nb_nodes = 0;
random->add_option("--nb-nodes", nb_nodes, "Number of nodes")->required();
random_graphs->add_option("--nb-nodes", nb_nodes, "Number of nodes")
->required();
int nb_edges = 0;
random->add_option("--nb-edges", nb_edges, "Number of edges")->required();
random_graphs->add_option("--nb-edges", nb_edges, "Number of edges")
->required();
int nb_labels = 0;
random->add_option("--nb-labels", nb_labels, "Number of labels")->required();
random_graphs->add_option("--nb-labels", nb_labels, "Number of labels")
->required();
auto *from_file =
app.add_subcommand("from-file", "Load an LTS from a dot file");
......@@ -49,7 +101,7 @@ int main(int argc, char *argv[]) {
Graph *g = nullptr;
std::string filename;
if (*random) {
if (*random_graphs) {
g = Graph::GenerateRandomGraph(nb_nodes, nb_edges, nb_labels);
} else if (*from_file) {
filename = input_file.stem().string();
......@@ -97,6 +149,7 @@ int main(int argc, char *argv[]) {
cout << " Average size of generated paths: " << average_size << endl;
// extract the shortest paths
cout << "\nExtracting shortest paths ... \n";
std::vector<std::string> optimal_paths =
PathGenerator::ExtractShortPaths(g->labels(), generated_paths);
......@@ -105,44 +158,12 @@ int main(int argc, char *argv[]) {
return 1;
}
size_t avg_opt_size = 0;
if (*from_file) {
std::filesystem::path output_filename = "result_opt_" + filename + ".txt";
ofstream file(output_folder / output_filename);
if (!file) {
std::cerr << "Unable to open file!\n";
return 1;
}
int index = 0;
std::stringstream log;
for (const string &path : optimal_paths) {
index++;
avg_opt_size += path.size();
log << "Optimal path (" << index << "):" << "\n - path: " << path
<< "\n - lenght: " << std::count(path.begin(), path.end(), '_')
<< "\n";
}
log << "\n# of observed paths: " << index << "";
log << "\nAverage optimal paths size: " << avg_opt_size << "\n";
cout << log.str();
file << log.str();
} else {
for (const string &path : optimal_paths) {
avg_opt_size += path.size();
}
const size_t nb_paths = optimal_paths.size();
cout << " # of generated paths: " << generated_paths.size() << "\n";
cout << " # of optimal paths: " << nb_paths << "\n";
cout << " Average optimal paths size: " << avg_opt_size / nb_paths << endl;
}
float elapsed_time = GetTime() - start_time;
cout << "\nTotal time: " << elapsed_time << " seconds\n";
cout << "\nOptimal paths found\n===================\n";
std::filesystem::path output_filename = "result_opt_" + filename + ".txt";
print_statistics(output_folder / output_filename, optimal_paths,
generated_paths, random_graphs_used);
cout << "\nTotal time: " << elapsed_time << " seconds\n\n";
return 0;
}
......@@ -145,13 +145,13 @@ std::vector<std::string> PathGenerator::ExtractShortPaths(
throw std::runtime_error("# of labels is different from # of rows");
}
cout << "constraint matrix size: (rows: " << rows << ", columns: " << columns
cout << " Constraint matrix size: (rows: " << rows << ", columns: " << columns
<< ")\n";
float start_time = GetTime();
// initialisation of the constraint matrix
cout << "initialising the constraint matrix ... ";
cout << " Initialising the constraint matrix ... ";
std::vector<std::vector<int>> constraints(rows, std::vector<int>(columns, 0));
// Charge constraint matrix with paths from regex
......@@ -171,7 +171,7 @@ std::vector<std::string> PathGenerator::ExtractShortPaths(
}
// Create variables
cout << "creating variables ... ";
cout << " Creating variables ... ";
std::vector<const operations_research::MPVariable *> x(columns + rows);
for (int j = 0; j < columns; ++j) {
x[j] = solver->MakeIntVar(0.0, 1, "x" + std::to_string(j));
......@@ -179,7 +179,7 @@ std::vector<std::string> PathGenerator::ExtractShortPaths(
cout << "DONE\n";
// Create constraints
cout << "creating constraints ... ";
cout << " Creating constraints ... ";
for (const auto &label : labels) {
operations_research::MPConstraint *constraint = solver->MakeRowConstraint(
1, operations_research::MPSolver::infinity(), "");
......@@ -192,7 +192,7 @@ std::vector<std::string> PathGenerator::ExtractShortPaths(
cout << "DONE\n";
// Create the objective function
cout << "creating objective function ... ";
cout << " Creating objective function ... ";
operations_research::MPObjective *const objective =
solver->MutableObjective();
for (int j = 0; j < columns; ++j) {
......@@ -201,7 +201,7 @@ std::vector<std::string> PathGenerator::ExtractShortPaths(
int path_size = static_cast<int>(std::count(path.begin(), path.end(), '_'));
objective->SetCoefficient(x[j], path_size);
}
cout << "DONE ...\n";
cout << "DONE\n";
// Set the objective function to minimization
objective->SetMinimization();
......@@ -211,15 +211,15 @@ std::vector<std::string> PathGenerator::ExtractShortPaths(
solver->Solve();
float lp_time = GetTime() - start_time;
cout << "\nILP time: " << lp_time << " seconds\n";
cout << " Elapsed time for solving ILP problem: " << lp_time << " seconds\n";
// Check that the problem has an optimal solution.
std::vector<std::string> optimal_paths;
if (result_status != operations_research::MPSolver::OPTIMAL) {
std::cout << "The problem does not have an optimal solution.\n";
} else {
std::cout << "Solution:\n";
std::cout << " Optimal objective value = " << objective->Value()
std::cout << " Solution => ";
std::cout << "optimal objective value = " << objective->Value()
<< std::endl;
for (int j = 0; j < columns; ++j) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment