Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GraphIndex] Detects duplicate edges on simple graphs #340

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Expand Up @@ -41,8 +41,8 @@ if(MSVC)
else(MSVC)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-std=c++11" SUPPORT_CXX11)
set(CMAKE_C_FLAGS "-O2 -Wall -fPIC ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-O2 -Wall -fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
set(CMAKE_C_FLAGS "-g -O0 -Wall -fPIC ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-g -O0 -Wall -fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
BarclayII marked this conversation as resolved.
Show resolved Hide resolved
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(CMAKE_C_FLAGS "-fopenmp ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-fopenmp ${CMAKE_CXX_FLAGS}")
Expand Down
54 changes: 42 additions & 12 deletions include/dgl/graph.h
Expand Up @@ -98,6 +98,10 @@ class Graph: public GraphInterface {
all_edges_dst_.clear();
read_only_ = false;
num_edges_ = 0;

src_count_buffer_.clear();
dst_count_buffer_.clear();
offset_buffer_.clear();
}

/*!
Expand Down Expand Up @@ -315,36 +319,39 @@ class Graph: public GraphInterface {
* \param vid The vertex id.
* \return the successor vector
*/
DGLIdIters SuccVec(dgl_id_t vid) const {
return DGLIdIters(adjlist_[vid].succ.begin(), adjlist_[vid].succ.end());
DGLIdVectorSlice SuccVec(dgl_id_t vid) const {
return DGLIdVectorSlice(adjlist_[vid].succ.begin(),
adjlist_[vid].succ.end());
}

/*!
* \brief Return the out edge id vector
* \param vid The vertex id.
* \return the out edge id vector
*/
DGLIdIters OutEdgeVec(dgl_id_t vid) const {
return DGLIdIters(adjlist_[vid].edge_id.begin(), adjlist_[vid].edge_id.end());
DGLIdVectorSlice OutEdgeVec(dgl_id_t vid) const {
return DGLIdVectorSlice(adjlist_[vid].edge_id.begin(),
adjlist_[vid].edge_id.end());
}

/*!
* \brief Return the predecessor vector
* \param vid The vertex id.
* \return the predecessor vector
*/
DGLIdIters PredVec(dgl_id_t vid) const {
return DGLIdIters(reverse_adjlist_[vid].succ.begin(), reverse_adjlist_[vid].succ.end());
DGLIdVectorSlice PredVec(dgl_id_t vid) const {
return DGLIdVectorSlice(reverse_adjlist_[vid].succ.begin(),
reverse_adjlist_[vid].succ.end());
}

/*!
* \brief Return the in edge id vector
* \param vid The vertex id.
* \return the in edge id vector
*/
DGLIdIters InEdgeVec(dgl_id_t vid) const {
return DGLIdIters(reverse_adjlist_[vid].edge_id.begin(),
reverse_adjlist_[vid].edge_id.end());
DGLIdVectorSlice InEdgeVec(dgl_id_t vid) const {
return DGLIdVectorSlice(reverse_adjlist_[vid].edge_id.begin(),
reverse_adjlist_[vid].edge_id.end());
}

/*!
Expand Down Expand Up @@ -381,7 +388,10 @@ class Graph: public GraphInterface {

protected:
friend class GraphOp;
/*! \brief Internal edge list type */
/*!
* \brief Internal edge list type
* \note The edges are sorted by `succ`.
*/
struct EdgeList {
/*! \brief successor vertex list */
std::vector<dgl_id_t> succ;
Expand All @@ -404,12 +414,32 @@ class Graph: public GraphInterface {
bool read_only_ = false;
/*!
* \brief Whether if this is a multigraph.
*
* When a multiedge is added, this flag switches to true.
*/
bool is_multigraph_ = false;
/*! \brief number of edges */
uint64_t num_edges_ = 0;

private:
std::vector<size_t> src_count_buffer_;
std::vector<size_t> dst_count_buffer_;
std::vector<size_t> offset_buffer_;
std::vector<dgl_id_t> eid_buffer_;
std::vector<dgl_id_t> eid_buffer2_;

/*!
* \brief helper function to insert dst and eid into sorted succ list
*/
void InsertEdgeId_(EdgeList* el, dgl_id_t dst, dgl_id_t eid);
bool CheckDuplicates_(const EdgeList& el, const dgl_id_t* dst, bool broadcast,
const std::vector<dgl_id_t>& eid, size_t begin, size_t end) const;
void MergeSorted_(EdgeList* el, const dgl_id_t* dst, bool broadcast,
const std::vector<dgl_id_t>& eid, int64_t begin, int64_t end);
bool InsertEdges_(AdjacencyList* adjlist, const dgl_id_t* lo, const dgl_id_t* hi,
bool lo_broadcast, bool hi_broadcast,
size_t len, const std::vector<dgl_id_t>& lo_count_buffer,
const std::vector<dgl_id_t>& hi_count_buffer, bool check_duplicates);
void EdgeIdRange_(dgl_id_t src, dgl_id_t dst, size_t* begin, size_t* end,
bool* reverse) const;
};

} // namespace dgl
Expand Down
19 changes: 8 additions & 11 deletions include/dgl/graph_interface.h
Expand Up @@ -23,16 +23,13 @@ struct Subgraph;
struct SampledSubgraph;

/*!
* \brief This class references data in std::vector.
*
* This isn't a STL-style iterator. It provides a STL data container interface.
* but it doesn't own data itself. instead, it only references data in std::vector.
* \brief This class references a slice in std::vector
*/
class DGLIdIters {
class DGLIdVectorSlice {
std::vector<dgl_id_t>::const_iterator begin_, end_;
public:
DGLIdIters(std::vector<dgl_id_t>::const_iterator begin,
std::vector<dgl_id_t>::const_iterator end) {
DGLIdVectorSlice(std::vector<dgl_id_t>::const_iterator begin,
std::vector<dgl_id_t>::const_iterator end) {
this->begin_ = begin;
this->end_ = end;
}
Expand Down Expand Up @@ -293,28 +290,28 @@ class GraphInterface {
* \param vid The vertex id.
* \return the successor vector iterator pair.
*/
virtual DGLIdIters SuccVec(dgl_id_t vid) const = 0;
virtual DGLIdVectorSlice SuccVec(dgl_id_t vid) const = 0;

/*!
* \brief Return the out edge id vector
* \param vid The vertex id.
* \return the out edge id vector iterator pair.
*/
virtual DGLIdIters OutEdgeVec(dgl_id_t vid) const = 0;
virtual DGLIdVectorSlice OutEdgeVec(dgl_id_t vid) const = 0;

/*!
* \brief Return the predecessor vector
* \param vid The vertex id.
* \return the predecessor vector iterator pair.
*/
virtual DGLIdIters PredVec(dgl_id_t vid) const = 0;
virtual DGLIdVectorSlice PredVec(dgl_id_t vid) const = 0;

/*!
* \brief Return the in edge id vector
* \param vid The vertex id.
* \return the in edge id vector iterator pair.
*/
virtual DGLIdIters InEdgeVec(dgl_id_t vid) const = 0;
virtual DGLIdVectorSlice InEdgeVec(dgl_id_t vid) const = 0;

/*!
* \brief Reset the data in the graph and move its data to the returned graph object.
Expand Down
36 changes: 18 additions & 18 deletions include/dgl/immutable_graph.h
Expand Up @@ -56,17 +56,17 @@ class ImmutableGraph: public GraphInterface {
return indices.size();
}

int64_t GetDegree(dgl_id_t vid) const {
uint64_t GetDegree(dgl_id_t vid) const {
return indptr[vid + 1] - indptr[vid];
}
DegreeArray GetDegrees(IdArray vids) const;
EdgeArray GetEdges(dgl_id_t vid) const;
EdgeArray GetEdges(IdArray vids) const;
/* \brief this returns the start and end position of the column indices corresponding v. */
DGLIdIters GetIndexRef(dgl_id_t v) const {
DGLIdVectorSlice GetIndexRef(dgl_id_t v) const {
const int64_t start = indptr[v];
const int64_t end = indptr[v + 1];
return DGLIdIters(indices.begin() + start, indices.begin() + end);
return DGLIdVectorSlice(indices.begin() + start, indices.begin() + end);
}
/*
* Read all edges and store them in the vector.
Expand All @@ -81,7 +81,7 @@ class ImmutableGraph: public GraphInterface {
* we simply sort on the input edge list. We allow sorting on both end points of an edge,
* which is specified by `sort_on`.
*/
static CSR::Ptr FromEdges(std::vector<Edge> *edges, int sort_on, int64_t num_nodes);
static CSR::Ptr FromEdges(std::vector<Edge> *edges, int sort_on, uint64_t num_nodes);
};

/*! \brief Construct an immutable graph from the COO format. */
Expand Down Expand Up @@ -411,39 +411,39 @@ class ImmutableGraph: public GraphInterface {
* \param vid The vertex id.
* \return the successor vector
*/
DGLIdIters SuccVec(dgl_id_t vid) const {
return DGLIdIters(out_csr_->indices.begin() + out_csr_->indptr[vid],
out_csr_->indices.begin() + out_csr_->indptr[vid + 1]);
DGLIdVectorSlice SuccVec(dgl_id_t vid) const {
return DGLIdVectorSlice(out_csr_->indices.begin() + out_csr_->indptr[vid],
out_csr_->indices.begin() + out_csr_->indptr[vid + 1]);
}

/*!
* \brief Return the out edge id vector
* \param vid The vertex id.
* \return the out edge id vector
*/
DGLIdIters OutEdgeVec(dgl_id_t vid) const {
return DGLIdIters(out_csr_->edge_ids.begin() + out_csr_->indptr[vid],
out_csr_->edge_ids.begin() + out_csr_->indptr[vid + 1]);
DGLIdVectorSlice OutEdgeVec(dgl_id_t vid) const {
return DGLIdVectorSlice(out_csr_->edge_ids.begin() + out_csr_->indptr[vid],
out_csr_->edge_ids.begin() + out_csr_->indptr[vid + 1]);
}

/*!
* \brief Return the predecessor vector
* \param vid The vertex id.
* \return the predecessor vector
*/
DGLIdIters PredVec(dgl_id_t vid) const {
return DGLIdIters(in_csr_->indices.begin() + in_csr_->indptr[vid],
in_csr_->indices.begin() + in_csr_->indptr[vid + 1]);
DGLIdVectorSlice PredVec(dgl_id_t vid) const {
return DGLIdVectorSlice(in_csr_->indices.begin() + in_csr_->indptr[vid],
in_csr_->indices.begin() + in_csr_->indptr[vid + 1]);
}

/*!
* \brief Return the in edge id vector
* \param vid The vertex id.
* \return the in edge id vector
*/
DGLIdIters InEdgeVec(dgl_id_t vid) const {
return DGLIdIters(in_csr_->edge_ids.begin() + in_csr_->indptr[vid],
in_csr_->edge_ids.begin() + in_csr_->indptr[vid + 1]);
DGLIdVectorSlice InEdgeVec(dgl_id_t vid) const {
return DGLIdVectorSlice(in_csr_->edge_ids.begin() + in_csr_->indptr[vid],
in_csr_->edge_ids.begin() + in_csr_->indptr[vid + 1]);
}

/*!
Expand Down Expand Up @@ -476,8 +476,8 @@ class ImmutableGraph: public GraphInterface {
virtual std::vector<IdArray> GetAdj(bool transpose, const std::string &fmt) const;

protected:
DGLIdIters GetInEdgeIdRef(dgl_id_t src, dgl_id_t dst) const;
DGLIdIters GetOutEdgeIdRef(dgl_id_t src, dgl_id_t dst) const;
DGLIdVectorSlice GetInEdgeIdRef(dgl_id_t src, dgl_id_t dst) const;
DGLIdVectorSlice GetOutEdgeIdRef(dgl_id_t src, dgl_id_t dst) const;

/*
* The immutable graph may only contain one of the CSRs (e.g., the sampled subgraphs).
Expand Down
2 changes: 1 addition & 1 deletion src/c_api_common.cc
Expand Up @@ -24,7 +24,7 @@ DLManagedTensor* CreateTmpDLManagedTensor(const DGLArgValue& arg) {

PackedFunc ConvertNDArrayVectorToPackedFunc(const std::vector<NDArray>& vec) {
auto body = [vec](DGLArgs args, DGLRetValue* rv) {
const int which = args[0];
const size_t which = args[0];
if (which >= vec.size()) {
LOG(FATAL) << "invalid choice";
} else {
Expand Down
5 changes: 5 additions & 0 deletions src/c_api_common.h
Expand Up @@ -52,6 +52,11 @@ dgl::runtime::NDArray CopyVectorToNDArray(
return a;
}

template<class T>
inline void grow(std::vector<T>& v, size_t len) {
v.resize(v.size() + len);
}

} // namespace dgl

#endif // DGL_C_API_COMMON_H_