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

BFS imported and python bindings added. #47

Merged
merged 8 commits into from
Feb 4, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -182,6 +182,7 @@ endif (NVGRAPH_INCLUDE AND NVGRAPH_LIBRARY)
include_directories(
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/src"
"${CMAKE_CURRENT_SOURCE_DIR}/external/cub"
"${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}"
"${CUDF_INCLUDE}"
"${NVGRAPH_INCLUDE}"
@@ -204,6 +205,7 @@ add_library(cugraph SHARED
src/grmat.cu
src/cugraph.cu
src/pagerank.cu
src/bfs.cu
src/nvgraph_gdf.cu
${CMAKE_CURRENT_BINARY_DIR}/gunrock/gunrock/util/test_utils.cu
${CMAKE_CURRENT_BINARY_DIR}/gunrock/gunrock/util/error_utils.cu
2 changes: 2 additions & 0 deletions include/functions.h
Original file line number Diff line number Diff line change
@@ -60,3 +60,5 @@ gdf_error gdf_delete_transpose(gdf_graph *graph);
gdf_error gdf_pagerank(gdf_graph *graph, gdf_column *pagerank, float alpha, float tolerance, int max_iter, bool has_guess);

gdf_error gdf_grmat_gen (const char* argv, size_t &vertices, size_t &edges, gdf_column* src, gdf_column* dest, gdf_column* val);

gdf_error gdf_bfs(gdf_graph *graph, gdf_column *distances, gdf_column *predecessors, int start_node, bool directed);
59 changes: 59 additions & 0 deletions python/bfs/bfs_wrapper.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from c_bfs cimport *
from libcpp cimport bool
from libc.stdint cimport uintptr_t
from libc.stdlib cimport calloc, malloc, free
import cudf
from librmm_cffi import librmm as rmm
#from pygdf import Column
import numpy as np

cpdef bfs(G, start, directed=True):
"""
Find the distances and predecessors for a breadth first traversal of a graph.

Parameters
----------
G : cugraph.graph
cuGraph graph descriptor, should contain the connectivity information as an
adjacency list.
start : Integer
The index of the graph vertex from which the traversal begins
directed : bool
Indicates whether the graph in question is a directed graph, or whether
each edge has a corresponding reverse edge. (Allows optimizations if the
graph is undirected)

Returns
-------
df : cudf.DataFrame
df['vertex'][i] gives the vertex id of the i'th vertex
df['distance'][i] gives the path distance for the i'th vertex from the starting vertex
df['predecessor'][i] gives for the i'th vertex the vertex it was reached from in the traversal

Examples
--------
>>> M = ReadMtxFile(graph_file)
>>> sources = cudf.Series(M.row)
>>> destinations = cudf.Series(M.col)
>>> G = cuGraph.Graph()
>>> G.add_edge_list(sources,destinations,none)
>>> dist, pred = cuGraph.bfs(G, 0, false)
"""

cdef uintptr_t graph = G.graph_ptr
cdef gdf_graph* g = <gdf_graph*>graph
num_verts = g.adjList.offsets.size - 1

df = cudf.DataFrame()
df['vertex'] = cudf.Series(np.zeros(num_verts, dtype=np.int32))
cdef uintptr_t vertex_ptr = create_column(df['vertex'])
df['distance'] = cudf.Series(np.zeros(num_verts, dtype=np.int32))
cdef uintptr_t distances_ptr = create_column(df['distance'])
df['predecessor'] = cudf.Series(np.zeros(num_verts, dtype=np.int32))
cdef uintptr_t predecessors_ptr = create_column(df['predecessor'])

err = g.adjList.get_vertex_identifiers(<gdf_column*>vertex_ptr)
cudf.bindings.cudf_cpp.check_gdf_error(err)

gdf_bfs(<gdf_graph*>g, <gdf_column*>distances_ptr, <gdf_column*>predecessors_ptr, <int>start, <bool>directed)
return df
6 changes: 6 additions & 0 deletions python/bfs/c_bfs.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from c_graph cimport *
from libcpp cimport bool

cdef extern from "cugraph.h":

cdef gdf_error gdf_bfs(gdf_graph *graph, gdf_column *distances, gdf_column *predecessors, int start_node, bool directed)
69 changes: 69 additions & 0 deletions python/bfs/test_bfs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import cugraph
import cudf
import time
from scipy.io import mmread
import pytest
import numpy as np

def ReadMtxFile(mmFile):
print('Reading ' + str(mmFile) + '...')
return mmread(mmFile).asfptype()


def cugraph_Call(M, start_vertex):

# Device data
M = M.tocsr()
sources = cudf.Series(M.indptr)
destinations = cudf.Series(M.indices)
values = cudf.Series(M.data)

G = cugraph.Graph()
G.add_adj_list(sources, destinations, values)

t1 = time.time()
df = cugraph.bfs(G, start_vertex)
t2 = time.time() - t1
print('Time : '+str(t2))

# Return distances as np.array()
return np.array(df['distance'])


def base_Call(M, start_vertex):
intMax = 2147483647
M = M.tocsr()
offsets = M.indptr
indices = M.indices
num_verts = len(offsets) - 1
dist = np.zeros(num_verts, dtype=np.int32)

for i in range(num_verts):
dist[i] = intMax
import queue
q = queue.Queue()
q.put(start_vertex)
dist[start_vertex] = 0
while(not q.empty()):
u = q.get()
for iCol in range(offsets[u],offsets[u + 1]):
v = indices[iCol]
if (dist[v] == intMax):
dist[v] = dist[u] + 1
q.put(v)
return dist

datasets = ['/datasets/networks/dolphins.mtx',
'/datasets/networks/karate.mtx',
'/datasets/golden_data/graphs/dblp.mtx']

@pytest.mark.parametrize('graph_file', datasets)
def test_bfs(graph_file):

M = ReadMtxFile(graph_file)
base_dist = base_Call(M, 0)
dist = cugraph_Call(M, 0)

assert len(base_dist) == len(dist)
for i in range(len(dist)):
assert base_dist[i] == dist[i]
1 change: 1 addition & 0 deletions python/cugraph.pyx
Original file line number Diff line number Diff line change
@@ -5,3 +5,4 @@ include "sssp/sssp_wrapper.pyx"
include "jaccard/jaccard_wrapper.pyx"
include "grmat/grmat_wrapper.pyx"
include "louvain/louvain_wrapper.pyx"
include "bfs/bfs_wrapper.pyx"
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -73,7 +73,6 @@ def locate_nvgraph():

# temporary fix. cudf 0.5 will have a cudf.get_include()
cudf_include = os.path.normpath(sys.prefix) + '/include'

cython_files = ['python/cugraph.pyx']

extensions = [
Loading