Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/networkx/utils/misc.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 1 """ | |
| 2 Miscellaneous Helpers for NetworkX. | |
| 3 | |
| 4 These are not imported into the base networkx namespace but | |
| 5 can be accessed, for example, as | |
| 6 | |
| 7 >>> import networkx | |
| 8 >>> networkx.utils.is_string_like('spam') | |
| 9 True | |
| 10 """ | |
| 11 # Authors: Aric Hagberg (hagberg@lanl.gov), | |
| 12 # Dan Schult(dschult@colgate.edu), | |
| 13 # Ben Edwards(bedwards@cs.unm.edu) | |
| 14 | |
| 15 # Copyright (C) 2004-2019 by | |
| 16 # Aric Hagberg <hagberg@lanl.gov> | |
| 17 # Dan Schult <dschult@colgate.edu> | |
| 18 # Pieter Swart <swart@lanl.gov> | |
| 19 # All rights reserved. | |
| 20 # BSD license. | |
| 21 from collections import defaultdict | |
| 22 from collections import deque | |
| 23 import warnings | |
| 24 import sys | |
| 25 import uuid | |
| 26 from itertools import tee, chain | |
| 27 import networkx as nx | |
| 28 | |
| 29 # itertools.accumulate is only available on Python 3.2 or later. | |
| 30 # | |
| 31 # Once support for Python versions less than 3.2 is dropped, this code should | |
| 32 # be removed. | |
| 33 try: | |
| 34 from itertools import accumulate | |
| 35 except ImportError: | |
| 36 import operator | |
| 37 | |
| 38 # The code for this function is from the Python 3.5 documentation, | |
| 39 # distributed under the PSF license: | |
| 40 # <https://docs.python.org/3.5/library/itertools.html#itertools.accumulate> | |
| 41 def accumulate(iterable, func=operator.add): | |
| 42 it = iter(iterable) | |
| 43 try: | |
| 44 total = next(it) | |
| 45 except StopIteration: | |
| 46 return | |
| 47 yield total | |
| 48 for element in it: | |
| 49 total = func(total, element) | |
| 50 yield total | |
| 51 | |
| 52 # 2.x/3.x compatibility | |
| 53 try: | |
| 54 basestring | |
| 55 except NameError: | |
| 56 basestring = str | |
| 57 unicode = str | |
| 58 | |
| 59 # some cookbook stuff | |
| 60 # used in deciding whether something is a bunch of nodes, edges, etc. | |
| 61 # see G.add_nodes and others in Graph Class in networkx/base.py | |
| 62 | |
| 63 | |
| 64 def is_string_like(obj): # from John Hunter, types-free version | |
| 65 """Check if obj is string.""" | |
| 66 return isinstance(obj, basestring) | |
| 67 | |
| 68 | |
| 69 def iterable(obj): | |
| 70 """ Return True if obj is iterable with a well-defined len().""" | |
| 71 if hasattr(obj, "__iter__"): | |
| 72 return True | |
| 73 try: | |
| 74 len(obj) | |
| 75 except: | |
| 76 return False | |
| 77 return True | |
| 78 | |
| 79 | |
| 80 def flatten(obj, result=None): | |
| 81 """ Return flattened version of (possibly nested) iterable object. """ | |
| 82 if not iterable(obj) or is_string_like(obj): | |
| 83 return obj | |
| 84 if result is None: | |
| 85 result = [] | |
| 86 for item in obj: | |
| 87 if not iterable(item) or is_string_like(item): | |
| 88 result.append(item) | |
| 89 else: | |
| 90 flatten(item, result) | |
| 91 return obj.__class__(result) | |
| 92 | |
| 93 | |
| 94 def make_list_of_ints(sequence): | |
| 95 """Return list of ints from sequence of integral numbers. | |
| 96 | |
| 97 All elements of the sequence must satisfy int(element) == element | |
| 98 or a ValueError is raised. Sequence is iterated through once. | |
| 99 | |
| 100 If sequence is a list, the non-int values are replaced with ints. | |
| 101 So, no new list is created | |
| 102 """ | |
| 103 msg = 'sequence is not all integers: %s' | |
| 104 if not isinstance(sequence, list): | |
| 105 result = [] | |
| 106 for i in sequence: | |
| 107 try: | |
| 108 ii = int(i) | |
| 109 except ValueError: | |
| 110 raise nx.NetworkXError(msg % i) from None | |
| 111 if ii != i: | |
| 112 raise nx.NetworkXError(msg % i) | |
| 113 result.append(ii) | |
| 114 return result | |
| 115 # original sequence is a list... in-place conversion to ints | |
| 116 for indx, i in enumerate(sequence): | |
| 117 if isinstance(i, int): | |
| 118 continue | |
| 119 try: | |
| 120 ii = int(i) | |
| 121 except ValueError: | |
| 122 raise nx.NetworkXError(msg % i) from None | |
| 123 if ii != i: | |
| 124 raise nx.NetworkXError(msg % i) | |
| 125 sequence[indx] = ii | |
| 126 return sequence | |
| 127 | |
| 128 | |
| 129 def is_list_of_ints(intlist): | |
| 130 """ Return True if list is a list of ints. """ | |
| 131 if not isinstance(intlist, list): | |
| 132 return False | |
| 133 for i in intlist: | |
| 134 if not isinstance(i, int): | |
| 135 return False | |
| 136 return True | |
| 137 | |
| 138 | |
| 139 PY2 = sys.version_info[0] == 2 | |
| 140 if PY2: | |
| 141 def make_str(x): | |
| 142 """Returns the string representation of t.""" | |
| 143 if isinstance(x, unicode): | |
| 144 return x | |
| 145 else: | |
| 146 # Note, this will not work unless x is ascii-encoded. | |
| 147 # That is good, since we should be working with unicode anyway. | |
| 148 # Essentially, unless we are reading a file, we demand that users | |
| 149 # convert any encoded strings to unicode before using the library. | |
| 150 # | |
| 151 # Also, the str() is necessary to convert integers, etc. | |
| 152 # unicode(3) works, but unicode(3, 'unicode-escape') wants a buffer | |
| 153 # | |
| 154 return unicode(str(x), 'unicode-escape') | |
| 155 else: | |
| 156 def make_str(x): | |
| 157 """Returns the string representation of t.""" | |
| 158 return str(x) | |
| 159 | |
| 160 | |
| 161 def generate_unique_node(): | |
| 162 """ Generate a unique node label.""" | |
| 163 return str(uuid.uuid1()) | |
| 164 | |
| 165 | |
| 166 def default_opener(filename): | |
| 167 """Opens `filename` using system's default program. | |
| 168 | |
| 169 Parameters | |
| 170 ---------- | |
| 171 filename : str | |
| 172 The path of the file to be opened. | |
| 173 | |
| 174 """ | |
| 175 from subprocess import call | |
| 176 | |
| 177 cmds = {'darwin': ['open'], | |
| 178 'linux': ['xdg-open'], | |
| 179 'linux2': ['xdg-open'], | |
| 180 'win32': ['cmd.exe', '/C', 'start', '']} | |
| 181 cmd = cmds[sys.platform] + [filename] | |
| 182 call(cmd) | |
| 183 | |
| 184 | |
| 185 def dict_to_numpy_array(d, mapping=None): | |
| 186 """Convert a dictionary of dictionaries to a numpy array | |
| 187 with optional mapping.""" | |
| 188 try: | |
| 189 return dict_to_numpy_array2(d, mapping) | |
| 190 except (AttributeError, TypeError): | |
| 191 # AttributeError is when no mapping was provided and v.keys() fails. | |
| 192 # TypeError is when a mapping was provided and d[k1][k2] fails. | |
| 193 return dict_to_numpy_array1(d, mapping) | |
| 194 | |
| 195 | |
| 196 def dict_to_numpy_array2(d, mapping=None): | |
| 197 """Convert a dictionary of dictionaries to a 2d numpy array | |
| 198 with optional mapping. | |
| 199 | |
| 200 """ | |
| 201 import numpy | |
| 202 if mapping is None: | |
| 203 s = set(d.keys()) | |
| 204 for k, v in d.items(): | |
| 205 s.update(v.keys()) | |
| 206 mapping = dict(zip(s, range(len(s)))) | |
| 207 n = len(mapping) | |
| 208 a = numpy.zeros((n, n)) | |
| 209 for k1, i in mapping.items(): | |
| 210 for k2, j in mapping.items(): | |
| 211 try: | |
| 212 a[i, j] = d[k1][k2] | |
| 213 except KeyError: | |
| 214 pass | |
| 215 return a | |
| 216 | |
| 217 | |
| 218 def dict_to_numpy_array1(d, mapping=None): | |
| 219 """Convert a dictionary of numbers to a 1d numpy array | |
| 220 with optional mapping. | |
| 221 | |
| 222 """ | |
| 223 import numpy | |
| 224 if mapping is None: | |
| 225 s = set(d.keys()) | |
| 226 mapping = dict(zip(s, range(len(s)))) | |
| 227 n = len(mapping) | |
| 228 a = numpy.zeros(n) | |
| 229 for k1, i in mapping.items(): | |
| 230 i = mapping[k1] | |
| 231 a[i] = d[k1] | |
| 232 return a | |
| 233 | |
| 234 | |
| 235 def is_iterator(obj): | |
| 236 """Returns True if and only if the given object is an iterator | |
| 237 object. | |
| 238 | |
| 239 """ | |
| 240 has_next_attr = hasattr(obj, '__next__') or hasattr(obj, 'next') | |
| 241 return iter(obj) is obj and has_next_attr | |
| 242 | |
| 243 | |
| 244 def arbitrary_element(iterable): | |
| 245 """Returns an arbitrary element of `iterable` without removing it. | |
| 246 | |
| 247 This is most useful for "peeking" at an arbitrary element of a set, | |
| 248 but can be used for any list, dictionary, etc., as well:: | |
| 249 | |
| 250 >>> arbitrary_element({3, 2, 1}) | |
| 251 1 | |
| 252 >>> arbitrary_element('hello') | |
| 253 'h' | |
| 254 | |
| 255 This function raises a :exc:`ValueError` if `iterable` is an | |
| 256 iterator (because the current implementation of this function would | |
| 257 consume an element from the iterator):: | |
| 258 | |
| 259 >>> iterator = iter([1, 2, 3]) | |
| 260 >>> arbitrary_element(iterator) | |
| 261 Traceback (most recent call last): | |
| 262 ... | |
| 263 ValueError: cannot return an arbitrary item from an iterator | |
| 264 | |
| 265 """ | |
| 266 if is_iterator(iterable): | |
| 267 raise ValueError('cannot return an arbitrary item from an iterator') | |
| 268 # Another possible implementation is ``for x in iterable: return x``. | |
| 269 return next(iter(iterable)) | |
| 270 | |
| 271 | |
| 272 # Recipe from the itertools documentation. | |
| 273 def consume(iterator): | |
| 274 "Consume the iterator entirely." | |
| 275 # Feed the entire iterator into a zero-length deque. | |
| 276 deque(iterator, maxlen=0) | |
| 277 | |
| 278 | |
| 279 # Recipe from the itertools documentation. | |
| 280 def pairwise(iterable, cyclic=False): | |
| 281 "s -> (s0, s1), (s1, s2), (s2, s3), ..." | |
| 282 a, b = tee(iterable) | |
| 283 first = next(b, None) | |
| 284 if cyclic is True: | |
| 285 return zip(a, chain(b, (first,))) | |
| 286 return zip(a, b) | |
| 287 | |
| 288 | |
| 289 def groups(many_to_one): | |
| 290 """Converts a many-to-one mapping into a one-to-many mapping. | |
| 291 | |
| 292 `many_to_one` must be a dictionary whose keys and values are all | |
| 293 :term:`hashable`. | |
| 294 | |
| 295 The return value is a dictionary mapping values from `many_to_one` | |
| 296 to sets of keys from `many_to_one` that have that value. | |
| 297 | |
| 298 For example:: | |
| 299 | |
| 300 >>> from networkx.utils import groups | |
| 301 >>> many_to_one = {'a': 1, 'b': 1, 'c': 2, 'd': 3, 'e': 3} | |
| 302 >>> groups(many_to_one) # doctest: +SKIP | |
| 303 {1: {'a', 'b'}, 2: {'c'}, 3: {'d', 'e'}} | |
| 304 | |
| 305 """ | |
| 306 one_to_many = defaultdict(set) | |
| 307 for v, k in many_to_one.items(): | |
| 308 one_to_many[k].add(v) | |
| 309 return dict(one_to_many) | |
| 310 | |
| 311 | |
| 312 def to_tuple(x): | |
| 313 """Converts lists to tuples. | |
| 314 | |
| 315 For example:: | |
| 316 | |
| 317 >>> from networkx.utils import to_tuple | |
| 318 >>> a_list = [1, 2, [1, 4]] | |
| 319 >>> to_tuple(a_list) | |
| 320 (1, 2, (1, 4)) | |
| 321 | |
| 322 """ | |
| 323 if not isinstance(x, (tuple, list)): | |
| 324 return x | |
| 325 return tuple(map(to_tuple, x)) | |
| 326 | |
| 327 | |
| 328 def create_random_state(random_state=None): | |
| 329 """Returns a numpy.random.RandomState instance depending on input. | |
| 330 | |
| 331 Parameters | |
| 332 ---------- | |
| 333 random_state : int or RandomState instance or None optional (default=None) | |
| 334 If int, return a numpy.random.RandomState instance set with seed=int. | |
| 335 if numpy.random.RandomState instance, return it. | |
| 336 if None or numpy.random, return the global random number generator used | |
| 337 by numpy.random. | |
| 338 """ | |
| 339 import numpy as np | |
| 340 | |
| 341 if random_state is None or random_state is np.random: | |
| 342 return np.random.mtrand._rand | |
| 343 if isinstance(random_state, np.random.RandomState): | |
| 344 return random_state | |
| 345 if isinstance(random_state, int): | |
| 346 return np.random.RandomState(random_state) | |
| 347 msg = '%r cannot be used to generate a numpy.random.RandomState instance' | |
| 348 raise ValueError(msg % random_state) | |
| 349 | |
| 350 | |
| 351 class PythonRandomInterface(object): | |
| 352 try: | |
| 353 def __init__(self, rng=None): | |
| 354 import numpy | |
| 355 if rng is None: | |
| 356 self._rng = numpy.random.mtrand._rand | |
| 357 self._rng = rng | |
| 358 except ImportError: | |
| 359 msg = 'numpy not found, only random.random available.' | |
| 360 warnings.warn(msg, ImportWarning) | |
| 361 | |
| 362 def random(self): | |
| 363 return self._rng.random_sample() | |
| 364 | |
| 365 def uniform(self, a, b): | |
| 366 return a + (b - a) * self._rng.random_sample() | |
| 367 | |
| 368 def randrange(self, a, b=None): | |
| 369 return self._rng.randint(a, b) | |
| 370 | |
| 371 def choice(self, seq): | |
| 372 return seq[self._rng.randint(0, len(seq))] | |
| 373 | |
| 374 def gauss(self, mu, sigma): | |
| 375 return self._rng.normal(mu, sigma) | |
| 376 | |
| 377 def shuffle(self, seq): | |
| 378 return self._rng.shuffle(seq) | |
| 379 | |
| 380 # Some methods don't match API for numpy RandomState. | |
| 381 # Commented out versions are not used by NetworkX | |
| 382 | |
| 383 def sample(self, seq, k): | |
| 384 return self._rng.choice(list(seq), size=(k,), replace=False) | |
| 385 | |
| 386 def randint(self, a, b): | |
| 387 return self._rng.randint(a, b + 1) | |
| 388 | |
| 389 # exponential as expovariate with 1/argument, | |
| 390 def expovariate(self, scale): | |
| 391 return self._rng.exponential(1/scale) | |
| 392 | |
| 393 # pareto as paretovariate with 1/argument, | |
| 394 def paretovariate(self, shape): | |
| 395 return self._rng.pareto(shape) | |
| 396 | |
| 397 # weibull as weibullvariate multiplied by beta, | |
| 398 # def weibullvariate(self, alpha, beta): | |
| 399 # return self._rng.weibull(alpha) * beta | |
| 400 # | |
| 401 # def triangular(self, low, high, mode): | |
| 402 # return self._rng.triangular(low, mode, high) | |
| 403 # | |
| 404 # def choices(self, seq, weights=None, cum_weights=None, k=1): | |
| 405 # return self._rng.choice(seq | |
| 406 | |
| 407 | |
| 408 def create_py_random_state(random_state=None): | |
| 409 """Returns a random.Random instance depending on input. | |
| 410 | |
| 411 Parameters | |
| 412 ---------- | |
| 413 random_state : int or random number generator or None (default=None) | |
| 414 If int, return a random.Random instance set with seed=int. | |
| 415 if random.Random instance, return it. | |
| 416 if None or the `random` package, return the global random number | |
| 417 generator used by `random`. | |
| 418 if np.random package, return the global numpy random number | |
| 419 generator wrapped in a PythonRandomInterface class. | |
| 420 if np.random.RandomState instance, return it wrapped in | |
| 421 PythonRandomInterface | |
| 422 if a PythonRandomInterface instance, return it | |
| 423 """ | |
| 424 import random | |
| 425 try: | |
| 426 import numpy as np | |
| 427 if random_state is np.random: | |
| 428 return PythonRandomInterface(np.random.mtrand._rand) | |
| 429 if isinstance(random_state, np.random.RandomState): | |
| 430 return PythonRandomInterface(random_state) | |
| 431 if isinstance(random_state, PythonRandomInterface): | |
| 432 return random_state | |
| 433 has_numpy = True | |
| 434 except ImportError: | |
| 435 has_numpy = False | |
| 436 | |
| 437 if random_state is None or random_state is random: | |
| 438 return random._inst | |
| 439 if isinstance(random_state, random.Random): | |
| 440 return random_state | |
| 441 if isinstance(random_state, int): | |
| 442 return random.Random(random_state) | |
| 443 msg = '%r cannot be used to generate a random.Random instance' | |
| 444 raise ValueError(msg % random_state) | |
| 445 | |
| 446 | |
| 447 # fixture for pytest | |
| 448 def setup_module(module): | |
| 449 import pytest | |
| 450 numpy = pytest.importorskip('numpy') |
