diff --git a/algorithms/partitioner/main.cpp b/algorithms/partitioner/main.cpp
index 1c1dbebd..6f773697 100644
--- a/algorithms/partitioner/main.cpp
+++ b/algorithms/partitioner/main.cpp
@@ -15,7 +15,7 @@
You should have received a copy of the GNU General Public License
along with SBG Partitioner. If not, see .
- ******************************************************************************/
+******************************************************************************/
#include
#include
@@ -31,15 +31,65 @@
#include "kernighan_lin_partitioner.hpp"
#include "partition_graph.hpp"
#include "partition_metrics_api.hpp"
+#include "sbg_partitioner_log.hpp"
using namespace std;
using namespace sbg_partitioner;
+
+static void read_configuration_file(const string& filename, PartitionerParams& params)
+{
+
+ // helper function
+ auto to_bool = [](string& str) {
+ std::transform(str.begin(), str.end(), str.begin(), ::tolower);
+ std::istringstream is(str);
+ bool b;
+ is >> std::boolalpha >> b;
+ return b;
+ };
+
+ ifstream ifs(filename);
+ string line;
+ while (std::getline(ifs, line)) {
+ std::istringstream is_line(line);
+ std::string key;
+ if(std::getline(is_line, key, '=')) {
+ std::string value;
+ if(std::getline(is_line, value)) {
+ if (key == "filename") {
+ params.filename = value;
+ } else if (key == "partitions") {
+ params.number_of_partitions = stoi(value);
+ } else if (key == "imbalance") {
+ params.epsilon = stof(value);
+ } else if (key == "multithreading") {
+ params.enable_multithreading = to_bool(value);
+ } else if (key == "initial_partition_strategy") {
+ params.initial_partition_strategy = InitialPartitionStrategy(stoi(value));
+ } else if (key == "metrics") {
+ params.compute_metrics = to_bool(value);
+ } else if (key == "partitions_directory") {
+ params.directory = value;
+ } else {
+ cerr << "Key " << key << " not found, it will be ignored" << endl;
+ }
+ }
+ }
+ }
+}
+
+
static void usage()
{
cout << "Usage sbg-partitioner" << endl;
cout << endl;
+
+ cout << "-c, --config-filename Path to the configuration file, a file with key/values "
+ "that represents the partitioner configuration. If a flag and value by configuration "
+ "file are passed, the flag will be used."
+ << endl;
cout << "-f, --filename Path to the input file, a json file that represents "
"the model we want to partitionate."
<< endl;
@@ -66,6 +116,7 @@ static void usage()
cout << "SBG Partitioner home page: https://github.com/CIFASIS/sbg-partitioner " << endl;
}
+
static void version()
{
cout << "SBG Partitioner 1.0.0" << endl;
@@ -82,6 +133,7 @@ void sort_before_print(PartitionMap partitions, const SBG::LIB::WeightedSBGraph&
cout << "partitions: " << partitions << endl;
}
+
void read_directory(const std::string& name, std::vector& v)
{
auto path_leaf_string = [](const std::filesystem::directory_entry& entry) { return entry.path().string(); };
@@ -92,136 +144,161 @@ void read_directory(const std::string& name, std::vector& v)
std::transform(start, end, std::back_inserter(v), path_leaf_string);
}
+
int main(int argc, char** argv)
{
int opt;
- optional filename = nullopt;
- optional directory = nullopt;
- optional number_of_partitions = nullopt;
- optional output_file;
- optional output_sb_graph = nullopt;
- optional epsilon = nullopt;
- InitialPartitionStrategy initial_partition_strategy = InitialPartitionStrategy::ALL;
- bool enable_multithreading = false;
- bool compute_metrics = false;
-
- while (true) {
- static struct option long_options[] = {{"filename", required_argument, 0, 'f'}, {"partitions", required_argument, 0, 'p'},
- {"output-file", required_argument, 0, 'g'}, {"output-graph", required_argument, 0, 'o'},
- {"compute-metrics", no_argument, 0, 'm'}, {"directory", required_argument, 0, 'd'},
- {"initial-partition-strategy", required_argument, 0, 'i'}, {"enable-multithreading", no_argument, 0, 't'},
- {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}};
+ PartitionerParams params;
+ // look for configuration file
+ while (true)
+ {
int option_index = 0;
- opt = getopt_long(argc, argv, "f:p:e:o:g:d:i:tmvh:", long_options, &option_index);
+ static struct option long_options[] = {{"config-filename", required_argument, 0, 'c'},
+ {"filename", required_argument, 0, 'f'}, {"partitions", required_argument, 0, 'p'},
+ {"output-file", required_argument, 0, 'g'}, {"output-graph", required_argument, 0, 'o'},
+ {"compute-metrics", no_argument, 0, 'm'}, {"directory", required_argument, 0, 'd'},
+ {"initial-partition-strategy", required_argument, 0, 'i'}, {"enable-multithreading", no_argument, 0, 't'},
+ {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}};
+
+ opt = getopt_long(argc, argv, "c:f:p:e:o:g:d:i:tmvh:", long_options, &option_index);
if (opt == EOF) break;
switch (opt) {
- case 'f':
- if (optarg) {
- filename = string(optarg);
- }
- break;
+ case 'c':
+ if (optarg) {
+ params.config_filename = string(optarg);
+ }
+ break;
- case 'p':
- if (optarg) {
- number_of_partitions = atoi(optarg);
+ default:
+ continue;
}
- break;
+ }
- case 'o':
- if (optarg) {
- output_sb_graph = string(optarg);
- }
- break;
+ // read configuration file if exists, before reading flags
+ if (params.config_filename) {
+ read_configuration_file(*params.config_filename, params);
+ }
+
+ // reset it to read values again. We reed them again because flags overwrite values from configuration file
+ optind = 0;
+ while (true) {
+ int option_index = 0;
+ static struct option long_options[] = {{"config-filename", required_argument, 0, 'c'},
+ {"filename", required_argument, 0, 'f'}, {"partitions", required_argument, 0, 'p'},
+ {"output-file", required_argument, 0, 'g'}, {"output-graph", required_argument, 0, 'o'},
+ {"compute-metrics", no_argument, 0, 'm'}, {"directory", required_argument, 0, 'd'},
+ {"initial-partition-strategy", required_argument, 0, 'i'}, {"enable-multithreading", no_argument, 0, 't'},
+ {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}};
+
+ opt = getopt_long(argc, argv, "c:f:p:e:o:g:d:i:tmvh:", long_options, &option_index);
+ if (opt == EOF) break;
- case 'g':
- if (optarg) {
- output_file = string(optarg);
- }
- break;
+ switch (opt) {
+ case 'c': // already read
+ break;
+
+ case 'f':
+ if (optarg) {
+ params.filename = string(optarg);
+ }
+ break;
- case 'e':
- if (optarg) {
- epsilon = atof(optarg);
- }
- break;
+ case 'p':
+ if (optarg) {
+ params.number_of_partitions = atoi(optarg);
+ }
+ break;
- case 'm':
- compute_metrics = true;
- break;
+ case 'o':
+ if (optarg) {
+ params.output_sb_graph = string(optarg);
+ }
+ break;
- case 'd':
- if (optarg) {
- directory = string(optarg);
- }
- break;
+ case 'g':
+ if (optarg) {
+ params.output_file = string(optarg);
+ }
+ break;
- case 'i':
- if (optarg) {
- initial_partition_strategy = InitialPartitionStrategy(atoi(optarg));
- }
- break;
+ case 'e':
+ if (optarg) {
+ params.epsilon = atof(optarg);
+ }
+ break;
- case 't':
- enable_multithreading = true;
- break;
+ case 'm':
+ params.compute_metrics = true;
+ break;
- case 'v':
- version();
- exit(0);
+ case 'd':
+ if (optarg) {
+ params.directory = string(optarg);
+ }
+ break;
- case 'h':
- usage();
- exit(0);
+ case 'i':
+ if (optarg) {
+ params.initial_partition_strategy = InitialPartitionStrategy(atoi(optarg));
+ }
+ break;
- case '?':
- usage();
- exit(-1);
- break;
+ case 't':
+ params.enable_multithreading = true;
+ break;
- default:
- cout << "opt " << opt << endl;
- abort();
+ case 'v':
+ version();
+ exit(0);
+
+ case 'h':
+ usage();
+ exit(0);
+
+ case '?':
+ usage();
+ exit(-1);
+ break;
+
+ default:
+ abort();
}
}
- if (not filename or not number_of_partitions) {
+ if (not params.filename or not params.number_of_partitions) {
usage();
exit(1);
}
- if (not epsilon) {
- epsilon = 0.0;
- }
-
- if (*epsilon < 0 or *epsilon > 1) {
+ if (params.epsilon < 0 or params.epsilon > 1) {
usage();
exit(1);
}
- cout << "filename is " << *filename << endl;
- cout << "number of partitions is " << *number_of_partitions << endl;
+ cout << "filename is " << *params.filename << endl;
+ cout << "number of partitions is " << *params.number_of_partitions << endl;
optional s;
- if (output_sb_graph) {
+ if (params.output_sb_graph) {
s = "";
}
auto start_build_graph = chrono::high_resolution_clock::now();
- auto sb_graph = build_sb_graph(filename->c_str());
+ auto sb_graph = build_sb_graph(params.filename->c_str());
auto end_build_graph = chrono::high_resolution_clock::now();
auto time_to_build_graph = chrono::duration(end_build_graph - start_build_graph).count();
cout << "sb_graph: " << sb_graph << endl;
auto start_partitionate = chrono::high_resolution_clock::now();
- auto partitions = best_initial_partition(sb_graph, *number_of_partitions, initial_partition_strategy, enable_multithreading);
- kl_sbg_imbalance_partitioner(sb_graph, partitions, *epsilon, enable_multithreading);
+ auto partitions = best_initial_partition(sb_graph, *params.number_of_partitions, params.initial_partition_strategy, params.enable_multithreading);
+ kl_sbg_imbalance_partitioner(sb_graph, partitions, params.epsilon, params.enable_multithreading);
auto end_partitionate = chrono::high_resolution_clock::now();
auto time_to_partitionate = chrono::duration(end_partitionate - start_partitionate).count();
- if (compute_metrics) {
+ if (params.compute_metrics) {
map metrics;
int edge_cut = metrics::edge_cut(partitions, sb_graph);
@@ -237,9 +314,9 @@ int main(int argc, char** argv)
cout << f << ": " << m << endl;
}
- if (compute_metrics and directory) {
+ if (params.compute_metrics and params.directory) {
std::vector dir_files;
- read_directory(*directory, dir_files);
+ read_directory(*params.directory, dir_files);
for (const auto& f : dir_files) {
auto partition_from_file = metrics::read_partition_from_file(f, sb_graph);
@@ -263,7 +340,7 @@ int main(int argc, char** argv)
cout << "time_to_partitionate = " << time_to_partitionate << " ms" << endl;
if (sanity_check_enabled) {
- sanity_check(sb_graph, partitions, *number_of_partitions);
+ sanity_check(sb_graph, partitions, *params.number_of_partitions);
}
if (s) {
diff --git a/algorithms/partitioner/partition_graph.hpp b/algorithms/partitioner/partition_graph.hpp
index 4f8592cd..13cb8bc3 100644
--- a/algorithms/partitioner/partition_graph.hpp
+++ b/algorithms/partitioner/partition_graph.hpp
@@ -25,6 +25,7 @@
#include
#include
+#include "partitioner_params.hpp"
#include "sbg_partitioner_types.hpp"
#include "weighted_sb_graph.hpp"
@@ -34,15 +35,6 @@ namespace sbg_partitioner {
constexpr bool sanity_check_enabled = false;
-enum InitialPartitionStrategy {
- ALL = 0,
- DFS_DISTRIBUTIVE_PREORDER = 1,
- DFS_DISTRIBUTIVE_POSTORDER = 2,
- DFS_GREEDY_PREORDER = 3,
- DFS_GREEDY_POSTORDER =4
-};
-
-
/// @brief Converts a Partition element into a Set.
/// @param partition - A list of SetPiece elements.
/// @return A SBG::LIB::Set representation of the Partition element.
diff --git a/algorithms/partitioner/partitioner_params.hpp b/algorithms/partitioner/partitioner_params.hpp
new file mode 100644
index 00000000..c7ff1d93
--- /dev/null
+++ b/algorithms/partitioner/partitioner_params.hpp
@@ -0,0 +1,50 @@
+/**
+ This file is part of Set--Based Graph Library.
+
+ SBG Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SBG Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SBG Library. If not, see .
+
+******************************************************************************/
+
+#pragma once
+
+#include
+#include
+
+namespace sbg_partitioner {
+
+
+enum InitialPartitionStrategy {
+ ALL = 0,
+ DFS_DISTRIBUTIVE_PREORDER = 1,
+ DFS_DISTRIBUTIVE_POSTORDER = 2,
+ DFS_GREEDY_PREORDER = 3,
+ DFS_GREEDY_POSTORDER =4
+};
+
+
+struct PartitionerParams
+{
+ std::optional config_filename = std::nullopt;
+ std::optional filename = std::nullopt;
+ std::optional directory = std::nullopt;
+ std::optional number_of_partitions = std::nullopt;
+ std::optional output_file;
+ std::optional output_sb_graph = std::nullopt;
+ float epsilon = 0.0;
+ InitialPartitionStrategy initial_partition_strategy = InitialPartitionStrategy::ALL;
+ bool enable_multithreading = false;
+ bool compute_metrics = false;
+};
+
+}
\ No newline at end of file