import numbers
from nxmetis import enums
from nxmetis import metis
__all__ = ['MetisOptions']
[docs]class MetisOptions(object):
"""Options controlling behaviors of METIS algorithms."""
[docs] def __init__(self, **kwargs):
"""Initializes a MetisOptions object. Values can be provided
for some parameters as arguments.
Example
-------
>>> options = MetisOptions(ncuts=2, niter=100)
"""
metis.set_default_options(self)
for key, value in kwargs.items():
if value is not None:
setattr(self, key, value)
@property
def ptype(self):
"""Types of Partitioning method.
==== =================================
rb Multilevel recursive bisectioning
kway Multilevel `k`-way partitioning
==== =================================
"""
return self._ptype
@ptype.setter
def ptype(self, value):
self._ptype = enums.MetisPType(value)
@property
def objtype(self):
"""Type of objective.
=== =======================================
cut Edge-cut minimization
vol Total communication volume minimization
=== =======================================
"""
return self._objtype
@objtype.setter
def objtype(self, value):
self._objtype = enums.MetisObjType(value)
@property
def ctype(self):
"""Matching scheme to be used during coarsening.
==== ==========================
rm Random matching
shem Sorted heavy-edge matching
==== ==========================
"""
return self._ctype
@ctype.setter
def ctype(self, value):
self._ctype = enums.MetisCType(value)
@property
def iptype(self):
"""Algorithm used during initial partitioning.
====== ======================================================
grow Grow a bisection using a greedy strategy
random Compute a bisection at random followed by a refinement
edge Derive a separator from an edge cut
node Grow a bisection using a greedy node-based strategy
====== ======================================================
"""
return self._iptype
@iptype.setter
def iptype(self, value):
self._iptype = enums.MetisIPType(value)
@property
def rtype(self):
"""Algorithm used for refinement.
========= ======================================
fm FM-based cut refinement
greedy Greedy-based cut and volume refinement
sep2sided Two-sided node FM refinement
sep1sided One-sided node FM refinement
========= ======================================
"""
return self._rtype
@rtype.setter
def rtype(self, value):
self._rtype = enums.MetisRType(value)
@property
def ncuts(self):
"""Number of cuts."""
return self._ncuts
@ncuts.setter
def ncuts(self, value):
if not isinstance(value, numbers.Number) or value != int(value):
raise ValueError('{0} is not an int'.format(repr(value)))
self._ncuts = int(value)
@property
def nseps(self):
"""Number of separators."""
return self._nseps
@nseps.setter
def nseps(self, value):
if not isinstance(value, numbers.Number) or value != int(value):
raise ValueError('{0} is not an int'.format(repr(value)))
self._nseps = int(value)
@property
def numbering(self):
"""Numbering scheme is used for the adjacency structure of a graph or the
element-node structure of a mesh.
==== =================================
zero C-style zero-based numbering
one Fortran-style one-based numbering
==== =================================
"""
return self._numbering
@numbering.setter
def numbering(self, value):
self._numbering = enums.MetisNumbering(value)
@property
def niter(self):
"""Number of refinement iterations."""
return self._niter
@niter.setter
def niter(self, value):
if not isinstance(value, numbers.Number) or value != int(value):
raise ValueError('{0} is not an int'.format(repr(value)))
self._niter = value
@property
def seed(self):
"""Random number seed."""
return self._seed
@seed.setter
def seed(self, value):
if not isinstance(value, numbers.Number) or value != int(value):
raise ValueError('{0} is not an int'.format(repr(value)))
self._seed = value
@property
def minconn(self):
"""Number of mimimum connectivity."""
return self._minconn
@minconn.setter
def minconn(self, value):
self._minconn = bool(value)
@property
def no2hop(self):
"""A boolean to perform a 2-hop matching."""
return self._no2hop
@no2hop.setter
def no2hop(self, value):
self._no2hop = bool(value)
@property
def contig(self):
"""A boolean to create contigous partitions."""
return self._contig
@contig.setter
def contig(self, value):
self._contig = bool(value)
@property
def compress(self):
"""A boolean to compress graph prior to ordering."""
return self._compress
@compress.setter
def compress(self, value):
self._compress = bool(value)
@property
def ccorder(self):
"""A boolean to detect & order connected components separately."""
return self._ccorder
@ccorder.setter
def ccorder(self, value):
self._ccorder = bool(value)
@property
def pfactor(self):
"""Prunning factor for high degree vertices."""
return self._pfactor
@pfactor.setter
def pfactor(self, value):
if not isinstance(value, numbers.Number) or value != int(value):
raise ValueError('{0} is not an int'.format(repr(value)))
self._pfactor = value
@property
def ufactor(self):
"""User-supplied ufactor."""
return self._ufactor
@ufactor.setter
def ufactor(self, value):
if not isinstance(value, numbers.Number) or value != int(value):
raise ValueError('{0} is not an int'.format(repr(value)))
self._ufactor = value
@property
def dbglvl(self):
"""Amount of progress/debugging information will be printed during the
execution of the algorithms. Can be combined by bit-wise OR.
========== ======================================================
info Print various diagnostic messages
time Perform timing analysis
coarsen Display various statistics during coarsening
refine Display various statistics during refinement
ipart Display various statistics during initial partitioning
moveinfo Display detailed information about vertex moves during
refinement
sepinfo Display information about vertex separators
conninfo Display information related to the minimization of
subdomain connectivity
contiginfo Display information related to the elimination of
connected components
========== ======================================================
"""
return self._dbglvl
@dbglvl.setter
def dbglvl(self, value):
if (not isinstance(value, numbers.Number) or value != int(value) or
not (value == -1 or (value >= 0 and value < 512) or
(value >= 2048 and value < 2560))):
raise ValueError('{0} is not a valid dbglvl'.format(repr(value)))
self._dbglvl = int(value)
def __repr__(self):
names = ['ptype', 'objtype', 'ctype', 'iptype', 'rtype', 'ncuts',
'nseps', 'numbering', 'niter', 'seed', 'minconn', 'no2hop',
'contig', 'compress', 'ccorder', 'pfactor', 'ufactor']
return '{0}({1})'.format(
self.__class__.__name__,
', '.join('{0}={1}'.format(name, repr(getattr(self, name)))
for name in names))