Ticket #11316: trac_11316.patch
File trac_11316.patch, 75.2 KB (added by , 10 years ago) |
---|
-
sage/crypto/mq/sr.py
# HG changeset patch # User Kwankyu Lee <ekwankyu@gmail.com> # Date 1305014300 -32400 # Node ID 294bf6fe3ba390d9c7c3145dd28d7c7bff605626 # Parent fb00ec75853019eb9799fd863b193fe82ee97c74 #11316: added weighted degree term orders diff -r fb00ec758530 -r 294bf6fe3ba3 sage/crypto/mq/sr.py
a b 1665 1665 1666 1666 sage: sr = mq.SR(2, 1, 1, 4) 1667 1667 sage: sr.block_order() 1668 degrevlex(16),degrevlex(16),degrevlex(4) term order 1668 Block term order with blocks: 1669 (Degree reverse lexicographic term order of length 16, 1670 Degree reverse lexicographic term order of length 16, 1671 Degree reverse lexicographic term order of length 4) 1669 1672 1670 1673 :: 1671 1674 -
sage/libs/singular/ring.pyx
diff -r fb00ec758530 -r 294bf6fe3ba3 sage/libs/singular/ring.pyx
a b 22 22 from sage.libs.singular.decl cimport number, lnumber, napoly, ring, currRing 23 23 from sage.libs.singular.decl cimport rChangeCurrRing, rCopy0, rComplete, rDelete 24 24 from sage.libs.singular.decl cimport omAlloc0, omStrDup, omAlloc, omAlloc0Bin, sip_sring_bin, rnumber_bin 25 from sage.libs.singular.decl cimport ringorder_dp, ringorder_Dp, ringorder_lp, ringorder_rp, ringorder_ds, ringorder_Ds, ringorder_ls, ringorder_M, ringorder_C 25 from sage.libs.singular.decl cimport ringorder_dp, ringorder_Dp, ringorder_lp, ringorder_rp, ringorder_ds, ringorder_Ds, ringorder_ls, ringorder_M, ringorder_C, ringorder_wp, ringorder_Wp, ringorder_ws, ringorder_Ws 26 26 from sage.libs.singular.decl cimport p_Copy 27 27 28 28 from sage.rings.integer cimport Integer … … 41 41 42 42 43 43 # mapping str --> SINGULAR representation 44 order_dict = {"dp":ringorder_dp, 45 "Dp":ringorder_Dp, 46 "lp":ringorder_lp, 47 "rp":ringorder_rp, 48 "ds":ringorder_ds, 49 "Ds":ringorder_Ds, 50 "ls":ringorder_ls, 51 } 44 order_dict = { 45 "dp": ringorder_dp, 46 "Dp": ringorder_Dp, 47 "lp": ringorder_lp, 48 "rp": ringorder_rp, 49 "ds": ringorder_ds, 50 "Ds": ringorder_Ds, 51 "ls": ringorder_ls, 52 "wp": ringorder_wp, 53 "Wp": ringorder_Wp, 54 "ws": ringorder_ws, 55 "Ws": ringorder_Ws, 56 } 52 57 53 58 cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: 54 59 """ … … 236 241 237 242 _ring.minpoly=<number*>nmp 238 243 239 nblcks = len(order.blocks )244 nblcks = len(order.blocks()) 240 245 offset = 0 241 246 242 247 _ring.wvhdl = <int **>omAlloc0((nblcks + 2) * sizeof(int *)) … … 250 255 _ring.OrdSgn = 1 251 256 252 257 for i from 0 <= i < nblcks: 253 if order[i].singular_str()[0] == 'M': 258 s = order[i].singular_str() 259 if s[0] == 'M': # matrix order 254 260 _ring.order[i] = ringorder_M 255 261 mtx = order[i].matrix().list() 256 m= <int *>omAlloc0(len(mtx)*sizeof(int))262 wv = <int *>omAlloc0(len(mtx)*sizeof(int)) 257 263 for j in range(len(mtx)): 258 m[j] = int(mtx[j]) 259 _ring.wvhdl[i] = m 260 else: 261 _ring.order[i] = order_dict.get(order[i].singular_str(), ringorder_dp) 264 wv[j] = int(mtx[j]) 265 _ring.wvhdl[i] = wv 266 elif s[0] == 'w' or s[0] == 'W': # weighted degree orders 267 _ring.order[i] = order_dict.get(s[:2], ringorder_dp) 268 wts = order[i].weights() 269 wv = <int *>omAlloc0(len(wts)*sizeof(int)) 270 for j in range(len(wts)): 271 wv[j] = int(wts[j]) 272 _ring.wvhdl[i] = wv 273 else: # ordinary orders 274 _ring.order[i] = order_dict.get(s, ringorder_dp) 262 275 _ring.block0[i] = offset + 1 263 276 if len(order[i]) == 0: # may be zero in some cases 264 277 _ring.block1[i] = offset + n -
sage/rings/polynomial/multi_polynomial_ring.py
diff -r fb00ec758530 -r 294bf6fe3ba3 sage/rings/polynomial/multi_polynomial_ring.py
a b 468 468 c = self.base_ring()(x) 469 469 return MPolynomial_polydict(self, {self._zero_tuple:c}) 470 470 471 472 473 471 class MPolynomialRing_polydict_domain(integral_domain.IntegralDomain, 474 472 MPolynomialRing_polydict, 475 473 MPolynomialRing_macaulay2_repr): 476 474 def __init__(self, base_ring, n, names, order): 477 order = TermOrder(order, n)475 order = TermOrder(order,n) 478 476 MPolynomialRing_polydict.__init__(self, base_ring, n, names, order) 479 477 480 478 def is_integral_domain(self, proof = True): … … 513 511 gens = [self(x) for x in gens] # this will even coerce from singular ideals correctly! 514 512 return multi_polynomial_ideal.MPolynomialIdeal(self, gens, **kwds) 515 513 516 517 514 def monomial_quotient(self,f, g, coeff=False): 518 515 """ 519 516 Return f/g, where both f and g are treated as monomials. … … 716 713 return 0,0 717 714 return 0,0 718 715 719 720 716 def monomial_divides(self, a, b): 721 717 """ 722 718 Return False if a does not divide b and True otherwise. -
sage/rings/polynomial/multi_polynomial_ring_generic.pyx
diff -r fb00ec758530 -r 294bf6fe3ba3 sage/rings/polynomial/multi_polynomial_ring_generic.pyx
a b 48 48 sage: A1(a) in A2 49 49 True 50 50 """ 51 order = TermOrder(order,n) 51 order = TermOrder(order,n) 52 52 53 if not base_ring.is_commutative(): 53 54 raise TypeError, "Base ring must be a commutative ring." 54 55 n = int(n) … … 252 253 _repr += " Size : %d Variables\n"%(n,) 253 254 offset = 0 254 255 i = 0 255 for order in T.blocks :256 for order in T.blocks(): 256 257 _repr += " Block % 2d : Ordering : %s\n"%(i,inv_singular_name_mapping.get(order.singular_str(), order.singular_str())) 257 258 _repr += " Names : %s\n"%(", ".join(names[offset:offset + len(order)])) 258 259 offset += len(order) -
sage/rings/polynomial/pbori.pyx
diff -r fb00ec758530 -r 294bf6fe3ba3 sage/rings/polynomial/pbori.pyx
a b 263 263 264 264 sage: R = BooleanPolynomialRing(5,'x',order='deglex(3),deglex(2)') 265 265 sage: R.term_order() 266 deglex(3),deglex(2) term order 266 Block term order with blocks: 267 (Degree lexicographic term order of length 3, 268 Degree lexicographic term order of length 2) 267 269 268 270 :: 269 271 … … 326 328 except KeyError: 327 329 raise ValueError, "Only lex, deglex, degrevlex orders are supported." 328 330 329 if len(order.blocks) > 1:331 if order.is_block_order(): 330 332 if pb_order_code is pblp: 331 333 raise ValueError, "Only deglex and degrevlex are supported for block orders." 332 334 elif pb_order_code is pbdlex: 333 335 pb_order_code = pbblock_dlex 334 336 elif pb_order_code is pbdp_asc: 335 337 pb_order_code = pbblock_dp_asc 336 for i in range(1, len(order.blocks )):337 if order[0] != order[i]:338 raise ValueError, "Each block must have the same order type (deglex or degrevlex) for block order ings."338 for i in range(1, len(order.blocks())): 339 if order[0].name() != order[i].name(): 340 raise ValueError, "Each block must have the same order type (deglex or degrevlex) for block orders." 339 341 340 342 if (pb_order_code is pbdlex) or (pb_order_code is pblp) or \ 341 343 (pb_order_code is pbblock_dlex): … … 347 349 else: 348 350 # pb_order_code is block_dp_asc: 349 351 bstart = 0 350 for i from 0 <= i < len(order.blocks ):352 for i from 0 <= i < len(order.blocks()): 351 353 bsize = len(order[i]) 352 354 for j from 0 <= j < bsize: 353 355 self.pbind[bstart + j] = bstart + bsize - j -1 … … 357 359 MPolynomialRing_generic.__init__(self, GF(2), n, names, order) 358 360 359 361 counter = 0 360 for i in range(len(order.blocks )-1):362 for i in range(len(order.blocks())-1): 361 363 counter += len(order[i]) 362 364 pb_append_block(counter) 363 365 … … 7056 7058 sage: change_ordering(block_dp_asc) 7057 7059 sage: append_ring_block(5) 7058 7060 sage: get_cring().term_order() 7059 deglex_asc(5),deglex_asc(5) term order 7061 Block term order with blocks: 7062 (deglex_asc term order of length 5, 7063 deglex_asc term order of length 5) 7060 7064 sage: change_ordering(lp) 7061 7065 7062 7066 sage: from polybori.blocks import * … … 7129 7133 else: 7130 7134 # pb_order_code is block_dp_asc: 7131 7135 bstart = 0 7132 for i from 0 <= i < len(T.blocks ):7136 for i from 0 <= i < len(T.blocks()): 7133 7137 bsize = len(T[i]) 7134 7138 for j from 0 <= j < bsize: 7135 7139 self.pbind[bstart + j] = bstart + j -
sage/rings/polynomial/polynomial_ring.py
diff -r fb00ec758530 -r 294bf6fe3ba3 sage/rings/polynomial/polynomial_ring.py
a b 688 688 except AttributeError: 689 689 return self.base_ring() 690 690 691 692 691 def characteristic(self): 693 692 """ 694 693 Return the characteristic of this polynomial ring, which is the -
sage/rings/polynomial/polynomial_ring_constructor.py
diff -r fb00ec758530 -r 294bf6fe3ba3 sage/rings/polynomial/polynomial_ring_constructor.py
a b 494 494 495 495 sage: R = BooleanPolynomialRing(5,'x',order='deglex(3),deglex(2)') 496 496 sage: R.term_order() 497 deglex(3),deglex(2) term order 497 Block term order with blocks: 498 (Degree lexicographic term order of length 3, 499 Degree lexicographic term order of length 2) 498 500 499 501 sage: R = BooleanPolynomialRing(3,'x',order='degrevlex') 500 502 sage: R.term_order() … … 531 533 532 534 from sage.rings.polynomial.term_order import TermOrder 533 535 from sage.rings.polynomial.pbori import set_cring 536 534 537 order = TermOrder(order, n) 535 538 536 539 key = ("pbori", names, n, order) -
sage/rings/polynomial/term_order.py
diff -r fb00ec758530 -r 294bf6fe3ba3 sage/rings/polynomial/term_order.py
a b 1 1 r""" 2 Term Orderings2 Term orders 3 3 4 Sage supports the following term order ings:4 Sage supports the following term orders: 5 5 6 Lexicographic (*lex*) 7 `x^a < x^b \Leftrightarrow \exists\; 0 \le i < n : a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i < b_i` 6 Lexicographic (lex) 7 `x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 8 This term order is called 'lp' in Singular. 8 9 9 10 EXAMPLES: 10 11 … … 22 23 sage: x^3*y^2*z^4 < x^3*y^2*z^1 23 24 False 24 25 25 This term ordering is called 'lp' in Singular. 26 27 Degree reverse lexicographic (*degrevlex*) 28 Let `deg(x^a) = a_0 + \cdots + a_{n-1},` then 29 `x^a < x^b \Leftrightarrow deg(x^a) < deg(x^b)` or 30 `deg(x^a) = deg(x^b)` and 31 `\exists\ 0 \le i < n: a_{n-1} = b_{n-1}, \ldots, a_{i+1} = b_{i+1}, a_i > b_i.` 26 Degree reverse lexicographic (degrevlex) 27 Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then 28 `x^a < x^b` if and only if `\deg(x^a) < \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 29 there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 30 This term order is called 'dp' in Singular. 32 31 33 32 EXAMPLES: 34 33 … … 46 45 sage: x^2*y*z^2 > x*y^3*z 47 46 False 48 47 49 This term ordering is called 'dp' in Singular. 50 51 Degree lexicographic (*deglex*) 52 Let `deg(x^a) = a_0 + \cdots + a_{n-1},` then 53 `x^a < x^b \Leftrightarrow deg(x^a) < deg(x^b)` or 54 `deg(x^a) = deg(x^b)` and 55 `\exists\ 0 \le i < n:a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i < b_i.` 48 Degree lexicographic (deglex) 49 Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then 50 `x^a < x^b` if and only if `\deg(x^a) < \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 51 there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 52 This term order is called 'Dp' in Singular. 56 53 57 54 EXAMPLES: 58 55 … … 70 67 sage: x^2*y*z^2 > x*y^3*z 71 68 True 72 69 73 This term order is called 'Dp' in Singular. 74 75 Inverse lexicographic (*invlex*) 76 `x^a < x^b \Leftrightarrow \exists\; 0 \le i < n : a_{n-1} = b_{n-1}, \ldots, a_{i+1} = b_{i+1}, a_i < b_i.` 70 Inverse lexicographic (invlex) 71 `x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i < b_i`. 72 This order is called 'rp' in Singular. 77 73 78 74 EXAMPLES: 79 75 … … 89 85 sage: x*y > z 90 86 False 91 87 92 This term order ingonly makes sense in a non-commutative setting88 This term order only makes sense in a non-commutative setting 93 89 because if P is the ring `k[x_1, \dots, x_n]` and term 94 order ing'invlex' then it is equivalent to the ring95 `k[x_n, \dots, x_1]` with term order ing'lex'.90 order 'invlex' then it is equivalent to the ring 91 `k[x_n, \dots, x_1]` with term order 'lex'. 96 92 97 This ordering is called 'rp' in Singular. 98 99 Negative lexicographic (*neglex*) 100 `x^a < x^b \Leftrightarrow \exists\; 0 \le i < n : a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i > b_i` 93 Negative lexicographic (neglex) 94 `x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i > b_i`. 95 This term order is called 'ls' in Singular. 101 96 102 97 EXAMPLES: 103 98 … … 115 110 sage: x*y > z 116 111 False 117 112 118 This term ordering is called 'ls' in Singular. 119 120 Negative degree reverse lexicographic (*negdegrevlex*) 121 Let `deg(x^a) = a_0 + \cdots + a_{n-1},` then 122 `x^a < x^b \Leftrightarrow deg(x^a) > deg(x^b)` or 123 `deg(x^a) = deg(x^b)` and 124 `\exists\ 0 \le i < n: a_{n-1} = b_{n-1}, \ldots, a_{i+1} = b_{i+1}, a_i > b_i.` 113 Negative degree reverse lexicographic (negdegrevlex) 114 Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then 115 `x^a < x^b` if and only if `\deg(x^a) > \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 116 there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 117 This term order is called 'ds' in Singular. 125 118 126 119 EXAMPLES: 127 120 … … 139 132 sage: x^2*y*z^2 > x*y^3*z 140 133 False 141 134 142 This term ordering is called 'ds' in Singular. 143 144 Negative degree lexicographic (*negdeglex*) 145 Let `deg(x^a) = a_0 + \cdots + a_{n-1},` then 146 `x^a < x^b \Leftrightarrow deg(x^a) > deg(x^b)` or 147 `deg(x^a) = deg(x^b)` and 148 `\exists\ 0 \le i < n: a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i < b_i.` 135 Negative degree lexicographic (negdeglex) 136 Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then 137 `x^a < x^b` if and only if `\deg(x^a) > \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 138 there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 139 This term order is called 'Ds' in Singular. 149 140 150 141 EXAMPLES: 151 142 … … 163 154 sage: x^2*y*z^2 > x*y^3*z 164 155 True 165 156 166 This term ordering is called 'Ds' in Singular. 157 Weighted degree reverse lexicographic (wdegrevlex) 158 Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then 159 `x^a < x^b` if and only if `\deg_w(x^a) < \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 160 there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 161 This term order is called 'wp' in Singular. 167 162 163 EXAMPLES: 168 164 169 Of these, only 'degrevlex', 'deglex', 'invlex' and 'lex' are global 170 orderings. 165 :: 171 166 172 Additionally all these monomial orderings may be combined to 173 product or block orderings, defined as: 167 sage: P.<x,y,z> = PolynomialRing(QQ, 3, order=TermOrder('wdegrevlex',(1,2,3))) 168 sage: x > y 169 False 170 sage: x > x^2 171 False 172 sage: x > 1 173 True 174 sage: x^1*y^2 > x^2*z 175 True 176 sage: y*z > x^3*y 177 False 174 178 175 Let `x = (x_0, \ldots, x_{n-1})` and 176 `y = (y_0, \ldots, y_{m-1})` be two ordered sets of 177 variables, `<_1` a monomial ordering on `k[x]` and 178 `<_2` a monomial ordering on `k[y]`. 179 Weighted degree lexicographic (wdeglex) 180 Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then 181 `x^a < x^b` if and only if `\deg_w(x^a) < \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 182 there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 183 This term order is called 'Wp' in Singular. 179 184 180 The product ordering (or block ordering) 181 `<\ := (<_1,<_2)` on `k[x,y]` is defined as: 182 `x^a y^b < x^A y^B \Leftrightarrow x^a <_1 x^A` or 183 `(x^a =x^A \textrm{ and } y^b <_2 y^B)`. 185 EXAMPLES: 184 186 185 These block orderings are constructed in Sage by giving a comma 186 separated list of monomial orderings with the length of each block 187 attached to them. 187 :: 188 189 sage: P.<x,y,z> = PolynomialRing(QQ, 3, order=TermOrder('wdeglex',(1,2,3))) 190 sage: x > y 191 False 192 sage: x > x^2 193 False 194 sage: x > 1 195 True 196 sage: x^1*y^2 > x^2*z 197 False 198 sage: y*z > x^3*y 199 False 200 201 Negative weighted degree reverse lexicographic (negwdegrevlex) 202 Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then 203 `x^a < x^b` if and only if `\deg_w(x^a) > \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 204 there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 205 This term order is called 'ws' in Singular. 206 207 EXAMPLES: 208 209 :: 210 211 sage: P.<x,y,z> = PolynomialRing(QQ, 3, order=TermOrder('negwdegrevlex',(1,2,3))) 212 sage: x > y 213 True 214 sage: x > x^2 215 True 216 sage: x > 1 217 False 218 sage: x^1*y^2 > x^2*z 219 True 220 sage: y*z > x^3*y 221 False 222 223 Negative weighted degree lexicographic (negwdeglex) 224 Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then 225 `x^a < x^b` if and only if `\deg_w(x^a) > \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 226 there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 227 This term order is called 'Ws' in Singular. 228 229 EXAMPLES: 230 231 :: 232 233 sage: P.<x,y,z> = PolynomialRing(QQ, 3, order=TermOrder('negwdeglex',(1,2,3))) 234 sage: x > y 235 True 236 sage: x > x^2 237 True 238 sage: x > 1 239 False 240 sage: x^1*y^2 > x^2*z 241 False 242 sage: y*z > x^3*y 243 False 244 245 Of these, only 'degrevlex', 'deglex', 'wdegrevlex', 'wdeglex', 'invlex' and 'lex' are global 246 orders. 247 248 Sage also supports matrix term order. Given a square matrix `A`, 249 250 `x^a <_A x^b` if and only if `Aa < Ab` 251 252 where `<` is the lexicographic term order. 253 254 EXAMPLE:: 255 256 sage: m = matrix(2,[2,3,0,1]); m 257 [2 3] 258 [0 1] 259 sage: T = TermOrder(m); T 260 Matrix term order with matrix 261 [2 3] 262 [0 1] 263 sage: P.<a,b> = PolynomialRing(QQ,2,order=T) 264 sage: P 265 Multivariate Polynomial Ring in a, b over Rational Field 266 sage: a > b 267 False 268 sage: a^3 < b^2 269 True 270 sage: S = TermOrder('M(2,3,0,1)') 271 sage: T == S 272 True 273 274 Additionally all these monomial orders may be combined to product or block orders, defined as: 275 276 Let `x = (x_1, x_2, \dots, x_n)` and `y = (y_1, y_2, \dots, y_m)` be two ordered sets of 277 variables, `<_1` a monomial order on `k[x]` and `<_2` a monomial order on `k[y]`. 278 279 The product order (or block order) `<` `:=` `(<_1,<_2)` on `k[x,y]` is defined as: 280 `x^a y^b < x^A y^B` if and only if `x^a <_1 x^A` or (`x^a =x^A` and `y^b <_2 y^B`). 281 282 These block orders are constructed in Sage by giving a comma separated list of monomial orders 283 with the length of each block attached to them. 188 284 189 285 EXAMPLE: 190 286 191 As an example, consider constructing a block order ingwhere the287 As an example, consider constructing a block order where the 192 288 first four variables are compared using the degree reverse 193 lexicographical order ingwhile the last two variables in the second194 block are compared using negative lexicographical order ing.289 lexicographical order while the last two variables in the second 290 block are compared using negative lexicographical order. 195 291 196 292 :: 197 293 … … 214 310 sage: a > e^4 215 311 True 216 312 217 Finally Sage supports matrix term order. Given a square matrix `A`, 313 If any other unsupported term order is given the provided string 314 can be forced to be passed through as is to Singular, Macaulay2, and Magma. 315 This ensures that it is for example possible to calculate a Groebner 316 basis with respect to some term order Singular supports but Sage 317 doesn't:: 218 318 219 `x^a < x^b \Leftrightarrow x^{Aa} <_{\mathrm{lex}} x^{Ab}` 220 221 where `<_{\mathrm{lex}}` is the lexicographic term order. 222 223 EXAMPLE:: 224 225 sage: m = matrix(2,[2,3,0,1]); m 226 [2 3] 227 [0 1] 228 sage: T = TermOrder(m); T 229 Matrix term order with matrix 230 [2 3] 231 [0 1] 232 sage: P.<a,b> = PolynomialRing(QQ,2,order=T) 233 sage: P 234 Multivariate Polynomial Ring in a, b over Rational Field 235 sage: a > b 236 False 237 sage: a^3 < b^2 238 True 239 sage: S = TermOrder('M(2,3,0,1)') 240 sage: T == S 241 True 242 243 A matrix term ordering is not allowed in block ordering yet:: 244 245 sage: T+S 319 sage: T = TermOrder("royalorder") 246 320 Traceback (most recent call last): 247 321 ... 248 NotImplementedError: Cannot use a matrix term order as a block. 249 250 If any other unsupported term ordering is given the provided string 251 is passed through as is to Singular, Macaulay2, and Magma. This 252 ensures that it is for example possible to calculate a Groebner 253 basis with respect to some term ordering Singular supports but Sage 254 doesn't. However a warning is issued to make the user aware of the 255 situation and potential typos:: 256 257 sage: T = TermOrder("royalorder") 258 verbose 0 (...: term_order.py, __init__) Term ordering 'royalorder' unknown. 259 322 TypeError: Unknown term order 'royalorder' 323 sage: T = TermOrder("royalorder",force=True) 324 sage: T 325 royalorder term order 326 sage: T.singular_str() 327 'royalorder' 328 260 329 AUTHORS: 261 330 262 - David Joyner and William Stein: initial version 263 multi_polynomial_ring 331 - David Joyner and William Stein: initial version of multi_polynomial_ring 264 332 265 333 - Kiran S. Kedlaya: added macaulay2 interface 266 334 267 - Martin Albrecht: implemented native term order ings, refactoring335 - Martin Albrecht: implemented native term orders, refactoring 268 336 269 - Kwankyu Lee (2010-06): implemented matrix term ordering337 - Kwankyu Lee: implemented matrix and weighted degree term orders, refactoring 270 338 """ 271 339 272 import re 273 from sage.structure.sage_object import SageObject 340 import re 341 from sage.structure.sage_object import SageObject 274 342 275 343 print_name_mapping = { 276 'lex' :'Lexicographic', 277 'invlex' :'Inverse Lexicographic', 278 'degrevlex' :'Degree reverse lexicographic', 279 'deglex' :'Degree lexicographic', 280 'neglex' :'Negative lexicographic', 281 'negdegrevlex' :'Negative degree reverse lexicographic', 282 'negdeglex' :'Negative degree lexicographic'} 344 'lex' : 'Lexicographic', 345 'invlex' : 'Inverse lexicographic', 346 'degrevlex' : 'Degree reverse lexicographic', 347 'deglex' : 'Degree lexicographic', 348 'neglex' : 'Negative lexicographic', 349 'negdegrevlex' : 'Negative degree reverse lexicographic', 350 'negdeglex' : 'Negative degree lexicographic', 351 'wdegrevlex' : 'Weighted degree reverse lexicographic', 352 'wdeglex' : 'Weighted degree lexicographic', 353 'negwdegrevlex' : 'Negative weighted degree reverse lexicographic', 354 'negwdeglex' : 'Negative weighted degree lexicographic', 355 } 283 356 284 357 singular_name_mapping = { 285 'lex' :'lp', 286 'invlex' :'rp', 287 'degrevlex' :'dp', 288 'deglex' :'Dp', 289 'neglex' :'ls', 290 'negdegrevlex' :'ds', 291 'negdeglex' :'Ds'} 358 'lex' : 'lp', 359 'invlex' : 'rp', 360 'degrevlex' : 'dp', 361 'deglex' : 'Dp', 362 'neglex' : 'ls', 363 'negdegrevlex' : 'ds', 364 'negdeglex' : 'Ds', 365 'wdegrevlex' : 'wp', 366 'wdeglex' : 'Wp', 367 'negwdegrevlex' : 'ws', 368 'negwdeglex' : 'Ws', 369 } 292 370 293 inv_singular_name_mapping = { 294 'lp' :'lex', 295 'rp' :'invlex', 296 'dp' :'degrevlex', 297 'Dp' :'deglex', 298 'ls' :'neglex', 299 'ds' :'negdegrevlex', 300 'Ds' :'negdeglex'} 371 inv_singular_name_mapping = dict(zip(singular_name_mapping.values(),singular_name_mapping.keys())) 301 372 302 373 macaulay2_name_mapping = { 303 'lex' :'Lex', 304 'revlex' :'RevLex, Global=>false', 305 'degrevlex' :'GRevLex', 306 'deglex' :'GLex'} 374 'lex' : 'Lex', 375 'revlex' : 'RevLex, Global=>false', 376 'degrevlex' : 'GRevLex', 377 'deglex' : 'GLex', 378 } 307 379 308 inv_macaulay2_name_mapping = { 309 'Lex' :'lex', 310 'RevLex,Global=>false' :'revlex', 311 'GRevLex' :"degrevlex", 312 'GLex' :'deglex'} 380 inv_macaulay2_name_mapping = dict(zip(macaulay2_name_mapping.values(),macaulay2_name_mapping.keys())) 313 381 314 magma_name_mapping = { 315 'lex' :'"lex"', 316 'degrevlex' :'"grevlex"', 317 'deglex' :'"glex"'} 382 magma_name_mapping = { 383 'lex' : '"lex"', 384 'degrevlex' : '"grevlex"', 385 'deglex' : '"glex"', 386 } 318 387 319 lp_description = """ 320 Lexicographic (lex) term ordering. 388 inv_magma_name_mapping = dict(zip(magma_name_mapping.values(),magma_name_mapping.keys())) 321 389 322 $x^a < x^b <=> \exists\; 0 <= i < n : a_0 = b_0, ..., a_{i-1} = b_{i-1}, a_i < b_i$ 390 lex_description = """ 391 Lexicographic (lex) term order. 392 393 `x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 323 394 """ 324 395 325 dp_description = """326 Degree reverse lexicographic (degrevlex) term ordering.396 invlex_description = """ 397 Inverse lexicographic (invlex) term order. 327 398 328 Let $deg(x^a) = a_0 + ... + a_{n-1},$ then $x^a < x^b <=> deg(x^a) < deg(x^b)$ or 329 $deg(x^a) = deg(x^b)$ and $\exists\ 0 <= i < n: a_{n-1} = b_{n-1}, ..., a_{i+1} = b_{i+1}, a_i > b_i.$ 399 `x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i < b_i`. 400 """ 401 402 degrevlex_description = """ 403 Degree reverse lexicographic (degrevlex) term order. 404 405 Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then 406 `x^a < x^b` if and only if `\deg(x^a) < \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 407 there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 330 408 """ 331 409 332 Dp_description = """333 Degree lexicographic (deglex) term order ing.410 deglex_description = """ 411 Degree lexicographic (deglex) term order. 334 412 335 Let $deg(x^a) = a_0 + \cdots + a_{n-1},$ then $x^a < x^b \Leftrightarrow deg(x^a) < deg(x^b)$ or 336 $deg(x^a) = deg(x^b)$ and $\exists\ 0 \le i < n:a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i < b_i.$ 413 Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then 414 `x^a < x^b` if and only if `\deg(x^a) < \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 415 there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 337 416 """ 338 417 339 rp_description = """340 Inverse lexicographic (invlex) term ordering.418 neglex_description = """ 419 Negative lexicographic (neglex) term order. 341 420 342 $x^a < x^b \Leftrightarrow \exists\; 0 \le i < n : a_{n-1} = b_{n-1}, \ldots, a_{i+1} = b_{i+1}, a_i < b_i.$ 421 `x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i > b_i`. 343 422 """ 344 423 345 ls_description = """346 Negative lexicographic (neglex) term ordering.424 negdegrevlex_description = """ 425 Negative degree reverse lexicographic (negdegrevlex) term order. 347 426 348 $x^a < x^b \Leftrightarrow \exists\; 0 \le i < n : a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i > b_i$ 427 Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then 428 `x^a < x^b` if and only if `\deg(x^a) > \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 429 there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 430 """ 431 432 negdeglex_description = """ 433 Negative degree lexicographic (negdeglex) term order. 434 435 Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then 436 `x^a < x^b` if and only if `\deg(x^a) > \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 437 there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 438 """ 439 440 wdegrevlex_description = """ 441 Weighted degree reverse lexicographic (wdegrevlex) term order. 442 443 Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then 444 `x^a < x^b` if and only if `\deg_w(x^a) < \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 445 there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 349 446 """ 447 448 wdeglex_description = r""" 449 Weighted degree lexicographic (wdeglex) term order. 350 450 351 ds_description = """ 352 Negative degree reverse lexicographic (negdegrevlex) term ordering. 451 Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then 452 `x^a < x^b` if and only if `\deg_w(x^a) < \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 453 there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 454 """ 353 455 354 Let $deg(x^a) = a_0 + \cdots + a_{n-1},$ then $x^a < x^b \Leftrightarrow deg(x^a) > deg(x^b)$ or 355 $deg(x^a) = deg(x^b)$ and $\exists\ 0 \le i < n: a_{n-1} = b_{n-1}, \ldots, a_{i+1} = b_{i+1}, a_i > b_i.$ 456 negwdegrevlex_description = """ 457 Negative weighted degree reverse lexicographic (negwdegrevlex) term order. 458 459 Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then 460 `x^a < x^b` if and only if `\deg_w(x^a) > \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 461 there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 356 462 """ 463 464 negwdeglex_description = """ 465 Negative weighted degree lexicographic (negwdeglex) term order. 357 466 358 Ds_description = """ 359 Negative degree lexicographic (negdeglex) term ordering. 467 Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then 468 `x^a < x^b` if and only if `\deg_w(x^a) > \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 469 there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 470 """ 360 471 361 Let $deg(x^a) = a_0 + \cdots + a_{n-1},$ then $x^a < x^b \Leftrightarrow deg(x^a) > deg(x^b)$ or 362 $deg(x^a) = deg(x^b)$ and $\exists\ 0 \le i < n: a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i < b_i.$ 363 """ 472 matrix_description = """ 473 Matrix term order defined by a matrix A. 474 475 `x^a < x^b` if and only if `x^{Aa} < x^{Ab}` where `<` is the lexicographic term order. 476 """ 477 478 block_description = """ 479 Block term order defined by term orders `<_1, <_2, \dots, <_n`. 480 481 `x^a < x^b` if and only if `a = b` with respect to the first `n-1` term orders and `a <_n b` 482 with respect to the `n`th term order `<_n`. 483 """ 364 484 365 485 description_mapping = { 366 "lp":lp_description, 367 "dp":dp_description, 368 "Dp":Dp_description, 369 "rp":rp_description, 370 "ls":ls_description, 371 "Ds":Ds_description, 372 "ds":ds_description} 486 'lex' : lex_description, 487 'invlex' : invlex_description, 488 'degrevlex' : degrevlex_description, 489 'deglex' : deglex_description, 490 'neglex' : neglex_description, 491 'negdegrevlex' : negdegrevlex_description, 492 'negdeglex' : negdeglex_description, 493 'wdeglex' : wdeglex_description, 494 'wdegrevlex' : wdegrevlex_description, 495 'negwdegrevlex' : negwdegrevlex_description, 496 'negwdeglex' : negwdeglex_description, 497 'matrix' : matrix_description, 498 'block' : block_description, 373 499 374 M_description = """ 375 Matrix term ordering defined by a matrix A. 376 377 $x^a < x^b \Leftrightarrow x^{Aa} <_{\mathrm{lex}} x^{Ab}$ 378 where $<_{\mathrm{lex}}$ is the lexicographic term ordering 379 """ 500 } 380 501 381 502 class TermOrder(SageObject): 382 503 r""" 383 504 A term order. 384 505 385 506 See ``sage.rings.polynomial.term_order`` for details 386 on supported term order ings.507 on supported term orders. 387 508 """ 388 def __init__(self, name='lex', n =0, blocks=True, force=False):509 def __init__(self, name='lex', n=0, blocks=True, force=False): 389 510 """ 390 Construct a new term order ingobject.511 Construct a new term order object. 391 512 392 513 INPUT: 393 514 394 - ``name`` - name of the term order ing(default: lex)515 - ``name`` - name of the term order (default: lex) 395 516 396 - ``n`` - number of variables in the polynomial ring 397 (default: 0) 517 - ``n`` - number of variables (default is `0`) or weights for 518 weighted degree orders 519 520 - ``blocks`` - this is deprecated. 398 521 399 - ``blocks`` - controls whether a list of blocks is 400 maintained (internal use only, default:True) 401 402 - ``force`` - ignore unknown term orderings. 522 - ``force`` - ignore unknown term orders. 403 523 404 524 See the ``sage.rings.polynomial.term_order`` module 405 for help which names and order ings are available.525 for help which names and orders are available. 406 526 407 527 EXAMPLES:: 408 528 … … 412 532 sage: loads(dumps(t)) == t 413 533 True 414 534 415 We can construct block order ings directly as535 We can construct block orders directly as 416 536 417 537 :: 418 538 419 539 sage: TermOrder('degrevlex(3),neglex(2)') 420 degrevlex(3),neglex(2) term order 540 Block term order with blocks: 541 (Degree reverse lexicographic term order of length 3, 542 Negative lexicographic term order of length 2) 421 543 422 544 or by adding together the blocks:: 423 545 424 546 sage: t1 = TermOrder('degrevlex',3) 425 547 sage: t2 = TermOrder('neglex',2) 426 548 sage: t1 + t2 427 degrevlex(3),neglex(2) term order 428 sage: t2 + t1 429 neglex(2),degrevlex(3) term order 549 Block term order with blocks: 550 (Degree reverse lexicographic term order of length 3, 551 Negative lexicographic term order of length 2) 552 sage: t3 = TermOrder('wdeglex',(1,2)) 553 sage: t1 + t3 554 Block term order with blocks: 555 (Degree reverse lexicographic term order of length 3, 556 Weighted degree lexicographic term order with weights (1, 2)) 430 557 431 558 .. note:: 432 559 433 560 The optional `n` parameter is not necessary if only 434 non-block order ings like `deglex` are435 constructed. However, it is useful if block order ings are561 non-block orders like `deglex` are 562 constructed. However, it is useful if block orders are 436 563 to be constructed from this ``TermOrder`` object later. 437 """ 564 """ 438 565 if isinstance(name, TermOrder): 439 if n == 0 and len(name) > 0: 440 n = len(name) 566 self.__copy(name) 567 if n > 0 and not name.is_block_order() and not name.is_weighted_degree_order(): 568 self.__length = n 569 return 570 571 if isinstance(name, str): 572 name = name.lower() 573 else: 441 574 try: 442 force = name.__force 443 except AttributeError: # pickled old TermOrders don't have this field 444 force = False 445 name = name.name() 446 else: 447 try: # name is a matrix 448 name = 'M('+','.join(["%i"%(i,) for i in name.list()])+')' 575 if not isinstance(name, (tuple,list)): 576 name = name.list() # name may be a matrix 577 name = tuple(name) 449 578 except: 450 pass 451 name = name.lower() 579 raise TypeError, "%s is not a valid term order"%(name,) 452 580 453 split_pattern = "([^(),]+(?:\([^()]*\)[^(),]*)*)" # split by outermost commas 454 length_pattern = re.compile("\(([0-9]+)\)$") # match with parenthesized block length at end 455 matrix_pattern = "([0-9,]+)" # match with list of integers 456 457 self.__force = force 458 self.__length = 0 459 self.__name = "" 460 self.__singular_str = "" 461 self.__macaulay2_str = "" 462 self.__magma_str = "" 463 self.__matrix = None # only for matrix ordering 464 465 block_names = re.findall(split_pattern,name) 581 self.__blocks = tuple() 582 self.__weights = None 583 self.__matrix = None 466 584 467 if len(block_names) == 0: 468 raise TypeError, "No term ordering specified" 469 elif len(block_names) == 1: 470 name = block_names[0] 471 if re.match('m\(([0-9,]+)\)$',name) != None: # matrix ordering 472 integers_str = re.search(matrix_pattern,name).group() 473 integers = map(int,integers_str.split(',')) 474 475 if n == 0: 476 from math import sqrt 477 n = int(sqrt(len(integers))) 478 479 if len(integers) != n**2: 480 raise TypeError, "%s does not specify a square matrix"%(name,) 481 482 self.__matrix = [] 483 for idx in range(0,len(integers),n): 484 self.__matrix.append(integers[idx:idx+n]) 485 486 self.__length = n 487 self.__name = "M(%s)"%(integers_str,) 488 self.__singular_str = "M(%s)"%(integers_str,) 489 self.__macaulay2_str = "" # Macaulay2 does not support matrix term order directly 490 self.__magma_str = '"weight",[%s]'%(integers_str,) 491 self.__doc__ = M_description 492 493 else: # simple ordering 494 self.__length = n 495 self.__name = name 496 self.__singular_str = singular_name_mapping.get(name,name) 497 self.__macaulay2_str = macaulay2_name_mapping.get(name,name) 498 self.__magma_str = magma_name_mapping.get(name,name) 499 500 if self.__singular_str in description_mapping: 501 self.__doc__ = description_mapping[self.__singular_str] 502 503 from sage.misc.misc import verbose 504 if blocks: 505 # we allow deglex_asc here which is used by PolyBoRi 506 if self.__matrix == None and \ 507 name not in singular_name_mapping.keys() and \ 508 name not in singular_name_mapping.values() and not force: 509 verbose("Term ordering '%s' unknown."%name,level=0) 510 self.blocks = (TermOrder(self.__name,n,blocks=False,force=force),) 511 else: 512 self.blocks = tuple() 513 514 else: # block ordering 585 if name == "block": # block term order with blocks in a list 515 586 length = 0 516 587 blocks = [] 517 588 name_str = [] 518 589 singular_str = [] 519 590 macaulay2_str = [] 520 591 521 for block in block_names: 522 try: 523 block_name, block_length, _ = re.split(length_pattern,block) 524 except ValueError: 525 raise TypeError, "%s is not a valid term ordering"%(name,) 592 for t in n: 593 if not isinstance(t, TermOrder): 594 try: 595 t = TermOrder(t,force=True) 596 except: 597 raise TypeError 598 if t.name() == 'block': 599 blocks = blocks + list(t.blocks()) 600 singular_str.append("%s"%(t.singular_str()[1:-1],)) # [1:-1] is needed to remove parenthesis 601 macaulay2_str.append("%s"%(t.macaulay2_str()[1:-1],)) 602 else: 603 if len(t) == 0: 604 raise ArithmeticError, "Can only concatenate term orders with length attribute." 605 blocks.append(t) 606 if t.is_weighted_degree_order(): # true if t is a matrix order as well 607 singular_str.append("%s"%(t.singular_str(),)) 608 else: 609 singular_str.append("%s(%d)"%(t.singular_str(), len(t))) 610 macaulay2_str.append("%s => %d"%(t.macaulay2_str(), len(t))) 611 length += len(t) 526 612 527 block_length = int(block_length) 613 self.__length = length 614 self.__name = "block" 615 self.__singular_str = "(" + ",".join(singular_str) + ")" 616 self.__macaulay2_str = "{" + ",".join(macaulay2_str) + "}" 617 self.__magma_str = "" # Magma does not support block order 618 self.__blocks = tuple(blocks) 619 elif isinstance(name, str) and not (isinstance(n, tuple) or isinstance(n,list)): # string representation of simple or block orders 620 split_pattern = "([^(),]+(?:\([^()]*\)[^(),]*)*)" # split by outermost commas 621 block_names = re.findall(split_pattern,name) 528 622 529 blocks.append( TermOrder(block_name,block_length,force=force) ) 530 name_str.append("%s(%d)"%(block_name,block_length)) 531 singular_str.append("%s(%d)"%(singular_name_mapping.get(block_name, block_name), block_length)) 532 macaulay2_str.append("%s => %d"%(macaulay2_name_mapping.get(block_name, block_name), block_length)) 623 if len(block_names) == 0: 624 raise TypeError, "No term order specified" 625 elif len(block_names) == 1: 626 name = block_names[0] 627 match = re.match('m\(([-+0-9,]+)\)$',name) 628 if match: # matrix term order 629 m = map(int,match.groups()[0].split(',')) # replace match.groups()[0] with match.group(1) later 630 self.__copy(TermOrder(m)) 631 else: # simple order 632 if name not in print_name_mapping.keys() and name not in singular_name_mapping.values() and not force: 633 raise TypeError, "Unknown term order '%s'"%(name,) 634 self.__length = n 635 self.__name = name 636 self.__singular_str = singular_name_mapping.get(name,name) 637 self.__macaulay2_str = macaulay2_name_mapping.get(name,name) 638 self.__magma_str = magma_name_mapping.get(name,name) 639 else: # len(block_names) > 1, and hence block order represented by a string 640 length = 0 641 blocks = [] 642 name_str = [] 643 singular_str = [] 644 macaulay2_str = [] 533 645 534 length += block_length 646 for block in block_names: 647 try: 648 length_pattern = re.compile("\(([0-9]+)\)$") # match with parenthesized block length at end 649 block_name, block_length, _ = re.split(length_pattern,block) 650 block_length = int(block_length) 651 blocks.append( TermOrder(block_name,block_length,force=force) ) 652 except: 653 raise TypeError, "%s is not a valid term order"%(name,) 654 length += block_length 535 655 536 self.blocks = tuple(blocks) 537 self.__length = length 538 self.__name = ",".join(name_str) 539 self.__singular_str = "(" + ",".join(singular_str) + ")" 540 self.__macaulay2_str = "(" + ",".join(macaulay2_str) + ")" 541 self.__magma_str = "" # Magma does not support block order 656 if n != 0 and length != n: 657 raise TypeError, "Term order length does not match the number of generators" 658 self.__copy(TermOrder('block', blocks)) 659 elif isinstance(name, str) and (isinstance(n, tuple) or isinstance(n,list)): # weighted degree term orders 660 if name not in print_name_mapping.keys() and name not in singular_name_mapping.values() and not force: 661 raise TypeError, "Unknown term order '%s'"%(name,) 662 weights = tuple(n) # n is a tuple of weights 663 664 self.__length = len(weights) 665 self.__name = name 666 self.__singular_str = singular_name_mapping.get(name,name) + '(' + ','.join([str(w) for w in weights]) + ')' 667 self.__macaulay2_str = "" 668 self.__magma_str = "" 669 self.__weights = weights # defined only for weighted degree orders 670 elif isinstance(name, tuple): # name represents a matrix 671 if n == 0: 672 from math import sqrt 673 n = int(sqrt(len(name))) 674 if n**2 != len(name): 675 raise TypeError, "%s does not specify a square matrix"%(name,) 542 676 543 if n != 0 and self.__length != n: 544 raise TypeError, "Term order length does not match the number of generators" 677 int_str = ','.join([str(int(e)) for e in name]) 678 679 self.__length = n 680 self.__name = "matrix" 681 self.__singular_str = "M(%s)"%(int_str,) 682 self.__macaulay2_str = "" # Macaulay2 does not support matrix term order directly 683 self.__magma_str = '"weight",[%s]'%(int_str,) 684 685 from sage.matrix.constructor import matrix 686 self.__matrix = matrix(n,name) # defined only for matrix term order 687 self.__weights = name[:n] # the first row of the matrix gives weights 688 else: 689 raise TypeError, "%s is not a valid term order"%(name,) 690 691 self.__doc__ = description_mapping.get(self.__name, "No description available") 692 693 def __copy(self, other): 694 """ 695 Copy other term order to self. 696 697 EXAMPLE:: 698 699 sage: t = TermOrder('lex') 700 sage: s = TermOrder(t) 701 sage: t == s # indirect test 702 True 703 """ 704 self.__length = other._TermOrder__length 705 self.__name = other._TermOrder__name 706 self.__singular_str = other._TermOrder__singular_str 707 self.__macaulay2_str = other._TermOrder__macaulay2_str 708 self.__magma_str = other._TermOrder__magma_str 709 self.__blocks = other._TermOrder__blocks 710 711 self.__matrix = other._TermOrder__matrix 712 self.__weights = other._TermOrder__weights 545 713 546 714 def __getattr__(self,name): 547 715 """ … … 550 718 EXAMPLE:: 551 719 552 720 sage: TermOrder('lex').compare_tuples 553 <bound method TermOrder.compare_tuples_l pof Lexicographic term order>721 <bound method TermOrder.compare_tuples_lex of Lexicographic term order> 554 722 555 723 :: 556 724 557 725 sage: TermOrder('deglex').compare_tuples 558 <bound method TermOrder.compare_tuples_ Dpof Degree lexicographic term order>726 <bound method TermOrder.compare_tuples_deglex of Degree lexicographic term order> 559 727 """ 560 728 if name == 'compare_tuples': 561 if len(self.blocks) <= 1: 562 if self.__matrix != None: 563 return self.compare_tuples_matrix 564 else: 565 return getattr(self,'compare_tuples_'+self.__singular_str) 566 else: 567 return self.compare_tuples_block 729 return getattr(self,'compare_tuples_'+self.__name) 568 730 elif name == 'greater_tuple': 569 if len(self.blocks) <= 1: 570 if self.__matrix != None: 571 return self.greater_tuple_matrix 572 else: 573 return getattr(self,'greater_tuple_'+self.__singular_str) 574 else: 575 return self.greater_tuple_block 731 return getattr(self,'greater_tuple_'+self.__name) 576 732 else: 577 733 raise AttributeError,name 578 734 … … 596 752 False 597 753 """ 598 754 for row in self.__matrix: 599 mf = sum(l*r for (l,r) in zip(row,f))600 mg = sum(l*r for (l,r) in zip(row,g))755 sf = sum(l*r for (l,r) in zip(row,f)) 756 sg = sum(l*r for (l,r) in zip(row,g)) 601 757 602 if mf > mg:758 if sf > sg: 603 759 return 1 604 elif mf < mg:760 elif sf < sg: 605 761 return -1 606 762 return 0 607 763 608 def compare_tuples_l p(self,f,g):764 def compare_tuples_lex(self,f,g): 609 765 """ 610 766 Compares two exponent tuples with respect to the lexicographical 611 767 term order. … … 624 780 sage: x > 1 625 781 True 626 782 """ 627 628 if f>g: 783 if f > g: 629 784 return 1 630 elif f <g:785 elif f < g: 631 786 return -1 632 787 else: 633 788 return 0 634 789 635 def compare_tuples_ rp(self,f,g):790 def compare_tuples_invlex(self,f,g): 636 791 """ 637 792 Compares two exponent tuples with respect to the inversed 638 793 lexicographical term order. … … 651 806 sage: x > 1 652 807 True 653 808 """ 654 return self.compare_tuples_l p(f.reversed(),g.reversed())809 return self.compare_tuples_lex(f.reversed(),g.reversed()) 655 810 656 def compare_tuples_ Dp(self,f,g):811 def compare_tuples_deglex(self,f,g): 657 812 """ 658 813 Compares two exponent tuples with respect to the degree 659 814 lexicographical term order. … … 676 831 sg = sum(g.nonzero_values(sort=False)) 677 832 if sf > sg: 678 833 return 1 679 elif sf <sg:834 elif sf < sg: 680 835 return -1 681 836 elif sf == sg: 682 return self.compare_tuples_l p(f,g)837 return self.compare_tuples_lex(f,g) 683 838 684 def compare_tuples_d p(self,f,g):839 def compare_tuples_degrevlex(self,f,g): 685 840 """ 686 841 Compares two exponent tuples with respect to the degree reversed 687 842 lexicographical term order. … … 704 859 sg = sum(g.nonzero_values(sort=False)) 705 860 if sf > sg: 706 861 return 1 707 elif sf <sg:862 elif sf < sg: 708 863 return -1 709 864 elif sf == sg: 710 return (-1)*self.compare_tuples_lp(f.reversed(),g.reversed())865 return -self.compare_tuples_lex(f.reversed(),g.reversed()) 711 866 712 def compare_tuples_ ls(self,f,g):867 def compare_tuples_neglex(self,f,g): 713 868 """ 714 869 Compares two exponent tuples with respect to the negative 715 870 lexicographical term order. … … 728 883 sage: x > 1 729 884 False 730 885 """ 731 return -self.compare_tuples_l p(f,g)886 return -self.compare_tuples_lex(f,g) 732 887 733 def compare_tuples_ ds(self,f,g):888 def compare_tuples_negdegrevlex(self,f,g): 734 889 """ 735 890 Compares two exponent tuples with respect to the negative degree 736 891 reverse lexicographical term order. … … 753 908 sg = sum(g.nonzero_values(sort=False)) 754 909 if sf > sg: 755 910 return -1 756 elif sf <sg:911 elif sf < sg: 757 912 return 1 758 913 elif sf == sg: 759 return (-1)*self.compare_tuples_l p(f.reversed(),g.reversed())914 return (-1)*self.compare_tuples_lex(f.reversed(),g.reversed()) 760 915 761 def compare_tuples_ Ds(self,f,g):916 def compare_tuples_negdeglex(self,f,g): 762 917 """ 763 918 Compares two exponent tuples with respect to the negative degree 764 919 lexicographical term order. … … 781 936 sg = sum(g.nonzero_values(sort=False)) 782 937 if sf > sg: 783 938 return -1 784 elif sf <sg:939 elif sf < sg: 785 940 return 1 786 941 elif sf == sg: 787 return self.compare_tuples_lp(f,g) 942 return self.compare_tuples_lex(f,g) 943 944 def compare_tuples_wdegrevlex(self,f,g): 945 """ 946 Compares two exponent tuples with respect to the weighted degree reverse 947 lexicographical term order. 948 949 INPUT: 950 951 - ``f`` - exponent tuple 952 953 - ``g`` - exponent tuple 954 955 EXAMPLE:: 956 957 sage: t = TermOrder('wdegrevlex',(3,2)) 958 sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t) 959 sage: x > y^2 # indirect doctest 960 False 961 sage: x^2 > y^3 962 True 963 """ 964 sf = sum(l*r for (l,r) in zip(f,self.__weights)) 965 sg = sum(l*r for (l,r) in zip(g,self.__weights)) 966 if sf > sg: 967 return 1 968 elif sf < sg: 969 return -1 970 elif sf == sg: 971 return -self.compare_tuples_lex(f.reversed(),g.reversed()) 972 973 def compare_tuples_wdeglex(self,f,g): 974 """ 975 Compares two exponent tuples with respect to the weighted degree 976 lexicographical term order. 977 978 INPUT: 979 980 - ``f`` - exponent tuple 981 982 - ``g`` - exponent tuple 983 984 EXAMPLE:: 985 986 sage: t = TermOrder('wdeglex',(3,2)) 987 sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t) 988 sage: x > y^2 # indirect doctest 989 False 990 sage: x > y 991 True 992 """ 993 sf = sum(l*r for (l,r) in zip(f,self.__weights)) 994 sg = sum(l*r for (l,r) in zip(g,self.__weights)) 995 if sf > sg: 996 return 1 997 elif sf < sg: 998 return -1 999 elif sf == sg: 1000 return self.compare_tuples_lex(f,g) 1001 1002 def compare_tuples_negwdeglex(self,f,g): 1003 """ 1004 Compares two exponent tuples with respect to the negative weighted 1005 degree lexicographical term order. 1006 1007 INPUT: 1008 1009 - ``f`` - exponent tuple 1010 1011 - ``g`` - exponent tuple 1012 1013 EXAMPLE:: 1014 1015 sage: t = TermOrder('negwdeglex',(3,2)) 1016 sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t) 1017 sage: x > y^2 # indirect doctest 1018 True 1019 sage: x^2 > y^3 1020 True 1021 """ 1022 sf = sum(l*r for (l,r) in zip(f,self.__weights)) 1023 sg = sum(l*r for (l,r) in zip(g,self.__weights)) 1024 if sf > sg: 1025 return -1 1026 elif sf < sg: 1027 return 1 1028 elif sf == sg: 1029 return self.compare_tuples_lex(f,g) 1030 1031 def compare_tuples_negwdegrevlex(self,f,g): 1032 """ 1033 Compares two exponent tuples with respect to the negative weighted 1034 degree reverse lexicographical term order. 1035 1036 INPUT: 1037 1038 - ``f`` - exponent tuple 1039 1040 - ``g`` - exponent tuple 1041 1042 EXAMPLE:: 1043 1044 sage: t = TermOrder('negwdegrevlex',(3,2)) 1045 sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t) 1046 sage: x > y^2 # indirect doctest 1047 True 1048 sage: x^2 > y^3 1049 True 1050 """ 1051 sf = sum(l*r for (l,r) in zip(f,self.__weights)) 1052 sg = sum(l*r for (l,r) in zip(g,self.__weights)) 1053 if sf > sg: 1054 return -1 1055 elif sf < sg: 1056 return 1 1057 elif sf == sg: 1058 return (-1)*self.compare_tuples_lex(f.reversed(),g.reversed()) 788 1059 789 1060 def compare_tuples_block(self, f,g): 790 1061 """ 791 Compares two exponent tuples with respect to the block order ingas1062 Compares two exponent tuples with respect to the block order as 792 1063 specified when constructing this element. 793 1064 794 1065 INPUT: … … 806 1077 True 807 1078 """ 808 1079 n = 0 809 for orderin self:810 r = getattr( self,"compare_tuples_"+order.singular_str())(f[n:n+len(order)],g[n:n+len(order)])1080 for block in self: 1081 r = getattr(block,"compare_tuples_" + block.name())(f[n:n+len(block)],g[n:n+len(block)]) 811 1082 if r != 0: 812 1083 return r 813 n += len( order)1084 n += len(block) 814 1085 return 0 815 1086 816 1087 def greater_tuple_matrix(self,f,g): … … 833 1104 False 834 1105 """ 835 1106 for row in self.__matrix: 836 mf = sum(l*r for (l,r) in zip(row,f))837 mg = sum(l*r for (l,r) in zip(row,g))1107 sf = sum(l*r for (l,r) in zip(row,f)) 1108 sg = sum(l*r for (l,r) in zip(row,g)) 838 1109 839 if mf>mg:1110 if sf > sg: 840 1111 return f 841 elif mf<mg:1112 elif sf < sg: 842 1113 return g 843 1114 return g 844 1115 845 def greater_tuple_l p(self,f,g):1116 def greater_tuple_lex(self,f,g): 846 1117 """ 847 Return sthe greater exponent tuple with respect to the1118 Return the greater exponent tuple with respect to the 848 1119 lexicographical term order. 849 1120 850 1121 INPUT: … … 864 1135 """ 865 1136 return f > g and f or g 866 1137 867 def greater_tuple_ rp(self,f,g):1138 def greater_tuple_invlex(self,f,g): 868 1139 """ 869 Return sthe greater exponent tuple with respect to the inversed1140 Return the greater exponent tuple with respect to the inversed 870 1141 lexicographical term order. 871 1142 872 1143 INPUT: … … 886 1157 This method is called by the lm/lc/lt methods of 887 1158 ``MPolynomial_polydict``. 888 1159 """ 889 return f.reversed() > g.reversed() 1160 return f.reversed() > g.reversed() and f or g 890 1161 891 def greater_tuple_ Dp(self,f,g):1162 def greater_tuple_deglex(self,f,g): 892 1163 """ 893 Return sthe greater exponent tuple with respect to the total degree1164 Return the greater exponent tuple with respect to the total degree 894 1165 lexicographical term order. 895 1166 896 1167 INPUT: … … 910 1181 This method is called by the lm/lc/lt methods of 911 1182 ``MPolynomial_polydict``. 912 1183 """ 913 return (sum(f.nonzero_values(sort=False))>sum(g.nonzero_values(sort=False)) 914 or (sum(f.nonzero_values(sort=False))==sum(g.nonzero_values(sort=False)) and f > g )) and f or g 1184 sf = sum(f.nonzero_values(sort=False)) 1185 sg = sum(g.nonzero_values(sort=False)) 1186 return ( sf > sg or ( sf == sg and f > g )) and f or g 915 1187 916 def greater_tuple_d p(self,f,g):1188 def greater_tuple_degrevlex(self,f,g): 917 1189 """ 918 Return sthe greater exponent tuple with respect to the total degree1190 Return the greater exponent tuple with respect to the total degree 919 1191 reversed lexicographical term order. 920 1192 921 1193 INPUT: … … 935 1207 This method is called by the lm/lc/lt methods of 936 1208 ``MPolynomial_polydict``. 937 1209 """ 938 return (sum(f.nonzero_values(sort=False))>sum(g.nonzero_values(sort=False))939 or (sum(f.nonzero_values(sort=False))==sum(g.nonzero_values(sort=False))940 and f.reversed() < g.reversed())) and f or g1210 sf = sum(f.nonzero_values(sort=False)) 1211 sg = sum(g.nonzero_values(sort=False)) 1212 return ( sf > sg or ( sf == sg and f.reversed() < g.reversed() )) and f or g 941 1213 942 def greater_tuple_ ds(self,f,g):1214 def greater_tuple_negdegrevlex(self,f,g): 943 1215 """ 944 Return sthe greater exponent tuple with respect to the negative1216 Return the greater exponent tuple with respect to the negative 945 1217 degree reverse lexicographical term order. 946 1218 947 1219 INPUT: … … 963 1235 This method is called by the lm/lc/lt methods of 964 1236 ``MPolynomial_polydict``. 965 1237 """ 966 if self.compare_tuples_ds(f,g) >= 0: 967 return f 968 else: 969 return g 1238 sf = sum(f.nonzero_values(sort=False)) 1239 sg = sum(g.nonzero_values(sort=False)) 1240 return ( sf < sg or ( sf == sg and f.reversed() < g.reversed() )) and f or g 970 1241 971 def greater_tuple_ Ds(self,f,g):1242 def greater_tuple_negdeglex(self,f,g): 972 1243 """ 973 Return sthe greater exponent tuple with respect to the negative1244 Return the greater exponent tuple with respect to the negative 974 1245 degree lexicographical term order. 975 1246 976 1247 INPUT: … … 992 1263 This method is called by the lm/lc/lt methods of 993 1264 ``MPolynomial_polydict``. 994 1265 """ 995 if self.compare_tuples_Ds(f,g) >= 0: 996 return f 997 else: 998 return g 1266 sf = sum(f.nonzero_values(sort=False)) 1267 sg = sum(g.nonzero_values(sort=False)) 1268 return ( sf < sg or ( sf == sg and f > g )) and f or g 999 1269 1000 def greater_tuple_ ls(self,f,g):1270 def greater_tuple_neglex(self,f,g): 1001 1271 """ 1002 Return sthe greater exponent tuple with respect to the negative1272 Return the greater exponent tuple with respect to the negative 1003 1273 lexicographical term order. 1004 1274 1005 1275 This method is called by the lm/lc/lt methods of … … 1019 1289 sage: g = a + e^4; g.lm() 1020 1290 a 1021 1291 """ 1022 if self.greater_tuple_lp(f,g) is f: 1023 return g 1024 else: 1025 return f 1292 return (f < g) and f or g 1026 1293 1294 def greater_tuple_wdeglex(self,f,g): 1295 """ 1296 Return the greater exponent tuple with respect to the weighted degree 1297 lexicographical term order. 1298 1299 INPUT: 1300 1301 - ``f`` - exponent tuple 1302 1303 - ``g`` - exponent tuple 1304 1305 EXAMPLE:: 1306 1307 sage: t = TermOrder('wdeglex',(1,2,3)) 1308 sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t) 1309 sage: f = x + y; f.lm() # indirect doctest 1310 y 1311 sage: f = x*y + z; f.lm() 1312 x*y 1313 1314 This method is called by the lm/lc/lt methods of 1315 ``MPolynomial_polydict``. 1316 """ 1317 sf = sum(l*r for (l,r) in zip(f,self.__weights)) 1318 sg = sum(l*r for (l,r) in zip(g,self.__weights)) 1319 return (sf > sg or ( sf == sg and f > g )) and f or g 1320 1321 def greater_tuple_wdegrevlex(self,f,g): 1322 """ 1323 Return the greater exponent tuple with respect to the weighted degree 1324 reverse lexicographical term order. 1325 1326 INPUT: 1327 1328 - ``f`` - exponent tuple 1329 1330 - ``g`` - exponent tuple 1331 1332 EXAMPLES:: 1333 1334 sage: t = TermOrder('wdegrevlex',(1,2,3)) 1335 sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t) 1336 sage: f = x + y; f.lm() # indirect doctest 1337 y 1338 sage: f = x + y^2*z; f.lm() 1339 y^2*z 1340 1341 This method is called by the lm/lc/lt methods of 1342 ``MPolynomial_polydict``. 1343 """ 1344 sf = sum(l*r for (l,r) in zip(f,self.__weights)) 1345 sg = sum(l*r for (l,r) in zip(g,self.__weights)) 1346 return (sf > sg or ( sf == sg and f.reversed() < g.reversed())) and f or g 1347 1348 def greater_tuple_negwdeglex(self,f,g): 1349 """ 1350 Return the greater exponent tuple with respect to the negative 1351 weighted degree lexicographical term order. 1352 1353 INPUT: 1354 1355 - ``f`` - exponent tuple 1356 1357 - ``g`` - exponent tuple 1358 1359 EXAMPLE:: 1360 1361 sage: t = TermOrder('negwdeglex',(1,2,3)) 1362 sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t) 1363 sage: f = x + y; f.lm() # indirect doctest 1364 x 1365 sage: f = x + x^2; f.lm() 1366 x 1367 sage: f = x^3 + z; f.lm() 1368 x^3 1369 1370 This method is called by the lm/lc/lt methods of 1371 ``MPolynomial_polydict``. 1372 """ 1373 sf = sum(l*r for (l,r) in zip(f,self.__weights)) 1374 sg = sum(l*r for (l,r) in zip(g,self.__weights)) 1375 return (sf < sg or ( sf == sg and f > g )) and f or g 1376 1377 def greater_tuple_negwdegrevlex(self,f,g): 1378 """ 1379 Return the greater exponent tuple with respect to the negative 1380 weighted degree reverse lexicographical term order. 1381 1382 INPUT: 1383 1384 - ``f`` - exponent tuple 1385 1386 - ``g`` - exponent tuple 1387 1388 EXAMPLE:: 1389 1390 sage: t = TermOrder('negwdegrevlex',(1,2,3)) 1391 sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t) 1392 sage: f = x + y; f.lm() # indirect doctest 1393 x 1394 sage: f = x + x^2; f.lm() 1395 x 1396 sage: f = x^3 + z; f.lm() 1397 x^3 1398 1399 This method is called by the lm/lc/lt methods of 1400 ``MPolynomial_polydict``. 1401 """ 1402 sf = sum(l*r for (l,r) in zip(f,self.__weights)) 1403 sg = sum(l*r for (l,r) in zip(g,self.__weights)) 1404 return (sf < sg or ( sf == sg and f.reversed() < g.reversed() )) and f or g 1405 1027 1406 def greater_tuple_block(self, f,g): 1028 1407 """ 1029 Return sthe greater exponent tuple with respect to the block1030 order ingas specified when constructing this element.1408 Return the greater exponent tuple with respect to the block 1409 order as specified when constructing this element. 1031 1410 1032 1411 This method is called by the lm/lc/lt methods of 1033 1412 ``MPolynomial_polydict``. … … 1047 1426 a 1048 1427 """ 1049 1428 n = 0 1050 for orderin self:1051 r = getattr( self,"compare_tuples_"+order.singular_str())(f[n:n+len(order)],g[n:n+len(order)])1429 for block in self: 1430 r = getattr(block,"compare_tuples_" + block.name())(f[n:n+len(block)],g[n:n+len(block)]) 1052 1431 if r != 0: 1053 1432 if r < 0: 1054 1433 return g 1055 1434 else: 1056 1435 return f 1057 n += len( order)1436 n += len(block) 1058 1437 return f 1059 1438 1439 def tuple_weight(self, f): 1440 """ 1441 Return the weight of tuple f. 1442 1443 INPUT: 1444 1445 - ``f`` - exponent tuple 1446 1447 EXAMPLE:: 1448 1449 sage: t=TermOrder('wdeglex',(1,2,3)) 1450 sage: P.<a,b,c>=PolynomialRing(QQbar, order=t) 1451 sage: P.term_order().tuple_weight([3,2,1]) 1452 10 1453 """ 1454 return sum(l*r for (l,r) in zip(f,self.__weights)) 1455 1060 1456 def name(self): 1061 1457 """ 1062 1458 EXAMPLE:: … … 1073 1469 sage: TermOrder('lex') # indirect doctest 1074 1470 Lexicographic term order 1075 1471 """ 1076 if self.__name[0] == 'M': 1077 return 'Matrix term order with matrix\n%s'%self.matrix() 1472 if self.__name == 'matrix': 1473 return 'Matrix term order with matrix\n%s'%(self.__matrix,) 1474 elif self.__name == 'block': 1475 s = [] 1476 for t in self.__blocks: 1477 if not t.is_weighted_degree_order(): 1478 s.append('%s of length %d'%(t,len(t))) 1479 else: # includes matrix order 1480 s.append('%s'%(t,)) 1481 return 'Block term order with blocks:\n(%s)'%(',\n '.join(s),) 1078 1482 else: 1079 s = print_name_mapping.get(self.__name,self.__name) 1080 return '%s term order'%s 1483 s = print_name_mapping.get(self.__name,self.__name) + ' term order' 1484 if self.is_weighted_degree_order(): 1485 s = s + ' with weights %s'%(self.__weights,) 1486 return s 1081 1487 1082 1488 def singular_str(self): 1083 1489 """ … … 1116 1522 sage: P = PolynomialRing(GF(127), 8,names='x',order='degrevlex(3),lex(5)') 1117 1523 sage: T = P.term_order() 1118 1524 sage: T.macaulay2_str() 1119 ' (GRevLex => 3,Lex => 5)'1525 '{GRevLex => 3,Lex => 5}' 1120 1526 sage: P._macaulay2_() # optional - macaulay2 1121 1527 ZZ/127 [x0, x1, x2, x3, x4, x5, x6, x7, MonomialOrder => {GRevLex => 3, Lex => 5}, MonomialSize => 16] 1122 1528 """ … … 1144 1550 """ 1145 1551 return self.__magma_str 1146 1552 1553 def blocks(self): 1554 """ 1555 Return the term order blocks of self. 1556 1557 EXAMPLE:: 1558 1559 sage: t=TermOrder('deglex',2)+TermOrder('lex',2) 1560 sage: t.blocks() 1561 (Degree lexicographic term order, Lexicographic term order) 1562 """ 1563 if self.__blocks: # self is a block order 1564 return self.__blocks 1565 else: 1566 return [self] 1567 1147 1568 def matrix(self): 1148 1569 """ 1149 Return the matrix defining matrix ordering.1570 Return the matrix defining matrix term order. 1150 1571 1151 1572 EXAMPLE:: 1152 1573 … … 1156 1577 [0 1] 1157 1578 1158 1579 """ 1159 from sage.matrix.constructor import matrix 1160 return matrix(self.__matrix) 1580 return self.__matrix 1161 1581 1162 def __cmp__(self, other):1582 def weights(self): 1163 1583 """ 1164 Only equality testing makes sense here. 1165 1584 Return the weights for weighted term orders. 1585 1586 EXAMPLE:: 1587 1588 sage: t=TermOrder('wdeglex',(2,3)) 1589 sage: t.weights() 1590 (2, 3) 1591 """ 1592 return self.__weights 1593 1594 def __eq__(self, other): 1595 """ 1596 Return true if self and other are equal. 1597 1166 1598 EXAMPLE:: 1167 1599 1168 1600 sage: TermOrder('lex') == TermOrder('lex',3) … … 1178 1610 sage: T1 = TermOrder('lex',2)+TermOrder('lex',3) 1179 1611 sage: T2 = TermOrder('lex',3)+TermOrder('lex',2) 1180 1612 sage: T1 == T2 1181 False1613 True 1182 1614 1183 1615 :: 1184 1616 … … 1188 1620 True 1189 1621 """ 1190 1622 if not isinstance(other, TermOrder): 1191 if isinstance(other, str):1623 try: 1192 1624 other = TermOrder(other, force=True) 1193 else: 1194 return cmp(type(self), type(other)) 1195 return cmp(self.singular_str(), other.singular_str()) 1625 except: 1626 return False 1627 1628 return (self.__name == other.__name # note that length is not considered. 1629 and self.__blocks == other.__blocks 1630 and self.__weights == other.__weights 1631 and self.__matrix == other.__matrix) 1632 1633 def __ne__(self, other): 1634 """ 1635 Return true if self and other are not equal. 1636 1637 EXAMPLE:: 1638 1639 sage: T1 = TermOrder('lex',2)+TermOrder('lex',3) 1640 sage: T2 = TermOrder('lex',3)+TermOrder('lex',2) 1641 sage: T1 != T2 1642 False 1643 """ 1644 return not self.__eq__(other) 1196 1645 1197 1646 def __add__(self, other): 1198 1647 """ 1199 Block ordering constructor.1648 Construct a block order combining self and other. 1200 1649 1201 1650 INPUT: 1202 1651 1203 1652 - ``other`` - a term order 1204 1653 1205 OUTPUT: a block order ing1654 OUTPUT: a block order 1206 1655 1207 1656 EXAMPLE:: 1208 1657 1209 1658 sage: from sage.rings.polynomial.term_order import TermOrder 1210 1659 sage: TermOrder('deglex',2) + TermOrder('degrevlex(3),neglex(3)') 1211 deglex(2),degrevlex(3),neglex(3) term order 1212 """ 1213 if other is None: 1660 Block term order with blocks: 1661 (Degree lexicographic term order of length 2, 1662 Degree reverse lexicographic term order of length 3, 1663 Negative lexicographic term order of length 3) 1664 """ 1665 if isinstance(other, TermOrder): 1666 return TermOrder('block',[self,other]) 1667 else: 1214 1668 return self 1215 1216 if not isinstance(other,TermOrder):1217 other = TermOrder(other, force = self.__force)1218 if len(self) == 0 or len(other) == 0:1219 raise ArithmeticError, "Can only concatenate term orders with length attribute."1220 1221 name = []1222 for block_order in self.blocks + other.blocks:1223 if 'M' in block_order.singular_str():1224 raise NotImplementedError, "Cannot use a matrix term order as a block."1225 nom = block_order.singular_str()1226 name.append("%s(%d)"%(inv_singular_name_mapping.get(nom,nom), len(block_order)))1227 1228 name = ",".join(name)1229 return TermOrder(name, len(self)+len(other), force=self.__force)1230 1669 1231 1670 def __len__(self): 1232 1671 """ 1233 Return the length of this term order ing, i.e. the number of1672 Return the length of this term order, i.e. the number of 1234 1673 variables it covers. This may be zero for indefinitely many 1235 1674 variables. 1236 1675 … … 1247 1686 1248 1687 def __getitem__(self, i): 1249 1688 r""" 1250 Return the i-th block of this term order ing.1689 Return the i-th block of this term order. 1251 1690 1252 1691 INPUT: 1253 1692 … … 1273 1712 sage: T = TermOrder('lex', 2) + TermOrder('degrevlex', 3) 1274 1713 sage: T[len(T)-1] 1275 1714 Traceback (most recent call last): 1276 ...1715 \dots 1277 1716 IndexError: tuple index out of range 1278 1717 """ 1279 return self.blocks [i]1718 return self.blocks()[i] 1280 1719 1281 1720 def __iter__(self): 1282 1721 r""" 1283 Iterate over the blocks of this term order ing.1722 Iterate over the blocks of this term order. 1284 1723 1285 1724 EXAMPLE:: 1286 1725 … … 1299 1738 the number of variables in ``self`` while the latter 1300 1739 counts the number of blocks. 1301 1740 """ 1302 return iter(self.blocks )1741 return iter(self.blocks()) 1303 1742 1304 1743 def is_global(self): 1305 1744 r""" 1306 Return ``True`` if this term orderingis definitely1307 global. Return ``False``otherwise, which includes1308 unknown term order ings.1745 Return true if this term order is definitely 1746 global. Return false otherwise, which includes 1747 unknown term orders. 1309 1748 1310 1749 EXAMPLE:: 1311 1750 … … 1319 1758 sage: T.is_global() 1320 1759 False 1321 1760 """ 1322 if len(self.blocks) == 1: 1323 if self.singular_str() in ('lp','dp','Dp'): 1324 return True 1325 else: 1326 return False 1761 if self.name() in ('lex','degrevlex','deglex','wdegrevlex','wdeglex'): 1762 return True 1763 elif self.name() is 'block': 1764 return all([t.is_global() for t in self.blocks()]) 1327 1765 else: 1328 return all([t.is_global() for t in self.blocks])1329 1766 return False 1767 1330 1768 def is_local(self): 1331 1769 r""" 1332 Return ``True`` if this term orderingis definitely1333 local. Return ``False``otherwise, which includes1334 unknown term order ings.1770 Return true if this term order is definitely 1771 local. Return false otherwise, which includes 1772 unknown term orders. 1335 1773 1336 1774 EXAMPLE:: 1337 1775 … … 1345 1783 sage: T.is_local() 1346 1784 False 1347 1785 """ 1348 if len(self.blocks) == 1:1349 if self.singular_str() in ('rp', 'ls','ds','Ds'):1350 1351 else:1352 return False1786 if (self.name() in ('neglex','negdegrevlex','negdeglex','negwdegrevlex','negwdeglex') or 1787 self.singular_str() in ('ls','ds','Ds','ws','Ws')): 1788 return True 1789 elif self.name() is 'block': 1790 return all([t.is_local() for t in self.blocks()]) 1353 1791 else: 1354 return all([t.is_local() for t in self.blocks]) 1792 return False 1793 1794 def is_block_order(self): 1795 """ 1796 Return true if self is a block term order. 1797 1798 EXAMPLE:: 1799 1800 sage: t=TermOrder('deglex',2)+TermOrder('lex',2) 1801 sage: t.is_block_order() 1802 True 1803 """ 1804 return self.__name == 'block' 1805 1806 def is_weighted_degree_order(self): 1807 """ 1808 Return true if self is a weighted degree term order. 1809 1810 EXAMPLE:: 1811 1812 sage: t=TermOrder('wdeglex',(2,3)) 1813 sage: t.is_weighted_degree_order() 1814 True 1815 """ 1816 return self.__weights is not None