Skip to content

Commit 55200c9

Browse files
moving hypergraph utility functions into separate file
1 parent 4b8b488 commit 55200c9

File tree

7 files changed

+161
-122
lines changed

7 files changed

+161
-122
lines changed

apps/ilp_hypergraph_partitioner.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ limitations under the License.
2626
#include "osp/auxiliary/misc.hpp"
2727
#include "osp/graph_algorithms/directed_graph_path_util.hpp"
2828
#include "osp/auxiliary/io/general_file_reader.hpp"
29+
#include "osp/partitioning/model/hypergraph_utility.hpp"
2930
#include "osp/partitioning/partitioners/generic_FM.hpp"
3031
#include "osp/partitioning/partitioners/partitioning_ILP.hpp"
3132
#include "osp/partitioning/partitioners/partitioning_ILP_replication.hpp"
@@ -86,7 +87,7 @@ int main(int argc, char *argv[]) {
8687
graph dag;
8788
file_status = file_reader::readComputationalDagHyperdagFormatDB(filename_hgraph, dag);
8889
if(file_status)
89-
hgraph.convert_from_cdag_as_hyperdag(dag);
90+
hgraph = convert_from_cdag_as_hyperdag<size_t, int, int, int, graph>(dag);
9091
} else if (file_ending == "mtx") {
9192
file_status = file_reader::readHypergraphMartixMarketFormat(filename_hgraph, hgraph);
9293
} else {

include/osp/partitioning/model/hypergraph.hpp

Lines changed: 0 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,13 @@ class Hypergraph {
5656
void set_vertex_memory_weight(index_type vertex_idx, memw_type weight);
5757
void set_hyperedge_weight(index_type hyperedge_idx, commw_type weight);
5858

59-
workw_type compute_total_vertex_work_weight() const;
60-
memw_type compute_total_vertex_memory_weight() const;
6159

6260
void clear();
6361
void reset(index_type num_vertices_, index_type num_hyperedges_);
6462

6563
inline const std::vector<index_type> &get_incident_hyperedges(index_type vertex) const { return incident_hyperedges_to_vertex[vertex]; }
6664
inline const std::vector<index_type> &get_vertices_in_hyperedge(index_type hyperedge) const { return vertices_in_hyperedge[hyperedge]; }
6765

68-
template<typename Graph_t>
69-
void convert_from_cdag_as_dag(const Graph_t& dag);
70-
71-
template<typename Graph_t>
72-
void convert_from_cdag_as_hyperdag(const Graph_t& dag);
73-
74-
Hypergraph<index_type, workw_type, memw_type, commw_type> create_induced_hypergraph(const std::vector<bool>& include) const;
7566

7667
private:
7768
index_type Num_vertices = 0, Num_hyperedges = 0, Num_pins = 0;
@@ -157,23 +148,6 @@ void Hypergraph<index_type, workw_type, memw_type, commw_type>::set_hyperedge_we
157148
hyperedge_weights[hyperedge_idx] = weight;
158149
}
159150

160-
template<typename index_type, typename workw_type, typename memw_type, typename commw_type>
161-
workw_type Hypergraph<index_type, workw_type, memw_type, commw_type>::compute_total_vertex_work_weight() const
162-
{
163-
workw_type total = 0;
164-
for(index_type node = 0; node < Num_vertices; ++node)
165-
total += vertex_work_weights[node];
166-
return total;
167-
}
168-
169-
template<typename index_type, typename workw_type, typename memw_type, typename commw_type>
170-
memw_type Hypergraph<index_type, workw_type, memw_type, commw_type>::compute_total_vertex_memory_weight() const
171-
{
172-
memw_type total = 0;
173-
for(index_type node = 0; node < Num_vertices; ++node)
174-
total += vertex_memory_weights[node];
175-
return total;
176-
}
177151

178152
template<typename index_type, typename workw_type, typename memw_type, typename commw_type>
179153
void Hypergraph<index_type, workw_type, memw_type, commw_type>::clear()
@@ -204,86 +178,5 @@ void Hypergraph<index_type, workw_type, memw_type, commw_type>::reset(index_type
204178
vertices_in_hyperedge.resize(num_hyperedges_);
205179
}
206180

207-
template<typename index_type, typename workw_type, typename memw_type, typename commw_type>
208-
template<typename Graph_t>
209-
void Hypergraph<index_type, workw_type, memw_type, commw_type>::convert_from_cdag_as_dag(const Graph_t& dag)
210-
{
211-
static_assert(std::is_same_v<vertex_idx_t<Graph_t>, index_type>, "Index type mismatch, cannot convert DAG to hypergraph.");
212-
static_assert(std::is_same_v<v_workw_t<Graph_t>, workw_type>, "Work weight type mismatch, cannot convert DAG to hypergraph.");
213-
static_assert(std::is_same_v<v_memw_t<Graph_t>, memw_type>, "Memory weight type mismatch, cannot convert DAG to hypergraph.");
214-
static_assert(!has_edge_weights_v<Graph_t> || std::is_same_v<e_commw_t<Graph_t>, commw_type>, "Communication weight type mismatch, cannot convert DAG to hypergraph.");
215-
216-
reset(dag.num_vertices(), 0);
217-
for(const auto &node : dag.vertices())
218-
{
219-
set_vertex_work_weight(node, dag.vertex_work_weight(node));
220-
set_vertex_memory_weight(node, dag.vertex_mem_weight(node));
221-
for (const auto &child : dag.children(node))
222-
if constexpr(has_edge_weights_v<Graph_t>)
223-
add_hyperedge({node, child}, dag.edge_comm_weight(edge_desc(node, child, dag).first));
224-
else
225-
add_hyperedge({node, child});
226-
}
227-
}
228-
229-
template<typename index_type, typename workw_type, typename memw_type, typename commw_type>
230-
template<typename Graph_t>
231-
void Hypergraph<index_type, workw_type, memw_type, commw_type>::convert_from_cdag_as_hyperdag(const Graph_t& dag)
232-
{
233-
static_assert(std::is_same_v<vertex_idx_t<Graph_t>, index_type>, "Index type mismatch, cannot convert DAG to hypergraph.");
234-
static_assert(std::is_same_v<v_workw_t<Graph_t>, workw_type>, "Work weight type mismatch, cannot convert DAG to hypergraph.");
235-
static_assert(std::is_same_v<v_memw_t<Graph_t>, memw_type>, "Memory weight type mismatch, cannot convert DAG to hypergraph.");
236-
static_assert(std::is_same_v<v_commw_t<Graph_t>, commw_type>, "Communication weight type mismatch, cannot convert DAG to hypergraph.");
237-
238-
reset(dag.num_vertices(), 0);
239-
for(const auto &node : dag.vertices())
240-
{
241-
set_vertex_work_weight(node, dag.vertex_work_weight(node));
242-
set_vertex_memory_weight(node, dag.vertex_mem_weight(node));
243-
if(dag.out_degree(node) == 0)
244-
continue;
245-
std::vector<index_type> new_hyperedge({node});
246-
for (const auto &child : dag.children(node))
247-
new_hyperedge.push_back(child);
248-
add_hyperedge(new_hyperedge, dag.vertex_comm_weight(node));
249-
}
250-
}
251-
252-
template<typename index_type, typename workw_type, typename memw_type, typename commw_type>
253-
Hypergraph<index_type, workw_type, memw_type, commw_type> Hypergraph<index_type, workw_type, memw_type, commw_type>::create_induced_hypergraph(const std::vector<bool>& include) const
254-
{
255-
if(include.size() != Num_vertices)
256-
throw std::invalid_argument("Invalid Argument while extracting induced hypergraph: input bool array has incorrect size.");
257-
258-
std::vector<index_type> new_index(Num_vertices);
259-
unsigned current_index = 0;
260-
for(index_type node = 0; node < Num_vertices; ++node)
261-
if(include[node])
262-
new_index[node] = current_index++;
263-
264-
Hypergraph<index_type, workw_type, memw_type, commw_type> hgraph(current_index, 0);
265-
for(index_type node = 0; node < Num_vertices; ++node)
266-
if(include[node])
267-
{
268-
hgraph.set_vertex_work_weight(new_index[node], vertex_work_weights[node]);
269-
hgraph.set_vertex_memory_weight(new_index[node], vertex_memory_weights[node]);
270-
}
271-
272-
for(index_type hyperedge = 0; hyperedge < Num_hyperedges; ++hyperedge)
273-
{
274-
unsigned nr_induced_pins = 0;
275-
std::vector<index_type> induced_hyperedge;
276-
for(index_type node : vertices_in_hyperedge[hyperedge])
277-
if(include[node])
278-
{
279-
induced_hyperedge.push_back(new_index[node]);
280-
++nr_induced_pins;
281-
}
282-
283-
if(nr_induced_pins >= 2)
284-
hgraph.add_hyperedge(induced_hyperedge, hyperedge_weights[hyperedge]);
285-
}
286-
return hgraph;
287-
}
288181

289182
} // namespace osp
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
Copyright 2024 Huawei Technologies Co., Ltd.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
16+
@author Toni Boehnlein, Benjamin Lozes, Pal Andras Papp, Raphael S. Steiner
17+
*/
18+
19+
#pragma once
20+
21+
#include <queue>
22+
#include <unordered_set>
23+
#include <vector>
24+
25+
#include "osp/partitioning/model/hypergraph.hpp"
26+
27+
/**
28+
* @file hypergraph_utility.hpp
29+
* @brief Utility functions and classes for working with hypergraphs graphs.
30+
*
31+
* This file provides a collection of simple utility functions for the hypergraph class.
32+
*/
33+
34+
namespace osp {
35+
36+
37+
// summing up weights
38+
39+
template<typename index_type, typename workw_type, typename memw_type, typename commw_type>
40+
workw_type compute_total_vertex_work_weight(const Hypergraph<index_type, workw_type, memw_type, commw_type>& hgraph)
41+
{
42+
workw_type total = 0;
43+
for(index_type node = 0; node < hgraph.num_vertices(); ++node)
44+
total += hgraph.get_vertex_work_weight(node);
45+
return total;
46+
}
47+
48+
template<typename index_type, typename workw_type, typename memw_type, typename commw_type>
49+
memw_type compute_total_vertex_memory_weight(const Hypergraph<index_type, workw_type, memw_type, commw_type>& hgraph)
50+
{
51+
memw_type total = 0;
52+
for(index_type node = 0; node < hgraph.num_vertices(); ++node)
53+
total += hgraph.get_vertex_memory_weight(node);
54+
return total;
55+
}
56+
57+
58+
// get induced subhypergraph
59+
60+
template<typename index_type, typename workw_type, typename memw_type, typename commw_type>
61+
Hypergraph<index_type, workw_type, memw_type, commw_type> create_induced_hypergraph(const Hypergraph<index_type, workw_type, memw_type, commw_type>& hgraph, const std::vector<bool>& include)
62+
{
63+
if(include.size() != hgraph.num_vertices())
64+
throw std::invalid_argument("Invalid Argument while extracting induced hypergraph: input bool array has incorrect size.");
65+
66+
std::vector<index_type> new_index(hgraph.num_vertices());
67+
unsigned current_index = 0;
68+
for(index_type node = 0; node < hgraph.num_vertices(); ++node)
69+
if(include[node])
70+
new_index[node] = current_index++;
71+
72+
Hypergraph<index_type, workw_type, memw_type, commw_type> new_hgraph(current_index, 0);
73+
for(index_type node = 0; node < hgraph.num_vertices(); ++node)
74+
if(include[node])
75+
{
76+
new_hgraph.set_vertex_work_weight(new_index[node], hgraph.get_vertex_work_weight(node));
77+
new_hgraph.set_vertex_memory_weight(new_index[node], hgraph.get_vertex_memory_weight(node));
78+
}
79+
80+
for(index_type hyperedge = 0; hyperedge < hgraph.num_hyperedges(); ++hyperedge)
81+
{
82+
unsigned nr_induced_pins = 0;
83+
std::vector<index_type> induced_hyperedge;
84+
for(index_type node : hgraph.get_vertices_in_hyperedge(hyperedge))
85+
if(include[node])
86+
{
87+
induced_hyperedge.push_back(new_index[node]);
88+
++nr_induced_pins;
89+
}
90+
91+
if(nr_induced_pins >= 2)
92+
new_hgraph.add_hyperedge(induced_hyperedge, hgraph.get_hyperedge_weight(hyperedge));
93+
}
94+
return new_hgraph;
95+
}
96+
97+
98+
// conversion
99+
100+
template<typename index_type, typename workw_type, typename memw_type, typename commw_type, typename Graph_t>
101+
Hypergraph<index_type, workw_type, memw_type, commw_type> convert_from_cdag_as_dag(const Graph_t& dag)
102+
{
103+
static_assert(std::is_same_v<vertex_idx_t<Graph_t>, index_type>, "Index type mismatch, cannot convert DAG to hypergraph.");
104+
static_assert(std::is_same_v<v_workw_t<Graph_t>, workw_type>, "Work weight type mismatch, cannot convert DAG to hypergraph.");
105+
static_assert(std::is_same_v<v_memw_t<Graph_t>, memw_type>, "Memory weight type mismatch, cannot convert DAG to hypergraph.");
106+
static_assert(!has_edge_weights_v<Graph_t> || std::is_same_v<e_commw_t<Graph_t>, commw_type>, "Communication weight type mismatch, cannot convert DAG to hypergraph.");
107+
108+
Hypergraph<index_type, workw_type, memw_type, commw_type> hgraph(dag.num_vertices(), 0);
109+
for(const auto &node : dag.vertices())
110+
{
111+
hgraph.set_vertex_work_weight(node, dag.vertex_work_weight(node));
112+
hgraph.set_vertex_memory_weight(node, dag.vertex_mem_weight(node));
113+
for (const auto &child : dag.children(node))
114+
if constexpr(has_edge_weights_v<Graph_t>)
115+
hgraph.add_hyperedge({node, child}, dag.edge_comm_weight(edge_desc(node, child, dag).first));
116+
else
117+
hgraph.add_hyperedge({node, child});
118+
}
119+
return hgraph;
120+
}
121+
122+
template<typename index_type, typename workw_type, typename memw_type, typename commw_type, typename Graph_t>
123+
Hypergraph<index_type, workw_type, memw_type, commw_type> convert_from_cdag_as_hyperdag(const Graph_t& dag)
124+
{
125+
static_assert(std::is_same_v<vertex_idx_t<Graph_t>, index_type>, "Index type mismatch, cannot convert DAG to hypergraph.");
126+
static_assert(std::is_same_v<v_workw_t<Graph_t>, workw_type>, "Work weight type mismatch, cannot convert DAG to hypergraph.");
127+
static_assert(std::is_same_v<v_memw_t<Graph_t>, memw_type>, "Memory weight type mismatch, cannot convert DAG to hypergraph.");
128+
static_assert(std::is_same_v<v_commw_t<Graph_t>, commw_type>, "Communication weight type mismatch, cannot convert DAG to hypergraph.");
129+
130+
Hypergraph<index_type, workw_type, memw_type, commw_type> hgraph(dag.num_vertices(), 0);
131+
for(const auto &node : dag.vertices())
132+
{
133+
hgraph.set_vertex_work_weight(node, dag.vertex_work_weight(node));
134+
hgraph.set_vertex_memory_weight(node, dag.vertex_mem_weight(node));
135+
if(dag.out_degree(node) == 0)
136+
continue;
137+
std::vector<index_type> new_hyperedge({node});
138+
for (const auto &child : dag.children(node))
139+
new_hyperedge.push_back(child);
140+
hgraph.add_hyperedge(new_hyperedge, dag.vertex_comm_weight(node));
141+
}
142+
return hgraph;
143+
}
144+
145+
} // namespace osp

include/osp/partitioning/model/partitioning_problem.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ limitations under the License.
2121
#include <iostream>
2222
#include <cmath>
2323

24-
#include "osp/partitioning/model/hypergraph.hpp"
24+
#include "osp/partitioning/model/hypergraph_utility.hpp"
2525

2626
namespace osp {
2727

@@ -80,14 +80,14 @@ class PartitioningProblem {
8080
if(imbalance < 0 )
8181
throw std::invalid_argument("Invalid Argument while setting imbalance parameter: parameter is negative.");
8282
else
83-
max_work_weight_per_partition = static_cast<workw_type>(ceil(hgraph.compute_total_vertex_work_weight()/ static_cast<double>(nr_of_partitions) * (1.0+imbalance)));
83+
max_work_weight_per_partition = static_cast<workw_type>(ceil(compute_total_vertex_work_weight(hgraph)/ static_cast<double>(nr_of_partitions) * (1.0+imbalance)));
8484
}
8585
inline void setMaxMemoryWeightExplicitly(memw_type max_weight_) { max_memory_weight_per_partition = max_weight_; }
8686
void setMaxMemoryWeightViaImbalanceFactor(double imbalance){
8787
if(imbalance < 0 )
8888
throw std::invalid_argument("Invalid Argument while setting imbalance parameter: parameter is negative.");
8989
else
90-
max_memory_weight_per_partition = static_cast<memw_type>(ceil(hgraph.compute_total_vertex_memory_weight()/ static_cast<double>(nr_of_partitions) * (1.0+imbalance)));
90+
max_memory_weight_per_partition = static_cast<memw_type>(ceil(compute_total_vertex_memory_weight(hgraph)/ static_cast<double>(nr_of_partitions) * (1.0+imbalance)));
9191
}
9292
};
9393

include/osp/partitioning/partitioners/generic_FM.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void GenericFM<index_type, workw_type, memw_type, commw_type>::ImprovePartitioni
7171

7272
if(max_nodes_in_part == 0) // if not initialized
7373
max_nodes_in_part = static_cast<index_type>(ceil(static_cast<double>(Hgraph.num_vertices()) * static_cast<double>(partition.getInstance().getMaxWorkWeightPerPartition())
74-
/ static_cast<double>(Hgraph.compute_total_vertex_work_weight()) ));
74+
/ static_cast<double>(compute_total_vertex_work_weight(Hgraph)) ));
7575

7676
for(unsigned pass_idx = 0; pass_idx < max_number_of_passes; ++pass_idx)
7777
{
@@ -282,7 +282,7 @@ void GenericFM<index_type, workw_type, memw_type, commw_type>::RecursiveFM(Parti
282282

283283
if(max_nodes_in_part == 0) // if not initialized
284284
max_nodes_in_part = static_cast<index_type>(ceil(static_cast<double>(nr_nodes) * static_cast<double>(partition.getInstance().getMaxWorkWeightPerPartition())
285-
/ static_cast<double>(partition.getInstance().getHypergraph().compute_total_vertex_work_weight()) ));
285+
/ static_cast<double>(compute_total_vertex_work_weight(partition.getInstance().getHypergraph())) ));
286286

287287
const std::vector<index_type> max_nodes_on_level = getMaxNodesOnLevel(nr_nodes, nr_parts);
288288

@@ -328,7 +328,7 @@ void GenericFM<index_type, workw_type, memw_type, commw_type>::RecursiveFM(Parti
328328
}
329329

330330
for(unsigned part = 0; part < 2; ++part)
331-
sub_hgraphs.push_back(sub_hgraphs[sub_hgraph_index].create_induced_hypergraph(part_indicator[part]));
331+
sub_hgraphs.push_back(create_induced_hypergraph(sub_hgraphs[sub_hgraph_index], part_indicator[part]));
332332

333333
++start_index;
334334
}

0 commit comments

Comments
 (0)