/usr/share/pyshared/sympy/polys/monomialtools.py is in python-sympy 0.7.1.rc1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | """Tools and arithmetics for monomials of distributed polynomials. """
from sympy.core.mul import Mul
from sympy.core.singleton import S
from sympy.core.basic import C
from sympy.polys.polyerrors import ExactQuotientFailed
from sympy.utilities import cythonized
from sympy.core.compatibility import cmp
def monomials(variables, degree):
r"""
Generate a set of monomials of the given total degree or less.
Given a set of variables `V` and a total degree `N` generate
a set of monomials of degree at most `N`. The total number of
monomials is huge and is given by the following formula:
.. math::
\frac{(\#V + N)!}{\#V! N!}
For example if we would like to generate a dense polynomial of
a total degree `N = 50` in 5 variables, assuming that exponents
and all of coefficients are 32-bit long and stored in an array we
would need almost 80 GiB of memory! Fortunately most polynomials,
that we will encounter, are sparse.
**Examples**
Consider monomials in variables `x` and `y`::
>>> from sympy import monomials
>>> from sympy.abc import x, y
>>> sorted(monomials([x, y], 2))
[1, x, y, x**2, y**2, x*y]
>>> sorted(monomials([x, y], 3))
[1, x, y, x**2, x**3, y**2, y**3, x*y, x*y**2, x**2*y]
"""
if not variables:
return set([S.One])
else:
x, tail = variables[0], variables[1:]
monoms = monomials(tail, degree)
for i in range(1, degree+1):
monoms |= set([ x**i * m for m in monomials(tail, degree-i) ])
return monoms
def monomial_count(V, N):
r"""
Computes the number of monomials.
The number of monomials is given by the following formula:
.. math::
\frac{(\#V + N)!}{\#V! N!}
where `N` is a total degree and `V` is a set of variables.
**Examples**
>>> from sympy import monomials, monomial_count
>>> from sympy.abc import x, y
>>> monomial_count(2, 2)
6
>>> M = monomials([x, y], 2)
>>> sorted(M)
[1, x, y, x**2, y**2, x*y]
>>> len(M)
6
"""
return C.factorial(V + N) / C.factorial(V) / C.factorial(N)
def monomial_lex_key(monom):
"""Key function for sorting monomials in lexicographic order. """
return monom
def monomial_grlex_key(monom):
"""Key function for sorting monomials in graded lexicographic order. """
return (sum(monom), monom)
def monomial_grevlex_key(monom):
"""Key function for sorting monomials in reversed graded lexicographic order. """
return (sum(monom), tuple(reversed(monom)))
_monomial_key = {
'lex' : monomial_lex_key,
'grlex' : monomial_grlex_key,
'grevlex' : monomial_grevlex_key,
}
def monomial_key(order=None):
"""
Return a function defining admissible order on monomials.
The result of a call to :func:`monomial_key` is a function which should
be used as a key to :func:`sorted` built-in function, to provide order
in a set of monomials of the same length.
Currently supported monomial orderings are:
1. lex - lexicographic order (default)
2. grlex - graded lexicographic order
3. grevlex - reversed graded lexicographic order
If the input argument is not a string but has ``__call__`` attribute,
then it will pass through with an assumption that the callable object
defines an admissible order on monomials.
"""
if order is None:
return _monomial_key['lex']
if isinstance(order, str):
try:
return _monomial_key[order]
except KeyError:
raise ValueError("supported monomial orderings are 'lex', 'grlex' and 'grevlex', got %r" % order)
elif hasattr(order, '__call__'):
return order
else:
raise ValueError("monomial ordering specification must be a string or a callable, got %s" % order)
def monomial_lex_cmp(a, b):
return cmp(a, b)
def monomial_grlex_cmp(a, b):
return cmp(sum(a), sum(b)) or cmp(a, b)
def monomial_grevlex_cmp(a, b):
return cmp(sum(a), sum(b)) or cmp(tuple(reversed(b)), tuple(reversed(a)))
_monomial_order = {
'lex' : monomial_lex_cmp,
'grlex' : monomial_grlex_cmp,
'grevlex' : monomial_grevlex_cmp,
}
def monomial_cmp(order):
"""
Returns a function defining admissible order on monomials.
Currently supported orderings are:
1. lex - lexicographic order
2. grlex - graded lexicographic order
3. grevlex - reversed graded lexicographic order
"""
try:
return _monomial_order[order]
except KeyError:
raise ValueError("expected valid monomial order, got %s" % order)
@cythonized("a,b")
def monomial_mul(A, B):
"""
Multiplication of tuples representing monomials.
Lets multiply `x**3*y**4*z` with `x*y**2`::
>>> from sympy.polys.monomialtools import monomial_mul
>>> monomial_mul((3, 4, 1), (1, 2, 0))
(4, 6, 1)
which gives `x**4*y**5*z`.
"""
return tuple([ a + b for a, b in zip(A, B) ])
@cythonized("a,b,c")
def monomial_div(A, B):
"""
Division of tuples representing monomials.
Lets divide `x**3*y**4*z` by `x*y**2`::
>>> from sympy.polys.monomialtools import monomial_div
>>> monomial_div((3, 4, 1), (1, 2, 0))
(2, 2, 1)
which gives `x**2*y**2*z`. However::
>>> monomial_div((3, 4, 1), (1, 2, 2)) is None
True
`x*y**2*z**2` does not divide `x**3*y**4*z`.
"""
C = [ a - b for a, b in zip(A, B) ]
if all([ c >= 0 for c in C ]):
return tuple(C)
else:
return None
@cythonized("a,b")
def monomial_gcd(A, B):
"""
Greatest common divisor of tuples representing monomials.
Lets compute GCD of `x**3*y**4*z` and `x*y**2`::
>>> from sympy.polys.monomialtools import monomial_gcd
>>> monomial_gcd((3, 4, 1), (1, 2, 0))
(1, 2, 0)
which gives `x*y**2`.
"""
return tuple([ min(a, b) for a, b in zip(A, B) ])
@cythonized("a,b")
def monomial_lcm(A, B):
"""
Least common multiple of tuples representing monomials.
Lets compute LCM of `x**3*y**4*z` and `x*y**2`::
>>> from sympy.polys.monomialtools import monomial_lcm
>>> monomial_lcm((3, 4, 1), (1, 2, 0))
(3, 4, 1)
which gives `x**3*y**4*z`.
"""
return tuple([ max(a, b) for a, b in zip(A, B) ])
@cythonized("i,n")
def monomial_max(*monoms):
"""
Returns maximal degree for each variable in a set of monomials.
Consider monomials `x**3*y**4*z**5`, `y**5*z` and `x**6*y**3*z**9`.
We wish to find out what is the maximal degree for each of `x`, `y`
and `z` variables::
>>> from sympy.polys.monomialtools import monomial_max
>>> monomial_max((3,4,5), (0,5,1), (6,3,9))
(6, 5, 9)
"""
M = list(monoms[0])
for N in monoms[1:]:
for i, n in enumerate(N):
M[i] = max(M[i], n)
return tuple(M)
@cythonized("i,n")
def monomial_min(*monoms):
"""
Returns minimal degree for each variable in a set of monomials.
Consider monomials `x**3*y**4*z**5`, `y**5*z` and `x**6*y**3*z**9`.
We wish to find out what is the minimal degree for each of `x`, `y`
and `z` variables::
>>> from sympy.polys.monomialtools import monomial_min
>>> monomial_min((3,4,5), (0,5,1), (6,3,9))
(0, 3, 1)
"""
M = list(monoms[0])
for N in monoms[1:]:
for i, n in enumerate(N):
M[i] = min(M[i], n)
return tuple(M)
class Monomial(object):
"""Class representing a monomial, i.e. a product of powers. """
__slots__ = ['data']
def __init__(self, *data):
self.data = tuple(map(int, data))
def __hash__(self):
return hash((self.__class__.__name__, self.data))
def __repr__(self):
return "Monomial(%s)" % ", ".join(map(str, self.data))
def as_expr(self, *gens):
"""Convert a monomial instance to a SymPy expression. """
return Mul(*[ gen**exp for gen, exp in zip(gens, self.data) ])
def __eq__(self, other):
if isinstance(other, Monomial):
return self.data == other.data
else:
return False
def __ne__(self, other):
return not self.__eq__(other)
def __mul__(self, other):
if isinstance(other, Monomial):
return Monomial(*monomial_mul(self.data, other.data))
else:
raise TypeError("an instance of Monomial class expected, got %s" % other)
def __pow__(self, other):
n = int(other)
if not n:
return Monomial(*((0,)*len(self.data)))
elif n > 0:
data = self.data
for i in xrange(1, n):
data = monomial_mul(data, self.data)
return Monomial(*data)
else:
raise ValueError("a non-negative integer expected, got %s" % other)
def __div__(self, other):
if isinstance(other, Monomial):
result = monomial_div(self.data, other.data)
if result is not None:
return Monomial(*result)
else:
raise ExactQuotientFailed(self, other)
else:
raise TypeError("an instance of Monomial class expected, got %s" % other)
__floordiv__ = __truediv__ = __div__
def gcd(self, other):
"""Greatest common divisor of monomials. """
if isinstance(other, Monomial):
return Monomial(*monomial_gcd(self.data, other.data))
else:
raise TypeError("an instance of Monomial class expected, got %s" % other)
def lcm(self, other):
"""Least common multiple of monomials. """
if isinstance(other, Monomial):
return Monomial(*monomial_lcm(self.data, other.data))
else:
raise TypeError("an instance of Monomial class expected, got %s" % other)
@classmethod
def max(cls, *monomials):
"""Returns maximal degree for each variable in a set of monomials. """
return Monomial(*monomial_max(*[ monomial.data for monomial in monomials ]))
@classmethod
def min(cls, *monomials):
"""Returns minimal degree for each variable in a set of monomials. """
return Monomial(*monomial_min(*[ monomial.data for monomial in monomials ]))
|