"docs/git@developer.sourcefind.cn:renzhc/diffusers_dcu.git" did not exist on "d44e31aec2a450a31bc80662942094d617a585c2"
Commit d1d580ec authored by Zihao Ye's avatar Zihao Ye Committed by Minjie Wang
Browse files

[feature & bugfix] adjacency_matrix_scipy, wrong order of edges in immutable graph. (#437)

* fix rgcn tutorial

* small fix

* upd

* findedge/s

* upd

* upd

* upd

* upd

* add test

* remove redundancy

* upd

* upd

* upd

* upd

* add edge_subgraph

* explicit cast

* add test immutable subg

* reformat

* reformat

* fix bug

* upd

* hotfix

* subgraph docs

* fix adj mat

* fix edges() order

* add test

* revert

* upd

* fix

* upd
parent 8f426250
......@@ -68,6 +68,7 @@ Converting from/to other format
DGLGraph.from_networkx
DGLGraph.from_scipy_sparse_matrix
DGLGraph.adjacency_matrix
DGLGraph.adjacency_matrix_scipy
DGLGraph.incidence_matrix
Using Node/edge features
......
......@@ -2831,6 +2831,32 @@ class DGLGraph(DGLBaseGraph):
sgi = self._graph.edge_subgraph(induced_edges)
return subgraph.DGLSubGraph(self, sgi.induced_nodes, sgi.induced_edges, sgi)
def adjacency_matrix_scipy(self, transpose=False, fmt='csr'):
"""Return the scipy adjacency matrix representation of this graph.
By default, a row of returned adjacency matrix represents the destination
of an edge and the column represents the source.
When transpose is True, a row represents the source and a column represents
a destination.
The elements in the adajency matrix are edge ids.
Parameters
----------
transpose : bool, optional (default=False)
A flag to transpose the returned adjacency matrix.
fmt : str, optional (default='csr')
Indicates the format of returned adjacency matrix.
Returns
-------
scipy.sparse.spmatrix
The scipy representation of adjacency matrix.
"""
return self._graph.adjacency_matrix_scipy(transpose, fmt)
def adjacency_matrix(self, transpose=False, ctx=F.cpu()):
"""Return the adjacency matrix representation of this graph.
......
......@@ -551,6 +551,51 @@ class GraphIndex(object):
induced_nodes = utils.toindex(rst(1))
return SubgraphIndex(rst(0), self, induced_nodes, e)
@utils.cached_member(cache='_cache', prefix='scipy_adj')
def adjacency_matrix_scipy(self, transpose, fmt):
"""Return the scipy adjacency matrix representation of this graph.
By default, a row of returned adjacency matrix represents the destination
of an edge and the column represents the source.
When transpose is True, a row represents the source and a column represents
a destination.
The elements in the adajency matrix are edge ids.
Parameters
----------
transpose : bool
A flag to transpose the returned adjacency matrix.
fmt : str
Indicates the format of returned adjacency matrix.
Returns
-------
scipy.sparse.spmatrix
The scipy representation of adjacency matrix.
"""
if not isinstance(transpose, bool):
raise DGLError('Expect bool value for "transpose" arg,'
' but got %s.' % (type(transpose)))
rst = _CAPI_DGLGraphGetAdj(self._handle, transpose, fmt)
if fmt == "csr":
indptr = utils.toindex(rst(0)).tonumpy()
indices = utils.toindex(rst(1)).tonumpy()
shuffle = utils.toindex(rst(2)).tonumpy()
n = self.number_of_nodes()
return scipy.sparse.csr_matrix((shuffle, indices, indptr), shape=(n, n))
elif fmt == 'coo':
idx = utils.toindex(rst(0)).tonumpy()
n = self.number_of_nodes()
m = self.number_of_edges()
row, col = np.reshape(idx, (2, m))
shuffle = np.arange(0, m)
return scipy.sparse.coo_matrix((shuffle, (row, col)), shape=(n, n))
else:
raise Exception("unknown format")
@utils.cached_member(cache='_cache', prefix='adj')
def adjacency_matrix(self, transpose, ctx):
"""Return the adjacency matrix representation of this graph.
......
......@@ -541,7 +541,7 @@ ImmutableGraph::EdgeArray ImmutableGraph::Edges(const std::string &order) const
dgl_id_t* rst_dst_data = static_cast<dgl_id_t*>(rst_dst->data);
dgl_id_t* rst_eid_data = static_cast<dgl_id_t*>(rst_eid->data);
if (order.empty() || order == "srcdst") {
if (order == "srcdst") {
auto out_csr = GetOutCSR();
// If sorted, the returned edges are sorted by the source Id and dest Id.
for (size_t i = 0; i < out_csr->indptr.size() - 1; i++) {
......@@ -550,7 +550,7 @@ ImmutableGraph::EdgeArray ImmutableGraph::Edges(const std::string &order) const
}
std::copy(out_csr->indices.begin(), out_csr->indices.end(), rst_dst_data);
std::copy(out_csr->edge_ids.begin(), out_csr->edge_ids.end(), rst_eid_data);
} else if (order == "eid") {
} else if (order.empty() || order == "eid") {
std::vector<Edge> edges;
auto out_csr = GetOutCSR();
out_csr->ReadAllEdges(&edges);
......
......@@ -38,6 +38,30 @@ def test_create_from_elist():
#for i, (u, v) in enumerate(elist):
# assert g.edge_id(u, v) == i
def test_scipy_adjmat():
g = dgl.DGLGraph()
g.add_nodes(10)
g.add_edges(range(9), range(1, 10))
adj_0 = g.adjacency_matrix_scipy()
adj_1 = g.adjacency_matrix_scipy(fmt='coo')
assert np.array_equal(adj_0.toarray(), adj_1.toarray())
adj_t0 = g.adjacency_matrix_scipy(transpose=True)
adj_t_1 = g.adjacency_matrix_scipy(transpose=True, fmt='coo')
assert np.array_equal(adj_0.toarray(), adj_1.toarray())
g.readonly()
adj_2 = g.adjacency_matrix_scipy()
adj_3 = g.adjacency_matrix_scipy(fmt='coo')
assert np.array_equal(adj_2.toarray(), adj_3.toarray())
assert np.array_equal(adj_0.toarray(), adj_2.toarray())
adj_t2 = g.adjacency_matrix_scipy(transpose=True)
adj_t3 = g.adjacency_matrix_scipy(transpose=True, fmt='coo')
assert np.array_equal(adj_t2.toarray(), adj_t3.toarray())
assert np.array_equal(adj_t0.toarray(), adj_t2.toarray())
def test_adjmat_cache():
n = 1000
p = 10 * math.log(n) / n
......@@ -217,6 +241,7 @@ if __name__ == '__main__':
test_graph_creation()
test_create_from_elist()
test_adjmat_cache()
test_scipy_adjmat()
test_incmat()
test_incmat_cache()
test_readonly()
......
......@@ -151,8 +151,25 @@ def test_create_from_elist():
# print(u, v, g.edge_id(u, v)[0])
# assert g.edge_id(u, v)[0] == i
def test_edges():
gi = create_graph_index()
gi.add_nodes(10)
gi.add_edges(toindex([5,5,5,5]), toindex([6,7,8,9]))
gi.add_edges(toindex([0,0,0,0]), toindex([1,2,3,4]))
gi.add_edges(toindex([1,1,1,1]), toindex([2,3,4,5]))
src, dst, eid = gi.edges()
src0, dst0, eid0 = src.tonumpy(), dst.tonumpy(), eid.tonumpy()
gi.readonly()
src, dst, eid = gi.edges()
src, dst, eid = src.tonumpy(), dst.tonumpy(), eid.tonumpy()
import numpy as np
assert np.array_equal(src, src0)
assert np.array_equal(dst, dst0)
assert np.array_equal(eid, eid0)
if __name__ == '__main__':
test_edge_id()
test_nx()
test_predsucc()
test_create_from_elist()
test_edges()
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