Unverified Commit f41934df authored by czkkkkkk's avatar czkkkkkk Committed by GitHub
Browse files

[Sparse] Add conversion between DGLGraph and SparseMatrix. (#5553)

parent e6226e82
......@@ -15,12 +15,10 @@ from .. import utils
@utils.parametrize("scipy_format", ["coo", "csr"])
def track_time(size, scipy_format):
matrix_dict = {
"small": dgl.data.CiteseerGraphDataset(verbose=False)[
0
].adjacency_matrix(scipy_fmt=scipy_format),
"large": utils.get_livejournal().adjacency_matrix(
"small": dgl.data.CiteseerGraphDataset(verbose=False)[0].adj_external(
scipy_fmt=scipy_format
),
"large": utils.get_livejournal().adj_external(scipy_fmt=scipy_format),
}
# dry run
......
......@@ -144,8 +144,9 @@ Methods for getting the adjacency and the incidence matrix of the graph.
:toctree: ../../generated/
DGLGraph.adj
DGLGraph.adj_sparse
DGLGraph.adjacency_matrix
DGLGraph.adj_tensors
DGLGraph.adj_external
DGLGraph.inc
DGLGraph.incidence_matrix
......
......@@ -19,7 +19,7 @@ def split_data(hg, etype_name):
pos_label = [1] * num_link
pos_data = list(zip(user_item_src, user_item_dst, pos_label))
ui_adj = np.array(hg.adj(etype=etype_name).to_dense())
ui_adj = np.array(hg.adj_external(etype=etype_name).to_dense())
full_idx = np.where(ui_adj == 0)
sample = random.sample(range(0, len(full_idx[0])), num_link)
......
......@@ -141,7 +141,7 @@ class DiffPoolBatchedGraphLayer(nn.Module):
) # size = (sum_N, batch_size * N_a)
h = torch.matmul(torch.t(assign_tensor), feat)
adj = g.adjacency_matrix(transpose=True, ctx=device)
adj = g.adj_external(transpose=True, ctx=device)
adj_new = torch.sparse.mm(adj, assign_tensor)
adj_new = torch.mm(torch.t(assign_tensor), adj_new)
......
......@@ -71,7 +71,7 @@ class DiffConv(nn.Module):
@staticmethod
def get_weight_matrix(g):
adj = g.adj(scipy_fmt="coo")
adj = g.adj_external(scipy_fmt="coo")
ind = g.in_degrees()
outd = g.out_degrees()
weight = g.edata["weight"]
......@@ -81,7 +81,7 @@ class DiffConv(nn.Module):
@staticmethod
def diffuse(progress_g, weighted_adj, degree):
device = progress_g.device
progress_adj = progress_g.adj(scipy_fmt="coo")
progress_adj = progress_g.adj_external(scipy_fmt="coo")
progress_adj.data = progress_g.edata["weight"].cpu().numpy()
ret_adj = sparse.coo_matrix(
progress_adj @ (weighted_adj / degree.cpu().numpy())
......
......@@ -85,7 +85,7 @@ class SEALOGBLDataset(Dataset):
NIDs, EIDs = subg.ndata[dgl.NID], subg.edata[dgl.EID]
z = drnl_node_labeling(subg.adj(scipy_fmt="csr"), 0, 1)
z = drnl_node_labeling(subg.adj_external(scipy_fmt="csr"), 0, 1)
edge_weights = (
self.edge_weights[EIDs] if self.edge_weights is not None else None
)
......
......@@ -150,7 +150,7 @@ class SealSampler(Sampler):
subg.remove_edges(edges_to_remove)
# add double radius node labeling
subg.ndata["z"] = self._double_radius_node_labeling(
subg.adj(scipy_fmt="csr")
subg.adj_external(scipy_fmt="csr")
)
subg_aug = subg.add_self_loop()
if "weight" in subg.edata:
......
......@@ -72,7 +72,7 @@ def drnl_node_labeling(subgraph, src, dst):
Returns:
z(Tensor): node labeling tensor
"""
adj = subgraph.adj().to_dense().numpy()
adj = subgraph.adj_external().to_dense().numpy()
src, dst = (dst, src) if src > dst else (src, dst)
idx = list(range(src)) + list(range(src + 1, adj.shape[0]))
......
......@@ -125,7 +125,7 @@ def dgl_main():
in_dim = feats.shape[-1]
# generate input
adj_orig = graph.adjacency_matrix().to_dense()
adj_orig = graph.adj_external().to_dense()
# build test set with 10% positive links
(
......@@ -142,7 +142,7 @@ def dgl_main():
train_edge_idx = torch.tensor(train_edge_idx).to(device)
train_graph = dgl.edge_subgraph(graph, train_edge_idx, relabel_nodes=False)
train_graph = train_graph.to(device)
adj = train_graph.adjacency_matrix().to_dense().to(device)
adj = train_graph.adj_external().to_dense().to(device)
# compute loss parameters
weight_tensor, norm = compute_loss_para(adj)
......
......@@ -3754,14 +3754,90 @@ class DGLGraph(object):
else:
return deg
def adjacency_matrix(
self, transpose=False, ctx=F.cpu(), scipy_fmt=None, etype=None
):
def adjacency_matrix(self, etype=None):
"""Alias of :meth:`adj`"""
return self.adj(transpose, ctx, scipy_fmt, etype)
return self.adj(etype)
def adj(self, etype=None, eweight_name=None):
"""Get the adjacency matrix of the graph.
Parameters
----------
etype : str or (str, str, str), optional
The type names of the edges. The allowed type name formats are:
* ``(str, str, str)`` for source node type, edge type and
destination node type.
* or one ``str`` edge type name if the name can uniquely identify a
triplet format in the graph.
Can be omitted if the graph has only one type of edges.
eweight_name : str, optional
The name of edge feature used as the non-zero values. If not given,
the non-zero values are all 1.
Returns
-------
SparseMatrix
The adjacency matrix.
Examples
--------
The following example uses PyTorch backend.
>>> import dgl
>>> import torch
>>> g = dgl.graph(([0, 1, 2], [1, 2, 3]))
>>> g.adj()
SparseMatrix(indices=tensor([[0, 1, 2],
[1, 2, 3]]),
values=tensor([1., 1., 1.]),
shape=(4, 4), nnz=3)
def adj(self, transpose=False, ctx=F.cpu(), scipy_fmt=None, etype=None):
"""Return the adjacency matrix of edges of the given edge type.
>>> g = dgl.heterograph({
... ('user', 'follows', 'user'): ([0, 1], [0, 1]),
... ('developer', 'develops', 'game'): ([0, 1], [0, 2])
... })
>>> g.adj(etype='develops')
SparseMatrix(indices=tensor([[0, 1],
[0, 2]]),
values=tensor([1., 1.]),
shape=(2, 3), nnz=2)
>>> g.edata['h'] = {('user', 'follows', 'user'): torch.tensor([3, 2])}
>>> g.adj(etype='follows', eweight_name='h')
SparseMatrix(indices=tensor([[0, 1],
[0, 1]]),
values=tensor([3, 2]),
shape=(2, 2), nnz=2)
"""
assert F.backend_name == "pytorch", "Only PyTorch backend supports adj."
# Temporal fix to introduce a dependency on torch
import torch
from .sparse import spmatrix
etype = self.to_canonical_etype(etype)
indices = torch.stack(self.all_edges(etype=etype))
shape = (self.num_nodes(etype[0]), self.number_of_nodes(etype[2]))
if eweight_name is not None:
val = self.edata[eweight_name][etype]
else:
val = None
return spmatrix(
indices,
val=val,
shape=shape,
)
def adj_external(
self, transpose=False, ctx=F.cpu(), scipy_fmt=None, etype=None
):
"""Return the adjacency matrix in an external format, such as Scipy or
backend dependent sparse tensor.
By default, a row of returned adjacency matrix represents the
source of an edge and the column represents the destination.
......@@ -3787,7 +3863,6 @@ class DGLGraph(object):
Can be omitted if the graph has only one type of edges.
Returns
-------
SparseTensor or scipy.sparse.spmatrix
......@@ -3810,7 +3885,7 @@ class DGLGraph(object):
Get a backend dependent sparse tensor. Here we use PyTorch for example.
>>> g.adj(etype='develops')
>>> g.adj_external(etype='develops')
tensor(indices=tensor([[0, 1],
[0, 2]]),
values=tensor([1., 1.]),
......@@ -3818,7 +3893,7 @@ class DGLGraph(object):
Get a scipy coo sparse matrix.
>>> g.adj(scipy_fmt='coo', etype='develops')
>>> g.adj_external(scipy_fmt='coo', etype='develops')
<2x3 sparse matrix of type '<class 'numpy.int64'>'
with 2 stored elements in COOrdinate format>
"""
......@@ -3830,44 +3905,37 @@ class DGLGraph(object):
etid, transpose, scipy_fmt, False
)
def adj_sparse(self, fmt, etype=None):
def adj_tensors(self, fmt, etype=None):
"""Return the adjacency matrix of edges of the given edge type as tensors of
a sparse matrix representation.
By default, a row of returned adjacency matrix represents the
source of an edge and the column represents the destination.
Parameters
----------
fmt : str
Either ``coo``, ``csr`` or ``csc``.
etype : str or (str, str, str), optional
The type names of the edges. The allowed type name formats are:
* ``(str, str, str)`` for source node type, edge type and destination node type.
* or one ``str`` edge type name if the name can uniquely identify a
triplet format in the graph.
Can be omitted if the graph has only one type of edges.
Returns
-------
tuple[Tensor]
If :attr:`fmt` is ``coo``, returns a pair of source and destination node ID
tensors.
If :attr:`fmt` is ``csr`` or ``csc``, return the CSR or CSC representation
of the adjacency matrix as a triplet of tensors
``(indptr, indices, edge_ids)``. Namely ``edge_ids`` could be an empty
tensor with 0 elements, in which case the edge IDs are consecutive
integers starting from 0.
Examples
--------
>>> g = dgl.graph(([0, 1, 2], [1, 2, 3]))
>>> g.adj_sparse('coo')
>>> g.adj_tensors('coo')
(tensor([0, 1, 2]), tensor([1, 2, 3]))
>>> g.adj_sparse('csr')
>>> g.adj_tensors('csr')
(tensor([0, 1, 2, 3, 3]), tensor([1, 2, 3]), tensor([0, 1, 2]))
"""
etid = self.get_etype_id(etype)
......
......@@ -163,7 +163,7 @@ class CuGraphGATConv(nn.Module):
:math:`H` is the number of heads, and :math:`D_{out}` is size of
output feature.
"""
offsets, indices, _ = g.adj_sparse("csc")
offsets, indices, _ = g.adj_tensors("csc")
if g.is_block:
if max_in_degree is None:
......
......@@ -177,7 +177,7 @@ class CuGraphRelGraphConv(nn.Module):
New node features. Shape: :math:`(|V|, D_{out})`.
"""
# Create csc-representation and cast etypes to int32.
offsets, indices, edge_ids = g.adj_sparse("csc")
offsets, indices, edge_ids = g.adj_tensors("csc")
edge_types_perm = etypes[edge_ids.long()].int()
# Create cugraph-ops graph.
......
......@@ -119,7 +119,7 @@ class CuGraphSAGEConv(nn.Module):
torch.Tensor
Output node features. Shape: :math:`(N, D_{out})`.
"""
offsets, indices, _ = g.adj_sparse("csc")
offsets, indices, _ = g.adj_tensors("csc")
if g.is_block:
if max_in_degree is None:
......
......@@ -1165,7 +1165,9 @@ def khop_adj(g, k):
[0., 1., 3., 3., 1.]])
"""
assert g.is_homogeneous, "only homogeneous graph is supported"
adj_k = g.adj(transpose=True, scipy_fmt=g.formats()["created"][0]) ** k
adj_k = (
g.adj_external(transpose=True, scipy_fmt=g.formats()["created"][0]) ** k
)
return F.tensor(adj_k.todense().astype(np.float32))
......@@ -1235,7 +1237,10 @@ def khop_graph(g, k, copy_ndata=True):
"""
assert g.is_homogeneous, "only homogeneous graph is supported"
n = g.num_nodes()
adj_k = g.adj(transpose=False, scipy_fmt=g.formats()["created"][0]) ** k
adj_k = (
g.adj_external(transpose=False, scipy_fmt=g.formats()["created"][0])
** k
)
adj_k = adj_k.tocoo()
multiplicity = adj_k.data
row = np.repeat(adj_k.row, multiplicity)
......@@ -1447,7 +1452,7 @@ def laplacian_lambda_max(g):
rst = []
for g_i in g_arr:
n = g_i.num_nodes()
adj = g_i.adj(
adj = g_i.adj_external(
transpose=True, scipy_fmt=g_i.formats()["created"][0]
).astype(float)
norm = sparse.diags(
......@@ -1511,7 +1516,9 @@ def metapath_reachable_graph(g, metapath):
"""
adj = 1
for etype in metapath:
adj = adj * g.adj(etype=etype, scipy_fmt="csr", transpose=False)
adj = adj * g.adj_external(
etype=etype, scipy_fmt="csr", transpose=False
)
adj = (adj != 0).tocsr()
srctype = g.to_canonical_etype(metapath[0])[0]
......@@ -2883,12 +2890,12 @@ def sort_csr_by_tag(g, tag, tag_offset_name="_TAG_OFFSET", tag_type="node"):
>>> import torch
>>> g = dgl.graph(([0,0,0,0,0,1,1,1],[0,1,2,3,4,0,1,2]))
>>> g.adjacency_matrix(scipy_fmt='csr').nonzero()
>>> g.adj_external(scipy_fmt='csr').nonzero()
(array([0, 0, 0, 0, 0, 1, 1, 1], dtype=int32),
array([0, 1, 2, 3, 4, 0, 1, 2], dtype=int32))
>>> tag = torch.IntTensor([1,1,0,2,0])
>>> g_sorted = dgl.sort_csr_by_tag(g, tag)
>>> g_sorted.adjacency_matrix(scipy_fmt='csr').nonzero()
>>> g_sorted.adj_external(scipy_fmt='csr').nonzero()
(array([0, 0, 0, 0, 0, 1, 1, 1], dtype=int32),
array([2, 4, 0, 1, 3, 2, 0, 1], dtype=int32))
>>> g_sorted.ndata['_TAG_OFFSET']
......@@ -2905,7 +2912,7 @@ def sort_csr_by_tag(g, tag, tag_offset_name="_TAG_OFFSET", tag_type="node"):
(tensor([0, 0, 0, 0, 0, 1, 1, 1]), tensor([0, 1, 2, 3, 4, 0, 1, 2]))
>>> tag = torch.tensor([1, 1, 0, 2, 0, 1, 1, 0])
>>> g_sorted = dgl.sort_csr_by_tag(g, tag, tag_type='edge')
>>> g_sorted.adj(scipy_fmt='csr').nonzero()
>>> g_sorted.adj_external(scipy_fmt='csr').nonzero()
(array([0, 0, 0, 0, 0, 1, 1, 1], dtype=int32), array([2, 4, 0, 1, 3, 2, 0, 1], dtype=int32))
>>> g_sorted.srcdata['_TAG_OFFSET']
tensor([[0, 2, 4, 5],
......@@ -3011,12 +3018,12 @@ def sort_csc_by_tag(g, tag, tag_offset_name="_TAG_OFFSET", tag_type="node"):
>>> import dgl
>>> import torch
>>> g = dgl.graph(([0,1,2,3,4,0,1,2],[0,0,0,0,0,1,1,1]))
>>> g.adjacency_matrix(scipy_fmt='csr', transpose=True).nonzero()
>>> g.adj_external(scipy_fmt='csr', transpose=True).nonzero()
(array([0, 0, 0, 0, 0, 1, 1, 1], dtype=int32),
array([0, 1, 2, 3, 4, 0, 1, 2], dtype=int32)))
>>> tag = torch.IntTensor([1,1,0,2,0])
>>> g_sorted = dgl.sort_csc_by_tag(g, tag)
>>> g_sorted.adjacency_matrix(scipy_fmt='csr', transpose=True).nonzero()
>>> g_sorted.adj_external(scipy_fmt='csr', transpose=True).nonzero()
(array([0, 0, 0, 0, 0, 1, 1, 1], dtype=int32),
array([2, 4, 0, 1, 3, 2, 0, 1], dtype=int32))
>>> g_sorted.ndata['_TAG_OFFSET']
......@@ -3031,7 +3038,7 @@ def sort_csc_by_tag(g, tag, tag_offset_name="_TAG_OFFSET", tag_type="node"):
>>> g = dgl.graph(([0,1,2,3,4,0,1,2],[0,0,0,0,0,1,1,1]))
>>> tag = torch.tensor([1, 1, 0, 2, 0, 1, 1, 0])
>>> g_sorted = dgl.sort_csc_by_tag(g, tag, tag_type='edge')
>>> g_sorted.adj(scipy_fmt='csr', transpose=True).nonzero()
>>> g_sorted.adj_external(scipy_fmt='csr', transpose=True).nonzero()
(array([0, 0, 0, 0, 0, 1, 1, 1], dtype=int32), array([2, 4, 0, 1, 3, 2, 0, 1], dtype=int32))
>>> g_sorted.dstdata['_TAG_OFFSET']
tensor([[0, 2, 4, 5],
......@@ -3376,7 +3383,7 @@ def rcmk_perm(g):
allowed_fmats = sum(g.formats().values(), [])
if fmat not in allowed_fmats:
g = g.formats(allowed_fmats + [fmat])
csr_adj = g.adj(scipy_fmt=fmat)
csr_adj = g.adj_external(scipy_fmt=fmat)
perm = sparse.csgraph.reverse_cuthill_mckee(csr_adj)
return perm.copy()
......@@ -3573,7 +3580,7 @@ def random_walk_pe(g, k, eweight_name=None):
"""
N = g.num_nodes() # number of nodes
M = g.num_edges() # number of edges
A = g.adj(scipy_fmt="csr") # adjacency matrix
A = g.adj_external(scipy_fmt="csr") # adjacency matrix
if eweight_name is not None:
# add edge weights if required
W = sparse.csr_matrix(
......@@ -3657,7 +3664,7 @@ def lap_pe(g, k, padding=False, return_eigval=False):
)
# get laplacian matrix as I - D^-0.5 * A * D^-0.5
A = g.adj(scipy_fmt="csr") # adjacency matrix
A = g.adj_external(scipy_fmt="csr") # adjacency matrix
N = sparse.diags(
F.asnumpy(g.in_degrees()).clip(1) ** -0.5, dtype=float
) # D^-1/2
......@@ -3789,7 +3796,7 @@ def double_radius_node_labeling(g, src, dst):
>>> dgl.double_radius_node_labeling(g, 0, 1)
tensor([1, 1, 3, 2, 3, 7, 0])
"""
adj = g.adj(scipy_fmt="csr")
adj = g.adj_external(scipy_fmt="csr")
src, dst = (dst, src) if src > dst else (src, dst)
idx = list(range(src)) + list(range(src + 1, adj.shape[0]))
......@@ -3899,14 +3906,14 @@ def shortest_dist(g, root=None, return_paths=False):
"""
if root is None:
dist, pred = sparse.csgraph.shortest_path(
g.adj(scipy_fmt="csr"),
g.adj_external(scipy_fmt="csr"),
return_predecessors=True,
unweighted=True,
directed=True,
)
else:
dist, pred = sparse.csgraph.dijkstra(
g.adj(scipy_fmt="csr"),
g.adj_external(scipy_fmt="csr"),
directed=True,
indices=root,
return_predecessors=True,
......@@ -4010,7 +4017,7 @@ def svd_pe(g, k, padding=False, random_flip=True):
"The number of singular values k must be no greater than the "
"number of nodes n, but " + f"got {k} and {n} respectively."
)
a = g.adj(ctx=g.device, scipy_fmt="coo").toarray()
a = g.adj_external(ctx=g.device, scipy_fmt="coo").toarray()
u, d, vh = scipy.linalg.svd(a)
v = vh.transpose()
m = min(n, k)
......
......@@ -144,11 +144,11 @@ def test_query():
assert F.allclose(g.out_degrees([8, 9]), F.tensor([0, 1]))
assert np.array_equal(
F.sparse_to_numpy(g.adjacency_matrix(transpose=True)),
F.sparse_to_numpy(g.adj_external(transpose=True)),
scipy_coo_input().toarray().T,
)
assert np.array_equal(
F.sparse_to_numpy(g.adjacency_matrix(transpose=False)),
F.sparse_to_numpy(g.adj_external(transpose=False)),
scipy_coo_input().toarray(),
)
......@@ -245,11 +245,11 @@ def test_query():
assert F.allclose(g.out_degrees([8, 9]), F.tensor([0, 1]))
assert np.array_equal(
F.sparse_to_numpy(g.adjacency_matrix(transpose=True)),
F.sparse_to_numpy(g.adj_external(transpose=True)),
scipy_coo_input().toarray().T,
)
assert np.array_equal(
F.sparse_to_numpy(g.adjacency_matrix(transpose=False)),
F.sparse_to_numpy(g.adj_external(transpose=False)),
scipy_coo_input().toarray(),
)
......@@ -308,12 +308,12 @@ def test_scipy_adjmat():
g.add_nodes(10)
g.add_edges(range(9), range(1, 10))
adj_0 = g.adj(scipy_fmt="csr")
adj_1 = g.adj(scipy_fmt="coo")
adj_0 = g.adj_external(scipy_fmt="csr")
adj_1 = g.adj_external(scipy_fmt="coo")
assert np.array_equal(adj_0.toarray(), adj_1.toarray())
adj_t0 = g.adj(transpose=False, scipy_fmt="csr")
adj_t_1 = g.adj(transpose=False, scipy_fmt="coo")
adj_t0 = g.adj_external(transpose=False, scipy_fmt="csr")
adj_t_1 = g.adj_external(transpose=False, scipy_fmt="coo")
assert np.array_equal(adj_0.toarray(), adj_1.toarray())
......
......@@ -708,41 +708,57 @@ def _test_edge_ids():
assert eid == 0
@pytest.mark.skipif(
F.backend_name != "pytorch", reason="Only support PyTorch for now"
)
@parametrize_idtype
def test_adj(idtype):
g = create_test_heterograph(idtype)
adj = F.sparse_to_numpy(g.adj(transpose=True, etype="follows"))
adj = g.adj("follows")
assert F.asnumpy(adj.indices()).tolist() == [[0, 1], [1, 2]]
assert np.allclose(F.asnumpy(adj.val), np.array([1, 1]))
g.edata["h"] = {("user", "plays", "game"): F.tensor([1, 2, 3, 4])}
print(g.edata["h"])
adj = g.adj("plays", "h")
assert F.asnumpy(adj.indices()).tolist() == [[0, 1, 2, 1], [0, 0, 1, 1]]
assert np.allclose(F.asnumpy(adj.val), np.array([1, 2, 3, 4]))
@parametrize_idtype
def test_adj_external(idtype):
g = create_test_heterograph(idtype)
adj = F.sparse_to_numpy(g.adj_external(transpose=True, etype="follows"))
assert np.allclose(
adj, np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
)
adj = F.sparse_to_numpy(g.adj(transpose=False, etype="follows"))
adj = F.sparse_to_numpy(g.adj_external(transpose=False, etype="follows"))
assert np.allclose(
adj, np.array([[0.0, 1.0, 0.0], [0.0, 0.0, 1.0], [0.0, 0.0, 0.0]])
)
adj = F.sparse_to_numpy(g.adj(transpose=True, etype="plays"))
adj = F.sparse_to_numpy(g.adj_external(transpose=True, etype="plays"))
assert np.allclose(adj, np.array([[1.0, 1.0, 0.0], [0.0, 1.0, 1.0]]))
adj = F.sparse_to_numpy(g.adj(transpose=False, etype="plays"))
adj = F.sparse_to_numpy(g.adj_external(transpose=False, etype="plays"))
assert np.allclose(adj, np.array([[1.0, 0.0], [1.0, 1.0], [0.0, 1.0]]))
adj = g.adj(transpose=True, scipy_fmt="csr", etype="follows")
adj = g.adj_external(transpose=True, scipy_fmt="csr", etype="follows")
assert np.allclose(
adj.todense(),
np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]),
)
adj = g.adj(transpose=True, scipy_fmt="coo", etype="follows")
adj = g.adj_external(transpose=True, scipy_fmt="coo", etype="follows")
assert np.allclose(
adj.todense(),
np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]),
)
adj = g.adj(transpose=True, scipy_fmt="csr", etype="plays")
adj = g.adj_external(transpose=True, scipy_fmt="csr", etype="plays")
assert np.allclose(
adj.todense(), np.array([[1.0, 1.0, 0.0], [0.0, 1.0, 1.0]])
)
adj = g.adj(transpose=True, scipy_fmt="coo", etype="plays")
adj = g.adj_external(transpose=True, scipy_fmt="coo", etype="plays")
assert np.allclose(
adj.todense(), np.array([[1.0, 1.0, 0.0], [0.0, 1.0, 1.0]])
)
adj = F.sparse_to_numpy(g["follows"].adj(transpose=True))
adj = F.sparse_to_numpy(g["follows"].adj_external(transpose=True))
assert np.allclose(
adj, np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
)
......@@ -3535,7 +3551,7 @@ def test_create_block(idtype):
@parametrize_idtype
@pytest.mark.parametrize("fmt", ["coo", "csr", "csc"])
def test_adj_sparse(idtype, fmt):
def test_adj_tensors(idtype, fmt):
if fmt == "coo":
A = ssp.random(10, 10, 0.2).tocoo()
A.data = np.arange(20)
......@@ -3562,11 +3578,11 @@ def test_adj_sparse(idtype, fmt):
A_coo = A.tocoo()
A_csr = A.tocsr()
A_csc = A.tocsc()
row, col = g.adj_sparse("coo")
row, col = g.adj_tensors("coo")
assert np.array_equal(F.asnumpy(row), A_coo.row)
assert np.array_equal(F.asnumpy(col), A_coo.col)
indptr, indices, eids = g.adj_sparse("csr")
indptr, indices, eids = g.adj_tensors("csr")
assert np.array_equal(F.asnumpy(indptr), A_csr.indptr)
if fmt == "csr":
assert len(eids) == 0
......@@ -3578,7 +3594,7 @@ def test_adj_sparse(idtype, fmt):
indices_sorted_np[A_csr.data] = A_csr.indices
assert np.array_equal(F.asnumpy(indices_sorted), indices_sorted_np)
indptr, indices, eids = g.adj_sparse("csc")
indptr, indices, eids = g.adj_tensors("csc")
assert np.array_equal(F.asnumpy(indptr), A_csc.indptr)
if fmt == "csc":
assert len(eids) == 0
......
......@@ -70,7 +70,7 @@ def test_topological_nodes(idtype, n=100):
layers_dgl = dgl.topological_nodes_generator(g)
adjmat = g.adjacency_matrix(transpose=True)
adjmat = g.adj_external(transpose=True)
def tensor_topo_traverse():
n = g.num_nodes()
......
......@@ -74,8 +74,8 @@ def test_sort_with_tag(idtype):
new_g = dgl.sort_csr_by_tag(
g, tag if tag_type == "node" else edge_tag_dst, tag_type=tag_type
)
old_csr = g.adjacency_matrix(scipy_fmt="csr")
new_csr = new_g.adjacency_matrix(scipy_fmt="csr")
old_csr = g.adj_external(scipy_fmt="csr")
new_csr = new_g.adj_external(scipy_fmt="csr")
assert check_sort(new_csr, tag, new_g.dstdata["_TAG_OFFSET"])
assert not check_sort(
old_csr, tag
......@@ -85,8 +85,8 @@ def test_sort_with_tag(idtype):
new_g = dgl.sort_csc_by_tag(
g, tag if tag_type == "node" else edge_tag_src, tag_type=tag_type
)
old_csc = g.adjacency_matrix(transpose=True, scipy_fmt="csr")
new_csc = new_g.adjacency_matrix(transpose=True, scipy_fmt="csr")
old_csc = g.adj_external(transpose=True, scipy_fmt="csr")
new_csc = new_g.adj_external(transpose=True, scipy_fmt="csr")
assert check_sort(new_csc, tag, new_g.srcdata["_TAG_OFFSET"])
assert not check_sort(old_csc, tag)
......@@ -103,14 +103,14 @@ def test_sort_with_tag_bipartite(idtype):
vtag = F.tensor(np.random.choice(num_tags, g.num_nodes("_V")))
new_g = dgl.sort_csr_by_tag(g, vtag)
old_csr = g.adjacency_matrix(scipy_fmt="csr")
new_csr = new_g.adjacency_matrix(scipy_fmt="csr")
old_csr = g.adj_external(scipy_fmt="csr")
new_csr = new_g.adj_external(scipy_fmt="csr")
assert check_sort(new_csr, vtag, new_g.nodes["_U"].data["_TAG_OFFSET"])
assert not check_sort(old_csr, vtag)
new_g = dgl.sort_csc_by_tag(g, utag)
old_csc = g.adjacency_matrix(transpose=True, scipy_fmt="csr")
new_csc = new_g.adjacency_matrix(transpose=True, scipy_fmt="csr")
old_csc = g.adj_external(transpose=True, scipy_fmt="csr")
new_csc = new_g.adj_external(transpose=True, scipy_fmt="csr")
assert check_sort(new_csc, utag, new_g.nodes["_V"].data["_TAG_OFFSET"])
assert not check_sort(old_csc, utag)
......
......@@ -3135,10 +3135,12 @@ def test_module_sign(g):
ctx = F.ctx()
g = g.to(ctx)
adj = g.adj(transpose=True, scipy_fmt="coo").todense()
adj = g.adj_external(transpose=True, scipy_fmt="coo").todense()
adj = torch.tensor(adj).float().to(ctx)
weight_adj = g.adj(transpose=True, scipy_fmt="coo").astype(float).todense()
weight_adj = (
g.adj_external(transpose=True, scipy_fmt="coo").astype(float).todense()
)
weight_adj = torch.tensor(weight_adj).float().to(ctx)
src, dst = g.edges()
src, dst = src.long(), dst.long()
......
......@@ -34,7 +34,7 @@ def test_graph_conv(idtype, out_dim):
g = dgl.from_networkx(nx.path_graph(3))
g = g.astype(idtype).to(F.ctx())
ctx = F.ctx()
adj = g.adjacency_matrix(transpose=True, ctx=ctx)
adj = g.adj_external(transpose=True, ctx=ctx)
conv = nn.GraphConv(5, out_dim, norm="none", bias=True)
conv.initialize(ctx=ctx)
......@@ -154,7 +154,7 @@ def _S2AXWb(A, N, X, W, b):
def test_tagconv(out_dim):
g = dgl.from_networkx(nx.path_graph(3)).to(F.ctx())
ctx = F.ctx()
adj = g.adjacency_matrix(transpose=True, ctx=ctx)
adj = g.adj_external(transpose=True, ctx=ctx)
norm = mx.nd.power(g.in_degrees().astype("float32"), -0.5)
conv = nn.TAGConv(5, out_dim, bias=True)
......@@ -361,7 +361,7 @@ def test_dense_cheb_conv(out_dim):
for k in range(1, 4):
ctx = F.ctx()
g = dgl.from_scipy(sp.sparse.random(100, 100, density=0.3)).to(F.ctx())
adj = g.adjacency_matrix(transpose=True, ctx=ctx).tostype("default")
adj = g.adj_external(transpose=True, ctx=ctx).tostype("default")
cheb = nn.ChebConv(5, out_dim, k)
dense_cheb = nn.DenseChebConv(5, out_dim, k)
cheb.initialize(ctx=ctx)
......@@ -387,7 +387,7 @@ def test_dense_cheb_conv(out_dim):
def test_dense_graph_conv(idtype, g, norm_type, out_dim):
g = g.astype(idtype).to(F.ctx())
ctx = F.ctx()
adj = g.adjacency_matrix(transpose=True, ctx=ctx).tostype("default")
adj = g.adj_external(transpose=True, ctx=ctx).tostype("default")
conv = nn.GraphConv(5, out_dim, norm=norm_type, bias=True)
dense_conv = nn.DenseGraphConv(5, out_dim, norm=norm_type, bias=True)
conv.initialize(ctx=ctx)
......@@ -408,7 +408,7 @@ def test_dense_graph_conv(idtype, g, norm_type, out_dim):
def test_dense_sage_conv(idtype, g, out_dim):
g = g.astype(idtype).to(F.ctx())
ctx = F.ctx()
adj = g.adjacency_matrix(transpose=True, ctx=ctx).tostype("default")
adj = g.adj_external(transpose=True, ctx=ctx).tostype("default")
sage = nn.SAGEConv(5, out_dim, "gcn")
dense_sage = nn.DenseSAGEConv(5, out_dim)
sage.initialize(ctx=ctx)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment