From a210fbef2be14ea88c28e2b7461aa04f5e701b6e Mon Sep 17 00:00:00 2001 From: Ali Rostami Date: Tue, 15 Jul 2025 13:28:52 +0200 Subject: [PATCH 1/2] the input output parts are improved, refactoring, adding csv reader --- Algorithms/ColoringAlgorithms.cpp | 1 + Algorithms/ColoringAlgorithms.h | 12 +- Algorithms/GreedyColoringSimpleGraph.h | 4 +- Algorithms/GreedyColoringSimpleGraphBoost.cpp | 13 +- Algorithms/OneSidedD2ColorNonReqDiag.h | 4 +- Algorithms/OneSidedD2Coloring.h | 61 ++-- Algorithms/OneSidedD2ColoringNonReq.h | 2 +- Algorithms/OneSidedD2ColoringNonReqBalanced.h | 7 +- Algorithms/StarBicoloringVertexCover.h | 6 +- Algorithms/StarBicoloringVertexCoverNonReq.h | 12 +- Algorithms/algorithms.h | 23 +- Algorithms/d2_color_omp.h | 2 +- Application/Preconditioning/main.cpp | 2 +- BoostTest/PreColTest.cpp | 34 +-- CMakeLists.txt | 11 +- Graph/ConvertGraph.cpp | 110 +------- Graph/GraphDataType.hpp | 8 +- Graph/Sparsify.cpp | 2 +- Graph/Sparsify.h | 2 +- Graph/neighbors.hpp | 102 +++---- InputOutput/HandleInputOutput.cpp | 264 ++++++++++-------- InputOutput/HandleInputOutput.h | 58 ++-- Main/InputTable.csv | 3 + Main/InputTableFullTest.csv | 26 ++ Main/PreCol.cpp | 102 ++++--- Orderings/orderings.h | 4 +- OtherSources/graph.h | 2 +- mybuild/OutputTable.csv | 26 ++ mybuild/compare.py | 73 +++++ mybuild/input.csv | 26 ++ mybuild/run_colpack.py | 69 +++++ 31 files changed, 617 insertions(+), 454 deletions(-) create mode 100644 Main/InputTable.csv create mode 100644 Main/InputTableFullTest.csv create mode 100644 mybuild/OutputTable.csv create mode 100644 mybuild/compare.py create mode 100644 mybuild/input.csv create mode 100644 mybuild/run_colpack.py diff --git a/Algorithms/ColoringAlgorithms.cpp b/Algorithms/ColoringAlgorithms.cpp index 12f7cdb..aaac558 100644 --- a/Algorithms/ColoringAlgorithms.cpp +++ b/Algorithms/ColoringAlgorithms.cpp @@ -12,6 +12,7 @@ std::tuple> ColoringAlgorithms::TupleNumOfColorAndColors() { std::vector colors; std::set unique_colors; + ForEachVertex(GraphInstance, [&](int v) { colors.push_back(get(vertex_color, GraphInstance, v)); int the_color = get(vertex_color, GraphInstance, v) - 1; diff --git a/Algorithms/ColoringAlgorithms.h b/Algorithms/ColoringAlgorithms.h index ef58cc8..11e255f 100644 --- a/Algorithms/ColoringAlgorithms.h +++ b/Algorithms/ColoringAlgorithms.h @@ -43,6 +43,7 @@ class ColoringAlgorithms { */ std::tuple> TupleNumOfColorAndColors(); public: + virtual ~ColoringAlgorithms() = default; explicit ColoringAlgorithms(Graph &G_b) : GraphInstance(G_b) { SetAllColorsTo(0);}; ColoringAlgorithms(Graph &G_b, vector &V, bool restricted = false, map&& pars = {}) @@ -89,11 +90,11 @@ class ColoringAlgorithms { * * @return Number of colors */ - int NumOfColors() { + [[nodiscard]] int NumOfColors() const + { int max_color = 0; - ForEachVertex(GraphInstance, [&](Ver v) { - int color = get(vertex_color, GraphInstance, v); - if (max_color < color) + ForEachVertex(GraphInstance, [&](const Ver& v) { + if (const int color = get(vertex_color, GraphInstance, v); max_color < color) max_color = color; }); return max_color; @@ -104,7 +105,8 @@ class ColoringAlgorithms { * * @param value the given value */ - void SetAllColorsTo(int value) { + void SetAllColorsTo(const int value) const + { ForEachVertexConst(GraphInstance, [&](Ver v) { boost::put(vertex_color, GraphInstance, v, value); }); diff --git a/Algorithms/GreedyColoringSimpleGraph.h b/Algorithms/GreedyColoringSimpleGraph.h index ca5a801..69e01ba 100644 --- a/Algorithms/GreedyColoringSimpleGraph.h +++ b/Algorithms/GreedyColoringSimpleGraph.h @@ -16,11 +16,11 @@ * Output: * - G a simple graph with colors as weights vertex_color */ -class GreedyColoringSimpleGraph : public ColoringAlgorithms { +class GreedyColoringSimpleGraph final : public ColoringAlgorithms { public: using ColoringAlgorithms::ColoringAlgorithms; - int color(); + int color() override; }; diff --git a/Algorithms/GreedyColoringSimpleGraphBoost.cpp b/Algorithms/GreedyColoringSimpleGraphBoost.cpp index 3297a37..a505fc8 100644 --- a/Algorithms/GreedyColoringSimpleGraphBoost.cpp +++ b/Algorithms/GreedyColoringSimpleGraphBoost.cpp @@ -13,12 +13,17 @@ int GreedyColoringSimpleGraphBoost::color() { Graph &g = GraphInstance; typedef graph_traits::vertices_size_type vertices_size_type; - typedef property_map::const_type vertex_index_map; std::vector color_vec(boost::num_vertices(g)); - boost::iterator_property_map color(&color_vec.front(), get(boost::vertex_index, g)); - auto num_colors = boost::sequential_vertex_coloring(g, color); + const boost::iterator_property_map color(&color_vec.front(), get(boost::vertex_index, g)); + auto ordering = boost::copy_range>(boost::vertices(g)); + std::ranges::sort(ordering, std::greater<>{}, + [&g](Ver v) { return degree(v, g); }); + const auto index_map = get(boost::vertex_index, g); + const auto order_map = boost::make_safe_iterator_property_map( + ordering.begin(), ordering.size(), index_map); + const auto num_colors = boost::sequential_vertex_coloring(g, order_map, color); ForEachVertexConst(g, [&](Ver v) { boost::put(vertex_color, g, v, color[v]); }); - return num_colors; + return static_cast(num_colors); } \ No newline at end of file diff --git a/Algorithms/OneSidedD2ColorNonReqDiag.h b/Algorithms/OneSidedD2ColorNonReqDiag.h index d8a6201..6a722c8 100644 --- a/Algorithms/OneSidedD2ColorNonReqDiag.h +++ b/Algorithms/OneSidedD2ColorNonReqDiag.h @@ -48,7 +48,7 @@ class OneSidedD2ColorNonReqDiag : public ColoringAlgorithms { //Find the first color which can be assigned to v auto result = find_if(forbiddenColors.begin(), forbiddenColors.end(), - bind1st(not_equal_to(), v)); + bind(not_equal_to(), v, std::placeholders::_1)); int col1 = distance(forbiddenColors.begin(), result); /////////////////////////////////////////////////////////////////////////////////////// @@ -66,7 +66,7 @@ class OneSidedD2ColorNonReqDiag : public ColoringAlgorithms { //Find first color which can be assigned to v result = find_if(forbiddenColors.begin(), forbiddenColors.end(), - bind1st(not_equal_to(), v)); + bind(not_equal_to(), v, std::placeholders::_1)); int col2 = distance(forbiddenColors.begin(), result); diff --git a/Algorithms/OneSidedD2Coloring.h b/Algorithms/OneSidedD2Coloring.h index bffbaa8..f3e3398 100644 --- a/Algorithms/OneSidedD2Coloring.h +++ b/Algorithms/OneSidedD2Coloring.h @@ -1,63 +1,58 @@ // -// Created by rostam on 20.07.16. +// Created by rostam on 20.07.16 // #ifndef PRECOL_ONESIDEDD2COLORING_H #define PRECOL_ONESIDEDD2COLORING_H #include "ColoringAlgorithms.h" + /** - * \brief Compute one-sided distance-2 coloring of a bipartite graph GraphInstance + * \brief One-sided distance-2 coloring for bipartite graphs. * - * It can be also IsRestrictedColoring to some required edges if the - * IsRestrictedColoring value is equal to true + * Performs a one-sided distance-2 coloring on the vertex set V of a bipartite graph. + * Optionally supports restricted coloring based on required edges. * * Input: - * - GraphInstance bipartite graph - * - V contained vertices are colored in the given ordering v_1, ..., v_n + * - GraphInstance: The bipartite graph to color. + * - V_c: The vertex subset to color, provided in a specific order. * * Output: - * - GraphInstance bipartite graph with colors as weights vertex_color + * - Colors assigned to vertices in GraphInstance, stored via vertex_color property. */ -class OneSidedD2Coloring : public ColoringAlgorithms { +class OneSidedD2Coloring final : public ColoringAlgorithms { public: using ColoringAlgorithms::ColoringAlgorithms; - int color() { - vector V = V_c; - property_map::type color = get(vertex_color, GraphInstance); - vector forbiddenColors(NumOfVertices(GraphInstance), -1); - //All edges in E_S have edge_weight=1; otherwise edge_weight=0 + int color() override { + const std::vector& V = V_c; + std::vector forbiddenColors(NumOfVertices(GraphInstance), static_cast(-1)); - //Iterate over all vertices which should be colored - for_each(V.begin(), V.end(), [&](unsigned int v) { + for (unsigned int v : V) { + // Reset forbidden color tracking for current vertex forbiddenColors[0] = v; + if (neighbors::IncidentToReqEdge(GraphInstance, v)) { - //Get the distance-2 neighbors - vector N_2 = neighbors::Distance2NeighborsRestricted(GraphInstance, v); - - //Iterate over distance-2 neighbors - for_each(N_2.begin(), N_2.end(), [&](unsigned int n_2) { - //Mark colors which are used by distance-2 neighbors in forbiddenColors - if (get(vertex_color, GraphInstance, n_2) > 0) { - forbiddenColors[get(vertex_color, GraphInstance, n_2)] = v; + for (std::vector N2 = neighbors::Distance2NeighborsRestricted(GraphInstance, v); unsigned int n2 : N2) { + if (const unsigned int n2_color = get(vertex_color, GraphInstance, n2); n2_color > 0) { + forbiddenColors[n2_color] = v; } - }); + } - //Find first color which can be assigned to v - auto result = find_if(forbiddenColors.begin(), forbiddenColors.end(), std::bind1st(std::not_equal_to(), v)); + // Find the first color not forbidden for this vertex + const auto available_color = std::ranges::find_if(forbiddenColors, + [v](const unsigned int c) { return c != v; }); - //Color v - SetVertexColor(GraphInstance, v,distance(forbiddenColors.begin(), result)); -// put(color, v, distance(forbiddenColors.begin(), result)); + const unsigned int assigned_color = std::distance(forbiddenColors.begin(), available_color); + SetVertexColor(GraphInstance, v, assigned_color); } else { + // Assign color 0 if no restriction SetVertexColor(GraphInstance, v, 0); -// put(color, v, 0); } - }); + } + return NumOfColors(); } }; - -#endif //PRECOL_ONESIDEDD2COLORING_H +#endif // PRECOL_ONESIDEDD2COLORING_H diff --git a/Algorithms/OneSidedD2ColoringNonReq.h b/Algorithms/OneSidedD2ColoringNonReq.h index 8d2ddf5..ab1097e 100644 --- a/Algorithms/OneSidedD2ColoringNonReq.h +++ b/Algorithms/OneSidedD2ColoringNonReq.h @@ -46,7 +46,7 @@ class OneSidedD2ColoringNonReq : public ColoringAlgorithms { //Find first color which can be assigned to v vector::iterator result = find_if(forbiddenColors.begin(), forbiddenColors.end(), - std::bind1st(std::not_equal_to(), v)); + std::bind(std::not_equal_to(), v, std::placeholders::_1)); //Color v SetVertexColor(GraphInstance, v, distance(forbiddenColors.begin(), result)); diff --git a/Algorithms/OneSidedD2ColoringNonReqBalanced.h b/Algorithms/OneSidedD2ColoringNonReqBalanced.h index b536061..5a06288 100644 --- a/Algorithms/OneSidedD2ColoringNonReqBalanced.h +++ b/Algorithms/OneSidedD2ColoringNonReqBalanced.h @@ -47,9 +47,10 @@ class OneSidedD2ColoringNonReqBalanced : public ColoringAlgorithms { } }); - //Find first color which can be assigned to v - vector::iterator result = find_if(forbiddenColors.begin(), forbiddenColors.end(), - std::bind1st(std::not_equal_to(), v)); + //Find the first color which can be assigned to v + vector::iterator result = find_if(forbiddenColors.begin(), + forbiddenColors.end(), + std::bind(std::not_equal_to(), v, std::placeholders::_1)); //Color v SetVertexColor(GraphInstance, v, distance(forbiddenColors.begin(), result)); diff --git a/Algorithms/StarBicoloringVertexCover.h b/Algorithms/StarBicoloringVertexCover.h index 1d9ab57..222d2f2 100644 --- a/Algorithms/StarBicoloringVertexCover.h +++ b/Algorithms/StarBicoloringVertexCover.h @@ -142,10 +142,10 @@ class StarBicoloringVertexCover : public ColoringAlgorithms { }); } }); - //Find first color which can be assigned to v_c + //Find the first color which can be assigned to v_c vector::iterator color_v_it = find_if(forbiddenColors.begin(), forbiddenColors.end(), - bind1st(not_equal_to(), *v) + bind(not_equal_to(), *v, std::placeholders::_1) ); SetVertexColor(GraphInstance, *v, distance(forbiddenColors.begin(), color_v_it)); // put(color, *v, distance(forbiddenColors.begin(), color_v_it)); @@ -203,7 +203,7 @@ class StarBicoloringVertexCover : public ColoringAlgorithms { } //Find first color which can be assigned to v_c auto color_v_it = find_if(forbiddenColors.begin(), forbiddenColors.end(), - bind1st(not_equal_to(), *v)); + bind(not_equal_to(), *v, std::placeholders::_1)); SetVertexColor(GraphInstance, *v, distance(forbiddenColors.begin(), color_v_it)); // put(color, *v, distance(forbiddenColors.begin(), color_v_it)); } diff --git a/Algorithms/StarBicoloringVertexCoverNonReq.h b/Algorithms/StarBicoloringVertexCoverNonReq.h index 982b965..1c6ce50 100644 --- a/Algorithms/StarBicoloringVertexCoverNonReq.h +++ b/Algorithms/StarBicoloringVertexCoverNonReq.h @@ -166,10 +166,10 @@ class StarBicoloringVertexCoverNonReq : public ColoringAlgorithms{ } } } - //Find first color which can be assigned to v_c - vector::iterator color_v_it = find_if(forbiddenColors.begin(), + //Find the first color which can be assigned to v_c + std::vector::iterator color_v_it = find_if(forbiddenColors.begin(), forbiddenColors.end(), - bind1st(not_equal_to(), *v) + bind(not_equal_to(), *v, std::placeholders::_1) ); SetVertexColor(GraphInstance, *v, distance(forbiddenColors.begin(), color_v_it)); // put(color, *v, distance(forbiddenColors.begin(), color_v_it)); @@ -233,7 +233,7 @@ class StarBicoloringVertexCoverNonReq : public ColoringAlgorithms{ //Find first color which can be assigned to v_c vector::iterator color_v_it = find_if(forbiddenColors.begin(), forbiddenColors.end(), - bind1st(not_equal_to(), *v) + bind(not_equal_to(), *v, std::placeholders::_1) ); SetVertexColor(GraphInstance, *v, distance(forbiddenColors.begin(),color_v_it)); // put(color,*v,distance(forbiddenColors.begin(),color_v_it)); @@ -503,7 +503,7 @@ class StarBicoloringVertexCoverNonReq : public ColoringAlgorithms{ //Find first color which can be assigned to v_c vector::iterator color_v_it = find_if(forbiddenColors.begin(), forbiddenColors.end(), - bind1st(not_equal_to(), *v) + bind(not_equal_to(), *v, std::placeholders::_1) ); SetVertexColor(GraphInstance, *v, distance(forbiddenColors.begin(), color_v_it)); // put(color, *v, distance(forbiddenColors.begin(), color_v_it)); @@ -591,7 +591,7 @@ class StarBicoloringVertexCoverNonReq : public ColoringAlgorithms{ //Find first color which can be assigned to v_c vector::iterator color_v_it = find_if(forbiddenColors.begin(), forbiddenColors.end(), - bind1st(not_equal_to(), *v) + bind(not_equal_to(), *v, std::placeholders::_1) ); SetVertexColor(GraphInstance, *v, distance(forbiddenColors.begin(), color_v_it)); // put(color, *v, distance(forbiddenColors.begin(), color_v_it)); diff --git a/Algorithms/algorithms.h b/Algorithms/algorithms.h index 4e37ad5..e84bb88 100644 --- a/Algorithms/algorithms.h +++ b/Algorithms/algorithms.h @@ -36,21 +36,22 @@ static vector algs = {"D2Columns", "D2Rows", "GreedyColoring","GreedyCol * @param G_b the input bipartite graph * @param V_r the row vertices * @param V_c the column vertices - * @param order the ordering of vertices for coloring + * @param alpha + * @param MaxColor * @return */ -static shared_ptr getAlg(int Mode2, const string &alg, - int Mode, Graph &G_b, vector &V_r, - vector &V_c, - unique_ptr& order, int alpha, int MaxColor = 0) { +static shared_ptr getAlg(int Mode2, const string& alg, + int Mode, Graph& G_b, vector& V_r, + vector& V_c, + int alpha, int MaxColor = 0) { if (alg == "D2Columns") { - return shared_ptr(new OneSidedD2Coloring(G_b, V_c, false)); + return std::make_shared(G_b, V_c, false); } else if (alg == "D2Rows") { - return shared_ptr(new OneSidedD2Coloring(G_b, V_r, false)); + return std::make_shared(G_b, V_r, false); } else if (alg == "D2RestrictedColumns") { - return shared_ptr(new OneSidedD2Coloring(G_b, V_c, true)); + return std::make_shared(G_b, V_c, true); } else if (alg == "D2RestrictedRows") { - return shared_ptr(new OneSidedD2Coloring(G_b, V_r, true)); + return std::make_shared(G_b, V_r, true); } else if (alg == "D2RestrictedColumnsNonReq") { return shared_ptr(new OneSidedD2ColoringNonReq(G_b, V_c, true, {{"alpha", alpha}})); } else if (alg == "D2RestrictedColumnsNonReqBalanced") { @@ -67,9 +68,9 @@ static shared_ptr getAlg(int Mode2, const string &alg, return shared_ptr(new StarBicoloringVertexCoverNonReq(G_b, V_r, V_c, true, {{"Mode", Mode},{"Mode2",Mode2},{"alpha",alpha}})); } else if (alg == "GreedyColoringBoost") { - return shared_ptr(new GreedyColoringSimpleGraphBoost(G_b)); + return std::make_shared(G_b); } else if (alg == "GreedyColoring") { - return shared_ptr(new GreedyColoringSimpleGraph(G_b, V_c)); + return std::make_shared(G_b, V_c); } else if (alg == "GreedyColoringLimitedMaxColor") { return shared_ptr(new GreedyColoringLimitedMaxColor(G_b, V_c, false, {{"MaxColor", MaxColor}})); } else { diff --git a/Algorithms/d2_color_omp.h b/Algorithms/d2_color_omp.h index 50189dc..e2a50b4 100644 --- a/Algorithms/d2_color_omp.h +++ b/Algorithms/d2_color_omp.h @@ -60,7 +60,7 @@ class D2ColorOMP : public ColAlg { //Find first color which can be assigned to v auto result = find_if(forbiddenColors.begin(), forbiddenColors.end(), - bind1st(std::not_equal_to(), v)); + bind(std::not_equal_to(), v, std::placeholders::_1)); //Color v put(color, v, distance(forbiddenColors.begin(), result)); diff --git a/Application/Preconditioning/main.cpp b/Application/Preconditioning/main.cpp index 1d7fbf5..9e7cd29 100644 --- a/Application/Preconditioning/main.cpp +++ b/Application/Preconditioning/main.cpp @@ -54,7 +54,7 @@ int main(int argc, char *argv[]) { ColoringOrder->OrderGivenVertexSubset(G_b, V_r, ColoringAlgorithm.find("Restricted") != string::npos); // ApplyColoringOrder(ColoringAlgorithm, ColoringOrder, GraphInstance, V_r, V_c); //Coloring of the vertices - int cols = getAlg(Mode2, ColoringAlgorithm, Mode, G_b, V_r, V_c, ColoringOrder, AlphaForBalancedColoring)->color(); + int cols = getAlg(Mode2, ColoringAlgorithm, Mode, G_b, V_r, V_c, AlphaForBalancedColoring)->color(); end = clock(); //all edges A - \Rinit vector edge_ordering; diff --git a/BoostTest/PreColTest.cpp b/BoostTest/PreColTest.cpp index 822ea8d..f13b391 100644 --- a/BoostTest/PreColTest.cpp +++ b/BoostTest/PreColTest.cpp @@ -26,7 +26,7 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) BOOST_AUTO_TEST_CASE(ArrowShapedTest) { std::string alg = "D2Columns"; std::string col_ord = "LargestFirstOrderingDegrees"; - unique_ptr col_ord_c = GetColoringOrder(col_ord); + auto col_ord_c = GetColoringOrder(col_ord); std::string pre_ord = "NaturalOrdering"; std::string filename = "ExampleMatrices/arrow-shaped.mtx"; KindOfSparsify sparsify = Full; @@ -46,7 +46,7 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) BOOST_CHECK_EQUAL(V_c.size(), 6); int entries_pattern = SparsifyBipartiteGraph(G_b, sparsify, mm.nrows(), blockSize, ""); BOOST_CHECK_EQUAL(entries_pattern, 16); - shared_ptr ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, col_ord_c, alpha); + shared_ptr ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, alpha); int num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 6); @@ -66,18 +66,18 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) BOOST_CHECK_EQUAL(num_of_colors, 4); alg = "D2RestrictedColumnsNonReq"; - ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, col_ord_c, alpha); + ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, alpha); num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 4); alg = "D2RestrictedColumnsNonReqBalanced"; - ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, col_ord_c, alpha); + ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, alpha); num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 4); alg = "D2Columns"; sparsify = Diagonal; - ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, col_ord_c, alpha); + ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, alpha); entries_pattern = SparsifyBipartiteGraph(G_b, sparsify, mm.nrows(), blockSize, ""); BOOST_CHECK_EQUAL(entries_pattern, 6); num_of_colors = ret->color(); @@ -88,7 +88,7 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) sparsify = Full; entries_pattern = SparsifyBipartiteGraph(G_b, sparsify, mm.nrows(), blockSize, ""); BOOST_CHECK_EQUAL(entries_pattern, 16); - ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, col_ord_c, alpha); + ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, alpha); num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 2); @@ -98,7 +98,7 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) blockSize = 3; entries_pattern = SparsifyBipartiteGraph(G_b, sparsify, mm.nrows(), blockSize, ""); BOOST_CHECK_EQUAL(entries_pattern, 10); - ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, col_ord_c, alpha); + ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, alpha); num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 2); @@ -112,17 +112,17 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) alg = "GreedyColoring"; vector order; ForEachVertex(G_CIG, [&](Ver v) { order.push_back(v); }); - ret = getAlg(Mode2, alg, Mode, G_CIG, V_r, order, col_ord_c, alpha); + ret = getAlg(Mode2, alg, Mode, G_CIG, V_r, order, alpha); num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 6); alg = "GreedyColoringBoost"; - ret = getAlg(Mode2, alg, Mode, G_CIG, V_r, V_c, col_ord_c, alpha); + ret = getAlg(Mode2, alg, Mode, G_CIG, V_r, V_c, alpha); num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 6); alg = "GreedyColoringLimitedMaxColor"; - ret = getAlg(Mode2, alg, Mode, G_CIG, V_r, order, col_ord_c, alpha, 5); + ret = getAlg(Mode2, alg, Mode, G_CIG, V_r, order, alpha, 5); num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 5); } @@ -130,7 +130,7 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) BOOST_AUTO_TEST_CASE(ArrowShapedPlusOneTest) { std::string alg = "D2Columns"; std::string col_ord = "LargestFirstOrderingDegrees"; - unique_ptr col_ord_c = GetColoringOrder(col_ord); + auto col_ord_c = GetColoringOrder(col_ord); std::string pre_ord = "NaturalOrdering"; std::string filename = "ExampleMatrices/arrow-shaped_plus_one.mtx"; std::string custom_required_pattern = "ExampleMatrices/custom_required_pattern1"; @@ -151,7 +151,7 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) BOOST_CHECK_EQUAL(V_c.size(), 6); int entries_pattern = SparsifyBipartiteGraph(G_b, sparsify, mm.nrows(), blockSize, ""); BOOST_CHECK_EQUAL(entries_pattern, 17); - shared_ptr ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, col_ord_c, alpha); + shared_ptr ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, alpha); int num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 6); @@ -171,7 +171,7 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) BOOST_AUTO_TEST_CASE(ArrowShapedPlusOneMinusOneTest) { std::string alg = "D2Columns"; std::string col_ord = "LargestFirstOrderingDegrees"; - unique_ptr col_ord_c = GetColoringOrder(col_ord); + auto col_ord_c = GetColoringOrder(col_ord); std::string pre_ord = "NaturalOrdering"; std::string filename = "ExampleMatrices/arrow-shaped_plus_one_minus_one.mtx"; KindOfSparsify sparsify = Full; @@ -191,12 +191,12 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) BOOST_CHECK_EQUAL(V_c.size(), 6); int entries_pattern = SparsifyBipartiteGraph(G_b, sparsify, mm.nrows(), blockSize, ""); BOOST_CHECK_EQUAL(entries_pattern, 16); - shared_ptr ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, col_ord_c, alpha); + shared_ptr ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, alpha); int num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 5); alg = "D2Rows"; - ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, col_ord_c, alpha); + ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, alpha); num_of_colors = ret->color(); BOOST_CHECK_EQUAL(num_of_colors, 6); @@ -211,7 +211,7 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) BOOST_AUTO_TEST_CASE(DifferentIndependentSet) { std::string alg = "D2Columns"; std::string col_ord = "LargestFirstOrderingDegrees"; - unique_ptr col_ord_c = GetColoringOrder(col_ord); + auto col_ord_c = GetColoringOrder(col_ord); std::string pre_ord = "NaturalOrdering"; std::string filename = "ExampleMatrices/arrow-shaped.mtx"; KindOfSparsify sparsify = Full; @@ -223,7 +223,7 @@ BOOST_AUTO_TEST_SUITE(ColoringTestSuite) vector V_r, V_c; ForEachVertex(G_b, [&](const unsigned int vi) { vi < mm.nrows() ? V_r.push_back(vi) : V_c.push_back(vi); }); int entries_pattern = SparsifyBipartiteGraph(G_b, sparsify, mm.nrows(), blockSize, ""); - shared_ptr ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, col_ord_c, alpha); + shared_ptr ret = getAlg(Mode2, alg, Mode, G_b, V_r, V_c, alpha); int num_of_colors = ret->color(); mm.MtxToBipGraph(G_b, 1); diff --git a/CMakeLists.txt b/CMakeLists.txt index ca07299..8f082e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,10 @@ -cmake_minimum_required(VERSION 3.2.2) +cmake_minimum_required(VERSION 4.0) project(precol) -find_package(Boost REQUIRED COMPONENTS unit_test_framework) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fopenmp") -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fopenmp -D_GLIBCXX_PARALLEL") +set (CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED True) +find_package(Boost REQUIRED COMPONENTS unit_test_framework) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -fopenmp") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -fopenmp -D_GLIBCXX_PARALLEL") include_directories(${Boost_INCLUDE_DIRS}) file(GLOB ALG_SRC "Algorithms/*.cpp") file(GLOB Application "Application/*.cpp") @@ -17,6 +19,7 @@ add_executable(BoostTest ${BoostTestSrc} ${ALG_SRC} ${GRAPH_SRC} ${ORD_SRC}) add_executable(Application ${Application} ${InputOutput} ${PRECONDITIONING_SRC} ${ALG_SRC} ${GRAPH_SRC} ${ORD_SRC}) add_executable(PreCol ${MainSRC} ${InputOutput} ${ALG_SRC} ${GRAPH_SRC} ${ORD_SRC}) add_executable(ColumnGain ${COLUMN_GAIN_GRAPH} ${ALG_SRC} ${GRAPH_SRC} ${ORD_SRC}) + target_link_libraries(Application ${Boost_LIBRARIES}) target_link_libraries(BoostTest ${Boost_LIBRARIES}) target_link_libraries(PreCol ${Boost_LIBRARIES}) diff --git a/Graph/ConvertGraph.cpp b/Graph/ConvertGraph.cpp index 196df96..b39b7a4 100644 --- a/Graph/ConvertGraph.cpp +++ b/Graph/ConvertGraph.cpp @@ -9,113 +9,13 @@ * @param ColumnIntersectionGraph * @return */ -bool BipartiteToColumnIntersectionGraph(const Graph& G_b, const vector& V_c, Graph& ColumnIntersectionGraph) { - for_each(V_c.begin(),V_c.end(),[&](unsigned int vc){ +bool BipartiteToColumnIntersectionGraph(const Graph& G_b, const vector& V_c, Graph& ColumnIntersectionGraph) +{ + std::ranges::for_each(V_c,[&](const unsigned int vc){ vector N_2 = neighbors::Distance2Neighbors(G_b, vc); - for_each(N_2.begin(),N_2.end(),[&](unsigned int n2){ + std::ranges::for_each(N_2,[&](const unsigned int n2){ add_edge(vc - V_c.size(), n2 - V_c.size(), 1, ColumnIntersectionGraph); }); }); return EXIT_SUCCESS; -} -//#include "neighbors.hpp" -// -// -////Convert bipartite graph to column intersection graph -//static bool bipartiteToCIG(const Graph& GraphInstance, const vector& V_c, Graph& G_c) { -// for_each(V_c.begin(),V_c.end(),[&](unsigned int vc){ -// vector Distance2Neighbors = neighbors::Distance2NeighborsRestricted(GraphInstance,vc); -// for_each(N_2.begin(),Distance2Neighbors.end(),[&](unsigned int n2){ -// add_edge(vc - V_c.size(), n2 - V_c.size(), 1, G_c); -// }); -// }); -//// for (vector::const_iterator v_c = V_c.begin(); -//// v_c != V_c.end(); -//// ++v_c) { -//// vector Distance2Neighbors; -//// Distance2Neighbors = neighbors::Distance2NeighborsRestricted(GraphInstance, *v_c); -//// int num_vertices_G_c = V_c.size(); -//// -//// for (vector::iterator n_2 = N_2.begin(); n_2 != Distance2Neighbors.end(); ++n_2) { -//// if (*n_2 > *v_c) { -//// add_edge(*v_c - num_vertices_G_c, *n_2 - num_vertices_G_c, 0, G_c); -//// cout << *v_c << " " << *n_2 << endl; -//// } -//// } -//// } -// -// return EXIT_SUCCESS; -//} -// -////Convert bipartite graph to column intersection graph with respect to -////the required elements -//static bool G_bToG_cRestricted(const Graph& GraphInstance, const vector& V_c, -// Graph& G_c) -//{ -// for (vector::const_iterator v_c = V_c.begin(); -// v_c != V_c.end(); -// ++v_c) { -// -// vector Distance2Neighbors; -// Distance2Neighbors = neighbors::Distance2NeighborsRestricted(GraphInstance,*v_c); -// int num_vertices_G_c = num_vertices(G_c); -// -// for (vector::iterator n_2 = Distance2Neighbors.begin(); -// n_2 != Distance2Neighbors.end(); -// ++n_2) { -// -// if (*n_2>*v_c) { -// add_edge(*v_c-num_vertices_G_c,*n_2-num_vertices_G_c,0,G_c); -// } -// } -// } -// -// return EXIT_SUCCESS; -//} -// -////Convert bipartite graph to row intersection graph (column -////intersection graph for rows instead of colums) -//static bool G_bToG_r(const Graph& GraphInstance, const vector& V_r, Graph& G_r) { -// for (vector::const_iterator v_r = V_r.begin(); -// v_r != V_r.end(); -// ++v_r) { -// -// vector Distance2Neighbors; -// Distance2Neighbors = neighbors::Distance2NeighborsRestricted(GraphInstance, *v_r); -// -// for (vector::iterator n_2 = Distance2Neighbors.begin(); -// n_2 != Distance2Neighbors.end(); -// ++n_2) { -// -// if (*n_2 > *v_r) { -// add_edge(*v_r, *n_2, 0, G_r); -// } -// } -// } -// -// return EXIT_SUCCESS; -//} -// -////Convert bipartite graph to row intersection graph with respect to -////the required elements (column intersection graph for rows instead of -////colums) -//static bool G_bToG_rRestricted(const Graph& GraphInstance, const vector& V_r, -// Graph& G_r) { -// for (vector::const_iterator v_r = V_r.begin(); -// v_r != V_r.end(); -// ++v_r) { -// -// vector Distance2Neighbors; -// Distance2Neighbors = neighbors::Distance2NeighborsRestricted(GraphInstance, *v_r); -// -// for (vector::iterator n_2 = Distance2Neighbors.begin(); -// n_2 != Distance2Neighbors.end(); -// ++n_2) { -// -// if (*n_2 > *v_r) { -// add_edge(*v_r, *n_2, 0, G_r); -// } -// } -// } -// return EXIT_SUCCESS; -//} +} \ No newline at end of file diff --git a/Graph/GraphDataType.hpp b/Graph/GraphDataType.hpp index 4e00d1e..4e29f25 100644 --- a/Graph/GraphDataType.hpp +++ b/Graph/GraphDataType.hpp @@ -273,19 +273,19 @@ namespace PreCol { } } - static inline int NumOfVertices(const Graph& g) { + static int NumOfVertices(const Graph& g) { return boost::num_vertices(g); } - static inline int NumOfEdges(const Graph& g) { + static int NumOfEdges(const Graph& g) { return boost::num_edges(g); } - static inline void SetVertexColor(Graph& g, Ver v, int color) { + static void SetVertexColor(Graph& g, const Ver& v, const unsigned int color) { boost::put(vertex_color, g, v, color); } - static inline int GetVertexColor(Graph& g, Ver v, int color) { + static int GetVertexColor(Graph& g, Ver v, int color) { return boost::get(vertex_color, g, v); } } diff --git a/Graph/Sparsify.cpp b/Graph/Sparsify.cpp index 88d50ff..fd634d2 100644 --- a/Graph/Sparsify.cpp +++ b/Graph/Sparsify.cpp @@ -15,7 +15,7 @@ * @param custom File name for reading the custom sparsification * @return Number of remaining nonzero elements */ -int SparsifyBipartiteGraph(Graph& G_b, KindOfSparsify sparsify, int nrows, int blockSize, std::string custom) { +int SparsifyBipartiteGraph(Graph& G_b, KindOfSparsify sparsify, unsigned int nrows, int blockSize, std::string custom) { property_map::type weight = get(edge_weight, G_b); property_map::type name = get(edge_name, G_b); diff --git a/Graph/Sparsify.h b/Graph/Sparsify.h index e4471e9..f2eb257 100644 --- a/Graph/Sparsify.h +++ b/Graph/Sparsify.h @@ -31,5 +31,5 @@ static std::map StringToKindOfSparsify = { * @param custom File name for reading the custom sparsification * @return Number of remaining nonzero elements */ -int SparsifyBipartiteGraph(Graph& G_b, KindOfSparsify sparsify, int nrows, int blockSize, std::string custom); +int SparsifyBipartiteGraph(Graph& G_b, KindOfSparsify sparsify, unsigned int nrows, int blockSize, std::string custom); #endif //PRECOL_SPARSIFY_H diff --git a/Graph/neighbors.hpp b/Graph/neighbors.hpp index 15e66d8..028b429 100644 --- a/Graph/neighbors.hpp +++ b/Graph/neighbors.hpp @@ -1,87 +1,65 @@ #ifndef NEIGHBORS_HPP #define NEIGHBORS_HPP -#include -#include -#include "boost/graph/adjacency_list.hpp" -#include "boost/graph/graph_utility.hpp" +#include +#include #include "GraphDataType.hpp" -/** - * \namespace neighbors - * \brief Contains functions to find the (IsRestrictedColoring) distance-2 neigbors of a vertex - */ namespace neighbors { using boost::out_edges; + using boost::target; + using boost::get; using boost::edge_weight; - //Compute the IsRestrictedColoring distance-2 neighbors of Vertex - /** - * \brief Find distance-2 neighbors of the given vertex with respect to required edges - * - * @param G_b the given bipartite graph - * @param Vertex the given vertex - * @return all distance-2 neighbors of the given vertex v - */ static std::vector Distance2NeighborsRestricted(const Graph& G_b, const unsigned int Vertex) { - std::vector neighbors; - for_each(boost::out_edges(Vertex, G_b).first,out_edges(Vertex, G_b).second,[&](Edge e) { - for_each(out_edges(target(e,G_b), G_b).first,out_edges(target(e,G_b), G_b).second,[&](Edge e2) { - if(Vertex != target(e2, G_b)) { - //Edge e_1 or e_2 must be in E_S - //Is Edge e_1 in E_S - if (get(edge_weight, G_b, e) == 1) { - neighbors.push_back(target(e2, G_b)); - } else { - //Is Edge e_1 in E_S - if (get(edge_weight, G_b, e2) == 1) { - neighbors.push_back(target(e2, G_b)); - } + std::unordered_set neighbor_set; + + auto [begin1, end1] = out_edges(Vertex, G_b); + for (auto e1 = begin1; e1 != end1; ++e1) { + auto u = target(*e1, G_b); + auto [begin2, end2] = out_edges(u, G_b); + + for (auto e2 = begin2; e2 != end2; ++e2) { + unsigned int v2 = target(*e2, G_b); + if (v2 != Vertex) { + if (get(edge_weight, G_b, *e1) == 1 || get(edge_weight, G_b, *e2) == 1) { + neighbor_set.insert(v2); } } - }); - }); + } + } - std::sort(neighbors.begin(), neighbors.end()); - auto new_end = unique(neighbors.begin(), neighbors.end()); - neighbors.resize(distance(neighbors.begin(), new_end)); - return neighbors; + return std::vector(neighbor_set.begin(), neighbor_set.end()); } - /** - * \brief Find distance-2 neighbors of the given vertex - * - * @param G_b the given bipartite graph - * @param Vertex the given vertex - * @return all distance-2 neighbors of the given vertex v - */ static std::vector Distance2Neighbors(const Graph& G_b, const unsigned int Vertex) { - std::vector neighbors; - for_each(boost::out_edges(Vertex, G_b).first,out_edges(Vertex, G_b).second,[&](Edge e) { - for_each(out_edges(target(e,G_b), G_b).first,out_edges(target(e,G_b), G_b).second,[&](Edge e2) { - if(Vertex != target(e2, G_b)) { - neighbors.push_back(target(e2, G_b)); + std::unordered_set neighbor_set; + + auto [begin1, end1] = out_edges(Vertex, G_b); + for (auto e1 = begin1; e1 != end1; ++e1) { + auto u = target(*e1, G_b); + auto [begin2, end2] = out_edges(u, G_b); + + for (auto e2 = begin2; e2 != end2; ++e2) { + unsigned int v2 = target(*e2, G_b); + if (v2 != Vertex) { + neighbor_set.insert(v2); } - }); - }); + } + } - std::sort(neighbors.begin(), neighbors.end()); - auto new_end = unique(neighbors.begin(), neighbors.end()); - neighbors.resize(distance(neighbors.begin(), new_end)); - return neighbors; + return std::vector(neighbor_set.begin(), neighbor_set.end()); } - static int IncidentToReqEdge(const Graph &G_b, const unsigned int v) { - bool incident = false; - std::for_each(out_edges(v, G_b).first, out_edges(v, G_b).second, [&](Edge e) { - if (boost::get(boost::edge_weight, G_b, e) == 1) { - incident = true; - return; + static bool IncidentToReqEdge(const Graph& G_b, const unsigned int v) { + auto [begin, end] = out_edges(v, G_b); + for (auto it = begin; it != end; ++it) { + if (get(edge_weight, G_b, *it) == 1) { + return true; } - }); - return incident; + } + return false; } } - #endif diff --git a/InputOutput/HandleInputOutput.cpp b/InputOutput/HandleInputOutput.cpp index 35475ce..1699f82 100644 --- a/InputOutput/HandleInputOutput.cpp +++ b/InputOutput/HandleInputOutput.cpp @@ -1,8 +1,3 @@ -// -// Created by rostam on 10.07.20. -// - - #include "HandleInputOutput.h" #include #include @@ -10,169 +5,190 @@ #include "../Algorithms/algorithms.h" #include "../Orderings/orderings.h" -/** - * Extract the value of parameter / line will be modified - * - * @param NameOfParameter - * @param line - * @return - */ +using std::ifstream; +using std::istringstream; +using std::string; +using std::vector; +using std::cout; +using std::endl; +using std::ostream_iterator; + bool ExtractValueOfParameter(const string& NameOfParameter, string& line) { - if(line.find(NameOfParameter) != std::string::npos && line.find('=') != std::string::npos) { + if (line.find(NameOfParameter) != string::npos && line.find('=') != string::npos) { line = line.substr(line.find('=') + 1); - line.erase(remove(line.begin(), line.end(), ' ')); + line.erase(remove(line.begin(), line.end(), ' '), line.end()); return true; } return false; } -/** - * \brief handle the input from file to the program - * - * @param argc the number of arguments - * @param argv the actual arguments - * @return tuple - * - */ -tuple, KindOfSparsify, int, string, int, string, int, int, int> -GetInputParametersForApplication(const std::string& FileName) { -// vector iset = {"Best", "Variant"}; +InputParameters GetInputParametersForApplication(const std::string& FileName) { ifstream InFile(FileName); - std::string line; - string MatrixName, ColoringAlgorithm, ColoringOrder, PreconditioningOrder, IndependentSetAlgorithm; - KindOfSparsify SparsificationKind; - int BlockSize, EliminationParameter, AlphaForBalancedColoring; - double RhoIndependentSet; + if (!InFile.is_open()) { + throw std::runtime_error("Could not open file: " + FileName); + } + + string line; + InputParameters params; + + params.blockSize = 0; + params.eliminationLevel = 0; + params.alpha = 0; + double rho = 0.0; + params.mode = 3; + params.mode2 = 0; + while (std::getline(InFile, line)) { - if(line.find('#') != std::string::npos || line.size() <= 3) { - // DO NOTHING - } else if(ExtractValueOfParameter("MATRIX", line)) { - MatrixName = line; + if (line.find('#') != string::npos || line.size() <= 3) { + continue; + } else if (ExtractValueOfParameter("MATRIX", line)) { + params.algorithm = line; } else if (ExtractValueOfParameter("COLORING_ALGORITHM", line)) { - ColoringAlgorithm = line; + params.coloringAlgorithm = line; } else if (ExtractValueOfParameter("COLORING_ORDERING", line)) { - ColoringOrder = line; + params.coloringOrder = GetColoringOrder(line); } else if (ExtractValueOfParameter("KIND_OF_SPARSIFICATION", line)) { - SparsificationKind = StringToKindOfSparsify[line]; + params.sparsificationKind = StringToKindOfSparsify[line]; } else if (ExtractValueOfParameter("BLOCK_SIZE", line)) { - std::istringstream iss(line); - iss>>BlockSize; + istringstream(line) >> params.blockSize; } else if (ExtractValueOfParameter("PRECONDITIONING_ORDERING", line)) { - PreconditioningOrder = line; + params.preconditioningOrder = line; } else if (ExtractValueOfParameter("PRECONDITIONING_ELIMINATION_LEVEL_PARAMETER", line)) { - std::istringstream iss(line); - iss>>EliminationParameter; + istringstream(line) >> params.eliminationLevel; } else if (ExtractValueOfParameter("INDEPENDENT_SET_ALGORITHM", line)) { - IndependentSetAlgorithm = line; + params.independentSetAlgorithm = line; } else if (ExtractValueOfParameter("RHO_FOR_INDEPENDENT_SET_ALGORITHM", line)) { - std::istringstream iss(line); - iss >> RhoIndependentSet; + istringstream(line) >> rho; } else if (ExtractValueOfParameter("ALPHA_FOR_BALANCED_COLORING", line)) { - std::istringstream iss(line); - iss>>AlphaForBalancedColoring; + istringstream(line) >> params.alpha; } } - int Mode2; - int Mode = 3; - if (IndependentSetAlgorithm == "Best") Mode = 3; - else if (IndependentSetAlgorithm == "Variant") Mode = 0; - if (Mode == 3) { - if (RhoIndependentSet != 0) { - Mode = 2 * RhoIndependentSet; - } - } - if (Mode == 0) { - if (RhoIndependentSet != 0) { - Mode2 = 2 * RhoIndependentSet; - } + if (params.independentSetAlgorithm == "Best") params.mode = 3; + else if (params.independentSetAlgorithm == "Variant") params.mode = 0; + + if (params.mode == 3 && rho != 0.0) { + params.mode = static_cast(2 * rho); + } else if (params.mode == 0 && rho != 0.0) { + params.mode2 = static_cast(2 * rho); } - return make_tuple(MatrixName, ColoringAlgorithm, GetColoringOrder(ColoringOrder), SparsificationKind, BlockSize, PreconditioningOrder, - EliminationParameter, IndependentSetAlgorithm, AlphaForBalancedColoring, Mode, Mode2); + return params; } - -using std::cout; -using std::ostream_iterator; -/** - * \brief handle the input to the program - * - * @param argc the number of arguments - * @param argv the actual arguments - * @return tuple - */ -tuple,string,int,int,string,int, int,string, int> GetInputParametersForApplication(int argc, char **argv) { +CLIInputParameters GetInputParametersForApplication(int argc, char **argv) { vector iset = {"Best", "Variant"}; vector pats = {"Full", "Diagonal", "BlockDiagonal"}; -// cout << fixed << setprecision(4); - if (argc < 3) { - cout << "Insufficient arguments... "; - cout << "\nColoring Algorithm [Ordering][Independent Set][Rho][Pattern][Blocksize] Matrix"; - cout << "\nAlgorithm: |"; - copy(algs.begin(), algs.end(), ostream_iterator(cout, "|")); - cout << "\nOrdering: |"; - copy(ords.begin(), ords.end(), ostream_iterator(cout, "|")); - cout << "\nIndependent Set: |"; - copy(iset.begin(), iset.end(), ostream_iterator(cout, "|")); - cout << "\nRho [1|1.5..]"; - cout << "\nPattern: |"; - copy(pats.begin(), pats.end(), ostream_iterator(cout, "|")); - cout << "\nBlocksize integer"; - cout << "\nLevel parameter"; - cout << "\nNote that not all parameters are required for all algorithms\n"; - return std::make_tuple("", nullptr,"",0,0,"",0, 0,"",0); + if (argc < 9) { + cout << "Insufficient arguments...\n" + << "Usage: [Algorithm] [Ordering] [IS Algorithm] [Rho] [Pattern] [Blocksize] [Level] [Alpha] [Matrix]\n"; + return {}; } + CLIInputParameters params; string alg = argv[1]; if (find(algs.begin(), algs.end(), alg) == algs.end()) { - cout << "\nThe first argument '" << alg << - "' must be a coloring algorithm from the following list:\n"; + cout << "\nInvalid algorithm: '" << alg << "'. Must be one of:\n"; copy(algs.begin(), algs.end(), ostream_iterator(cout, "|")); cout << endl; - return std::make_tuple("", nullptr,"",0,0,"",0, 0,"",0); + return {}; } + params.algorithm = alg; + string ord = argv[2]; size_t pos = ord.find('_'); - string col_ord = ord.substr(0,pos); - string pre_ord = ord.substr(pos+1); - shared_ptr col_ord_c = GetColoringOrder(col_ord); - - int Mode2; - int Mode = 3; - if (string(argv[3]) == "Best") Mode = 3; - else if (string(argv[3]) == "Variant") Mode = 0; - if (Mode == 3) { - if (int rho = atoi(argv[4]); rho != 0) { - Mode = 2 * rho; - } - } - if (Mode == 0) { - if (int rho = atoi(argv[4]); rho != 0) { - Mode2 = 2 * rho; - } - } - string sparsify = argv[5]; - int blockSize = 0; - if (sparsify == "BlockDiagonal") { - if (int bls = atoi(argv[6]); bls != 0) blockSize = bls; + string col_ord = ord.substr(0, pos); + string pre_ord = ord.substr(pos + 1); + params.coloringOrder = GetColoringOrder(col_ord); + params.preconditioningOrder = pre_ord; + + const string is_alg = argv[3]; + const double rho = atof(argv[4]); + params.mode = (is_alg == "Best") ? 3 : 0; + if (params.mode == 3 && rho != 0.0) params.mode = static_cast(2 * rho); + if (params.mode == 0 && rho != 0.0) params.mode2 = static_cast(2 * rho); + + params.sparsify = argv[5]; + if (params.sparsify == "BlockDiagonal") { + int bls = atoi(argv[6]); + params.blockSize = (bls != 0) ? bls : 0; + } else { + params.blockSize = 0; } - int el = atoi(argv[7]); - int alpha = atoi(argv[8]); - string filename; - filename.insert(0, argv[6]); + params.eliminationLevel = atoi(argv[7]); + params.alpha = atoi(argv[8]); + params.matrixFilename = argv[9]; - return make_tuple(alg,col_ord_c,pre_ord,Mode,Mode2,sparsify, blockSize, el,filename,alpha); + return params; } -void write_csv_line(std::ofstream& outfile, vector&& v) { - for(int i=0;i < v.size();i++) { +void write_csv_line(ofstream& outfile, vector&& v) { + for (size_t i = 0; i < v.size(); ++i) { outfile << v[i]; - if(i != v.size() - 1) outfile << ","; + if (i != v.size() - 1) outfile << ","; else outfile << "\n"; } } + +std::vector GetInputParametersFromCSV(const std::string& csvFilename) { + std::ifstream infile(csvFilename); + if (!infile.is_open()) { + throw std::runtime_error("Could not open CSV file: " + csvFilename); + } + + std::vector allParams; + std::string line; + + // Read header + std::getline(infile, line); + + while (std::getline(infile, line)) { + std::istringstream ss(line); + std::string token; + InputParameters params; + double rho = 0.0; + + std::getline(ss, token, ','); + params.algorithm = token; + + std::getline(ss, token, ','); + params.coloringAlgorithm = token; + + std::getline(ss, token, ','); + params.coloringOrder = GetColoringOrder(token); + + std::getline(ss, token, ','); + params.sparsificationKind = StringToKindOfSparsify[token]; + + std::getline(ss, token, ','); + params.blockSize = std::stoi(token); + + std::getline(ss, token, ','); + params.independentSetAlgorithm = token; + + std::getline(ss, token, ','); + params.alpha = std::stoi(token); + + std::getline(ss, token, ','); + rho = std::stod(token); + + params.mode = (params.independentSetAlgorithm == "Best" || params.independentSetAlgorithm == "BEST") ? 3 : 0; + if (params.mode == 3 && rho != 0.0) { + params.mode = static_cast(2 * rho); + } else if (params.mode == 0 && rho != 0.0) { + params.mode2 = static_cast(2 * rho); + } + + // Optional fallbacks + params.preconditioningOrder = ""; + params.eliminationLevel = 0; + + allParams.push_back(std::move(params)); + } + + return allParams; +} + diff --git a/InputOutput/HandleInputOutput.h b/InputOutput/HandleInputOutput.h index eea67d0..2009fdd 100644 --- a/InputOutput/HandleInputOutput.h +++ b/InputOutput/HandleInputOutput.h @@ -1,36 +1,52 @@ -// -// Created by rostam on 05.08.16. -// - #ifndef PRECOL_HANDLEINPUTOUTPUT_H #define PRECOL_HANDLEINPUTOUTPUT_H + #include "../Graph/GraphDataType.hpp" #include "../Orderings/Ordering.h" #include "../Graph/Sparsify.h" #include #include +#include -using std::tuple; -/** - * \brief handle the input from file to the program - * - * @param argc the number of arguments - * @param argv the actual arguments - * @return tuple - */ -tuple, KindOfSparsify, int, string, int, string, int, int, int> -GetInputParametersForApplication(const std::string& FileName); +using std::string; +using std::unique_ptr; +using std::shared_ptr; +using std::vector; +using std::ofstream; /** - * \brief handle the input to the program - * - * @param argc the number of arguments - * @param argv the actual arguments - * @return tuple + * Struct to hold all input parameters for the application */ -tuple,string,int,int,string,int, int,string, int> -GetInputParametersForApplication(int argc, char **argv); +struct InputParameters { + std::string algorithm{}; + std::string coloringAlgorithm{}; + std::shared_ptr coloringOrder{nullptr}; + KindOfSparsify sparsificationKind{}; + int blockSize = 0; + std::string preconditioningOrder{}; + int eliminationLevel = 0; + std::string independentSetAlgorithm{}; + int alpha = 0; + int mode = 3; + int mode2 = 0; +}; + +struct CLIInputParameters { + string algorithm; + shared_ptr coloringOrder; + string preconditioningOrder; + int mode; + int mode2; + string sparsify; + int blockSize; + int eliminationLevel; + string matrixFilename; + int alpha; +}; +InputParameters GetInputParametersForApplication(const std::string& FileName); +CLIInputParameters GetInputParametersForApplication(int argc, char **argv); +std::vector GetInputParametersFromCSV(const std::string& csvFilename); void write_csv_line(std::ofstream& outfile, vector&& v); #endif //PRECOL_HANDLEINPUTOUTPUT_H diff --git a/Main/InputTable.csv b/Main/InputTable.csv new file mode 100644 index 0000000..ca44e10 --- /dev/null +++ b/Main/InputTable.csv @@ -0,0 +1,3 @@ +Matrix,COLORING_ALGORITHM,COLORING_ORDERING,KIND_OF_SPARSIFICATION,BLOCK_SIZE,INDEPENDENT_SET_ALGORITHM,ALPHA_FOR_BALANCED_COLORING,RHO_FOR_INDEPENDENT_SET_ALGORITHM +ExampleMatrices/FloridaSparseMatrixCollection/ex33.mtx,D2RestrictedColumns,LargestFirstOrderingDegrees,BlockDiagonal,30,BEST,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/ex33.mtx,D2RestrictedColumns,LargestFirstOrderingDegrees,BlockDiagonal,40,BEST,1,1 \ No newline at end of file diff --git a/Main/InputTableFullTest.csv b/Main/InputTableFullTest.csv new file mode 100644 index 0000000..f3766cb --- /dev/null +++ b/Main/InputTableFullTest.csv @@ -0,0 +1,26 @@ +Matrix,COLORING_ALGORITHM,COLORING_ORDERING,KIND_OF_SPARSIFICATION,BLOCK_SIZE,INDEPENDENT_SET_ALGORITHM,ALPHA_FOR_BALANCED_COLORING,RHO_FOR_INDEPENDENT_SET_ALGORITHM +ExampleMatrices/FloridaSparseMatrixCollection/685_bus.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/1138_bus.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/ash608.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk01.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk01_mod.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk08.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk09.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstm01.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstm13.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bp_1400.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bp_1600.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/ex33.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/hess_pat.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/hess_pat_small.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/jac_pat.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/mtx-spear-head.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/fs_183_1.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/mymatrix.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/mymatrix1.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/fs_183_3.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/G51.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/nos3.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/plbuckle.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/str_200.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/str_400.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 diff --git a/Main/PreCol.cpp b/Main/PreCol.cpp index 46b2623..008686f 100755 --- a/Main/PreCol.cpp +++ b/Main/PreCol.cpp @@ -6,62 +6,84 @@ #include #include "../Graph/GraphDataType.hpp" #include "../Graph/ConvertGraph.hpp" -#include "../Orderings/orderings.h" #include "../Graph/GraphOutput.hpp" #include "../Algorithms/algorithms.h" #include "../Graph/Sparsify.h" #include "../InputOutput/HandleInputOutput.h" #include "../Graph/MatrixMarket.hpp" +#include +#include -//#include "../../Algorithms/exact_coloring.h" int main(int argc, char *argv[]) { -// auto [alg, ColoringOrdering, PreconditioningOrdering, Mode, Mode2, sparsify, BlockSize, EliminationParameter, MatrixFileName, Alpha] -// = GetInputParametersForApplication(argc, argv); + std::vector allInputParams; + std::string output_file; + if (argc == 3 && std::string(argv[1]).find(".csv") != std::string::npos) { + allInputParams = GetInputParametersFromCSV(argv[1]); + output_file = argv[2]; + std::string formatted_str = std::format("The program runs the algorithms on each row of the given csv file {} " + "and writes the output table to {}.", argv[1], output_file); + std::cout << formatted_str << std::endl; + } else if (argc >= 10) { + CLIInputParameters cliParams = GetInputParametersForApplication(argc, argv); + InputParameters singleRun; + singleRun.algorithm = cliParams.matrixFilename; + singleRun.coloringAlgorithm = cliParams.algorithm; + singleRun.coloringOrder = cliParams.coloringOrder; + singleRun.sparsificationKind = StringToKindOfSparsify[cliParams.sparsify]; + singleRun.blockSize = cliParams.blockSize; + singleRun.preconditioningOrder = cliParams.preconditioningOrder; + singleRun.eliminationLevel = cliParams.eliminationLevel; + singleRun.independentSetAlgorithm = argv[3]; + singleRun.alpha = cliParams.alpha; + singleRun.mode = cliParams.mode; + singleRun.mode2 = cliParams.mode2; + allInputParams.push_back(std::move(singleRun)); + } else { + allInputParams.push_back(GetInputParametersForApplication("Main/InputFile")); + } - auto [MatrixFileName, ColoringAlgorithm, ColoringOrder, SparsificationKind, BlockSize, PreconditioningOrder, - EliminationParameter, IndependentSetAlgorithm, AlphaForBalancedColoring, Mode, Mode2] - = GetInputParametersForApplication("Main/InputFile"); + if (output_file.empty()) + output_file = "OutputFile.csv"; + std::ofstream OutputFile(output_file); + write_csv_line(OutputFile, {"Matrix","NumOfRows","NumOfColumns","KindOfSparsification","BlockSize", + "NumOfRemainedNonzeros", "NumOfColors","Time"}); - clock_t start, end; - start = clock(); + for (const auto& params : allInputParams) { - //Initialize mm-object (matrixmarket) - MatrixMarket mm(MatrixFileName.c_str()); - mysymmetric = mm.issym(); + MatrixMarket mm(params.algorithm.c_str()); + mysymmetric = mm.issym(); - //Initialize graph-object (boost) - Graph G_b(2 * mm.nrows()); - vector V_r, V_c; - Graph G_ilu(mm.nrows()); - //Add vertices to graph - ForEachVertex(G_b, [&](const unsigned int vi) { vi < mm.nrows() ? V_r.push_back(vi) : V_c.push_back(vi); }); - //Add edges to graph - mm.MtxToBipGraph(G_b, 1); - Graph G_c; - BipartiteToColumnIntersectionGraph(G_b, V_c, G_c); + Graph G_b(2 * mm.nrows()); + std::vector V_r, V_c; + Graph G_ilu(mm.nrows()); -// graph2dot(GraphInstance); + ForEachVertex(G_b, [&](const unsigned int vi) { + (vi < mm.nrows()) ? V_r.push_back(vi) : V_c.push_back(vi); + }); - //Initialize required pattern - //If edge e \in E_S then edge_property edge_weight=1 else - //edge_weight=0 - int NumOfRemainedNonzeros = SparsifyBipartiteGraph(G_b, SparsificationKind, mm.nrows(), BlockSize, ""); + mm.MtxToBipGraph(G_b, 1); + // Graph G_c; + // BipartiteToColumnIntersectionGraph(G_b, V_c, G_c); - ColoringOrder->OrderGivenVertexSubset(G_b, V_r, ColoringAlgorithm.find("Restricted") != string::npos); + int NumOfRemainedNonzeros = SparsifyBipartiteGraph(G_b, params.sparsificationKind, mm.nrows(), params.blockSize, ""); - int cols = getAlg(Mode2, ColoringAlgorithm, Mode, G_b, V_r, V_c, ColoringOrder, AlphaForBalancedColoring)->color(); - end = clock(); + params.coloringOrder->OrderGivenVertexSubset(G_b, V_r, params.coloringAlgorithm.find("Restricted") != std::string::npos); + clock_t start = clock(); + int cols = getAlg(params.mode2, params.coloringAlgorithm, params.mode, G_b, V_r, V_c, params.alpha)->color(); + clock_t end = clock(); - ofstream OutputFile("OutputFile"); - write_csv_line(OutputFile, {"Matrix","NumOfRows","NumOfColumns","KindOfSparsification","BlockSize", - "NumOfRemainedNonzeros", "NumOfColors","Time"}); - write_csv_line(OutputFile, {MatrixFileName, std::to_string(mm.nrows()), std::to_string(mm.ncols()), - KindOfSparsifyToString[SparsificationKind], - std::to_string(BlockSize), std::to_string(NumOfRemainedNonzeros), - std::to_string(cols), - std::to_string((end - start) / double(CLOCKS_PER_SEC))}); - return EXIT_SUCCESS; -} + write_csv_line(OutputFile, { + params.algorithm, std::to_string(mm.nrows()), std::to_string(mm.ncols()), + KindOfSparsifyToString[params.sparsificationKind], + std::to_string(params.blockSize), std::to_string(NumOfRemainedNonzeros), + std::to_string(cols), std::to_string((end - start) / double(CLOCKS_PER_SEC)) + }); + } + OutputFile.close(); + std::string formatted_str = std::format("The program has with the code {} finished.", EXIT_SUCCESS); + std::cout << formatted_str << std::endl; + return EXIT_SUCCESS; +} diff --git a/Orderings/orderings.h b/Orderings/orderings.h index 3f91de7..94f5aa6 100644 --- a/Orderings/orderings.h +++ b/Orderings/orderings.h @@ -37,14 +37,14 @@ static vector ords = {"LargestFirstOrderingDegrees","SLO","IDO"}; * @param col_ord the string value contains both coloring and ordering * @return the ordering */ -static std::unique_ptr GetColoringOrder(const string& ColoringOrdering) { +static std::shared_ptr GetColoringOrder(const string& ColoringOrdering) { using std::make_unique; if (ColoringOrdering == "LargestFirstOrderingDegrees") return make_unique(); if (ColoringOrdering == "SLO") return make_unique(); if (ColoringOrdering == "IDO") return make_unique(); if (ColoringOrdering == "NaturalOrdering") return make_unique(); if (ColoringOrdering == "WeightOptimumOrdering") return make_unique(); - return make_unique(); + return std::make_shared(); } diff --git a/OtherSources/graph.h b/OtherSources/graph.h index 4ba1f1b..f9cd931 100644 --- a/OtherSources/graph.h +++ b/OtherSources/graph.h @@ -484,7 +484,7 @@ //// //// //Find first color which can be assigned to v //// vector::iterator result = find_if(forbiddenColors.begin(), forbiddenColors.end(), -//// bind1st(not_equal_to(), v)); +//// bind(not_equal_to(), v, std::placeholders::_1)); //// //// //Color v //// put(color, v, distance(forbiddenColors.begin(), result)); diff --git a/mybuild/OutputTable.csv b/mybuild/OutputTable.csv new file mode 100644 index 0000000..9ff543e --- /dev/null +++ b/mybuild/OutputTable.csv @@ -0,0 +1,26 @@ +Matrix,NumOfRows,NumOfColumns,KindOfSparsification,BlockSize,NumOfRemainedNonzeros,NumOfColors,Time +ExampleMatrices/FloridaSparseMatrixCollection/685_bus.mtx,685,685,Full,0,3249,14,0.001600 +ExampleMatrices/FloridaSparseMatrixCollection/1138_bus.mtx,1138,1138,Full,0,4054,18,0.001444 +ExampleMatrices/FloridaSparseMatrixCollection/ash608.mtx,608,188,Full,0,1216,6,0.000130 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk01.mtx,48,48,Full,0,400,15,0.000278 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk01_mod.mtx,48,48,Full,0,400,18,0.000213 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk08.mtx,1074,1074,Full,0,12960,339,0.041989 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk09.mtx,1083,1083,Full,0,18437,27,0.006203 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstm01.mtx,48,48,Full,0,48,1,0.000005 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstm13.mtx,2003,2003,Full,0,21943,78,0.022651 +ExampleMatrices/FloridaSparseMatrixCollection/bp_1400.mtx,822,822,Full,0,4790,311,0.010324 +ExampleMatrices/FloridaSparseMatrixCollection/bp_1600.mtx,822,822,Full,0,4841,304,0.010106 +ExampleMatrices/FloridaSparseMatrixCollection/ex33.mtx,1733,1733,Full,0,22189,28,0.010528 +ExampleMatrices/FloridaSparseMatrixCollection/hess_pat.mtx,43,43,Full,0,230,12,0.000109 +ExampleMatrices/FloridaSparseMatrixCollection/hess_pat_small.mtx,10,10,Full,0,36,6,0.000051 +ExampleMatrices/FloridaSparseMatrixCollection/jac_pat.mtx,10,43,Full,0,78,5,0.000020 +ExampleMatrices/FloridaSparseMatrixCollection/mtx-spear-head.mtx,10,10,Full,0,28,10,0.000013 +ExampleMatrices/FloridaSparseMatrixCollection/fs_183_1.mtx,183,183,Full,0,1069,72,0.001359 +ExampleMatrices/FloridaSparseMatrixCollection/mymatrix.mtx,3,6,Full,0,8,2,0.000004 +ExampleMatrices/FloridaSparseMatrixCollection/mymatrix1.mtx,6,6,Full,0,14,4,0.000005 +ExampleMatrices/FloridaSparseMatrixCollection/fs_183_3.mtx,183,183,Full,0,1069,72,0.001490 +ExampleMatrices/FloridaSparseMatrixCollection/G51.mtx,1000,1000,Full,0,11818,157,0.026693 +ExampleMatrices/FloridaSparseMatrixCollection/nos3.mtx,960,960,Full,0,15844,18,0.004160 +ExampleMatrices/FloridaSparseMatrixCollection/plbuckle.mtx,1282,1282,Full,0,30644,52,0.019106 +ExampleMatrices/FloridaSparseMatrixCollection/str_200.mtx,363,363,Full,0,3068,31,0.001557 +ExampleMatrices/FloridaSparseMatrixCollection/str_400.mtx,363,363,Full,0,3157,34,0.001661 diff --git a/mybuild/compare.py b/mybuild/compare.py new file mode 100644 index 0000000..2e73531 --- /dev/null +++ b/mybuild/compare.py @@ -0,0 +1,73 @@ +import pandas as pd +import matplotlib.pyplot as plt +import seaborn as sns +# Load CSVs +df1 = pd.read_csv('output.csv') # Replace with the actual path to first CSV +df2 = pd.read_csv('OutputTable.csv') # Replace with the actual path to second CSV + +# Strip whitespace and standardize +df1['Matrix'] = df1['Matrix'].astype(str).str.strip() +df2['Matrix'] = df2['Matrix'].astype(str).str.strip() + +# Merge +merged = pd.merge(df1, df2, on='Matrix', suffixes=('_Original', '_New')) + +# Compute differences +merged['ColorDifference'] = merged['NumOfColors'] - merged['NumberOfColors'] +merged['AbsoluteDifference'] = merged['ColorDifference'].abs() +merged['RelativeDifference'] = ( + merged['AbsoluteDifference'] / merged[['NumOfColors', 'NumberOfColors']].max(axis=1) +) + +# Flag significant differences +THRESHOLD_ABS = 10 +THRESHOLD_REL = 0.10 +merged['SignificantDifference'] = ( + (merged['AbsoluteDifference'] > THRESHOLD_ABS) | + (merged['RelativeDifference'] > THRESHOLD_REL) +) + +# Print significant differences +print("Significant Differences:") +print(merged[merged['SignificantDifference']][[ + 'Matrix', 'NumOfColors', 'NumberOfColors', 'ColorDifference', 'RelativeDifference' +]]) + +# Save merged table +merged.to_csv('merged_comparison_cleaned.csv', index=False) + +# ---- Visualization ---- + +# Prepare data for plotting +melted = merged.melt( + id_vars=['Matrix', 'SignificantDifference'], + value_vars=['NumOfColors', 'NumberOfColors'], + var_name='Source', + value_name='ColorCount' +) + +# Shorten matrix names for x-axis +melted['MatrixShort'] = melted['Matrix'].apply(lambda x: x.split('/')[-1].replace('.mtx', '')) + +# Plot +plt.figure(figsize=(14, 6)) +sns.barplot( + data=melted, + x='MatrixShort', + y='ColorCount', + hue='Source', + palette=['#4C72B0', '#55A868'] +) + +# Highlight significant matrices +for idx, row in merged.iterrows(): + if row['SignificantDifference']: + plt.gca().get_xticklabels()[idx].set_color('red') + +plt.xticks(rotation=45, ha='right') +plt.title('Comparison of NumOfColors (Original vs New)') +plt.tight_layout() +plt.legend(title='Color Count Source') +plt.grid(axis='y') +plt.savefig('color_comparison_plot.png', dpi=300) +plt.show() diff --git a/mybuild/input.csv b/mybuild/input.csv new file mode 100644 index 0000000..f3766cb --- /dev/null +++ b/mybuild/input.csv @@ -0,0 +1,26 @@ +Matrix,COLORING_ALGORITHM,COLORING_ORDERING,KIND_OF_SPARSIFICATION,BLOCK_SIZE,INDEPENDENT_SET_ALGORITHM,ALPHA_FOR_BALANCED_COLORING,RHO_FOR_INDEPENDENT_SET_ALGORITHM +ExampleMatrices/FloridaSparseMatrixCollection/685_bus.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/1138_bus.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/ash608.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk01.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk01_mod.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk08.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstk09.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstm01.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bcsstm13.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bp_1400.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/bp_1600.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/ex33.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/hess_pat.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/hess_pat_small.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/jac_pat.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/mtx-spear-head.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/fs_183_1.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/mymatrix.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/mymatrix1.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/fs_183_3.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/G51.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/nos3.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/plbuckle.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/str_200.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 +ExampleMatrices/FloridaSparseMatrixCollection/str_400.mtx,D2Columns,LargestFirstOrderingDegrees,Full,0,Best,1,1 diff --git a/mybuild/run_colpack.py b/mybuild/run_colpack.py new file mode 100644 index 0000000..6d03e8a --- /dev/null +++ b/mybuild/run_colpack.py @@ -0,0 +1,69 @@ +import csv +import subprocess +import re + +input_csv = "input.csv" +output_csv = "output.csv" +colpack_executable = "./ColPack" + +# Mapping CSV values to command-line options +ordering_map = { + "LargestFirstOrderingDegrees": "LARGEST_FIRST", + "SLO": "SMALLEST_LAST" +} + +method_map = { + "D2RestrictedColumns": "DISTANCE_TWO", + "D2Columns": "DISTANCE_TWO" +} + +# Function to extract metrics from ColPack output +def parse_colpack_output(output_text): + ordering = method = coloring_time = num_colors = "N/A" + + for line in output_text.splitlines(): + if line.startswith("order:"): + ordering = line.split(":")[1].strip() + elif line.startswith("methd:"): + method = line.split(":")[1].strip() + elif "order+color time" in line: + match = re.search(r"order\+color time = ([0-9.]+)", line) + if match: + coloring_time = match.group(1) + elif "number of colors" in line: + match = re.search(r"number of colors: (\d+)", line) + if match: + num_colors = match.group(1) + return ordering, method, coloring_time, num_colors + +# Open output CSV +with open(output_csv, mode='w', newline='') as out_csv: + writer = csv.writer(out_csv) + writer.writerow(["Matrix", "ExitCode", "Ordering", "Method", "ColoringTime", "NumberOfColors"]) + + # Read input CSV + with open(input_csv, mode='r') as in_csv: + reader = csv.DictReader(in_csv) + for row in reader: + matrix_path = row["Matrix"] + method = method_map.get(row["COLORING_ALGORITHM"], "DISTANCE_TWO") + ordering = ordering_map.get(row["COLORING_ORDERING"], "LARGEST_FIRST") + + cmd = [ + colpack_executable, + "-f", matrix_path, + "-o", ordering, + "-m", method, + "-v" + ] + + print(f"Running: {' '.join(cmd)}") + + try: + result = subprocess.run(cmd, capture_output=True, text=True, timeout=120) + exit_code = result.returncode + ordering_out, method_out, time, colors = parse_colpack_output(result.stdout) + writer.writerow([matrix_path, exit_code, ordering_out, method_out, time, colors]) + + except Exception as e: + writer.writerow([matrix_path, "ERROR", "N/A", "N/A", "N/A", str(e)]) From 53b2399004e33f9b60d519b9aeac6194fd5d8d12 Mon Sep 17 00:00:00 2001 From: Ali Rostami Date: Sat, 2 Aug 2025 15:48:40 +0200 Subject: [PATCH 2/2] the input output parts are improved, refactoring, adding csv reader --- BoostTest/ApplicationTest.cpp | 2 +- CMakeLists.txt | 2 +- Main/PreCol.cpp | 1 - mybuild/compare.py | 19 ++++++++++++++----- mybuild/run_colpack.py | 1 + 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/BoostTest/ApplicationTest.cpp b/BoostTest/ApplicationTest.cpp index 6438ad0..338937d 100644 --- a/BoostTest/ApplicationTest.cpp +++ b/BoostTest/ApplicationTest.cpp @@ -8,7 +8,7 @@ #include #define BOOST_TEST_DYN_LINK -//#define BOOST_TEST_MAIN - dont need to repeat this define in more than one cpp file +//#define BOOST_TEST_MAIN - don't need to repeat this definition in more than one cpp file BOOST_AUTO_TEST_SUITE(ApplicationTestSuite) BOOST_AUTO_TEST_CASE(SILUTest) { diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f082e2..f9e86f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 4.0) +#cmake_minimum_required(VERSION 4.0) project(precol) set (CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) diff --git a/Main/PreCol.cpp b/Main/PreCol.cpp index 008686f..45ef240 100755 --- a/Main/PreCol.cpp +++ b/Main/PreCol.cpp @@ -49,7 +49,6 @@ int main(int argc, char *argv[]) { "NumOfRemainedNonzeros", "NumOfColors","Time"}); for (const auto& params : allInputParams) { - MatrixMarket mm(params.algorithm.c_str()); mysymmetric = mm.issym(); diff --git a/mybuild/compare.py b/mybuild/compare.py index 2e73531..dd5a480 100644 --- a/mybuild/compare.py +++ b/mybuild/compare.py @@ -2,8 +2,8 @@ import matplotlib.pyplot as plt import seaborn as sns # Load CSVs -df1 = pd.read_csv('output.csv') # Replace with the actual path to first CSV -df2 = pd.read_csv('OutputTable.csv') # Replace with the actual path to second CSV +df1 = pd.read_csv('output.csv') # Replace it with the actual path to the first CSV +df2 = pd.read_csv('OutputTable.csv') # Replace it with the actual path to the second CSV # Strip whitespace and standardize df1['Matrix'] = df1['Matrix'].astype(str).str.strip() @@ -38,7 +38,7 @@ # ---- Visualization ---- -# Prepare data for plotting +# Prepare data for plotting with new labels melted = merged.melt( id_vars=['Matrix', 'SignificantDifference'], value_vars=['NumOfColors', 'NumberOfColors'], @@ -46,6 +46,15 @@ value_name='ColorCount' ) +# Create a mapping for the labels +label_map = { + 'NumOfColors': 'Number of Colors from PreCol', + 'NumberOfColors': 'Number of Colors from ColPack' +} + +# Apply the mapping to the Source column +melted['Source'] = melted['Source'].map(label_map) + # Shorten matrix names for x-axis melted['MatrixShort'] = melted['Matrix'].apply(lambda x: x.split('/')[-1].replace('.mtx', '')) @@ -65,9 +74,9 @@ plt.gca().get_xticklabels()[idx].set_color('red') plt.xticks(rotation=45, ha='right') -plt.title('Comparison of NumOfColors (Original vs New)') +plt.title('Comparison of Color Counts (PreCol vs ColPack)') plt.tight_layout() plt.legend(title='Color Count Source') plt.grid(axis='y') plt.savefig('color_comparison_plot.png', dpi=300) -plt.show() +plt.show() \ No newline at end of file diff --git a/mybuild/run_colpack.py b/mybuild/run_colpack.py index 6d03e8a..339d4f6 100644 --- a/mybuild/run_colpack.py +++ b/mybuild/run_colpack.py @@ -12,6 +12,7 @@ "SLO": "SMALLEST_LAST" } + method_map = { "D2RestrictedColumns": "DISTANCE_TWO", "D2Columns": "DISTANCE_TWO"