def test_scipy_api_compat(): graph_file = utils.DATASETS[0] input_cugraph_graph = utils.create_obj_from_csv(graph_file, cugraph.Graph, edgevals=True) input_coo_matrix = utils.create_obj_from_csv(graph_file, cp_coo_matrix, edgevals=True) # Ensure scipy-only options are rejected for cugraph inputs with pytest.raises(TypeError): cugraph.bfs(input_cugraph_graph, start=0, directed=False) with pytest.raises(TypeError): cugraph.bfs(input_cugraph_graph) # required arg missing # Ensure cugraph-compatible options work as expected cugraph.bfs(input_cugraph_graph, i_start=0) cugraph.bfs(input_cugraph_graph, i_start=0, return_sp_counter=True) # cannot have start and i_start with pytest.raises(TypeError): cugraph.bfs(input_cugraph_graph, start=0, i_start=0) # Ensure SciPy options for matrix inputs work as expected cugraph.bfs(input_coo_matrix, i_start=0) cugraph.bfs(input_coo_matrix, i_start=0, directed=True) cugraph.bfs(input_coo_matrix, i_start=0, directed=False) result = cugraph.bfs(input_coo_matrix, i_start=0, return_sp_counter=True) assert type(result) is tuple assert len(result) == 3
def test_bfs_spc_full(gpubenchmark, dataset_nxresults_allstartvertices_spc, cugraph_input_type): """ Test BFS traversal on every vertex with shortest path counting """ (dataset, directed, all_nx_values, start_vertices, use_spc) = \ dataset_nxresults_allstartvertices_spc # use_spc is currently always True # special case: ensure cugraph and Nx Graph types are DiGraphs if # "directed" is set, since the graph type parameterization is currently # independent of the directed parameter. Unfortunately this does not # change the "id" in the pytest output. if directed: if cugraph_input_type is cugraph.Graph: cugraph_input_type = cugraph.DiGraph elif cugraph_input_type is nx.Graph: cugraph_input_type = nx.DiGraph G_or_matrix = utils.create_obj_from_csv(dataset, cugraph_input_type) compare_bfs(gpubenchmark, G_or_matrix, all_nx_values, start_vertex=start_vertices, return_sp_counter=use_spc)
def test_bfs(gpubenchmark, dataset_nxresults_startvertex_spc, cugraph_input_type): """ Test BFS traversal on random source with distance and predecessors """ (dataset, directed, nx_values, start_vertex, use_spc) = \ dataset_nxresults_startvertex_spc # special case: ensure cugraph and Nx Graph types are DiGraphs if # "directed" is set, since the graph type parameterization is currently # independent of the directed parameter. Unfortunately this does not # change the "id" in the pytest output. if directed: if cugraph_input_type is cugraph.Graph: cugraph_input_type = cugraph.DiGraph elif cugraph_input_type is nx.Graph: cugraph_input_type = nx.DiGraph G_or_matrix = utils.create_obj_from_csv(dataset, cugraph_input_type) compare_bfs(gpubenchmark, G_or_matrix, nx_values, start_vertex, return_sp_counter=use_spc)
def test_sssp_edgevals(gpubenchmark, dataset_source_nxresults_weighted, cugraph_input_type): # Extract the params generated from the fixture (graph_file, source, nx_paths, Gnx) = dataset_source_nxresults_weighted input_G_or_matrix = utils.create_obj_from_csv(graph_file, cugraph_input_type, edgevals=True) cu_paths, max_val = cugraph_call(gpubenchmark, input_G_or_matrix, source, edgevals=True) # Calculating mismatch err = 0 for vid in cu_paths: # Validate vertices that are reachable # NOTE : If distance type is float64 then cu_paths[vid][0] # should be compared against np.finfo(np.float64).max) if cu_paths[vid][0] != max_val: if cu_paths[vid][0] != nx_paths[vid]: err = err + 1 # check pred dist + edge_weight = current dist if vid != source: pred = cu_paths[vid][1] edge_weight = Gnx[pred][vid]["weight"] if cu_paths[pred][0] + edge_weight != cu_paths[vid][0]: err = err + 1 else: if vid in nx_paths.keys(): err = err + 1 assert err == 0
def test_scipy_api_compat(connection_type): if connection_type == "strong": graph_file = utils.STRONGDATASETS[0] else: graph_file = utils.DATASETS[0] input_cugraph_graph = utils.create_obj_from_csv(graph_file, cugraph.Graph, edgevals=True) input_coo_matrix = utils.create_obj_from_csv(graph_file, cp_coo_matrix, edgevals=True) # connection is the only API that is accepted with cugraph objs retval = cugraph.connected_components(input_cugraph_graph, connection=connection_type) assert type(retval) is cudf.DataFrame # Ensure scipy-only options (except connection) are rejected for cugraph # inputs with pytest.raises(TypeError): cugraph.connected_components(input_cugraph_graph, directed=True) with pytest.raises(TypeError): cugraph.connected_components(input_cugraph_graph, return_labels=False) with pytest.raises(TypeError): cugraph.connected_components(input_cugraph_graph, connection=connection_type, return_labels=False) # only accept weak or strong with pytest.raises(ValueError): cugraph.connected_components(input_cugraph_graph, connection="invalid") (n_components, labels) = cugraph.connected_components(input_coo_matrix, connection=connection_type) # FIXME: connection should default to "weak", need to test that (n_components, labels) = cugraph.connected_components(input_coo_matrix, directed=False) n_components = cugraph.connected_components(input_coo_matrix, return_labels=False) assert type(n_components) is int
def test_strong_cc(gpubenchmark, dataset_nxresults_strong, cugraph_input_type): # NetX returns a list of components, each component being a # collection (set{}) of vertex indices (graph_file, netx_labels, nx_n_components, lst_nx_components, api_type) = dataset_nxresults_strong input_G_or_matrix = utils.create_obj_from_csv(graph_file, cugraph_input_type, edgevals=True) cugraph_labels = cugraph_call(gpubenchmark, cugraph.strongly_connected_components, input_G_or_matrix) assert isinstance(input_G_or_matrix, cugraph_input_type) # while cugraph returns a component label for each vertex; cg_n_components = len(cugraph_labels) # Comapre number of components found assert nx_n_components == cg_n_components lst_nx_components_lens = [len(c) for c in lst_nx_components] cugraph_vertex_lst = cugraph_labels.values() lst_cg_components = sorted(cugraph_vertex_lst, key=len, reverse=True) lst_cg_components_lens = [len(c) for c in lst_cg_components] # Compare lengths of each component assert lst_nx_components_lens == lst_cg_components_lens # Compare vertices of largest component # note that there might be more than one largest component nx_vertices = sorted(lst_nx_components[0]) first_vert = nx_vertices[0] idx = which_cluster_idx(lst_cg_components, first_vert) assert idx != -1, "Check for Nx vertex in cuGraph results failed" cg_vertices = sorted(lst_cg_components[idx]) assert nx_vertices == cg_vertices
def test_weak_cc(gpubenchmark, dataset_nxresults_weak, cugraph_input_type): (graph_file, netx_labels, nx_n_components, lst_nx_components, api_type) = dataset_nxresults_weak input_G_or_matrix = utils.create_obj_from_csv(graph_file, cugraph_input_type, edgevals=True) cugraph_labels = cugraph_call(gpubenchmark, cugraph.weakly_connected_components, input_G_or_matrix) # while cugraph returns a component label for each vertex; cg_n_components = len(cugraph_labels) # Comapre number of components assert nx_n_components == cg_n_components lst_nx_components_lens = [len(c) for c in lst_nx_components] cugraph_vertex_lst = cugraph_labels.values() lst_cg_components = sorted(cugraph_vertex_lst, key=len, reverse=True) lst_cg_components_lens = [len(c) for c in lst_cg_components] # Compare lengths of each component assert lst_nx_components_lens == lst_cg_components_lens # Compare vertices of largest component nx_vertices = sorted(lst_nx_components[0]) first_vert = nx_vertices[0] idx = which_cluster_idx(lst_cg_components, first_vert) assert idx != -1, "Check for Nx vertex in cuGraph results failed" cg_vertices = sorted(lst_cg_components[idx]) assert nx_vertices == cg_vertices
def test_scipy_api_compat(): graph_file = utils.DATASETS[0] input_cugraph_graph = utils.create_obj_from_csv(graph_file, cugraph.Graph, edgevals=True) input_coo_matrix = utils.create_obj_from_csv(graph_file, cp_coo_matrix, edgevals=True) # Ensure scipy-only options are rejected for cugraph inputs with pytest.raises(TypeError): cugraph.shortest_path(input_cugraph_graph, source=0, directed=False) with pytest.raises(TypeError): cugraph.shortest_path(input_cugraph_graph, source=0, unweighted=False) with pytest.raises(TypeError): cugraph.shortest_path(input_cugraph_graph, source=0, overwrite=False) with pytest.raises(TypeError): cugraph.shortest_path(input_cugraph_graph, source=0, return_predecessors=False) # Ensure cugraph-compatible options work as expected # cannot set both source and indices, but must set one with pytest.raises(TypeError): cugraph.shortest_path(input_cugraph_graph, source=0, indices=0) with pytest.raises(TypeError): cugraph.shortest_path(input_cugraph_graph) with pytest.raises(ValueError): cugraph.shortest_path(input_cugraph_graph, source=0, method="BF") cugraph.shortest_path(input_cugraph_graph, indices=0) with pytest.raises(ValueError): cugraph.shortest_path(input_cugraph_graph, indices=[0, 1, 2]) cugraph.shortest_path(input_cugraph_graph, source=0, method="auto") # Ensure SciPy options for matrix inputs work as expected # cannot set both source and indices, but must set one with pytest.raises(TypeError): cugraph.shortest_path(input_coo_matrix, source=0, indices=0) with pytest.raises(TypeError): cugraph.shortest_path(input_coo_matrix) with pytest.raises(ValueError): cugraph.shortest_path(input_coo_matrix, source=0, method="BF") cugraph.shortest_path(input_coo_matrix, source=0, method="auto") with pytest.raises(ValueError): cugraph.shortest_path(input_coo_matrix, source=0, directed=3) cugraph.shortest_path(input_coo_matrix, source=0, directed=True) cugraph.shortest_path(input_coo_matrix, source=0, directed=False) with pytest.raises(ValueError): cugraph.shortest_path(input_coo_matrix, source=0, return_predecessors=3) (distances, preds) = cugraph.shortest_path(input_coo_matrix, source=0, return_predecessors=True) distances = cugraph.shortest_path(input_coo_matrix, source=0, return_predecessors=False) assert type(distances) != tuple with pytest.raises(ValueError): cugraph.shortest_path(input_coo_matrix, source=0, unweighted=False) cugraph.shortest_path(input_coo_matrix, source=0, unweighted=True) with pytest.raises(ValueError): cugraph.shortest_path(input_coo_matrix, source=0, overwrite=True) cugraph.shortest_path(input_coo_matrix, source=0, overwrite=False) with pytest.raises(ValueError): cugraph.shortest_path(input_coo_matrix, indices=[0, 1, 2]) cugraph.shortest_path(input_coo_matrix, indices=0)
def assert_scipy_api_compat(graph_file, api_type): """ Ensure cugraph.scc() and cugraph.connected_components() can be used as drop-in replacements for scipy.connected_components(): scipy.sparse.csgraph.connected_components(csgraph, directed=True, connection='weak', return_labels=True) Parameters ---------- csgraph : array_like or sparse matrix The N x N matrix representing the compressed sparse graph. The input csgraph will be converted to csr format for the calculation. directed : bool, optional If True (default), then operate on a directed graph: only move from point i to point j along paths csgraph[i, j]. If False, then find the shortest path on an undirected graph: the algorithm can progress from point i to j along csgraph[i, j] or csgraph[j, i]. connection : str, optional [‘weak’|’strong’]. For directed graphs, the type of connection to use. Nodes i and j are strongly connected if a path exists both from i to j and from j to i. A directed graph is weakly connected if replacing all of its directed edges with undirected edges produces a connected (undirected) graph. If directed == False, this keyword is not referenced. return_labels : bool, optional If True (default), then return the labels for each of the connected components. Returns ------- n_components : int The number of connected components. labels : ndarray The length-N array of labels of the connected components. """ api_call = {"strong": cugraph.strongly_connected_components, "weak": cugraph.weakly_connected_components}[api_type] connection = api_type wrong_connection = {"strong": "weak", "weak": "strong"}[api_type] input_cugraph_graph = utils.create_obj_from_csv(graph_file, cugraph.Graph, edgevals=True) input_coo_matrix = utils.create_obj_from_csv(graph_file, cp_coo_matrix, edgevals=True) # Ensure scipy-only options are rejected for cugraph inputs with pytest.raises(TypeError): api_call(input_cugraph_graph, directed=False) with pytest.raises(TypeError): api_call(input_cugraph_graph, return_labels=False) # Setting connection to strong for strongly_* and weak for weakly_* is # redundant, but valid api_call(input_cugraph_graph, connection=connection) # Invalid for the API with pytest.raises(TypeError): (n_components, labels) = api_call(input_coo_matrix, connection=wrong_connection) (n_components, labels) = api_call(input_coo_matrix, directed=False) (n_components, labels) = api_call(input_coo_matrix, connection=connection) n_components = api_call(input_coo_matrix, return_labels=False) assert type(n_components) is int