Skip to content

Commit 8c542b7

Browse files
committed
- In the Prim's MST algorithm implementation:
- Removed the negative weight check - Enqueueing edges only if the target vertex in a current iteration is not yet visited - Improved vertex degree calculating for the adjacency matrix representation
1 parent f8559a6 commit 8c542b7

3 files changed

Lines changed: 18 additions & 24 deletions

File tree

include/gl/algorithm/mst.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,12 @@ template <
8484
if (visited[target_id])
8585
continue;
8686

87-
visited[target_id] = true;
88-
++n_vertices_in_mst;
89-
}
87+
// add the minimum weight edge to the mst
88+
mst.edges.emplace_back(min_edge);
89+
mst.weight += min_weight;
90+
91+
visited[target_id] = true;
92+
++n_vertices_in_mst;
9093

9194
// enqueue all edges adjacent to the `target` vertex if they lead to unvisited verties
9295
for (const auto& edge : graph.adjacent_edges(target_id))

include/gl/impl/specialized/adjacency_matrix.hpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,12 @@ struct directed_adjacency_matrix {
7878
[[nodiscard]] gl_attr_force_inline static types::size_type degree(
7979
const impl_type& self, const types::id_type vertex_id
8080
) {
81-
return in_degree(self, vertex_id) + out_degree(self, vertex_id);
81+
types::size_type deg = constants::zero;
82+
for (types::id_type i = constants::initial_id; i < self._matrix.size(); ++i)
83+
deg += static_cast<types::size_type>(self._matrix[vertex_id][i] != nullptr)
84+
+ static_cast<types::size_type>(self._matrix[i][vertex_id] != nullptr);
85+
86+
return deg;
8287
}
8388

8489
[[nodiscard]] static std::vector<types::size_type> in_degree_map(const impl_type& self) {
@@ -182,11 +187,11 @@ struct undirected_adjacency_matrix {
182187
[[nodiscard]] gl_attr_force_inline static types::size_type degree(
183188
const impl_type& self, const types::id_type vertex_id
184189
) {
185-
types::size_type degree = constants::default_size;
186-
for (const auto& edge : self._matrix[vertex_id])
187-
if (edge)
188-
degree += constants::one + static_cast<types::size_type>(edge->is_loop());
189-
return degree;
190+
const auto& loop = self._matrix[vertex_id][vertex_id];
191+
return std::ranges::count_if(
192+
self._matrix[vertex_id], [](const auto& edge) { return edge != nullptr; }
193+
)
194+
+ static_cast<types::size_type>(loop and loop->is_loop());
190195
}
191196

192197
[[nodiscard]] gl_attr_force_inline static std::vector<types::size_type> in_degree_map(

tests/source/gl/test_alg_mst.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,7 @@ TEST_CASE_TEMPLATE_DEFINE(
2323
using weight_type = typename sut_type::edge_properties_type::weight_type;
2424
using distance_type = weight_type;
2525

26-
static_assert(gl::type_traits::c_weight_properties_type<
27-
typename sut_type::edge_properties_type>);
28-
29-
SUBCASE("should throw if there is an edge with a negative weight") {
30-
const auto sut = lib::topology::clique<sut_type>(constants::n_elements_alg);
31-
sut.get_edge(constants::vertex_id_1, constants::vertex_id_2)
32-
.value()
33-
.get()
34-
.properties.weight = -static_cast<weight_type>(constants::n_elements_alg);
35-
36-
CHECK_THROWS_AS(
37-
func::discard_result(lib::algorithm::prim_mst(sut, constants::vertex_id_1)),
38-
std::invalid_argument
39-
);
40-
}
26+
static_assert(gl::type_traits::c_weight_properties_type<typename sut_type::edge_properties_type>);
4127

4228
SUBCASE("should return a proper mst descriptor for a valid graph") {
4329
using vertex_id_pair = std::pair<gl::types::id_type, gl::types::id_type>;

0 commit comments

Comments
 (0)