FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

"""Provides some utilities widely used by other modules""" import bisect import collections import collections.abc import operator import os.path import random import math import functools # ______________________________________________________________________________ # Functions on Sequences and Iterables def sequence(iterable): """Coerce iterable to sequence, if it is not already one.""" return (iterable if isinstance(iterable, collections.abc.Sequence) else tuple(iterable)) def removeall(item, seq): """Return a copy of seq (or string) with all occurences of item removed.""" if isinstance(seq, str): return seq.replace(item, '') else: return [x for x in seq if x != item] def unique(seq): # TODO: replace with set """Remove duplicate elements from seq. Assumes hashable elements.""" return list(set(seq)) def count(seq): """Count the number of items in sequence that are interpreted as true.""" return sum(bool(x) for x in seq) def product(numbers): """Return the product of the numbers, e.g. product([2, 3, 10]) == 60""" result = 1 for x in numbers: result *= x return result def first(iterable, default=None): """Return the first element of an iterable or the next element of a generator; or default.""" try: return iterable[0] except IndexError: return default except TypeError: return next(iterable, default) def is_in(elt, seq): """Similar to (elt in seq), but compares with 'is', not '=='.""" return any(x is elt for x in seq) def mode(data): """Return the most common data item. If there are ties, return any one of them.""" [(item, count)] = collections.Counter(data).most_common(1) return item # ______________________________________________________________________________ # argmin and argmax identity = lambda x: x argmin = min argmax = max def argmin_random_tie(seq, key=identity): """Return a minimum element of seq; break ties at random.""" return argmin(shuffled(seq), key=key) def argmax_random_tie(seq, key=identity): """Return an element with highest fn(seq[i]) score; break ties at random.""" return argmax(shuffled(seq), key=key) def shuffled(iterable): """Randomly shuffle a copy of iterable.""" items = list(iterable) random.shuffle(items) return items # ______________________________________________________________________________ # Statistical and mathematical functions def histogram(values, mode=0, bin_function=None): """Return a list of (value, count) pairs, summarizing the input values. Sorted by increasing value, or if mode=1, by decreasing count. If bin_function is given, map it over values first.""" if bin_function: values = map(bin_function, values) bins = {} for val in values: bins[val] = bins.get(val, 0) + 1 if mode: return sorted(list(bins.items()), key=lambda x: (x[1], x[0]), reverse=True) else: return sorted(bins.items()) def dotproduct(X, Y): """Return the sum of the element-wise product of vectors X and Y.""" return sum(x * y for x, y in zip(X, Y)) def element_wise_product(X, Y): """Return vector as an element-wise product of vectors X and Y""" assert len(X) == len(Y) return [x * y for x, y in zip(X, Y)] def matrix_multiplication(X_M, *Y_M): """Return a matrix as a matrix-multiplication of X_M and arbitary number of matrices *Y_M""" def _mat_mult(X_M, Y_M): """Return a matrix as a matrix-multiplication of two matrices X_M and Y_M >>> matrix_multiplication([[1, 2, 3], [2, 3, 4]], [[3, 4], [1, 2], [1, 0]]) [[8, 8],[13, 14]] """ assert len(X_M[0]) == len(Y_M) result = [[0 for i in range(len(Y_M[0]))] for j in range(len(X_M))] for i in range(len(X_M)): for j in range(len(Y_M[0])): for k in range(len(Y_M)): result[i][j] += X_M[i][k] * Y_M[k][j] return result result = X_M for Y in Y_M: result = _mat_mult(result, Y) return result def vector_to_diagonal(v): """Converts a vector to a diagonal matrix with vector elements as the diagonal elements of the matrix""" diag_matrix = [[0 for i in range(len(v))] for j in range(len(v))] for i in range(len(v)): diag_matrix[i][i] = v[i] return diag_matrix def vector_add(a, b): """Component-wise addition of two vectors.""" return tuple(map(operator.add, a, b)) def scalar_vector_product(X, Y): """Return vector as a product of a scalar and a vector""" return [X * y for y in Y] def scalar_matrix_product(X, Y): """Return matrix as a product of a scalar and a matrix""" return [scalar_vector_product(X, y) for y in Y] def inverse_matrix(X): """Inverse a given square matrix of size 2x2""" assert len(X) == 2 assert len(X[0]) == 2 det = X[0][0] * X[1][1] - X[0][1] * X[1][0] assert det != 0 inv_mat = scalar_matrix_product(1.0/det, [[X[1][1], -X[0][1]], [-X[1][0], X[0][0]]]) return inv_mat def probability(p): """Return true with probability p.""" return p > random.uniform(0.0, 1.0) def weighted_sample_with_replacement(n, seq, weights): """Pick n samples from seq at random, with replacement, with the probability of each element in proportion to its corresponding weight.""" sample = weighted_sampler(seq, weights) return [sample() for _ in range(n)] def weighted_sampler(seq, weights): """Return a random-sample function that picks from seq weighted by weights.""" totals = [] for w in weights: totals.append(w + totals[-1] if totals else w) return lambda: seq[bisect.bisect(totals, random.uniform(0, totals[-1]))] def rounder(numbers, d=4): """Round a single number, or sequence of numbers, to d decimal places.""" if isinstance(numbers, (int, float)): return round(numbers, d) else: constructor = type(numbers) # Can be list, set, tuple, etc. return constructor(rounder(n, d) for n in numbers) def num_or_str(x): """The argument is a string; convert to a number if possible, or strip it.""" try: return int(x) except ValueError: try: return float(x) except ValueError: return str(x).strip() def normalize(dist): """Multiply each number by a constant such that the sum is 1.0""" if isinstance(dist, dict): total = sum(dist.values()) for key in dist: dist[key] = dist[key] / total assert 0 odict.__tuplify__() def __le__(self, odict): assert isinstance(odict, hashabledict) return self.__tuplify__() = odict.__tuplify__() # ______________________________________________________________________________ # Queues: Stack, FIFOQueue, PriorityQueue # TODO: queue.PriorityQueue # TODO: Priority queues may not belong here -- see treatment in search.py class Queue: """Queue is an abstract class/interface. There are three types: Stack(): A Last In First Out Queue. FIFOQueue(): A First In First Out Queue. PriorityQueue(order, f): Queue in sorted order (default min-first). Each type supports the following methods and functions: q.append(item) -- add an item to the queue q.extend(items) -- equivalent to: for item in items: q.append(item) q.pop() -- return the top item from the queue len(q) -- number of items in q (also q.__len()) item in q -- does q contain item? Note that isinstance(Stack(), Queue) is false, because we implement stacks as lists. If Python ever gets interfaces, Queue will be an interface.""" def __init__(self): raise NotImplementedError def extend(self, items): for item in items: self.append(item) def Stack(): """Return an empty list, suitable as a Last-In-First-Out Queue.""" return [] class FIFOQueue(Queue): """A First-In-First-Out Queue.""" def __init__(self, maxlen=None, items=[]): self.queue = collections.deque(items, maxlen) def append(self, item): if not self.queue.maxlen or len(self.queue) < self.queue.maxlen: self.queue.append(item) else: raise Exception('FIFOQueue is full') def extend(self, items): if not self.queue.maxlen or len(self.queue) + len(items) 0: return self.queue.popleft() else: raise Exception('FIFOQueue is empty') def __len__(self): return len(self.queue) def __contains__(self, item): return item in self.queue class PriorityQueue(Queue): """A queue in which the minimum (or maximum) element (as determined by f and order) is returned first. If order is min, the item with minimum f(x) is returned first; if order is max, then it is the item with maximum f(x). Also supports dict-like lookup.""" def __init__(self, order=min, f=lambda x: x): self.A = [] self.order = order self.f = f def append(self, item): bisect.insort(self.A, (self.f(item), item)) def __len__(self): return len(self.A) def pop(self): if self.order == min: return self.A.pop(0)[1] else: return self.A.pop()[1] def __contains__(self, item): return any(item == pair[1] for pair in self.A) def __getitem__(self, key): for _, item in self.A: if item == key: return item def __delitem__(self, key): for i, (value, item) in enumerate(self.A): if item == key: self.A.pop(i) # ______________________________________________________________________________ # Useful Shorthands class Bool(int): """Just like `bool`, except values display as 'T' and 'F' instead of 'True' and 'False'""" __str__ = __repr__ = lambda self: 'T' if self else 'F' T = Bool(True) F = Bool(False)

Back | FazBrowse Home | New Git URL