Skip to content

Commit

Permalink
Add type definitions to edge_descriptor
Browse files Browse the repository at this point in the history
Add edgelist_range_iterator (incomplete)
  • Loading branch information
pratzl committed Dec 1, 2023
1 parent 1d22712 commit 546d11f
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 3 deletions.
40 changes: 40 additions & 0 deletions include/graph/graph_descriptors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ using copyable_vertex_t = vertex_descriptor<VId, void, VV>; // {id, value}
//
template <class VId, bool Sourced, class E, class EV>
struct edge_descriptor {
using source_id_type = VId;
using target_id_type = VId;
using edge_type = E;
using value_type = EV;

VId source_id;
VId target_id;
E edge;
Expand All @@ -49,41 +54,76 @@ struct edge_descriptor {

template <class VId, class E>
struct edge_descriptor<VId, true, E, void> {
using source_id_type = VId;
using target_id_type = VId;
using edge_type = E;
using value_type = void;

VId source_id;
VId target_id;
E edge;
};
template <class VId>
struct edge_descriptor<VId, true, void, void> {
using source_id_type = VId;
using target_id_type = VId;
using edge_type = void;
using value_type = void;

VId source_id;
VId target_id;
};
template <class VId, class EV>
struct edge_descriptor<VId, true, void, EV> {
using source_id_type = VId;
using target_id_type = VId;
using edge_type = void;
using value_type = EV;

VId source_id;
VId target_id;
EV value;
};

template <class VId, class E, class EV>
struct edge_descriptor<VId, false, E, EV> {
using source_id_type = void;
using target_id_type = VId;
using edge_type = void;
using value_type = EV;

VId target_id;
E edge;
EV value;
};
template <class VId, class E>
struct edge_descriptor<VId, false, E, void> {
using source_id_type = void;
using target_id_type = VId;
using edge_type = E;
using value_type = void;

VId target_id;
E edge;
};

template <class VId, class EV>
struct edge_descriptor<VId, false, void, EV> {
using source_id_type = void;
using target_id_type = VId;
using edge_type = void;
using value_type = EV;

VId target_id;
EV value;
};
template <class VId>
struct edge_descriptor<VId, false, void, void> {
using source_id_type = void;
using target_id_type = VId;
using edge_type = void;
using value_type = void;

VId target_id;
};

Expand Down
107 changes: 104 additions & 3 deletions include/graph/views/edgelist.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
//
// basic_edgelist(elr,proj) -> edge_descriptor<VId,true,void,void> -> {source_id, target_id}, where VId is defined by proj
// Note: proj(range_value_t<ELR>&) is a projection and determines whether to return a value member or not
//
//
// given: auto evf = [&g](edge_reference_t<G> uv) { return edge_value(uv); }
//
// vertex_id<G> first_id = ..., last_id = ...;
Expand Down Expand Up @@ -292,6 +292,107 @@ class edgelist_iterator<G, void> : public edgelist_iterator_base<G> {
};


/**
* @brief Iterator for a range with values that can be projected to a edge_descriptor.
*
* @tparam ELR Graph type
* @tparam Proj Edge Value Function type
*/
#if 0
template <edgelist_range ELR, class Proj>
class edgelist_range_iterator {
public:
using edge_range = ELR;
using edge_iterator = ranges::iterator_t<edge_range>;
using edge_type = ranges::range_value_t<edge_range>;
using edge_reference_type = ranges::range_reference_t<edge_range>;
using edge_value_type = invoke_result_t<Proj, edge_reference_type>;

using iterator_category = forward_iterator_tag;
using value_type = edge_descriptor<const vertex_id_type, true, edge_reference_type, edge_value_type>;
using difference_type = ranges::range_difference_t<edge_range>;
using pointer = value_type*;
using const_pointer = const value_type*;
using reference = value_type&;
using const_reference = const value_type&;
using rvalue_reference = value_type&&;

public:
edgelist_range_iterator(graph_type& g, vertex_iterator ui, const Proj& proj_fn)
: base_type(), g_(g), ui_(ui), uvi_(), proj_fn_(&proj_fn) {}
edgelist_range_iterator(graph_type& g, const Proj& proj_fn)
: edgelist_range_iterator(g, ranges::begin(vertices(g)), proj_fn) {
this->find_non_empty_vertex(g_, ui_, uvi_);
}

constexpr edgelist_range_iterator() = default;
constexpr edgelist_range_iterator(const edgelist_range_iterator&) = default;
constexpr edgelist_range_iterator(edgelist_range_iterator&&) = default;
constexpr ~edgelist_range_iterator() = default;

constexpr edgelist_range_iterator& operator=(const edgelist_range_iterator&) = default;
constexpr edgelist_range_iterator& operator=(edgelist_range_iterator&&) = default;

protected:
// avoid difficulty in undefined vertex reference value in value_type
// shadow_vertex_value_type: ptr if vertex_value_type is ref or ptr, value otherwise
using shadow_edge_type = remove_reference_t<edge_reference_type>;
using shadow_value_type =
edge_descriptor<vertex_id_type, true, shadow_edge_type*, _detail::ref_to_ptr<edge_value_type>>;

union internal_value {
value_type value_;
shadow_value_type shadow_;

internal_value(const internal_value& rhs) : shadow_(rhs.shadow_) {}
internal_value() : shadow_{} {}
~internal_value() {}
internal_value& operator=(const internal_value& rhs) { value_.shadow = rhs.value_.shadow; }
};

public:
constexpr reference operator*() const {
if constexpr (unordered_edge<ELR, edge_type>) {
if (target_id(g_, *uvi_) != vertex_id(g_, ui_)) {
value_.shadow_.source_id = source_id(g_, *uvi_);
value_.shadow_.target_id = target_id(g_, *uvi_);
} else {
value_.shadow_.source_id = target_id(g_, *uvi_);
value_.shadow_.target_id = source_id(g_, *uvi_);
}
value_.shadow_.edge = &*uvi_;
value_.shadow_.value = invoke(*proj_fn_, *uvi_);
} else {
value_.shadow_ = {vertex_id(g_, ui_), target_id(g_, *uvi_), &*uvi_, invoke(*proj_fn_, *uvi_)};
}
return value_.value_;
}

constexpr edgelist_range_iterator& operator++() {
this->find_next_edge(g_, ui_, uvi_);
return *this;
}
constexpr edgelist_range_iterator operator++(int) const {
edgelist_range_iterator tmp(*this);
++*this;
return tmp;
}

constexpr bool operator==(const edgelist_range_iterator& rhs) const { return uvi_ == rhs.uvi_; }
//constexpr bool operator==(const edgelist_range_iterator& rhs) const { return uvi_ == rhs; }

private: // member variables
mutable internal_value value_;
_detail::ref_to_ptr<graph_type&> g_;
vertex_iterator ui_;
edge_iterator uvi_;
const Proj* proj_fn_ = nullptr;

friend bool operator==(const vertex_iterator& lhs, const edgelist_range_iterator& rhs) { return lhs == rhs.ui_; }
};
#endif


template <class G, class EVF>
using edgelist_view = ranges::subrange<edgelist_iterator<G, EVF>, vertex_iterator_t<G>>;

Expand All @@ -300,7 +401,7 @@ using edgelist_view = ranges::subrange<edgelist_iterator<G, EVF>, vertex_iterato
// edgelist(g,fn) -> edges[uid,vid,uv,value]
// edgelist(g,uid,vid) -> edges[uid,vid,uv]
// edgelist(g,uid,vid,fn) -> edges[uid,vid,uv,value]
//
//
// edgelist(elr,proj) -> edges[uid,vid,uv] ; proj determines whether value is included or not
// edgelist(elr,proj) -> edges[uid,vid,uv,value]
namespace _Edgelist {
Expand Down Expand Up @@ -656,7 +757,7 @@ namespace _Edgelist {
}
#endif //ENABLE_EDGELIST_RANGE

}; // class _Cpo
}; // class _Cpo
} // namespace _Edgelist

inline namespace _Cpos {
Expand Down

0 comments on commit 546d11f

Please sign in to comment.