Skip to content

Commit ed95050

Browse files
committed
merged in/ou_view
1 parent d74cdc5 commit ed95050

2 files changed

Lines changed: 76 additions & 114 deletions

File tree

include/osp/concepts/directed_graph_edge_desc_concept.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ inline edge_view<Graph_t> edges(const Graph_t &graph) {
8383
* @return An `out_edge_view` allowing iteration over outgoing edges from `u`.
8484
*/
8585
template<typename Graph_t>
86-
inline out_edge_view<Graph_t> out_edges(vertex_idx_t<Graph_t> u, const Graph_t &graph) {
87-
return out_edge_view(graph, u);
86+
inline OutEdgeView<Graph_t> out_edges(vertex_idx_t<Graph_t> u, const Graph_t &graph) {
87+
return OutEdgeView<Graph_t>(graph, u);
8888
}
8989

9090
/**
@@ -96,8 +96,8 @@ inline out_edge_view<Graph_t> out_edges(vertex_idx_t<Graph_t> u, const Graph_t &
9696
* @return An `in_edge_view` allowing iteration over incoming edges to `v`.
9797
*/
9898
template<typename Graph_t>
99-
inline in_edge_view<Graph_t> in_edges(vertex_idx_t<Graph_t> v, const Graph_t &graph) {
100-
return in_edge_view(graph, v);
99+
inline InEdgeView<Graph_t> in_edges(vertex_idx_t<Graph_t> v, const Graph_t &graph) {
100+
return InEdgeView<Graph_t>(graph, v);
101101
}
102102

103103
/**

include/osp/graph_algorithms/directed_graph_edge_view.hpp

Lines changed: 72 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -168,23 +168,24 @@ class edge_view {
168168
};
169169

170170
/**
171-
* @brief A view over the outgoing edges of a specific vertex in a directed graph.
171+
* @brief A view over the incident edges of a specific vertex in a directed graph.
172172
*
173-
* This class provides an iterator-based view to iterate over the outgoing edges
174-
* of a given vertex `u`. It is a lightweight, non-owning view.
173+
* This class provides an iterator-based view to iterate over either outgoing or incoming edges
174+
* of a given vertex. It is a lightweight, non-owning view.
175175
*
176176
* @tparam Graph_t The type of the graph, which must satisfy the `is_directed_graph_v` concept.
177+
* @tparam IsOutgoing If true, iterates over outgoing edges; otherwise, incoming edges.
177178
*/
178-
template<typename Graph_t>
179-
class out_edge_view {
179+
template<typename Graph_t, bool IsOutgoing>
180+
class IncidentEdgeView {
180181
private:
181182
static_assert(is_directed_graph_v<Graph_t>, "Graph_t must satisfy the directed_graph concept");
182183

183184
const Graph_t &graph_;
184-
vertex_idx_t<Graph_t> sourceVertex_;
185+
vertex_idx_t<Graph_t> anchorVertex_;
185186

186187
template<typename child_iterator_t>
187-
class OutEdgeIterator {
188+
class IncidentEdgeIterator {
188189
public:
189190
using iterator_category = typename std::iterator_traits<child_iterator_t>::iterator_category;
190191
using difference_type = std::ptrdiff_t;
@@ -198,145 +199,106 @@ class out_edge_view {
198199
};
199200

200201
private:
201-
vertex_idx_t<Graph_t> sourceVertex_;
202-
child_iterator_t currentChildIt_;
202+
vertex_idx_t<Graph_t> anchorVertex_;
203+
child_iterator_t currentIt_;
203204

204205
public:
205-
OutEdgeIterator() = default;
206-
OutEdgeIterator(vertex_idx_t<Graph_t> u, child_iterator_t it) : sourceVertex_(u), currentChildIt_(it) {}
206+
IncidentEdgeIterator() = default;
207+
IncidentEdgeIterator(vertex_idx_t<Graph_t> u, child_iterator_t it) : anchorVertex_(u), currentIt_(it) {}
207208

208-
[[nodiscard]] value_type operator*() const { return {sourceVertex_, *currentChildIt_}; }
209+
[[nodiscard]] value_type operator*() const {
210+
if constexpr (IsOutgoing) {
211+
return {anchorVertex_, *currentIt_};
212+
} else {
213+
return {*currentIt_, anchorVertex_};
214+
}
215+
}
209216
[[nodiscard]] arrow_proxy operator->() const { return {operator*()}; }
210217

211-
OutEdgeIterator &operator++() {
212-
++currentChildIt_;
218+
IncidentEdgeIterator &operator++() {
219+
++currentIt_;
213220
return *this;
214221
}
215222

216-
OutEdgeIterator operator++(int) {
217-
OutEdgeIterator temp = *this;
223+
IncidentEdgeIterator operator++(int) {
224+
IncidentEdgeIterator temp = *this;
218225
++(*this);
219226
return temp;
220227
}
221228

222-
OutEdgeIterator &operator--() {
223-
--currentChildIt_;
229+
IncidentEdgeIterator &operator--() {
230+
--currentIt_;
224231
return *this;
225232
}
226233

227-
OutEdgeIterator operator--(int) {
228-
OutEdgeIterator temp = *this;
234+
IncidentEdgeIterator operator--(int) {
235+
IncidentEdgeIterator temp = *this;
229236
--(*this);
230237
return temp;
231238
}
232239

233-
[[nodiscard]] bool operator==(const OutEdgeIterator &other) const noexcept {
234-
return currentChildIt_ == other.currentChildIt_;
240+
[[nodiscard]] bool operator==(const IncidentEdgeIterator &other) const noexcept {
241+
return currentIt_ == other.currentIt_;
235242
}
236243

237-
[[nodiscard]] bool operator!=(const OutEdgeIterator &other) const noexcept { return !(*this == other); }
244+
[[nodiscard]] bool operator!=(const IncidentEdgeIterator &other) const noexcept { return !(*this == other); }
238245
};
239246

247+
// Helper to deduce iterator type based on direction
248+
using base_iterator_type =
249+
std::conditional_t<IsOutgoing, decltype(std::declval<Graph_t>().children(std::declval<vertex_idx_t<Graph_t>>()).begin()),
250+
decltype(std::declval<Graph_t>().parents(std::declval<vertex_idx_t<Graph_t>>()).begin())>;
251+
240252
public:
241-
using iterator = OutEdgeIterator<decltype(std::declval<Graph_t>().children(std::declval<vertex_idx_t<Graph_t>>()).begin())>;
253+
using iterator = IncidentEdgeIterator<base_iterator_type>;
242254
using constIterator = iterator;
243255

244-
out_edge_view(const Graph_t &graph, vertex_idx_t<Graph_t> u) : graph_(graph), sourceVertex_(u) {}
256+
IncidentEdgeView(const Graph_t &graph, vertex_idx_t<Graph_t> u) : graph_(graph), anchorVertex_(u) {}
245257

246-
[[nodiscard]] auto begin() const { return iterator(sourceVertex_, graph_.children(sourceVertex_).begin()); }
258+
[[nodiscard]] auto begin() const {
259+
if constexpr (IsOutgoing) {
260+
return iterator(anchorVertex_, graph_.children(anchorVertex_).begin());
261+
} else {
262+
return iterator(anchorVertex_, graph_.parents(anchorVertex_).begin());
263+
}
264+
}
247265
[[nodiscard]] auto cbegin() const { return begin(); }
248266

249-
[[nodiscard]] auto end() const { return iterator(sourceVertex_, graph_.children(sourceVertex_).end()); }
267+
[[nodiscard]] auto end() const {
268+
if constexpr (IsOutgoing) {
269+
return iterator(anchorVertex_, graph_.children(anchorVertex_).end());
270+
} else {
271+
return iterator(anchorVertex_, graph_.parents(anchorVertex_).end());
272+
}
273+
}
250274
[[nodiscard]] auto cend() const { return end(); }
251275

252-
[[nodiscard]] auto size() const { return graph_.out_degree(sourceVertex_); }
253-
[[nodiscard]] bool empty() const { return graph_.out_degree(sourceVertex_) == 0; }
276+
[[nodiscard]] auto size() const {
277+
if constexpr (IsOutgoing) {
278+
return graph_.out_degree(anchorVertex_);
279+
} else {
280+
return graph_.in_degree(anchorVertex_);
281+
}
282+
}
283+
[[nodiscard]] bool empty() const {
284+
if constexpr (IsOutgoing) {
285+
return graph_.out_degree(anchorVertex_) == 0;
286+
} else {
287+
return graph_.in_degree(anchorVertex_) == 0;
288+
}
289+
}
254290
};
255291

256292
/**
257-
* @brief A view over the incoming edges of a specific vertex in a directed graph.
258-
*
259-
* This class provides an iterator-based view to iterate over the incoming edges
260-
* of a given vertex `v`. It is a lightweight, non-owning view.
261-
*
262-
* @tparam Graph_t The type of the graph, which must satisfy the `is_directed_graph_v` concept.
293+
* @brief A view over the outgoing edges of a specific vertex in a directed graph.
263294
*/
264295
template<typename Graph_t>
265-
class in_edge_view {
266-
private:
267-
static_assert(is_directed_graph_v<Graph_t>, "Graph_t must satisfy the directed_graph concept");
268-
269-
const Graph_t &graph_;
270-
vertex_idx_t<Graph_t> targetVertex_;
271-
272-
template<typename parent_iterator_t>
273-
class InEdgeIterator {
274-
public:
275-
using iterator_category = typename std::iterator_traits<parent_iterator_t>::iterator_category;
276-
using difference_type = std::ptrdiff_t;
277-
using value_type = directed_edge<Graph_t>;
278-
using pointer = value_type *;
279-
using reference = value_type &;
280-
281-
struct arrow_proxy {
282-
value_type value;
283-
const value_type *operator->() const noexcept { return &value; }
284-
};
285-
286-
private:
287-
vertex_idx_t<Graph_t> targetVertex_;
288-
parent_iterator_t currentParentIt_;
289-
290-
public:
291-
InEdgeIterator() = default;
292-
InEdgeIterator(vertex_idx_t<Graph_t> v, parent_iterator_t it) : targetVertex_(v), currentParentIt_(it) {}
296+
using OutEdgeView = IncidentEdgeView<Graph_t, true>;
293297

294-
[[nodiscard]] value_type operator*() const { return {*currentParentIt_, targetVertex_}; }
295-
[[nodiscard]] arrow_proxy operator->() const { return {operator*()}; }
296-
297-
InEdgeIterator &operator++() {
298-
++currentParentIt_;
299-
return *this;
300-
}
301-
302-
InEdgeIterator operator++(int) {
303-
InEdgeIterator temp = *this;
304-
++(*this);
305-
return temp;
306-
}
307-
308-
InEdgeIterator &operator--() {
309-
--currentParentIt_;
310-
return *this;
311-
}
312-
313-
InEdgeIterator operator--(int) {
314-
InEdgeIterator temp = *this;
315-
--(*this);
316-
return temp;
317-
}
318-
319-
[[nodiscard]] bool operator==(const InEdgeIterator &other) const noexcept {
320-
return currentParentIt_ == other.currentParentIt_;
321-
}
322-
323-
[[nodiscard]] bool operator!=(const InEdgeIterator &other) const noexcept { return !(*this == other); }
324-
};
325-
326-
public:
327-
using iterator = InEdgeIterator<decltype(std::declval<Graph_t>().parents(std::declval<vertex_idx_t<Graph_t>>()).begin())>;
328-
using constIterator = iterator;
329-
330-
in_edge_view(const Graph_t &graph, vertex_idx_t<Graph_t> v) : graph_(graph), targetVertex_(v) {}
331-
332-
[[nodiscard]] auto begin() const { return iterator(targetVertex_, graph_.parents(targetVertex_).begin()); }
333-
[[nodiscard]] auto cbegin() const { return begin(); }
334-
335-
[[nodiscard]] auto end() const { return iterator(targetVertex_, graph_.parents(targetVertex_).end()); }
336-
[[nodiscard]] auto cend() const { return end(); }
337-
338-
[[nodiscard]] auto size() const { return graph_.in_degree(targetVertex_); }
339-
[[nodiscard]] bool empty() const { return graph_.in_degree(targetVertex_) == 0; }
340-
};
298+
/**
299+
* @brief A view over the incoming edges of a specific vertex in a directed graph.
300+
*/
301+
template<typename Graph_t>
302+
using InEdgeView = IncidentEdgeView<Graph_t, false>;
341303

342304
} // namespace osp

0 commit comments

Comments
 (0)