2 Term Order for polynomials. 10 _INTERFACE_MSG =
"%s is interface" 16 A term order is primalily a function, which determines precedence 17 between two terms (or monomials). By the precedence, all terms 20 More precisely in terms of Python, a term order accepts two tuples 21 of integers, each of which represents power indices of the term, 22 and returns 0, 1 or -1 just like cmp built-in function. 24 A TermOrder object provides not only the precedence function, but 25 also a method to format a string for a polynomial, to tell degree, 26 leading coefficients, etc. 29 _PLUS_MINUS = re.compile(
r"(^-|\+ -)")
33 'comparator' accepts two tuples of integers, each of which 34 represents power indices of the term, and returns 0, 1 or -1 35 just like cmp built-in function. 37 if type(self)
is TermOrderInterface:
38 raise NotImplementedError(_INTERFACE_MSG % self.__class__.__name__)
41 def cmp(self, left, right):
43 Compare two indices left and right and determine precedence by 48 def bisect(self, array, elem, lo=0, hi=None):
50 Return the index where to insert item `elem' in a list `array', 51 assuming array is sorted with the order. (In the following, 52 a refers `array' and x refers `elem') 54 The return value i is such that all e in a[:i] have e <= x, and 55 all e in a[i:] have e > x. So if x already appears in the list, 56 a.insert(x) will insert just after the rightmost x already there. 58 Optional args lo (default 0) and hi (default len(a)) bound the 59 slice of a to be searched. 61 This function is based on the bisect.bisect_right of the Python 68 if self.
cmp(elem, array[mid]) < 0:
75 Return the formatted string of the polynomial. 79 def bisect(self, array, elem, lo=0, hi=None):
81 Return the index where to insert item `elem' in a list `array', 82 assuming array is sorted with the order. (In the following, 83 a refers `array' and x refers `elem') 85 The return value i is such that all e in a[:i] have e <= x, and 86 all e in a[i:] have e > x. So if x already appears in the list, 87 a.insert(x) will insert just after the rightmost x already there. 89 Optional args lo (default 0) and hi (default len(a)) bound the 90 slice of a to be searched. 92 This function is based on the bisect.bisect_right of the Python 99 if self.
cmp(elem, array[mid]) < 0:
106 Return the leading coefficient of polynomial 'polynom' with 107 respect to the term order. 109 raise NotImplementedError(_INTERFACE_MSG % self.__class__.__name__)
113 Return the leading term of polynomial 'polynom' as tuple of 114 (degree index, coefficient) with respect to the term order. 116 raise NotImplementedError(_INTERFACE_MSG % self.__class__.__name__)
121 term order for univariate polynomials. 123 One thing special to univariate case is that powers are not tuples 128 UnivarTermOrder(comparator) 130 'comparator' can be any callable that accepts two integers and 131 returns 0, 1 or -1 just like cmp, i.e. if they are equal it 132 returns 0, first one is greater 1, and otherwise -1. 133 Theoretically acceptable comparator is only the cmp function. 135 TermOrderInterface.__init__(self, comparator)
137 def format(self, polynom, varname="X", reverse=False):
139 Return the formatted string of the polynomial. 141 - 'polynom' must be a univariate polynomial. 142 - 'varname' can be set to the name of the variable (default to 144 - 'reverse' can be either True or False. If it's True, terms 145 appear in reverse (descending) order. 148 [base
for base
in polynom.iterbases()],
152 str_terms = [(
"%s * %s ** %d" % (polynom[d], varname, d))
for d
in degrees
if polynom[d]]
154 if 0
in degrees
and polynom[0]:
155 const_term = str(polynom[0])
156 if (hasattr(polynom,
"getCoefficientRing")
and 157 polynom[0] == polynom.getCoefficientRing().one):
159 str_terms[str_terms.index(
"%s * %s ** 0" % (polynom[0], varname))] = const_term
161 if 1
in degrees
and polynom[1]:
162 str_terms[str_terms.index(
"%s * %s ** 1" % (polynom[1], varname))] =
"%s * %s" % (polynom[1], varname)
163 result =
" + ".join(str_terms)
167 if hasattr(polynom,
"getCoefficientRing"):
168 one_times_x = re.compile(
r"(^| )%s \* %s" % (polynom.getCoefficientRing().one, varname))
170 one_times_x = re.compile(
r"(^| )1 \* %s" % varname)
171 result = one_times_x.sub(
" " + varname, result)
172 result = result.lstrip()
177 Return the degree of the polynomial 'polynom'. 179 if hasattr(polynom,
"degree"):
180 return polynom.degree()
182 for d
in polynom.iterbases():
189 Return the leading coefficient of polynomial 'polynom' with 190 respect to the term order. 192 if hasattr(polynom,
'leading_coefficient'):
193 return polynom.leading_coefficient()
202 Return the leading term of polynomial 'polynom' as tuple of 203 (degree, coefficient) with respect to the term order. 205 if hasattr(polynom,
'leading_term'):
206 return polynom.leading_term()
215 Return the least degree among all terms of the polynomial 218 This method is EXPERIMENTAL. 220 if hasattr(polynom,
"tail_degree"):
221 return polynom.tail_degree()
223 for d
in polynom.iterbases():
224 if degree == -1
or self.
comparator(degree, d) > 0:
236 A class of term orders for multivariate polynomials. 240 'comparator' accepts two tuples of integers, each of which 241 represents power indices of the term, and returns 0, 1 or -1 242 just like cmp built-in function. 246 def format(self, polynom, varnames=None, reverse=False, **kwds):
248 Return the formatted string of the polynomial. 250 An additional keyword argument 'varnames' is required to name 254 raise TypeError(
"keyword argument 'varnames' is required")
260 result =
" + ".join([self.
_format_term((base, polynom[base]), varnames)
for base
in bases
if polynom[base]])
264 if hasattr(polynom,
"getCoefficientRing"):
265 one_times = re.compile(
r"(^| )%s \* " % polynom.getCoefficientRing().one)
267 one_times = re.compile(
r"(^| )1 \* ")
268 result = one_times.sub(
" ", result)
270 result = result.lstrip()
277 Return formatted term string. 279 'term' is a tuple of indices and coefficient. 283 if term[1] == ring.getRing(term[1]).one:
286 powlist = [str(term[1])]
287 for v, d
in zip(varnames, term[0]):
289 powlist.append(
"%s ** %d" % (v, d))
296 return " * ".join(powlist)
300 Return the leading coefficient of polynomial 'polynom' with 301 respect to the term order. 303 if hasattr(polynom,
'leading_coefficient'):
304 return polynom.leading_coefficient()
305 return polynom[self.
_max(polynom.bases())]
309 Return the leading term of polynomial 'polynom' as tuple of 310 (degree index, coefficient) with respect to the term order. 312 if hasattr(polynom,
'leading_term'):
313 return polynom.leading_term()
314 max_indices = self.
_max(polynom.bases())
315 return max_indices, polynom[max_indices]
319 Return the maximum indices with respect to the comparator. 322 raise ValueError(
"max() arg is an empty sequence")
323 it = iter(indices_list)
333 Return a comparator of weight ordering. 335 The weight ordering is defined for arguments x and y that x < y 336 if w.x < w.y (dot products) or w.x == w.y and tie breaker tells 339 The option 'tie_breaker' is another comparator that will be used 340 if dot products with the weight vector leaves arguments tie. If 341 the option is None (default) and a tie breaker is indeed necessary 342 to order given arguments, a TypeError is raised. 344 def _order(mono, mial):
347 wx = sum(w * x
for (w, x)
in zip(weight, mono))
348 wy = sum(w * y
for (w, y)
in zip(weight, mial))
351 return tie_breaker(mono, mial)
357 Total degree lexicographic (or graded lexicographic) term order : 359 (1) sum(li) < sum(ri) or 360 (2) sum(li) = sum(ri) and 361 there exists i s.t. l0 == r0, ..., l(i-1) == r(i-1), li < ri. 363 sum_left, sum_right = sum(left), sum(right)
364 if sum_left != sum_right:
365 return cmp(sum_left, sum_right)
366 return cmp(left, right)
370 Total degree reverse lexicographic (or graded reverse 371 lexicographic) term order : 373 (1) sum(li) < sum(ri) or 374 (2) sum(li) = sum(ri) and 375 there exists i s.t. ln == rn, ..., l(i+1) == r(i+1), li > ri. 377 sum_left, sum_right = sum(left), sum(right)
378 if sum_left != sum_right:
379 return cmp(sum_left, sum_right)
380 return cmp(right[::-1], left[::-1])
385 total_degree_reverse_lexicographic_order =
MultivarTermOrder(_total_degree_reverse_lexicographic)
391 Return the sorted seq by using the comparator function mycmp. 395 return sorted(seq, cmp=mycmp)
398 def __init__(self, obj):
400 def __gt__(self, other):
401 return mycmp(self.obj, other.obj) > 0
402 def __ge__(self, other):
403 return mycmp(self.obj, other.obj) >= 0
404 def __lt__(self, other):
405 return mycmp(self.obj, other.obj) < 0
406 def __le__(self, other):
407 return mycmp(self.obj, other.obj) <= 0
408 def __cmp__(self, other):
409 return mycmp(self.obj, other.obj)
410 return sorted(seq, key=internal_cmp)