"git@developer.sourcefind.cn:OpenDAS/vision.git" did not exist on "cac4e228c9ca9e7564cb34406e7ebccfdd736976"
Unverified Commit 04dce1e6 authored by Rhett-Ying's avatar Rhett-Ying Committed by GitHub
Browse files

[Doc] refine doc and optimize metis part for dgl.reorder() (#3090)


Co-authored-by: default avatarTong He <hetong007@gmail.com>
parent 0b3a6216
...@@ -2895,48 +2895,55 @@ def sort_in_edges(g, tag, tag_offset_name='_TAG_OFFSET'): ...@@ -2895,48 +2895,55 @@ def sort_in_edges(g, tag, tag_offset_name='_TAG_OFFSET'):
def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None): def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None):
r"""Return a new graph which re-order and re-label the nodes r"""Return a new graph which re-order and re-label the nodes
according to the specified permute algo. according to the specified permute algorithm.
Homogeneous graph is supported only. Support homogeneous graph only for the moment.
This API is basically implemented by leveraging dgl.node_subgraph(), This API is basically implemented by leveraging :func:`~dgl.node_subgraph`,
so the function signature is similar and raw IDs could be stored so the function signature is similar and raw IDs could be stored
in dgl.NID and dgl.EID. in ``dgl.NID`` and ``dgl.EID``.
Please note that edges are re-ordered/re-labeled according to re-ordered
``'src'`` nodes. This behavior is realized in :func:`dgl.node_subgraph`.
What's more, if user wants to re-order/re-label according to ``'dst'`` nodes
or any other algorithms, please use :func:`dgl.edge_subgraph` with new edge
permutation.
Parameters Parameters
---------- ----------
g : DGLGraph g : DGLGraph
The homogeneous graph. The homogeneous graph.
permute_algo: str, optional permute_algo: str, optional
can be ``'rcmk'`` or ``'metis'`` or ``'custom'``. ``'rcmk'`` is the default algo. can be ``'rcmk'`` or ``'metis'`` or ``'custom'``. ``'rcmk'`` is the default value.
* ``'rcmk'``: The Reverse Cuthill–McKee algorithm is an algorithm to permute
a sparse matrix that has a symmetric sparsity pattern into a band matrix form * ``'rcmk'``: Call `Reverse Cuthill–McKee <https://docs.scipy.org/doc/scipy/reference/
with a small bandwidth. The resulting index numbers is reversed. generated/scipy.sparse.csgraph.reverse_cuthill_mckee.html#
* ``'metis'``: METIS is a set of serial algorithms for partitioning graphs, scipy-sparse-csgraph-reverse-cuthill-mckee>`__ from ``'scipy'`` to generate nodes
partitioning finite element meshes, and producing fill reducing orderings permutation and pass it into :func:`~dgl.node_subgraph` to generate new graph.
for sparse matrices. This algorithm has already available in DGL: * ``'metis'``: Call :func:`~dgl.partition.metis_partition_assignment` from ``'DGL'``
``'dgl.partition.metis_partition_assignment'``. to generate nodes permutation and pass it into :func:`~dgl.node_subgraph` to generate
new graph.
* ``'custom'``: This enables user to pass in self-designed reorder algorithm. * ``'custom'``: This enables user to pass in self-designed reorder algorithm.
User should pass in ``'nodes_perm'`` via another argument ``'permute_config'`` with User should pass in ``'nodes_perm'`` via another argument :attr:`permute_config` with
``'custom'`` is specified here. By this way, can the graph be reordered according to ``'custom'`` is specified here. By this way, can the graph be reordered according to
passed in nodes permutation. passed in nodes permutation.
store_ids: bool, optional store_ids: bool, optional
It's passed into dgl.node_subgraph(). If True, it will store It is passed into :func:`~dgl.node_subgraph()`. If True, it will store
the raw IDs of the extracted nodes and edges in the ndata the raw IDs of the extracted nodes and edges in the ndata and edata of
and edata of the resulting graph under name dgl.NID and the resulting graph under name ``'dgl.NID'`` and ``'dgl.EID'``, respectively.
dgl.EID, respectively.
permute_config: dict, optional permute_config: dict, optional
additional config data for specified permute_algo. Additional config data for specified :attr:`permute_algo`.
* for ``'rcmk'``, this argument is not required.
* for ``'metis'``, partition part number ``'k'`` is required and specified in this
argument like this: {'k':10}.
* for ``'custom'``, ``'nodes_perm'`` should be specified in this argument like this:
{'nodes_perm':[1,2,3,0]}.
Return * For ``'rcmk'``, this argument is not required.
------ * For ``'metis'``, partition part number ``'k'`` is required and specified in this
argument like this: {'k':10}.
* For ``'custom'``, ``'nodes_perm'`` should be specified in the format of
``'Int Tensor'`` or ``'iterable[int]'`` like :attr:`nodes` in :func:`~dgl.node_subgraph`.
Returns
-------
DGLGraph DGLGraph
The re-ordered graph The re-ordered graph.
Examples Examples
-------- --------
...@@ -2958,8 +2965,7 @@ def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None): ...@@ -2958,8 +2965,7 @@ def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None):
[3], [3],
[4]])} [4]])}
Reorder according to 'rcmk' permute_algo which is implemented in Reorder according to ``'rcmk'`` permute algorithm.
scipy.sparse.csgraph.reverse_cuthill_mckee().
>>> rg = dgl.reorder(g) >>> rg = dgl.reorder(g)
>>> rg.ndata >>> rg.ndata
...@@ -2975,8 +2981,7 @@ def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None): ...@@ -2975,8 +2981,7 @@ def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None):
[2], [2],
[0]]), '_ID': tensor([4, 3, 1, 2, 0])} [0]]), '_ID': tensor([4, 3, 1, 2, 0])}
Reorder with according to 'metis' permute_algo which is implemented in Reorder with according to ``'metis'`` permute algorithm.
dgl.partition.metis_partition_assignment().
>>> rg = dgl.reorder(g, 'metis', permute_config={'k':2}) >>> rg = dgl.reorder(g, 'metis', permute_config={'k':2})
>>> rg.ndata >>> rg.ndata
...@@ -2992,7 +2997,7 @@ def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None): ...@@ -2992,7 +2997,7 @@ def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None):
[4], [4],
[3]]), '_ID': tensor([2, 1, 0, 4, 3])} [3]]), '_ID': tensor([2, 1, 0, 4, 3])}
Reorder according to 'custom' permute_algo with user-provided nodes_perm. Reorder according to ``'custom'`` permute algorithm with user-provided nodes_perm.
>>> nodes_perm = torch.randperm(g.num_nodes()) >>> nodes_perm = torch.randperm(g.num_nodes())
>>> nodes_perm >>> nodes_perm
...@@ -3019,12 +3024,12 @@ def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None): ...@@ -3019,12 +3024,12 @@ def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None):
raise DGLError("Unexpected permute_algo is specified: {}. Expected algos: {}".format( raise DGLError("Unexpected permute_algo is specified: {}. Expected algos: {}".format(
permute_algo, expected_algo)) permute_algo, expected_algo))
if permute_algo == 'rcmk': if permute_algo == 'rcmk':
nodes_perm = RCMKPerm(g) nodes_perm = rcmk_perm(g)
elif permute_algo == 'metis': elif permute_algo == 'metis':
if permute_config is None or 'k' not in permute_config: if permute_config is None or 'k' not in permute_config:
raise DGLError( raise DGLError(
"Partition parts 'k' is required for metis. Please specify in permute_config.") "Partition parts 'k' is required for metis. Please specify in permute_config.")
nodes_perm = METISPerm(g, permute_config['k']) nodes_perm = metis_perm(g, permute_config['k'])
else: else:
if permute_config is None or 'nodes_perm' not in permute_config: if permute_config is None or 'nodes_perm' not in permute_config:
raise DGLError( raise DGLError(
...@@ -3040,30 +3045,43 @@ def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None): ...@@ -3040,30 +3045,43 @@ def reorder(g, permute_algo='rcmk', store_ids=True, permute_config=None):
DGLHeteroGraph.reorder = utils.alias_func(reorder) DGLHeteroGraph.reorder = utils.alias_func(reorder)
def METISPerm(g, k): def metis_perm(g, k):
""" r"""Return nodes permutation according to ``'metis'`` algorithm.
For internal use. For internal use.
g: graph
k: partition parts number Parameters
return: permutation of node ids via metis partition and assignment ----------
g : DGLGraph
The homogeneous graph.
k: int
The partition parts number.
Returns
-------
iterable[int]
The nodes permutation.
""" """
pids = metis_partition_assignment( pids = metis_partition_assignment(
g if g.device == F.cpu() else g.to(F.cpu()), k) g if g.device == F.cpu() else g.to(F.cpu()), k)
pids = F.asnumpy(pids) pids = F.asnumpy(pids)
perm = np.zeros(pids.shape, np.int64) return np.argsort(pids).copy()
bincnt = np.bincount(pids)
idcnt = np.cumsum(bincnt)
for i, e in enumerate(pids):
idcnt[e] -= 1
perm[idcnt[e]] = i
return perm
def RCMKPerm(g): def rcmk_perm(g):
""" r"""Return nodes permutation according to ``'rcmk'`` algorithm.
For internal use. For internal use.
g: graph
return: permutation of node ids via RCMK algorithm Parameters
----------
g : DGLGraph
The homogeneous graph.
Returns
-------
iterable[int]
The nodes permutation.
""" """
fmat = 'csr' fmat = 'csr'
allowed_fmats = sum(g.formats().values(), []) allowed_fmats = sum(g.formats().values(), [])
......
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