Skip to content

Commit

Permalink
construction algorithm for fixed vertex free subhypergraph
Browse files Browse the repository at this point in the history
  • Loading branch information
kittobi1992 committed Jul 26, 2023
1 parent 34b3544 commit c1b17cb
Show file tree
Hide file tree
Showing 9 changed files with 306 additions and 3 deletions.
3 changes: 2 additions & 1 deletion mt-kahypar/partition/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_subdirectory(preprocessing/)
add_subdirectory(preprocessing)
add_subdirectory(coarsening)
add_subdirectory(fixed_vertices)
add_subdirectory(refinement)
add_subdirectory(initial_partitioning)
add_subdirectory(mapping)
Expand Down
6 changes: 6 additions & 0 deletions mt-kahypar/partition/fixed_vertices/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
set(FixedVertexSources
fixed_vertex_removal.cpp)

foreach(modtarget IN LISTS PARTITIONING_SUITE_TARGETS)
target_sources(${modtarget} PRIVATE ${FixedVertexSources})
endforeach()
119 changes: 119 additions & 0 deletions mt-kahypar/partition/fixed_vertices/fixed_vertex_removal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*******************************************************************************
* MIT License
*
* This file is part of Mt-KaHyPar.
*
* Copyright (C) 2023 Tobias Heuer <tobias.heuer@kit.edu>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
******************************************************************************/

#include "mt-kahypar/partition/fixed_vertices/fixed_vertex_removal.h"

#include "tbb/parallel_invoke.h"

#include "mt-kahypar/definitions.h"
#include "mt-kahypar/parallel/parallel_prefix_sum.h"

namespace mt_kahypar {

template<typename Hypergraph>
ExtractedHypergraph<Hypergraph> FixedVertexRemoval<Hypergraph>::remove(const Hypergraph& hypergraph) {
ExtractedHypergraph<Hypergraph> extracted_hg;
vec<HypernodeID>& hn_mapping = extracted_hg.hn_mapping;
vec<HyperedgeID> he_mapping;

parallel::TBBPrefixSum<HypernodeID> hn_mapping_prefix_sum(hn_mapping);
parallel::TBBPrefixSum<HyperedgeID> he_mapping_prefix_sum(he_mapping);
tbb::parallel_invoke([&] {
hn_mapping.assign(hypergraph.initialNumNodes() + 1, 0);
hypergraph.doParallelForAllNodes([&](const HypernodeID hn) {
if ( !hypergraph.isFixed(hn) ) {
// Mark free vertices as valid
hn_mapping[hn + 1] = 1;
}
});
// Prefix sums computes mapping of the nodes of the input hypergraph to the nodes
// of the fixed vertex free subhypergraph
tbb::parallel_scan(tbb::blocked_range<size_t>(UL(0), UL(hypergraph.initialNumNodes() + 1)), hn_mapping_prefix_sum);
}, [&] {
he_mapping.assign(hypergraph.initialNumEdges() + 1, 0);
hypergraph.doParallelForAllEdges([&](const HypernodeID he) {
size_t edge_size = 0;
for ( const HypernodeID& pin : hypergraph.pins(he) ) {
if ( !hypergraph.isFixed(pin) ) {
++edge_size;
}
}
if ( edge_size > 1 ) {
// Mark edges with more than one pin as valid
he_mapping[he + 1] = 1;
}
});
// Prefix sums computes mapping of the edges of the input hypergraph to the edges
// of the fixed vertex free subhypergraph
tbb::parallel_scan(tbb::blocked_range<size_t>(UL(0), UL(hypergraph.initialNumEdges() + 1)), he_mapping_prefix_sum);
});
// Remove sentinel
hn_mapping.pop_back();

const HypernodeID num_nodes = hn_mapping_prefix_sum.total_sum();
const HyperedgeID num_edges = he_mapping_prefix_sum.total_sum();
HyperedgeVector edge_vector;
vec<HyperedgeWeight> hyperedge_weights;
vec<HypernodeWeight> hypernode_weights;
tbb::parallel_invoke([&] {
tbb::parallel_invoke([&] {
edge_vector.resize(num_edges);
}, [&] {
hyperedge_weights.resize(num_edges);
});

// Construct edge vector of the fixed vertex free subhypergraph
hypergraph.doParallelForAllEdges([&](const HyperedgeID& he) {
if ( he_mapping_prefix_sum.value(he + 1) ) {
// Hyperedge contains more than one pin in fixed vertex free subhypergraph
const HyperedgeID e = he_mapping[he];
hyperedge_weights[e] = hypergraph.edgeWeight(he);
for ( const HypernodeID& pin : hypergraph.pins(he) ) {
if ( !hypergraph.isFixed(pin) ) {
edge_vector[e].push_back(hn_mapping[pin]);
}
}
}
});
}, [&] {
hypernode_weights.resize(num_nodes);
hypergraph.doParallelForAllNodes([&](const HypernodeID& hn) {
if ( !hypergraph.isFixed(hn) ) {
hypernode_weights[hn_mapping[hn]] = hypergraph.nodeWeight(hn);
} else {
hn_mapping[hn] = kInvalidHypernode;
}
});
});

// Construct fixed vertex free subhypergraph
extracted_hg.hg = Factory::construct(num_nodes, num_edges,
edge_vector, hyperedge_weights.data(), hypernode_weights.data(), true);
return extracted_hg;
}

INSTANTIATE_CLASS_WITH_HYPERGRAPHS(FixedVertexRemoval)
}
47 changes: 47 additions & 0 deletions mt-kahypar/partition/fixed_vertices/fixed_vertex_removal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*******************************************************************************
* MIT License
*
* This file is part of Mt-KaHyPar.
*
* Copyright (C) 2023 Tobias Heuer <tobias.heuer@kit.edu>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
******************************************************************************/

#pragma once

#include <atomic>

#include "mt-kahypar/datastructures/hypergraph_common.h"
#include "mt-kahypar/parallel/stl/scalable_vector.h"

namespace mt_kahypar {

template<typename Hypergraph>
class FixedVertexRemoval {

using Factory = typename Hypergraph::Factory;
using HyperedgeVector = vec<vec<HypernodeID>>;

public:
static ExtractedHypergraph<Hypergraph> remove(const Hypergraph& hypergraph);

};

} // namespace mt_kahypar
3 changes: 1 addition & 2 deletions tests/datastructures/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ target_sources(mt_kahypar_tests PRIVATE
array_test.cc
sparse_map_test.cc
pin_count_in_part_test.cc
static_bitset_test.cc
fixed_vertex_support_test.cc)
static_bitset_test.cc)

if ( KAHYPAR_ENABLE_GRAPH_PARTITIONING_FEATURES )
target_sources(mt_kahypar_tests PRIVATE
Expand Down
1 change: 1 addition & 0 deletions tests/partition/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_subdirectory(preprocessing)
add_subdirectory(mapping)
add_subdirectory(coarsening)
add_subdirectory(fixed_vertices)
add_subdirectory(initial_partitioning)
add_subdirectory(refinement)
add_subdirectory(determinism)
3 changes: 3 additions & 0 deletions tests/partition/fixed_vertices/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
target_sources(mt_kahypar_tests PRIVATE
fixed_vertex_support_test.cc
fixed_vertex_removal_test.cc)
127 changes: 127 additions & 0 deletions tests/partition/fixed_vertices/fixed_vertex_removal_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*******************************************************************************
* MIT License
*
* This file is part of Mt-KaHyPar.
*
* Copyright (C) 2023 Tobias Heuer <tobias.heuer@kit.edu>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
******************************************************************************/



#include "gmock/gmock.h"
#include "tbb/task_group.h"

#include "mt-kahypar/datastructures/static_hypergraph.h"
#include "mt-kahypar/datastructures/static_hypergraph_factory.h"
#include "mt-kahypar/datastructures/fixed_vertex_support.h"
#include "mt-kahypar/partition/fixed_vertices/fixed_vertex_removal.h"

using ::testing::Test;

namespace mt_kahypar {
namespace ds {


class AFixedVertexRemoval : public Test {

public:
using Hypergraph = StaticHypergraph;
using Factory = typename Hypergraph::Factory;

AFixedVertexRemoval() :
hypergraph(Factory::construct(
7 , 4, { {0, 2}, {0, 1, 3, 4}, {3, 4, 6}, {2, 5, 6} })) { }

void addFixedVertices(const PartitionID k,
const vec<PartitionID>& fixed_vertex_blocks) {
FixedVertexSupport<Hypergraph> fixed_vertices(hypergraph.initialNumNodes(), k);
fixed_vertices.setHypergraph(&hypergraph);
for ( const HypernodeID& hn : hypergraph.nodes() ) {
if ( fixed_vertex_blocks[hn] != kInvalidPartition ) {
fixed_vertices.fixToBlock(hn, fixed_vertex_blocks[hn]);
}
}
hypergraph.addFixedVertexSupport(std::move(fixed_vertices));
}

void verifyFixedVertexFreeSubhypergraph(const Hypergraph& hypergraph,
const vec<HypernodeID>& hn_mapping,
const HypernodeID expected_num_nodes,
const vec<vec<HypernodeID>>& expected_pins) {
const HyperedgeID expected_num_edges = expected_pins.size();
ASSERT_EQ(expected_num_nodes, hypergraph.initialNumNodes());
ASSERT_EQ(expected_num_edges, hypergraph.initialNumEdges());

vec<HypernodeID> to_original(expected_num_nodes, 0);
for ( size_t i = 0; i < hn_mapping.size(); ++i ) {
if ( hn_mapping[i] != kInvalidHypernode ) {
to_original[hn_mapping[i]] = i;
}
}

for ( const HyperedgeID& he : hypergraph.edges() ) {
ASSERT_EQ(UL(hypergraph.edgeSize(he)), expected_pins[he].size());
size_t i = 0;
for ( const HypernodeID& pin : hypergraph.pins(he) ) {
ASSERT_EQ(expected_pins[he][i++], to_original[pin]);
}
}
}

Hypergraph hypergraph;
};


TEST_F(AFixedVertexRemoval, ConstructFixedVertexFreeSubhypergraph1) {
addFixedVertices(3, { kInvalidPartition, kInvalidPartition, 0, kInvalidPartition, 1, kInvalidPartition, 2 });
ExtractedHypergraph<StaticHypergraph> extracted_hg = FixedVertexRemoval<StaticHypergraph>::remove(hypergraph);
verifyFixedVertexFreeSubhypergraph(extracted_hg.hg, extracted_hg.hn_mapping, 4, { { 0, 1, 3 } });
}

TEST_F(AFixedVertexRemoval, ConstructFixedVertexFreeSubhypergraph2) {
addFixedVertices(3, { 0, kInvalidPartition, kInvalidPartition, kInvalidPartition, kInvalidPartition, kInvalidPartition, 2 });
ExtractedHypergraph<StaticHypergraph> extracted_hg = FixedVertexRemoval<StaticHypergraph>::remove(hypergraph);
verifyFixedVertexFreeSubhypergraph(extracted_hg.hg, extracted_hg.hn_mapping,
5, { { 1, 3, 4 }, { 3, 4 }, { 2, 5 } });
}

TEST_F(AFixedVertexRemoval, ConstructFixedVertexFreeSubhypergraph3) {
addFixedVertices(3, { 0, 1, 2, kInvalidPartition, kInvalidPartition, 2, 2 });
ExtractedHypergraph<StaticHypergraph> extracted_hg = FixedVertexRemoval<StaticHypergraph>::remove(hypergraph);
verifyFixedVertexFreeSubhypergraph(extracted_hg.hg, extracted_hg.hn_mapping,
2, { { 3, 4 }, { 3, 4 } });
}

TEST_F(AFixedVertexRemoval, ConstructFixedVertexFreeSubhypergraph4) {
addFixedVertices(3, { kInvalidPartition, 1, kInvalidPartition, 2, 1, kInvalidPartition, 2 });
ExtractedHypergraph<StaticHypergraph> extracted_hg = FixedVertexRemoval<StaticHypergraph>::remove(hypergraph);
verifyFixedVertexFreeSubhypergraph(extracted_hg.hg, extracted_hg.hn_mapping,
3, { { 0, 2 }, { 2, 5 } });
}

TEST_F(AFixedVertexRemoval, ConstructFixedVertexFreeSubhypergraph5) {
addFixedVertices(3, { kInvalidPartition, 1, 0, 2, 1, kInvalidPartition, 2 });
ExtractedHypergraph<StaticHypergraph> extracted_hg = FixedVertexRemoval<StaticHypergraph>::remove(hypergraph);
verifyFixedVertexFreeSubhypergraph(extracted_hg.hg, extracted_hg.hn_mapping, 2, { });
}

} // namespace ds
} // namespace mt_kahypar

0 comments on commit c1b17cb

Please sign in to comment.