Skip to content

Commit 65c80f1

Browse files
hypergraph-partitioning-ILP app added
1 parent d901d26 commit 65c80f1

File tree

4 files changed

+156
-2
lines changed

4 files changed

+156
-2
lines changed

apps/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ endif()
5050

5151
if (COPT_FOUND)
5252
_add_executable( ilp_bsp_scheduler )
53+
_add_executable( ilp_hypergraph_partitioner )
5354
endif()
5455

5556
endif()
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
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+
#include <filesystem>
20+
#include <fstream>
21+
#include <iostream>
22+
#include <set>
23+
#include <string>
24+
#include <vector>
25+
26+
#include "osp/auxiliary/misc.hpp"
27+
#include "osp/graph_algorithms/directed_graph_path_util.hpp"
28+
#include "osp/auxiliary/io/general_file_reader.hpp"
29+
#include "osp/partitioning/partitioners/partitioning_ILP.hpp"
30+
#include "osp/partitioning/partitioners/partitioning_ILP_replication.hpp"
31+
#include "osp/graph_implementations/adj_list_impl/computational_dag_vector_impl.hpp"
32+
#include "osp/auxiliary/io/hdag_graph_file_reader.hpp"
33+
#include "osp/auxiliary/io/mtx_hypergraph_file_reader.hpp"
34+
#include "osp/auxiliary/io/partitioning_file_writer.hpp"
35+
36+
37+
using namespace osp;
38+
39+
using graph = computational_dag_vector_impl_def_int_t;
40+
41+
int main(int argc, char *argv[]) {
42+
if (argc < 4) {
43+
std::cerr << "Usage: " << argv[0] << " <input_file> <nr_parts> <imbalance> <optional:part_repl|full_repl>"
44+
<< std::endl;
45+
return 1;
46+
}
47+
48+
std::string filename_hgraph = argv[1];
49+
std::string name_hgraph = filename_hgraph.substr(0, filename_hgraph.rfind("."));
50+
std::string file_ending = filename_hgraph.substr(filename_hgraph.rfind(".") + 1);
51+
if (!file_reader::isPathSafe(filename_hgraph)) {
52+
std::cerr << "Error: Unsafe file path (possible traversal or invalid type).\n";
53+
return 1;
54+
}
55+
56+
std::cout << name_hgraph << std::endl;
57+
58+
int nr_parts = std::stoi(argv[2]);
59+
if (nr_parts < 2 || nr_parts > 32) {
60+
std::cerr << "Argument nr_parts must be an integer between 2 and 32: " << nr_parts << std::endl;
61+
return 1;
62+
}
63+
64+
float imbalance = std::stof(argv[3]);
65+
if (imbalance < 0.01 || imbalance > .99) {
66+
std::cerr << "Argument imbalance must be a float between 0.01 and 0.99: " << imbalance << std::endl;
67+
return 1;
68+
}
69+
70+
unsigned replicate = 0;
71+
72+
if (argc > 4 && std::string(argv[4]) == "part_repl") {
73+
replicate = 1;
74+
} else if (argc > 4 && std::string(argv[4]) == "full_repl") {
75+
replicate = 2;
76+
} else if (argc > 4) {
77+
std::cerr << "Unknown argument: " << argv[4] << ". Expected 'part_repl' or 'full_repl' for replication." << std::endl;
78+
return 1;
79+
}
80+
81+
Hypergraph hgraph;
82+
83+
bool file_status = true;
84+
if (file_ending == "hdag") {
85+
graph dag;
86+
file_status = file_reader::readComputationalDagHyperdagFormatDB(filename_hgraph, dag);
87+
if(file_status)
88+
hgraph.convert_from_cdag_as_hyperdag(dag);
89+
} else if (file_ending == "mtx") {
90+
file_status = file_reader::readHypergraphMartixMarketFormat(filename_hgraph, hgraph);
91+
} else {
92+
std::cout << "Unknown file extension." << std::endl;
93+
return 1;
94+
}
95+
if (!file_status) {
96+
97+
std::cout << "Reading input file failed." << std::endl;
98+
return 1;
99+
}
100+
101+
PartitioningProblem instance(hgraph, static_cast<unsigned>(nr_parts));
102+
instance.setMaxWorkWeightViaImbalanceFactor(imbalance);
103+
104+
if (replicate > 0) {
105+
106+
PartitioningWithReplication partition(instance);
107+
HypergraphPartitioningILPWithReplication partitioner;
108+
109+
for(size_t node = 0; node < hgraph.num_vertices(); ++node)
110+
partition.setAssignedPartitions(node, {static_cast<unsigned>(node % static_cast<size_t>(nr_parts))});
111+
if(partition.satisfiesBalanceConstraint())
112+
partitioner.setUseInitialSolution(true);
113+
114+
partitioner.setTimeLimitSeconds(600);
115+
if(replicate == 2)
116+
partitioner.setReplicationModel(HypergraphPartitioningILPWithReplication<>::REPLICATION_MODEL_IN_ILP::GENERAL);
117+
118+
auto solve_status = partitioner.computePartitioning(partition);
119+
120+
if (solve_status == RETURN_STATUS::OSP_SUCCESS || solve_status == RETURN_STATUS::BEST_FOUND) {
121+
file_writer::write_txt(name_hgraph + "_" + std::to_string(nr_parts) + "_" + std::to_string(imbalance) +
122+
"_ILP_rep" + std::to_string(replicate) + ".txt", partition);
123+
std::cout << "Partitioning (with replicaiton) computed with costs: " << partition.computeConnectivityCost() << std::endl;
124+
} else {
125+
std::cout << "Computing partition failed." << std::endl;
126+
return 1;
127+
}
128+
129+
} else {
130+
131+
Partitioning partition(instance);
132+
HypergraphPartitioningILP partitioner;
133+
134+
for(size_t node = 0; node < hgraph.num_vertices(); ++node)
135+
partition.setAssignedPartition(node, static_cast<unsigned>(node % static_cast<size_t>(nr_parts)));
136+
if(partition.satisfiesBalanceConstraint())
137+
partitioner.setUseInitialSolution(true);
138+
139+
partitioner.setTimeLimitSeconds(600);
140+
141+
auto solve_status = partitioner.computePartitioning(partition);
142+
143+
if (solve_status == RETURN_STATUS::OSP_SUCCESS || solve_status == RETURN_STATUS::BEST_FOUND) {
144+
file_writer::write_txt(name_hgraph + "_" + std::to_string(nr_parts) + "_" + std::to_string(imbalance) +
145+
"_ILP_rep" + std::to_string(replicate) + ".txt", partition);
146+
std::cout << "Partitioning computed with costs: " << partition.computeConnectivityCost() << std::endl;
147+
} else {
148+
std::cout << "Computing partition failed." << std::endl;
149+
return 1;
150+
}
151+
}
152+
return 0;
153+
}

include/osp/partitioning/partitioners/partitioning_ILP.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ void HypergraphPartitioningILP<index_type, workw_type, memw_type, commw_type>::s
111111
template<typename index_type, typename workw_type, typename memw_type, typename commw_type>
112112
std::vector<unsigned> HypergraphPartitioningILP<index_type, workw_type, memw_type, commw_type>::readCoptAssignment(const PartitioningProblem<index_type, workw_type, memw_type, commw_type> &instance, Model& model)
113113
{
114-
std::vector<unsigned> node_to_partition(instance.getHypergraph().num_vertices(), UINT_MAX);
114+
std::vector<unsigned> node_to_partition(instance.getHypergraph().num_vertices(), std::numeric_limits<unsigned>::max());
115115
std::vector<std::vector<unsigned> > assignmentsGenericForm = this->readAllCoptAssignments(instance, model);
116116

117117
for (index_type node = 0; node < instance.getHypergraph().num_vertices(); node++)

include/osp/partitioning/partitioners/partitioning_ILP_base.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ std::vector<std::vector<unsigned> > HypergraphPartitioningILPBase<index_type, wo
146146
if(chosen_partitions.empty())
147147
{
148148
std::cout<<"Error: partitioning returned by ILP seems incomplete!"<<std::endl;
149-
chosen_partitions.push_back(UINT_MAX);
149+
chosen_partitions.push_back(std::numeric_limits<unsigned>::max());
150150
}
151151

152152
unsigned current_index = 0;

0 commit comments

Comments
 (0)