analytical_engine/core/fragment/dynamic_projected_fragment.h (745 lines of code) (raw):

/** Copyright 2020 Alibaba Group Holding Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANALYTICAL_ENGINE_CORE_FRAGMENT_DYNAMIC_PROJECTED_FRAGMENT_H_ #define ANALYTICAL_ENGINE_CORE_FRAGMENT_DYNAMIC_PROJECTED_FRAGMENT_H_ #ifdef NETWORKX #include <cassert> #include <cstddef> #include <memory> #include <string> #include <type_traits> #include <utility> #include <vector> #include "grape/fragment/fragment_base.h" #include "grape/graph/adj_list.h" #include "grape/types.h" #include "core/config.h" #include "core/fragment/dynamic_fragment.h" #include "core/object/dynamic.h" namespace grape { class CommSpec; } namespace gs { namespace dynamic_projected_fragment_impl { /** * @brief A specialized UnpackDynamicVData for int32_t type */ template <typename T> typename std::enable_if<std::is_integral<T>::value, T>::type unpack_dynamic( const dynamic::Value& data, const std::string& v_prop_key) { return data[v_prop_key].GetInt64(); } template <typename T> typename std::enable_if<std::is_floating_point<T>::value, T>::type unpack_dynamic(const dynamic::Value& data, const std::string& v_prop_key) { return data[v_prop_key].GetDouble(); } template <typename T> typename std::enable_if<std::is_same<T, bool>::value, T>::type unpack_dynamic( const dynamic::Value& data, const std::string& v_prop_key) { return data[v_prop_key].GetBool(); } template <typename T> typename std::enable_if<std::is_same<T, std::string>::value, T>::type unpack_dynamic(const dynamic::Value& data, const std::string& v_prop_key) { return data[v_prop_key].GetString(); } template <typename T> typename std::enable_if<std::is_same<T, grape::EmptyType>::value, T>::type unpack_dynamic(const dynamic::Value& data, const std::string& v_prop_key) { return grape::EmptyType(); } template <typename VID_T, typename T> typename std::enable_if<std::is_integral<T>::value>::type unpack_nbr( grape::Nbr<VID_T, T>& nbr, const dynamic::Value& d, const char* key) { nbr.data = d[key].GetInt64(); } template <typename VID_T, typename T> typename std::enable_if<std::is_floating_point<T>::value>::type unpack_nbr( grape::Nbr<VID_T, T>& nbr, const dynamic::Value& d, const char* key) { nbr.data = d[key].GetDouble(); } template <typename VID_T, typename T> typename std::enable_if<std::is_same<std::string, T>::value>::type unpack_nbr( grape::Nbr<VID_T, T>& nbr, const dynamic::Value& d, const char* key) { nbr.data = d[key].GetString(); } template <typename VID_T, typename T> typename std::enable_if<std::is_same<bool, T>::value>::type unpack_nbr( grape::Nbr<VID_T, T>& nbr, const dynamic::Value& d, const char* key) { nbr.data = d[key].GetBool(); } template <typename VID_T, typename T> typename std::enable_if<std::is_same<grape::EmptyType, T>::value>::type unpack_nbr(grape::Nbr<VID_T, T>& nbr, const dynamic::Value& d, const std::string& key) { return; } #define SET_PROJECTED_POC_NBR \ void set_nbr() { \ unpack_nbr<VID_T, EDATA_T>(internal_nbr, current_->data, prop_key_); \ internal_nbr.neighbor = current_->neighbor; \ } /** * @brief This is an internal representation of neighbor vertices using * std::map. * * @tparam EDATA_T Data type of edge */ template <typename VID_T, typename EDATA_T> class AdjList { using NbrT = grape::Nbr<VID_T, dynamic::Value>; using InternalNbrT = grape::Nbr<VID_T, EDATA_T>; public: AdjList() = default; AdjList(NbrT* b, NbrT* e, const std::string& prop_key) : begin_(b), end_(e), prop_key_(prop_key.data()) {} ~AdjList() = default; inline bool Empty() const { return begin_ == end_; } inline bool NotEmpty() const { return !Empty(); } inline size_t Size() const { return end_ - begin_; } class iterator { using pointer_type = InternalNbrT*; using reference_type = InternalNbrT&; private: NbrT* current_; const char* prop_key_; InternalNbrT internal_nbr; SET_PROJECTED_POC_NBR public: iterator() = default; iterator(NbrT* c, const char* prop_key) noexcept : current_(c), prop_key_(prop_key) {} reference_type operator*() noexcept { set_nbr(); return internal_nbr; } pointer_type operator->() noexcept { set_nbr(); return &internal_nbr; } iterator& operator++() noexcept { ++current_; return *this; } iterator operator++(int) noexcept { return iterator(current_++, prop_key_); } iterator& operator--() noexcept { --current_; return *this; } iterator operator--(int) noexcept { return iterator(current_--, prop_key_); } iterator operator+(size_t offset) noexcept { return iterator(current_ + offset, prop_key_); } bool operator==(const iterator& rhs) noexcept { return current_ == rhs.current_; } bool operator!=(const iterator& rhs) noexcept { return current_ != rhs.current_; } }; class const_iterator { using pointer_type = const InternalNbrT*; using reference_type = const InternalNbrT&; private: const NbrT* current_; const char* prop_key_; InternalNbrT internal_nbr; SET_PROJECTED_POC_NBR public: const_iterator() = default; const_iterator(const NbrT* c, const char* prop_key) noexcept : current_(c), prop_key_(prop_key) {} reference_type operator*() noexcept { set_nbr(); return internal_nbr; } pointer_type operator->() noexcept { set_nbr(); return &internal_nbr; } const_iterator& operator++() noexcept { ++current_; return *this; } const_iterator operator++(int) noexcept { return const_iterator(current_++, prop_key_); } const_iterator& operator--() noexcept { --current_; return *this; } const_iterator operator--(int) noexcept { return const_iterator(current_--, prop_key_); } const_iterator operator+(size_t offset) noexcept { return const_iterator(current_ + offset, prop_key_); } bool operator==(const const_iterator& rhs) noexcept { return current_ == rhs.current_; } bool operator!=(const const_iterator& rhs) noexcept { return current_ != rhs.current_; } }; iterator begin() { return iterator(begin_, prop_key_); } iterator end() { return iterator(end_, prop_key_); } iterator begin() const { return const_iterator(begin_, prop_key_); } iterator end() const { return const_iterator(end_, prop_key_); } bool empty() const { return begin_ == end_; } private: NbrT* begin_; NbrT* end_; const char* prop_key_; }; /** * @brief primitive adj linked list * @tparam EDATA_T */ template <typename VID_T, typename EDATA_T> class ConstAdjList { using NbrT = grape::Nbr<VID_T, dynamic::Value>; using InternalNbrT = grape::Nbr<VID_T, EDATA_T>; public: ConstAdjList() = default; ConstAdjList(const NbrT* b, const NbrT* e, const std::string& prop_key) : begin_(b), end_(e), prop_key_(prop_key.data()) {} ~ConstAdjList() = default; inline bool Empty() const { return begin_ == end_; } inline bool NotEmpty() const { return !Empty(); } inline size_t Size() const { return end_ - begin_; } class const_iterator { using pointer_type = const InternalNbrT*; using reference_type = const InternalNbrT&; private: const NbrT* current_; const char* prop_key_; InternalNbrT internal_nbr; SET_PROJECTED_POC_NBR public: const_iterator() = default; const_iterator(const NbrT* c, const char* prop_key) noexcept : current_(c), prop_key_(prop_key) {} reference_type operator*() noexcept { set_nbr(); return internal_nbr; } pointer_type operator->() noexcept { set_nbr(); return &internal_nbr; } const_iterator& operator++() noexcept { ++current_; return *this; } const_iterator operator++(int) noexcept { return const_iterator(current_++, prop_key_); } const_iterator& operator--() noexcept { --current_; return *this; } const_iterator operator--(int) noexcept { return const_iterator(current_--, prop_key_); } const_iterator operator+(size_t offset) noexcept { return const_iterator(current_ + offset, prop_key_); } bool operator==(const const_iterator& rhs) noexcept { return current_ == rhs.current_; } bool operator!=(const const_iterator& rhs) noexcept { return current_ != rhs.current_; } }; const_iterator begin() { return const_iterator(begin_, prop_key_); } const_iterator end() { return const_iterator(end_, prop_key_); } bool empty() const { return begin_ == end_; } private: const NbrT* begin_; const NbrT* end_; const char* prop_key_; }; } // namespace dynamic_projected_fragment_impl /** * @brief A wrapper class of DynamicFragment. * Inheritance does not work because of different return type of some methods. * We forward most of methods to DynamicFragment but enact * GetIncoming(Outgoing)AdjList, Get(Set)Data... * * @tparam VDATA_T The type of data attached with the vertex * @tparam EDATA_T The type of data attached with the edge */ template <typename VDATA_T, typename EDATA_T> class DynamicProjectedFragment { public: using fragment_t = DynamicFragment; using oid_t = typename fragment_t::oid_t; using vid_t = typename fragment_t::vid_t; using vertex_t = typename fragment_t::vertex_t; using vdata_t = VDATA_T; using edata_t = EDATA_T; using vertex_map_t = fragment_t::vertex_map_t; using adj_list_t = dynamic_projected_fragment_impl::AdjList<vid_t, edata_t>; using const_adj_list_t = dynamic_projected_fragment_impl::ConstAdjList<vid_t, edata_t>; using inner_vertices_t = typename fragment_t::inner_vertices_t; using outer_vertices_t = typename fragment_t::outer_vertices_t; using vertices_t = typename fragment_t::vertices_t; using sub_vertices_t = typename fragment_t::sub_vertices_t; template <typename DATA_T> using vertex_array_t = typename fragment_t::vertex_array_t<DATA_T>; template <typename DATA_T> using inner_vertex_array_t = typename fragment_t::inner_vertex_array_t<DATA_T>; template <typename DATA_T> using outer_vertex_array_t = typename fragment_t::outer_vertex_array_t<DATA_T>; using vertex_range_t = inner_vertices_t; // This member is used by grape::check_load_strategy_compatible() static constexpr grape::LoadStrategy load_strategy = grape::LoadStrategy::kBothOutIn; DynamicProjectedFragment(fragment_t* frag, const std::string& v_prop_key, const std::string& e_prop_key) : fragment_(frag), v_prop_key_(std::move(v_prop_key)), e_prop_key_(std::move(e_prop_key)) {} static std::shared_ptr<DynamicProjectedFragment<VDATA_T, EDATA_T>> Project( const std::shared_ptr<DynamicFragment>& frag, const std::string& v_prop, const std::string& e_prop) { return std::make_shared<DynamicProjectedFragment>(frag.get(), v_prop, e_prop); } void PrepareToRunApp(const grape::CommSpec& comm_spec, grape::PrepareConf conf) { fragment_->PrepareToRunApp(comm_spec, conf); } inline fid_t fid() const { return fragment_->fid(); } inline fid_t fnum() const { return fragment_->fnum(); } inline bool directed() const { return fragment_->directed(); } std::shared_ptr<vertex_map_t> GetVertexMap() const { return fragment_->GetVertexMap(); } inline const vertices_t& Vertices() const { return fragment_->Vertices(); } inline const inner_vertices_t& InnerVertices() const { return fragment_->InnerVertices(); } inline const outer_vertices_t& OuterVertices() const { return fragment_->OuterVertices(); } inline bool GetVertex(const oid_t& oid, vertex_t& v) const { return fragment_->GetVertex(oid, v); } inline oid_t GetId(const vertex_t& v) const { return fragment_->GetId(v); } inline fid_t GetFragId(const vertex_t& u) const { return fragment_->GetFragId(u); } inline bool Gid2Vertex(const vid_t& gid, vertex_t& v) const { return fragment_->Gid2Vertex(gid, v); } inline vid_t Vertex2Gid(const vertex_t& v) const { return fragment_->Vertex2Gid(v); } inline vdata_t GetData(const vertex_t& v) const { assert(fragment_->IsInnerVertex(v)); auto data = fragment_->GetData(v); return dynamic_projected_fragment_impl::unpack_dynamic<vdata_t>( data, v_prop_key_); } inline vid_t GetInnerVerticesNum() const { return fragment_->GetInnerVerticesNum(); } inline vid_t GetOuterVerticesNum() const { return fragment_->GetOuterVerticesNum(); } inline vid_t GetVerticesNum() const { return fragment_->GetVerticesNum(); } size_t GetTotalVerticesNum() const { return fragment_->GetTotalVerticesNum(); } inline size_t GetEdgeNum() const { return fragment_->GetEdgeNum(); } inline size_t GetOutgoingEdgeNum() const { return fragment_->GetOutgoingEdgeNum(); } inline size_t GetIncomingEdgeNum() const { return fragment_->GetIncomingEdgeNum(); } inline bool IsInnerVertex(const vertex_t& v) const { return fragment_->IsInnerVertex(v); } inline bool IsOuterVertex(const vertex_t& v) const { return fragment_->IsOuterVertex(v); } inline bool GetInnerVertex(const oid_t& oid, vertex_t& v) const { return fragment_->GetInnerVertex(oid, v); } inline oid_t GetOuterVertexId(const vertex_t& v) const { return fragment_->GetOuterVertexId(v); } inline oid_t Gid2Oid(const vid_t& gid) const { return fragment_->Gid2Oid(gid); } inline bool InnerVertexGid2Vertex(const vid_t& gid, vertex_t& v) const { return fragment_->InnerVertexGid2Vertex(gid, v); } inline bool OuterVertexGid2Vertex(const vid_t& gid, vertex_t& v) const { return fragment_->OuterVertexGid2Vertex(gid, v); } inline vid_t GetOuterVertexGid(const vertex_t& v) const { return fragment_->GetOuterVertexGid(v); } inline vid_t GetInnerVertexGid(const vertex_t& v) const { return fragment_->GetInnerVertexGid(v); } inline bool IsAliveInnerVertex(const vertex_t& v) const { return fragment_->IsAliveInnerVertex(v); } inline bool HasChild(const vertex_t& v) const { return fragment_->HasChild(v); } inline bool HasParent(const vertex_t& v) const { return fragment_->HasParent(v); } inline adj_list_t GetIncomingAdjList(const vertex_t& v) { assert(IsInnerVertex(v)); if (!fragment_->directed()) { return adj_list_t(fragment_->get_oe_begin(v), fragment_->get_oe_end(v), e_prop_key_); } return adj_list_t(fragment_->get_ie_begin(v), fragment_->get_ie_end(v), e_prop_key_); } inline const_adj_list_t GetIncomingAdjList(const vertex_t& v) const { assert(IsInnerVertex(v)); if (!fragment_->directed()) { return const_adj_list_t(fragment_->get_oe_begin(v), fragment_->get_oe_end(v), e_prop_key_); } return const_adj_list_t(fragment_->get_ie_begin(v), fragment_->get_ie_end(v), e_prop_key_); } inline adj_list_t GetOutgoingAdjList(const vertex_t& v) { assert(IsInnerVertex(v)); return adj_list_t(fragment_->get_oe_begin(v), fragment_->get_oe_end(v), e_prop_key_); } inline const_adj_list_t GetOutgoingAdjList(const vertex_t& v) const { assert(IsInnerVertex(v)); return const_adj_list_t(fragment_->get_oe_begin(v), fragment_->get_oe_end(v), e_prop_key_); } inline adj_list_t GetIncomingInnerVertexAdjList(const vertex_t& v) { assert(IsInnerVertex(v)); if (!fragment_->directed()) { return adj_list_t(fragment_->get_oe_begin(v), fragment_->oespliter_[v], e_prop_key_); } return adj_list_t(fragment_->get_ie_begin(v), fragment_->iespliter_[v], e_prop_key_); } inline const_adj_list_t GetIncomingInnerVertexAdjList( const vertex_t& v) const { assert(IsInnerVertex(v)); if (!fragment_->directed()) { return const_adj_list_t(fragment_->get_oe_begin(v), fragment_->oespliter_[v], e_prop_key_); } return const_adj_list_t(fragment_->get_ie_begin(v), fragment_->iespliter_[v], e_prop_key_); } inline adj_list_t GetIncomingOuterVertexAdjList(const vertex_t& v) { assert(IsInnerVertex(v)); if (!fragment_->directed()) { return adj_list_t(fragment_->oespliter_[v], fragment_->get_oe_end(v), e_prop_key_); } return adj_list_t(fragment_->iespliter_[v], fragment_->get_ie_end(v), e_prop_key_); } inline const_adj_list_t GetIncomingOuterVertexAdjList( const vertex_t& v) const { assert(IsInnerVertex(v)); if (!fragment_->directed()) { return const_adj_list_t(fragment_->oespliter_[v], fragment_->get_oe_end(v), e_prop_key_); } return const_adj_list_t(fragment_->iespliter_[v], fragment_->get_ie_end(v), e_prop_key_); } inline adj_list_t GetOutgoingInnerVertexAdjList(const vertex_t& v) { assert(IsInnerVertex(v)); return adj_list_t(fragment_->get_oe_begin(v), fragment_->oespliter_[v], e_prop_key_); } inline const_adj_list_t GetOutgoingInnerVertexAdjList( const vertex_t& v) const { assert(IsInnerVertex(v)); return const_adj_list_t(fragment_->get_oe_begin(v), fragment_->oespliter_[v], e_prop_key_); } inline adj_list_t GetOutgoingOuterVertexAdjList(const vertex_t& v) { assert(IsInnerVertex(v)); return adj_list_t(fragment_->oespliter_[v], fragment_->get_oe_end(v), e_prop_key_); } inline const_adj_list_t GetOutgoingOuterVertexAdjList( const vertex_t& v) const { assert(IsInnerVertex(v)); return const_adj_list_t(fragment_->oespliter_[v], fragment_->get_oe_end(v), e_prop_key_); } inline int GetLocalOutDegree(const vertex_t& v) const { return fragment_->GetLocalOutDegree(v); } inline int GetLocalInDegree(const vertex_t& v) const { return fragment_->GetLocalInDegree(v); } inline grape::DestList IEDests(const vertex_t& v) const { return fragment_->IEDests(v); } inline size_t IEDestsSize() const { return fragment_->IEDestsSize(); } inline grape::DestList OEDests(const vertex_t& v) const { return fragment_->OEDests(v); } inline size_t OEDestsSize() const { return fragment_->OEDestsSize(); } inline grape::DestList IOEDests(const vertex_t& v) const { return fragment_->IOEDests(v); } inline size_t IOEDestsSize() const { return fragment_->IOEDestsSize(); } inline const std::vector<vertex_t>& MirrorVertices(fid_t fid) const { return fragment_->MirrorVertices(fid); } inline bool Oid2Gid(const oid_t& oid, vid_t& gid) const { return fragment_->Oid2Gid(oid, gid); } inline bool HasNode(const oid_t& node) const { return fragment_->HasNode(node); } private: fragment_t* fragment_; std::string v_prop_key_; std::string e_prop_key_; static_assert(std::is_same<int, VDATA_T>::value || std::is_same<int64_t, VDATA_T>::value || std::is_same<double, VDATA_T>::value || std::is_same<std::string, VDATA_T>::value || std::is_same<grape::EmptyType, VDATA_T>::value, "unsupported type"); static_assert(std::is_same<int, EDATA_T>::value || std::is_same<int64_t, EDATA_T>::value || std::is_same<double, EDATA_T>::value || std::is_same<std::string, EDATA_T>::value || std::is_same<grape::EmptyType, EDATA_T>::value, "unsupported type"); }; template <> class DynamicProjectedFragment<grape::EmptyType, grape::EmptyType> { public: using fragment_t = DynamicFragment; using oid_t = typename fragment_t::oid_t; using vid_t = typename fragment_t::vid_t; using vertex_t = typename fragment_t::vertex_t; using vdata_t = grape::EmptyType; using edata_t = grape::EmptyType; using vertex_map_t = fragment_t::vertex_map_t; using adj_list_t = typename fragment_t::adj_list_t; using const_adj_list_t = typename fragment_t::const_adj_list_t; using inner_vertices_t = typename fragment_t::inner_vertices_t; using outer_vertices_t = typename fragment_t::outer_vertices_t; using vertices_t = typename fragment_t::vertices_t; using sub_vertices_t = typename fragment_t::sub_vertices_t; template <typename DATA_T> using vertex_array_t = typename fragment_t::vertex_array_t<DATA_T>; template <typename DATA_T> using inner_vertex_array_t = typename fragment_t::inner_vertex_array_t<DATA_T>; template <typename DATA_T> using outer_vertex_array_t = typename fragment_t::outer_vertex_array_t<DATA_T>; using vertex_range_t = inner_vertices_t; // This member is used by grape::check_load_strategy_compatible() static constexpr grape::LoadStrategy load_strategy = grape::LoadStrategy::kBothOutIn; DynamicProjectedFragment(fragment_t* frag, const std::string& v_prop_key, const std::string& e_prop_key) : fragment_(frag), v_prop_key_(std::move(v_prop_key)), e_prop_key_(std::move(e_prop_key)) {} static std::shared_ptr<DynamicProjectedFragment<vdata_t, edata_t>> Project( const std::shared_ptr<DynamicFragment>& frag, const std::string& v_prop, const std::string& e_prop) { return std::make_shared<DynamicProjectedFragment>(frag.get(), v_prop, e_prop); } void PrepareToRunApp(const grape::CommSpec& comm_spec, grape::PrepareConf conf) { fragment_->PrepareToRunApp(comm_spec, conf); } inline fid_t fid() const { return fragment_->fid(); } inline fid_t fnum() const { return fragment_->fnum(); } inline bool directed() const { return fragment_->directed(); } std::shared_ptr<vertex_map_t> GetVertexMap() const { return fragment_->GetVertexMap(); } inline const vertices_t& Vertices() const { return fragment_->Vertices(); } inline const inner_vertices_t& InnerVertices() const { return fragment_->InnerVertices(); } inline const outer_vertices_t& OuterVertices() const { return fragment_->OuterVertices(); } inline bool GetVertex(const oid_t& oid, vertex_t& v) const { return fragment_->GetVertex(oid, v); } inline oid_t GetId(const vertex_t& v) const { return fragment_->GetId(v); } inline fid_t GetFragId(const vertex_t& u) const { return fragment_->GetFragId(u); } inline bool Gid2Vertex(const vid_t& gid, vertex_t& v) const { return fragment_->Gid2Vertex(gid, v); } inline vid_t Vertex2Gid(const vertex_t& v) const { return fragment_->Vertex2Gid(v); } inline vdata_t GetData(const vertex_t& v) const { assert(fragment_->IsInnerVertex(v)); return grape::EmptyType(); } inline vid_t GetInnerVerticesNum() const { return fragment_->GetInnerVerticesNum(); } inline vid_t GetOuterVerticesNum() const { return fragment_->GetOuterVerticesNum(); } inline vid_t GetVerticesNum() const { return fragment_->GetVerticesNum(); } size_t GetTotalVerticesNum() const { return fragment_->GetTotalVerticesNum(); } inline size_t GetEdgeNum() const { return fragment_->GetEdgeNum(); } inline size_t GetOutgoingEdgeNum() const { return fragment_->GetOutgoingEdgeNum(); } inline size_t GetIncomingEdgeNum() const { return fragment_->GetIncomingEdgeNum(); } inline bool IsInnerVertex(const vertex_t& v) const { return fragment_->IsInnerVertex(v); } inline bool IsOuterVertex(const vertex_t& v) const { return fragment_->IsOuterVertex(v); } inline bool GetInnerVertex(const oid_t& oid, vertex_t& v) const { return fragment_->GetInnerVertex(oid, v); } inline oid_t GetOuterVertexId(const vertex_t& v) const { return fragment_->GetOuterVertexId(v); } inline oid_t Gid2Oid(const vid_t& gid) const { return fragment_->Gid2Oid(gid); } inline bool InnerVertexGid2Vertex(const vid_t& gid, vertex_t& v) const { return fragment_->InnerVertexGid2Vertex(gid, v); } inline bool OuterVertexGid2Vertex(const vid_t& gid, vertex_t& v) const { return fragment_->OuterVertexGid2Vertex(gid, v); } inline vid_t GetOuterVertexGid(const vertex_t& v) const { return fragment_->GetOuterVertexGid(v); } inline vid_t GetInnerVertexGid(const vertex_t& v) const { return fragment_->GetInnerVertexGid(v); } inline bool IsAliveInnerVertex(const vertex_t& v) const { return fragment_->IsAliveInnerVertex(v); } inline bool HasChild(const vertex_t& v) const { return fragment_->HasChild(v); } inline bool HasParent(const vertex_t& v) const { return fragment_->HasParent(v); } inline adj_list_t GetIncomingAdjList(const vertex_t& v) { if (!fragment_->directed_) { return adj_list_t(fragment_->get_oe_begin(v), fragment_->get_oe_end(v)); } return adj_list_t(fragment_->get_ie_begin(v), fragment_->get_ie_end(v)); } inline const_adj_list_t GetIncomingAdjList(const vertex_t& v) const { if (!fragment_->directed()) { return const_adj_list_t(fragment_->get_oe_begin(v), fragment_->get_oe_end(v)); } return const_adj_list_t(fragment_->get_ie_begin(v), fragment_->get_ie_end(v)); } inline adj_list_t GetOutgoingAdjList(const vertex_t& v) { return adj_list_t(fragment_->get_oe_begin(v), fragment_->get_oe_end(v)); } inline const_adj_list_t GetOutgoingAdjList(const vertex_t& v) const { return const_adj_list_t(fragment_->get_oe_begin(v), fragment_->get_oe_end(v)); } inline adj_list_t GetIncomingInnerVertexAdjList(const vertex_t& v) { assert(IsInnerVertex(v)); if (!fragment_->directed()) { return adj_list_t(fragment_->get_oe_begin(v), fragment_->oespliter_[v]); } return adj_list_t(fragment_->get_ie_begin(v), fragment_->iespliter_[v]); } inline const_adj_list_t GetIncomingInnerVertexAdjList( const vertex_t& v) const { assert(IsInnerVertex(v)); if (!fragment_->directed()) { return const_adj_list_t(fragment_->get_oe_begin(v), fragment_->oespliter_[v]); } return const_adj_list_t(fragment_->get_ie_begin(v), fragment_->iespliter_[v]); } inline adj_list_t GetIncomingOuterVertexAdjList(const vertex_t& v) { assert(IsInnerVertex(v)); if (!fragment_->directed()) { return adj_list_t(fragment_->oespliter_[v], fragment_->get_oe_end(v)); } return adj_list_t(fragment_->iespliter_[v], fragment_->get_ie_end(v)); } inline const_adj_list_t GetIncomingOuterVertexAdjList( const vertex_t& v) const { assert(IsInnerVertex(v)); if (!fragment_->directed()) { return const_adj_list_t(fragment_->oespliter_[v], fragment_->get_oe_end(v)); } return const_adj_list_t(fragment_->iespliter_[v], fragment_->get_ie_end(v)); } inline adj_list_t GetOutgoingInnerVertexAdjList(const vertex_t& v) { assert(IsInnerVertex(v)); return adj_list_t(fragment_->get_oe_begin(v), fragment_->oespliter_[v]); } inline const_adj_list_t GetOutgoingInnerVertexAdjList( const vertex_t& v) const { assert(IsInnerVertex(v)); return const_adj_list_t(fragment_->get_oe_begin(v), fragment_->oespliter_[v]); } inline adj_list_t GetOutgoingOuterVertexAdjList(const vertex_t& v) { assert(IsInnerVertex(v)); return adj_list_t(fragment_->oespliter_[v], fragment_->get_oe_end(v)); } inline const_adj_list_t GetOutgoingOuterVertexAdjList( const vertex_t& v) const { assert(IsInnerVertex(v)); return const_adj_list_t(fragment_->oespliter_[v], fragment_->get_oe_end(v)); } inline int GetLocalOutDegree(const vertex_t& v) const { return fragment_->GetLocalOutDegree(v); } inline int GetLocalInDegree(const vertex_t& v) const { return fragment_->GetLocalInDegree(v); } inline grape::DestList IEDests(const vertex_t& v) const { return fragment_->IEDests(v); } inline size_t IEDestsSize() const { return fragment_->IEDestsSize(); } inline grape::DestList OEDests(const vertex_t& v) const { return fragment_->OEDests(v); } inline size_t OEDestsSize() const { return fragment_->OEDestsSize(); } inline grape::DestList IOEDests(const vertex_t& v) const { return fragment_->IOEDests(v); } inline size_t IOEDestsSize() const { return fragment_->IOEDestsSize(); } inline const std::vector<vertex_t>& MirrorVertices(fid_t fid) const { return fragment_->MirrorVertices(fid); } inline bool Oid2Gid(const oid_t& oid, vid_t& gid) const { return fragment_->Oid2Gid(oid, gid); } inline bool HasNode(const oid_t& node) const { return fragment_->HasNode(node); } private: fragment_t* fragment_; std::string v_prop_key_; std::string e_prop_key_; }; } // namespace gs #endif #endif // ANALYTICAL_ENGINE_CORE_FRAGMENT_DYNAMIC_PROJECTED_FRAGMENT_H_