| | 1 | r""" |
| | 2 | Noncommutative Polynomials via libSINGULAR/Plural |
| | 3 | |
| | 4 | This module implements specialized and optimized implementations for |
| | 5 | noncommutative multivariate polynomials over many coefficient rings, via the |
| | 6 | shared library interface to SINGULAR. In particular, the following coefficient |
| | 7 | rings are supported by this implementation: |
| | 8 | |
| | 9 | - the rational numbers `\QQ`, and |
| | 10 | |
| | 11 | - finite fields `\GF{p}` for `p` prime |
| | 12 | |
| | 13 | AUTHORS: |
| | 14 | |
| | 15 | The PLURAL wrapper is due to |
| | 16 | |
| | 17 | - Burcin Erocal (2008-11 and 2010-07): initial implementation and concept |
| | 18 | |
| | 19 | - Michael Brickenstein (2008-11 and 2010-07): initial implementation and concept |
| | 20 | |
| | 21 | - Oleksandr Motsak (2010-07): complete overall fnoncommutative unctionality and first release |
| | 22 | |
| | 23 | - Alexander Dreyer (2010-07): noncommutative ring functionality and documentation |
| | 24 | |
| | 25 | The underlying libSINGULAR interface was implemented by |
| | 26 | |
| | 27 | - Martin Albrecht (2007-01): initial implementation |
| | 28 | |
| | 29 | - Joel Mohler (2008-01): misc improvements, polishing |
| | 30 | |
| | 31 | - Martin Albrecht (2008-08): added `\QQ(a)` and `\ZZ` support |
| | 32 | |
| | 33 | - Simon King (2009-04): improved coercion |
| | 34 | |
| | 35 | - Martin Albrecht (2009-05): added `\ZZ/n\ZZ` support, refactoring |
| | 36 | |
| | 37 | - Martin Albrecht (2009-06): refactored the code to allow better |
| | 38 | re-use |
| | 39 | |
| | 40 | TODO: |
| | 41 | |
| | 42 | - extend functionality towards those of libSINGULARs commutative part |
| | 43 | |
| | 44 | EXAMPLES: |
| | 45 | |
| | 46 | We show how to construct various noncommutative polynomial rings:: |
| | 47 | |
| | 48 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 49 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 50 | sage: P.inject_variables() |
| | 51 | Defining x, y, z |
| | 52 | |
| | 53 | sage: P |
| | 54 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} |
| | 55 | |
| | 56 | sage: y*x + 1/2 |
| | 57 | -x*y + 1/2 |
| | 58 | |
| | 59 | sage: A.<x,y,z> = FreeAlgebra(GF(17), 3) |
| | 60 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 61 | sage: P.inject_variables() |
| | 62 | Defining x, y, z |
| | 63 | |
| | 64 | sage: P |
| | 65 | Noncommutative Multivariate Polynomial Ring in x, y, z over Finite Field of size 17, nc-relations: {y*x: -x*y} |
| | 66 | |
| | 67 | sage: y*x + 7 |
| | 68 | -x*y + 7 |
| | 69 | |
| | 70 | |
| | 71 | Raw use of this class:: |
| | 72 | sage: from sage.matrix.constructor import Matrix |
| | 73 | sage: c = Matrix(3) |
| | 74 | sage: c[0,1] = -2 |
| | 75 | sage: c[0,2] = 1 |
| | 76 | sage: c[1,2] = 1 |
| | 77 | |
| | 78 | sage: d = Matrix(3) |
| | 79 | sage: d[0, 1] = 17 |
| | 80 | |
| | 81 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 82 | sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = d, order='lex') |
| | 83 | sage: R |
| | 84 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -2*x*y + 17} |
| | 85 | |
| | 86 | sage: R.term_order() |
| | 87 | Lexicographic term order |
| | 88 | |
| | 89 | sage: a,b,c = R.gens() |
| | 90 | sage: f = 57 * a^2*b + 43 * c + 1; f |
| | 91 | 57*x^2*y + 43*z + 1 |
| | 92 | |
| | 93 | sage: R.term_order() |
| | 94 | Lexicographic term order |
| | 95 | |
| | 96 | TESTS:: |
| | 97 | |
| | 98 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 99 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 100 | sage: P.inject_variables() |
| | 101 | Defining x, y, z |
| | 102 | |
| | 103 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural, NCPolynomial_plural |
| | 104 | sage: TestSuite(NCPolynomialRing_plural).run() |
| | 105 | sage: TestSuite(NCPolynomial_plural).run() |
| | 106 | """ |
| | 107 | include "sage/ext/stdsage.pxi" |
| | 108 | include "sage/ext/interrupt.pxi" |
| | 109 | |
| | 110 | |
| | 111 | from sage.libs.singular.function cimport RingWrap |
| | 112 | from sage.structure.parent_base cimport ParentWithBase |
| | 113 | from sage.structure.parent_gens cimport ParentWithGens |
| | 114 | |
| | 115 | # singular rings |
| | 116 | from sage.libs.singular.ring cimport singular_ring_new, singular_ring_delete |
| | 117 | |
| | 118 | from sage.rings.integer cimport Integer |
| | 119 | from sage.structure.element cimport Element, ModuleElement |
| | 120 | |
| | 121 | from sage.libs.singular.polynomial cimport singular_polynomial_call, singular_polynomial_cmp, singular_polynomial_add, singular_polynomial_sub, singular_polynomial_neg, singular_polynomial_pow, singular_polynomial_mul, singular_polynomial_rmul |
| | 122 | from sage.libs.singular.polynomial cimport singular_polynomial_deg, singular_polynomial_str_with_changed_varnames, singular_polynomial_latex, singular_polynomial_str, singular_polynomial_div_coeff |
| | 123 | |
| | 124 | from sage.rings.polynomial.polydict import ETuple |
| | 125 | |
| | 126 | from sage.libs.singular.singular cimport si2sa, sa2si, overflow_check |
| | 127 | from sage.rings.integer_ring import ZZ |
| | 128 | from term_order import TermOrder |
| | 129 | |
| | 130 | |
| | 131 | from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular |
| | 132 | #from sage.rings.polynomial.multi_polynomial_libsingular cimport addwithcarry |
| | 133 | from sage.rings.polynomial.multi_polynomial_ring_generic import MPolynomialRing_generic |
| | 134 | |
| | 135 | |
| | 136 | from sage.structure.parent cimport Parent |
| | 137 | from sage.structure.element cimport CommutativeRingElement |
| | 138 | from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn |
| | 139 | from sage.rings.integer_ring import is_IntegerRing, ZZ |
| | 140 | |
| | 141 | cdef class NCPolynomialRing_plural(Ring): |
| | 142 | def __init__(self, base_ring, n, names, c, d, order='degrevlex', check = True): |
| | 143 | """ |
| | 144 | Construct a noncommutative polynomial G-algebra subject to the following conditions: |
| | 145 | |
| | 146 | INPUT: |
| | 147 | |
| | 148 | - ``base_ring`` - base ring (must be either GF(q), ZZ, ZZ/nZZ, |
| | 149 | QQ or absolute number field) |
| | 150 | |
| | 151 | - ``n`` - number of variables (must be at least 1) |
| | 152 | |
| | 153 | - ``names`` - names of ring variables, may be string of list/tuple |
| | 154 | |
| | 155 | - ``c``, ``d``- upper triangular matrices of coefficients, |
| | 156 | resp. commutative polynomials, satisfying the nondegeneracy conditions, which |
| | 157 | are to be tested if check == True. These matrices describe the noncommutative |
| | 158 | relations: |
| | 159 | |
| | 160 | self.gen(j)*self.gen(i) == c[i, j] * self.gen(i)*self.gen(j) + d[i, j], |
| | 161 | |
| | 162 | where 0 <= i < j < self.ngens() |
| | 163 | |
| | 164 | - ``order`` - term order (default: ``degrevlex``) |
| | 165 | |
| | 166 | - ``check`` - check the noncommutative conditions (default: ``True``) |
| | 167 | |
| | 168 | EXAMPLES:: |
| | 169 | |
| | 170 | sage: from sage.matrix.constructor import Matrix |
| | 171 | sage: c = Matrix(3) |
| | 172 | sage: c[0,1] = -1 |
| | 173 | sage: c[0,2] = 1 |
| | 174 | sage: c[1,2] = 1 |
| | 175 | |
| | 176 | sage: d = Matrix(3) |
| | 177 | sage: d[0, 1] = 17 |
| | 178 | |
| | 179 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 180 | sage: P.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = d, order='lex') |
| | 181 | |
| | 182 | sage: P # indirect doctest |
| | 183 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y + 17} |
| | 184 | |
| | 185 | sage: P(x*y) |
| | 186 | x*y |
| | 187 | |
| | 188 | sage: f = 27/113 * x^2 + y*z + 1/2; f |
| | 189 | 27/113*x^2 + y*z + 1/2 |
| | 190 | |
| | 191 | sage: P.term_order() |
| | 192 | Lexicographic term order |
| | 193 | |
| | 194 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 195 | sage: P.<x,y,z> = NCPolynomialRing_plural(GF(7), 3, c = c, d = d, order='degrevlex') |
| | 196 | |
| | 197 | sage: P # indirect doctest |
| | 198 | Noncommutative Multivariate Polynomial Ring in x, y, z over Finite Field of size 7, nc-relations: {y*x: -x*y + 3} |
| | 199 | |
| | 200 | sage: P(x*y) |
| | 201 | x*y |
| | 202 | |
| | 203 | sage: f = 3 * x^2 + y*z + 5; f |
| | 204 | 3*x^2 + y*z - 2 |
| | 205 | |
| | 206 | sage: P.term_order() |
| | 207 | Degree reverse lexicographic term order |
| | 208 | |
| | 209 | """ |
| | 210 | |
| | 211 | self._relations = None |
| | 212 | n = int(n) |
| | 213 | if n < 0: |
| | 214 | raise ValueError, "Multivariate Polynomial Rings must " + \ |
| | 215 | "have more than 0 variables." |
| | 216 | |
| | 217 | from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing |
| | 218 | |
| | 219 | order = TermOrder(order,n) |
| | 220 | P = PolynomialRing(base_ring, n, names, order=order) |
| | 221 | |
| | 222 | self._c = c.change_ring(P) |
| | 223 | self._d = d.change_ring(P) |
| | 224 | |
| | 225 | from sage.libs.singular.function import singular_function |
| | 226 | ncalgebra = singular_function('nc_algebra') |
| | 227 | |
| | 228 | cdef RingWrap rw = ncalgebra(self._c, self._d, ring = P) |
| | 229 | |
| | 230 | # rw._output() |
| | 231 | self._ring = rw._ring |
| | 232 | self._ring.ShortOut = 0 |
| | 233 | |
| | 234 | self.__ngens = n |
| | 235 | self.__term_order = order |
| | 236 | |
| | 237 | ParentWithGens.__init__(self, base_ring, names) |
| | 238 | self._populate_coercion_lists_() |
| | 239 | |
| | 240 | #MPolynomialRing_generic.__init__(self, base_ring, n, names, order) |
| | 241 | #self._has_singular = True |
| | 242 | assert(n == len(self._names)) |
| | 243 | |
| | 244 | self._one_element = new_NCP(self, p_ISet(1, self._ring)) |
| | 245 | self._zero_element = new_NCP(self, NULL) |
| | 246 | |
| | 247 | |
| | 248 | if check: |
| | 249 | import sage.libs.singular |
| | 250 | test = sage.libs.singular.ff.nctools__lib.ndcond(ring = self) |
| | 251 | if (len(test) != 1) or (test[0] != 0): |
| | 252 | raise ValueError, "NDC check failed!" |
| | 253 | |
| | 254 | def __dealloc__(self): |
| | 255 | r""" |
| | 256 | Carefully deallocate the ring, without changing "currRing" |
| | 257 | (since this method can be at unpredictable times due to garbage |
| | 258 | collection). |
| | 259 | |
| | 260 | TESTS: |
| | 261 | This example caused a segmentation fault with a previous version |
| | 262 | of this method: |
| | 263 | sage: import gc |
| | 264 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 265 | sage: from sage.algebras.free_algebra import FreeAlgebra |
| | 266 | sage: A1.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 267 | sage: R1 = A1.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2)) |
| | 268 | sage: A2.<x,y,z> = FreeAlgebra(GF(5), 3) |
| | 269 | sage: R2 = A2.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2)) |
| | 270 | sage: A3.<x,y,z> = FreeAlgebra(GF(11), 3) |
| | 271 | sage: R3 = A3.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2)) |
| | 272 | sage: A4.<x,y,z> = FreeAlgebra(GF(13), 3) |
| | 273 | sage: R4 = A4.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2)) |
| | 274 | sage: _ = gc.collect() |
| | 275 | sage: foo = R1.gen(0) |
| | 276 | sage: del foo |
| | 277 | sage: del R1 |
| | 278 | sage: _ = gc.collect() |
| | 279 | sage: del R2 |
| | 280 | sage: _ = gc.collect() |
| | 281 | sage: del R3 |
| | 282 | sage: _ = gc.collect() |
| | 283 | """ |
| | 284 | singular_ring_delete(self._ring) |
| | 285 | |
| | 286 | def _element_constructor_(self, element): |
| | 287 | """ |
| | 288 | Make sure element is a valid member of self, and return the constructed element. |
| | 289 | |
| | 290 | EXAMPLES:: |
| | 291 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 292 | |
| | 293 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 294 | |
| | 295 | We can construct elements from the base ring:: |
| | 296 | |
| | 297 | sage: P(1/2) |
| | 298 | 1/2 |
| | 299 | |
| | 300 | |
| | 301 | and all kinds of integers:: |
| | 302 | |
| | 303 | sage: P(17) |
| | 304 | 17 |
| | 305 | |
| | 306 | sage: P(int(19)) |
| | 307 | 19 |
| | 308 | |
| | 309 | sage: P(long(19)) |
| | 310 | 19 |
| | 311 | |
| | 312 | TESTS:: |
| | 313 | |
| | 314 | Check conversion from self:: |
| | 315 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 316 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 317 | sage: P.inject_variables() |
| | 318 | Defining x, y, z |
| | 319 | |
| | 320 | sage: P._element_constructor_(1/2) |
| | 321 | 1/2 |
| | 322 | |
| | 323 | sage: P._element_constructor_(x*y) |
| | 324 | x*y |
| | 325 | |
| | 326 | sage: P._element_constructor_(y*x) |
| | 327 | -x*y |
| | 328 | |
| | 329 | Raw use of this class:: |
| | 330 | sage: from sage.matrix.constructor import Matrix |
| | 331 | sage: c = Matrix(3) |
| | 332 | sage: c[0,1] = -2 |
| | 333 | sage: c[0,2] = 1 |
| | 334 | sage: c[1,2] = 1 |
| | 335 | |
| | 336 | sage: d = Matrix(3) |
| | 337 | sage: d[0, 1] = 17 |
| | 338 | |
| | 339 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 340 | sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = d, order='lex') |
| | 341 | sage: R._element_constructor_(x*y) |
| | 342 | x*y |
| | 343 | |
| | 344 | sage: P._element_constructor_(17) |
| | 345 | 17 |
| | 346 | |
| | 347 | sage: P._element_constructor_(int(19)) |
| | 348 | 19 |
| | 349 | |
| | 350 | Testing special cases:: |
| | 351 | sage: P._element_constructor_(1) |
| | 352 | 1 |
| | 353 | |
| | 354 | sage: P._element_constructor_(0) |
| | 355 | 0 |
| | 356 | """ |
| | 357 | |
| | 358 | if element == 0: |
| | 359 | return self._zero_element |
| | 360 | if element == 1: |
| | 361 | return self._one_element |
| | 362 | |
| | 363 | cdef poly *_p |
| | 364 | cdef ring *_ring, |
| | 365 | cdef number *_n |
| | 366 | |
| | 367 | _ring = self._ring |
| | 368 | |
| | 369 | base_ring = self.base_ring() |
| | 370 | |
| | 371 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 372 | |
| | 373 | |
| | 374 | if PY_TYPE_CHECK(element, NCPolynomial_plural): |
| | 375 | |
| | 376 | if element.parent() is <object>self: |
| | 377 | return element |
| | 378 | elif element.parent() == self: |
| | 379 | # is this safe? |
| | 380 | _p = p_Copy((<NCPolynomial_plural>element)._poly, _ring) |
| | 381 | |
| | 382 | elif PY_TYPE_CHECK(element, CommutativeRingElement): |
| | 383 | # base ring elements |
| | 384 | if <Parent>element.parent() is base_ring: |
| | 385 | # shortcut for GF(p) |
| | 386 | if isinstance(base_ring, FiniteField_prime_modn): |
| | 387 | _p = p_ISet(int(element) % _ring.ch, _ring) |
| | 388 | else: |
| | 389 | _n = sa2si(element,_ring) |
| | 390 | _p = p_NSet(_n, _ring) |
| | 391 | |
| | 392 | # also accepting ZZ |
| | 393 | elif is_IntegerRing(element.parent()): |
| | 394 | if isinstance(base_ring, FiniteField_prime_modn): |
| | 395 | _p = p_ISet(int(element),_ring) |
| | 396 | else: |
| | 397 | _n = sa2si(base_ring(element),_ring) |
| | 398 | _p = p_NSet(_n, _ring) |
| | 399 | else: |
| | 400 | # fall back to base ring |
| | 401 | element = base_ring._coerce_c(element) |
| | 402 | _n = sa2si(element,_ring) |
| | 403 | _p = p_NSet(_n, _ring) |
| | 404 | |
| | 405 | # Accepting int |
| | 406 | elif PY_TYPE_CHECK(element, int): |
| | 407 | if isinstance(base_ring, FiniteField_prime_modn): |
| | 408 | _p = p_ISet(int(element) % _ring.ch,_ring) |
| | 409 | else: |
| | 410 | _n = sa2si(base_ring(element),_ring) |
| | 411 | _p = p_NSet(_n, _ring) |
| | 412 | |
| | 413 | # and longs |
| | 414 | elif PY_TYPE_CHECK(element, long): |
| | 415 | if isinstance(base_ring, FiniteField_prime_modn): |
| | 416 | element = element % self.base_ring().characteristic() |
| | 417 | _p = p_ISet(int(element),_ring) |
| | 418 | else: |
| | 419 | _n = sa2si(base_ring(element),_ring) |
| | 420 | _p = p_NSet(_n, _ring) |
| | 421 | |
| | 422 | else: |
| | 423 | raise NotImplementedError("not able to constructor "+repr(element) + |
| | 424 | " of type "+ repr(type(element))) #### ?????? |
| | 425 | |
| | 426 | |
| | 427 | return new_NCP(self,_p) |
| | 428 | |
| | 429 | |
| | 430 | |
| | 431 | cpdef _coerce_map_from_(self, S): |
| | 432 | """ |
| | 433 | The only things that coerce into this ring are: |
| | 434 | - the integer ring |
| | 435 | - other localizations away from fewer primes |
| | 436 | |
| | 437 | EXAMPLES:: |
| | 438 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 439 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 440 | |
| | 441 | sage: P._coerce_map_from_(ZZ) |
| | 442 | True |
| | 443 | """ |
| | 444 | |
| | 445 | if self.base_ring().has_coerce_map_from(S): |
| | 446 | return True |
| | 447 | |
| | 448 | |
| | 449 | |
| | 450 | def __hash__(self): |
| | 451 | """ |
| | 452 | Return a hash for this noncommutative ring, that is, a hash of the string |
| | 453 | representation of this polynomial ring. |
| | 454 | |
| | 455 | EXAMPLES:: |
| | 456 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 457 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 458 | sage: hash(P) # somewhat random output |
| | 459 | ... |
| | 460 | |
| | 461 | TESTS:: |
| | 462 | |
| | 463 | Check conversion from self:: |
| | 464 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 465 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 466 | sage: from sage.matrix.constructor import Matrix |
| | 467 | sage: c = Matrix(3) |
| | 468 | sage: c[0,1] = -1 |
| | 469 | sage: c[0,2] = 1 |
| | 470 | sage: c[1,2] = 1 |
| | 471 | |
| | 472 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 473 | sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = Matrix(3), order='lex') |
| | 474 | sage: hash(R) == hash(P) |
| | 475 | True |
| | 476 | """ |
| | 477 | return hash(str(self.__repr__()) + str(self.term_order()) ) |
| | 478 | |
| | 479 | |
| | 480 | def __cmp__(self, right): |
| | 481 | r""" |
| | 482 | Multivariate polynomial rings are said to be equal if: |
| | 483 | |
| | 484 | - their base rings match, |
| | 485 | - their generator names match, |
| | 486 | - their term orderings match, and |
| | 487 | - their relations match. |
| | 488 | |
| | 489 | |
| | 490 | EXAMPLES:: |
| | 491 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 492 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 493 | |
| | 494 | sage: P == P |
| | 495 | True |
| | 496 | sage: Q = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 497 | sage: Q == P |
| | 498 | True |
| | 499 | |
| | 500 | sage: from sage.matrix.constructor import Matrix |
| | 501 | sage: c = Matrix(3) |
| | 502 | sage: c[0,1] = -1 |
| | 503 | sage: c[0,2] = 1 |
| | 504 | sage: c[1,2] = 1 |
| | 505 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 506 | sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = Matrix(3), order='lex') |
| | 507 | sage: R == P |
| | 508 | True |
| | 509 | |
| | 510 | sage: c[0,1] = -2 |
| | 511 | sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = Matrix(3), order='lex') |
| | 512 | sage: P == R |
| | 513 | False |
| | 514 | """ |
| | 515 | |
| | 516 | if PY_TYPE_CHECK(right, NCPolynomialRing_plural): |
| | 517 | |
| | 518 | return cmp( (self.base_ring(), map(str, self.gens()), |
| | 519 | self.term_order(), self._c, self._d), |
| | 520 | (right.base_ring(), map(str, right.gens()), |
| | 521 | right.term_order(), |
| | 522 | (<NCPolynomialRing_plural>right)._c, |
| | 523 | (<NCPolynomialRing_plural>right)._d) |
| | 524 | ) |
| | 525 | else: |
| | 526 | return cmp(type(self),type(right)) |
| | 527 | |
| | 528 | def __pow__(self, n, _): |
| | 529 | """ |
| | 530 | Return the free module of rank `n` over this ring. |
| | 531 | |
| | 532 | EXAMPLES:: |
| | 533 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 534 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 535 | sage: P.inject_variables() |
| | 536 | Defining x, y, z |
| | 537 | |
| | 538 | sage: f = x^3 + y |
| | 539 | sage: f^2 |
| | 540 | x^6 + y^2 |
| | 541 | """ |
| | 542 | import sage.modules.all |
| | 543 | return sage.modules.all.FreeModule(self, n) |
| | 544 | |
| | 545 | def term_order(self): |
| | 546 | """ |
| | 547 | Return the term ordering of the noncommutative ring. |
| | 548 | |
| | 549 | EXAMPLES:: |
| | 550 | |
| | 551 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 552 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 553 | sage: P.term_order() |
| | 554 | Lexicographic term order |
| | 555 | |
| | 556 | sage: P = A.g_algebra(relations={y*x:-x*y}) |
| | 557 | sage: P.term_order() |
| | 558 | Degree reverse lexicographic term order |
| | 559 | """ |
| | 560 | return self.__term_order |
| | 561 | |
| | 562 | def is_commutative(self): |
| | 563 | """ |
| | 564 | Return False. |
| | 565 | |
| | 566 | EXAMPLES:: |
| | 567 | |
| | 568 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 569 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 570 | sage: P.is_commutative() |
| | 571 | False |
| | 572 | """ |
| | 573 | return False |
| | 574 | |
| | 575 | def is_field(self): |
| | 576 | """ |
| | 577 | Return False. |
| | 578 | |
| | 579 | EXAMPLES:: |
| | 580 | |
| | 581 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 582 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 583 | sage: P.is_field() |
| | 584 | False |
| | 585 | """ |
| | 586 | return False |
| | 587 | |
| | 588 | def _repr_(self): |
| | 589 | """ |
| | 590 | EXAMPLE: |
| | 591 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 592 | sage: from sage.matrix.constructor import Matrix |
| | 593 | sage: c=Matrix(2) |
| | 594 | sage: c[0,1]=-1 |
| | 595 | sage: P.<x,y> = NCPolynomialRing_plural(QQ, 2, c=c, d=Matrix(2)) |
| | 596 | sage: P # indirect doctest |
| | 597 | Noncommutative Multivariate Polynomial Ring in x, y over Rational Field, nc-relations: {y*x: -x*y} |
| | 598 | sage: x*y |
| | 599 | x*y |
| | 600 | sage: y*x |
| | 601 | -x*y |
| | 602 | """ |
| | 603 | #TODO: print the relations |
| | 604 | varstr = ", ".join([ rRingVar(i,self._ring) for i in range(self.__ngens) ]) |
| | 605 | return "Noncommutative Multivariate Polynomial Ring in %s over %s, nc-relations: %s"%(varstr,self.base_ring(), self.relations()) |
| | 606 | |
| | 607 | |
| | 608 | def _ringlist(self): |
| | 609 | """ |
| | 610 | Return an internal list representation of the noncummutative ring. |
| | 611 | |
| | 612 | EXAMPLES:: |
| | 613 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 614 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 615 | sage: P._ringlist() |
| | 616 | [0, ['x', 'y', 'z'], [['lp', (1, 1, 1)], ['C', (0,)]], [0], [ 0 -1 1] |
| | 617 | [ 0 0 1] |
| | 618 | [ 0 0 0], [0 0 0] |
| | 619 | [0 0 0] |
| | 620 | [0 0 0]] |
| | 621 | """ |
| | 622 | cdef ring* _ring = self._ring |
| | 623 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 624 | from sage.libs.singular.function import singular_function |
| | 625 | ringlist = singular_function('ringlist') |
| | 626 | result = ringlist(self, ring=self) |
| | 627 | |
| | 628 | |
| | 629 | |
| | 630 | |
| | 631 | return result |
| | 632 | |
| | 633 | |
| | 634 | def relations(self, add_commutative = False): |
| | 635 | """ |
| | 636 | EXAMPLE: |
| | 637 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 638 | sage: from sage.matrix.constructor import Matrix |
| | 639 | sage: c=Matrix(2) |
| | 640 | sage: c[0,1]=-1 |
| | 641 | sage: P = NCPolynomialRing_plural(QQ, 2, 'x,y', c=c, d=Matrix(2)) |
| | 642 | sage: P # indirect doctest |
| | 643 | Noncommutative Multivariate Polynomial Ring in x, y over Rational Field, nc-relations: ... |
| | 644 | """ |
| | 645 | if self._relations is not None: |
| | 646 | return self._relations |
| | 647 | |
| | 648 | from sage.algebras.free_algebra import FreeAlgebra |
| | 649 | A = FreeAlgebra( self.base_ring(), self.ngens(), self.gens() ) |
| | 650 | |
| | 651 | res = {} |
| | 652 | n = self.ngens() |
| | 653 | for r in range(0, n-1, 1): |
| | 654 | for c in range(r+1, n, 1): |
| | 655 | if (self.gen(c) * self.gen(r) != self.gen(r) * self.gen(c)) or add_commutative: |
| | 656 | res[ A.gen(c) * A.gen(r) ] = self.gen(c) * self.gen(r) # C[r, c] * P.gen(r) * P.gen(c) + D[r, c] |
| | 657 | |
| | 658 | |
| | 659 | self._relations = res |
| | 660 | return self._relations |
| | 661 | |
| | 662 | def ngens(self): |
| | 663 | """ |
| | 664 | Returns the number of variables in this noncommutative polynomial ring. |
| | 665 | |
| | 666 | EXAMPLES:: |
| | 667 | |
| | 668 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 669 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 670 | sage: P.inject_variables() |
| | 671 | Defining x, y, z |
| | 672 | |
| | 673 | sage: P.ngens() |
| | 674 | 3 |
| | 675 | """ |
| | 676 | return int(self.__ngens) |
| | 677 | |
| | 678 | def gen(self, int n=0): |
| | 679 | """ |
| | 680 | Returns the ``n``-th generator of this noncommutative polynomial |
| | 681 | ring. |
| | 682 | |
| | 683 | INPUT: |
| | 684 | |
| | 685 | - ``n`` -- an integer ``>= 0`` |
| | 686 | |
| | 687 | EXAMPLES:: |
| | 688 | |
| | 689 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 690 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 691 | sage: P.gen(),P.gen(1) |
| | 692 | (x, y) |
| | 693 | |
| | 694 | sage: P.gen(1) |
| | 695 | y |
| | 696 | """ |
| | 697 | cdef poly *_p |
| | 698 | cdef ring *_ring = self._ring |
| | 699 | |
| | 700 | if n < 0 or n >= self.__ngens: |
| | 701 | raise ValueError, "Generator not defined." |
| | 702 | |
| | 703 | rChangeCurrRing(_ring) |
| | 704 | _p = p_ISet(1,_ring) |
| | 705 | p_SetExp(_p, n+1, 1, _ring) |
| | 706 | p_Setm(_p, _ring); |
| | 707 | |
| | 708 | return new_NCP(self,_p) |
| | 709 | |
| | 710 | def ideal(self, *gens, **kwds): |
| | 711 | """ |
| | 712 | Create an ideal in this polynomial ring. |
| | 713 | |
| | 714 | INPUT: |
| | 715 | |
| | 716 | - ``*gens`` - list or tuple of generators (or several input arguments) |
| | 717 | |
| | 718 | - ``coerce`` - bool (default: ``True``); this must be a |
| | 719 | keyword argument. Only set it to ``False`` if you are certain |
| | 720 | that each generator is already in the ring. |
| | 721 | |
| | 722 | EXAMPLES:: |
| | 723 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 724 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 725 | sage: P.inject_variables() |
| | 726 | Defining x, y, z |
| | 727 | |
| | 728 | sage: P.ideal([x + 2*y + 2*z-1, 2*x*y + 2*y*z-y, x^2 + 2*y^2 + 2*z^2-x]) |
| | 729 | Ideal (x + 2*y + 2*z - 1, 2*x*y + 2*y*z - y, x^2 - x + 2*y^2 + 2*z^2) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} |
| | 730 | """ |
| | 731 | from sage.rings.polynomial.multi_polynomial_ideal import \ |
| | 732 | NCPolynomialIdeal |
| | 733 | coerce = kwds.get('coerce', True) |
| | 734 | if len(gens) == 1: |
| | 735 | gens = gens[0] |
| | 736 | #if is_SingularElement(gens): |
| | 737 | # gens = list(gens) |
| | 738 | # coerce = True |
| | 739 | #elif is_Macaulay2Element(gens): |
| | 740 | # gens = list(gens) |
| | 741 | # coerce = True |
| | 742 | if not isinstance(gens, (list, tuple)): |
| | 743 | gens = [gens] |
| | 744 | if coerce: |
| | 745 | gens = [self(x) for x in gens] # this will even coerce from singular ideals correctly! |
| | 746 | return NCPolynomialIdeal(self, gens, coerce=False) |
| | 747 | |
| | 748 | def _list_to_ring(self, L): |
| | 749 | """ |
| | 750 | Convert internal list representation to noncommutative ring. |
| | 751 | |
| | 752 | EXAMPLES:: |
| | 753 | |
| | 754 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 755 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 756 | sage: rlist = P._ringlist(); |
| | 757 | sage: Q = P._list_to_ring(rlist) |
| | 758 | sage: Q # indirect doctest |
| | 759 | <noncommutative RingWrap> |
| | 760 | """ |
| | 761 | |
| | 762 | cdef ring* _ring = self._ring |
| | 763 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 764 | |
| | 765 | from sage.libs.singular.function import singular_function |
| | 766 | ring = singular_function('ring') |
| | 767 | return ring(L, ring=self) |
| | 768 | |
| | 769 | def quotient(self, I): |
| | 770 | """ |
| | 771 | Construct quotient ring of ``self`` and the two-sided Groebner basis of `ideal` |
| | 772 | |
| | 773 | EXAMPLE:: |
| | 774 | |
| | 775 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 776 | sage: H = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 777 | sage: I = H.ideal([H.gen(i) ^2 for i in [0, 1]]).twostd() |
| | 778 | |
| | 779 | sage: Q = H.quotient(I); Q |
| | 780 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} |
| | 781 | |
| | 782 | TESTS:: |
| | 783 | |
| | 784 | check coercion bug:: |
| | 785 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 786 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 787 | sage: rlist = P._ringlist(); |
| | 788 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 789 | sage: H = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 790 | sage: I = H.ideal([H.gen(i) ^2 for i in [0, 1]]).twostd() |
| | 791 | sage: Q = H.quotient(I); Q |
| | 792 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} |
| | 793 | sage: Q.gen(0)^2 |
| | 794 | 0 |
| | 795 | sage: Q.gen(1) * Q.gen(0) |
| | 796 | -x*y |
| | 797 | """ |
| | 798 | L = self._ringlist() |
| | 799 | L[3] = I.twostd() |
| | 800 | W = self._list_to_ring(L) |
| | 801 | return new_NRing(W, self.base_ring()) |
| | 802 | |
| | 803 | |
| | 804 | ### The following methods are handy for implementing Groebner |
| | 805 | ### basis algorithms. They do only superficial type/sanity checks |
| | 806 | ### and should be called carefully. |
| | 807 | |
| | 808 | def monomial_quotient(self, NCPolynomial_plural f, NCPolynomial_plural g, coeff=False): |
| | 809 | r""" |
| | 810 | Return ``f/g``, where both ``f`` and`` ``g`` are treated as |
| | 811 | monomials. |
| | 812 | |
| | 813 | Coefficients are ignored by default. |
| | 814 | |
| | 815 | INPUT: |
| | 816 | |
| | 817 | - ``f`` - monomial |
| | 818 | - ``g`` - monomial |
| | 819 | - ``coeff`` - divide coefficients as well (default: ``False``) |
| | 820 | |
| | 821 | EXAMPLES:: |
| | 822 | |
| | 823 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 824 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 825 | sage: P.inject_variables() |
| | 826 | Defining x, y, z |
| | 827 | |
| | 828 | sage: P.monomial_quotient(3/2*x*y,x,coeff=True) |
| | 829 | 3/2*y |
| | 830 | |
| | 831 | Note, that `\ZZ` behaves different if ``coeff=True``:: |
| | 832 | |
| | 833 | sage: P.monomial_quotient(2*x,3*x) |
| | 834 | 1 |
| | 835 | sage: P.monomial_quotient(2*x,3*x,coeff=True) |
| | 836 | 2/3 |
| | 837 | |
| | 838 | TESTS:: |
| | 839 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 840 | sage: R = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 841 | sage: R.inject_variables() |
| | 842 | Defining x, y, z |
| | 843 | |
| | 844 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 845 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 846 | sage: P.inject_variables() |
| | 847 | Defining x, y, z |
| | 848 | |
| | 849 | sage: P.monomial_quotient(x*y,x) |
| | 850 | y |
| | 851 | |
| | 852 | ## sage: P.monomial_quotient(x*y,R.gen()) |
| | 853 | ## y |
| | 854 | |
| | 855 | sage: P.monomial_quotient(P(0),P(1)) |
| | 856 | 0 |
| | 857 | |
| | 858 | sage: P.monomial_quotient(P(1),P(0)) |
| | 859 | Traceback (most recent call last): |
| | 860 | ... |
| | 861 | ZeroDivisionError |
| | 862 | |
| | 863 | sage: P.monomial_quotient(P(3/2),P(2/3), coeff=True) |
| | 864 | 9/4 |
| | 865 | |
| | 866 | sage: P.monomial_quotient(x,P(1)) |
| | 867 | x |
| | 868 | |
| | 869 | TESTS:: |
| | 870 | |
| | 871 | sage: P.monomial_quotient(x,y) # Note the wrong result |
| | 872 | x*y^1048575*z^1048575 # 64-bit |
| | 873 | x*y^65535 # 32-bit |
| | 874 | |
| | 875 | .. warning:: |
| | 876 | |
| | 877 | Assumes that the head term of f is a multiple of the head |
| | 878 | term of g and return the multiplicant m. If this rule is |
| | 879 | violated, funny things may happen. |
| | 880 | """ |
| | 881 | cdef poly *res |
| | 882 | cdef ring *r = self._ring |
| | 883 | cdef number *n, *denom |
| | 884 | |
| | 885 | if not <ParentWithBase>self is f._parent: |
| | 886 | f = self._coerce_c(f) |
| | 887 | if not <ParentWithBase>self is g._parent: |
| | 888 | g = self._coerce_c(g) |
| | 889 | |
| | 890 | if(r != currRing): rChangeCurrRing(r) |
| | 891 | |
| | 892 | if not f._poly: |
| | 893 | return self._zero_element |
| | 894 | if not g._poly: |
| | 895 | raise ZeroDivisionError |
| | 896 | |
| | 897 | res = pDivide(f._poly,g._poly) |
| | 898 | if coeff: |
| | 899 | if r.ringtype == 0 or r.cf.nDivBy(p_GetCoeff(f._poly, r), p_GetCoeff(g._poly, r)): |
| | 900 | n = r.cf.nDiv( p_GetCoeff(f._poly, r) , p_GetCoeff(g._poly, r)) |
| | 901 | p_SetCoeff0(res, n, r) |
| | 902 | else: |
| | 903 | raise ArithmeticError("Cannot divide these coefficients.") |
| | 904 | else: |
| | 905 | p_SetCoeff0(res, n_Init(1, r), r) |
| | 906 | return new_NCP(self, res) |
| | 907 | |
| | 908 | def monomial_divides(self, NCPolynomial_plural a, NCPolynomial_plural b): |
| | 909 | """ |
| | 910 | Return ``False`` if a does not divide b and ``True`` |
| | 911 | otherwise. |
| | 912 | |
| | 913 | Coefficients are ignored. |
| | 914 | |
| | 915 | INPUT: |
| | 916 | |
| | 917 | - ``a`` -- monomial |
| | 918 | |
| | 919 | - ``b`` -- monomial |
| | 920 | |
| | 921 | EXAMPLES:: |
| | 922 | |
| | 923 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 924 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 925 | sage: P.inject_variables() |
| | 926 | Defining x, y, z |
| | 927 | |
| | 928 | sage: P.monomial_divides(x*y*z, x^3*y^2*z^4) |
| | 929 | True |
| | 930 | sage: P.monomial_divides(x^3*y^2*z^4, x*y*z) |
| | 931 | False |
| | 932 | |
| | 933 | TESTS:: |
| | 934 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 935 | sage: Q = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 936 | sage: Q.inject_variables() |
| | 937 | Defining x, y, z |
| | 938 | |
| | 939 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 940 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 941 | sage: P.inject_variables() |
| | 942 | Defining x, y, z |
| | 943 | |
| | 944 | sage: P.monomial_divides(P(1), P(0)) |
| | 945 | True |
| | 946 | sage: P.monomial_divides(P(1), x) |
| | 947 | True |
| | 948 | """ |
| | 949 | cdef poly *_a |
| | 950 | cdef poly *_b |
| | 951 | cdef ring *_r |
| | 952 | if a._parent is not b._parent: |
| | 953 | b = (<NCPolynomialRing_plural>a._parent)._coerce_c(b) |
| | 954 | |
| | 955 | _a = a._poly |
| | 956 | _b = b._poly |
| | 957 | _r = (<NCPolynomialRing_plural>a._parent)._ring |
| | 958 | |
| | 959 | if _a == NULL: |
| | 960 | raise ZeroDivisionError |
| | 961 | if _b == NULL: |
| | 962 | return True |
| | 963 | |
| | 964 | if not p_DivisibleBy(_a, _b, _r): |
| | 965 | return False |
| | 966 | else: |
| | 967 | return True |
| | 968 | |
| | 969 | |
| | 970 | def monomial_lcm(self, NCPolynomial_plural f, NCPolynomial_plural g): |
| | 971 | """ |
| | 972 | LCM for monomials. Coefficients are ignored. |
| | 973 | |
| | 974 | INPUT: |
| | 975 | |
| | 976 | - ``f`` - monomial |
| | 977 | |
| | 978 | - ``g`` - monomial |
| | 979 | |
| | 980 | EXAMPLES:: |
| | 981 | |
| | 982 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 983 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 984 | sage: P.inject_variables() |
| | 985 | Defining x, y, z |
| | 986 | |
| | 987 | sage: P.monomial_lcm(3/2*x*y,x) |
| | 988 | x*y |
| | 989 | |
| | 990 | TESTS:: |
| | 991 | |
| | 992 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 993 | sage: R = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 994 | sage: R.inject_variables() |
| | 995 | Defining x, y, z |
| | 996 | |
| | 997 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 998 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 999 | sage: P.inject_variables() |
| | 1000 | Defining x, y, z |
| | 1001 | |
| | 1002 | ## sage: P.monomial_lcm(x*y,R.gen()) |
| | 1003 | ## x*y |
| | 1004 | |
| | 1005 | sage: P.monomial_lcm(P(3/2),P(2/3)) |
| | 1006 | 1 |
| | 1007 | |
| | 1008 | sage: P.monomial_lcm(x,P(1)) |
| | 1009 | x |
| | 1010 | """ |
| | 1011 | cdef poly *m = p_ISet(1,self._ring) |
| | 1012 | |
| | 1013 | if not <ParentWithBase>self is f._parent: |
| | 1014 | f = self._coerce_c(f) |
| | 1015 | if not <ParentWithBase>self is g._parent: |
| | 1016 | g = self._coerce_c(g) |
| | 1017 | |
| | 1018 | if f._poly == NULL: |
| | 1019 | if g._poly == NULL: |
| | 1020 | return self._zero_element |
| | 1021 | else: |
| | 1022 | raise ArithmeticError, "Cannot compute LCM of zero and nonzero element." |
| | 1023 | if g._poly == NULL: |
| | 1024 | raise ArithmeticError, "Cannot compute LCM of zero and nonzero element." |
| | 1025 | |
| | 1026 | if(self._ring != currRing): rChangeCurrRing(self._ring) |
| | 1027 | |
| | 1028 | pLcm(f._poly, g._poly, m) |
| | 1029 | p_Setm(m, self._ring) |
| | 1030 | return new_NCP(self,m) |
| | 1031 | |
| | 1032 | def monomial_reduce(self, NCPolynomial_plural f, G): |
| | 1033 | """ |
| | 1034 | Try to find a ``g`` in ``G`` where ``g.lm()`` divides |
| | 1035 | ``f``. If found ``(flt,g)`` is returned, ``(0,0)`` otherwise, |
| | 1036 | where ``flt`` is ``f/g.lm()``. |
| | 1037 | |
| | 1038 | It is assumed that ``G`` is iterable and contains *only* |
| | 1039 | elements in this polynomial ring. |
| | 1040 | |
| | 1041 | Coefficients are ignored. |
| | 1042 | |
| | 1043 | INPUT: |
| | 1044 | |
| | 1045 | - ``f`` - monomial |
| | 1046 | - ``G`` - list/set of mpolynomials |
| | 1047 | |
| | 1048 | EXAMPLES:: |
| | 1049 | |
| | 1050 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1051 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1052 | sage: P.inject_variables() |
| | 1053 | Defining x, y, z |
| | 1054 | |
| | 1055 | sage: f = x*y^2 |
| | 1056 | sage: G = [ 3/2*x^3 + y^2 + 1/2, 1/4*x*y + 2/7, 1/2 ] |
| | 1057 | sage: P.monomial_reduce(f,G) |
| | 1058 | (y, 1/4*x*y + 2/7) |
| | 1059 | |
| | 1060 | TESTS:: |
| | 1061 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1062 | sage: Q = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1063 | sage: Q.inject_variables() |
| | 1064 | Defining x, y, z |
| | 1065 | |
| | 1066 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1067 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1068 | sage: P.inject_variables() |
| | 1069 | Defining x, y, z |
| | 1070 | sage: f = x*y^2 |
| | 1071 | sage: G = [ 3/2*x^3 + y^2 + 1/2, 1/4*x*y + 2/7, 1/2 ] |
| | 1072 | |
| | 1073 | sage: P.monomial_reduce(P(0),G) |
| | 1074 | (0, 0) |
| | 1075 | |
| | 1076 | sage: P.monomial_reduce(f,[P(0)]) |
| | 1077 | (0, 0) |
| | 1078 | """ |
| | 1079 | cdef poly *m = f._poly |
| | 1080 | cdef ring *r = self._ring |
| | 1081 | cdef poly *flt |
| | 1082 | |
| | 1083 | if not m: |
| | 1084 | return f,f |
| | 1085 | |
| | 1086 | for g in G: |
| | 1087 | if PY_TYPE_CHECK(g, NCPolynomial_plural) \ |
| | 1088 | and (<NCPolynomial_plural>g) \ |
| | 1089 | and p_LmDivisibleBy((<NCPolynomial_plural>g)._poly, m, r): |
| | 1090 | flt = pDivide(f._poly, (<NCPolynomial_plural>g)._poly) |
| | 1091 | #p_SetCoeff(flt, n_Div( p_GetCoeff(f._poly, r) , p_GetCoeff((<NCPolynomial_plural>g)._poly, r), r), r) |
| | 1092 | p_SetCoeff(flt, n_Init(1, r), r) |
| | 1093 | return new_NCP(self,flt), g |
| | 1094 | return self._zero_element,self._zero_element |
| | 1095 | |
| | 1096 | def monomial_pairwise_prime(self, NCPolynomial_plural g, NCPolynomial_plural h): |
| | 1097 | """ |
| | 1098 | Return ``True`` if ``h`` and ``g`` are pairwise prime. Both |
| | 1099 | are treated as monomials. |
| | 1100 | |
| | 1101 | Coefficients are ignored. |
| | 1102 | |
| | 1103 | INPUT: |
| | 1104 | |
| | 1105 | - ``h`` - monomial |
| | 1106 | - ``g`` - monomial |
| | 1107 | |
| | 1108 | EXAMPLES:: |
| | 1109 | |
| | 1110 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1111 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1112 | sage: P.inject_variables() |
| | 1113 | Defining x, y, z |
| | 1114 | |
| | 1115 | sage: P.monomial_pairwise_prime(x^2*z^3, y^4) |
| | 1116 | True |
| | 1117 | |
| | 1118 | sage: P.monomial_pairwise_prime(1/2*x^3*y^2, 3/4*y^3) |
| | 1119 | False |
| | 1120 | |
| | 1121 | TESTS:: |
| | 1122 | |
| | 1123 | sage: A.<x1,y1,z1> = FreeAlgebra(QQ, 3) |
| | 1124 | sage: Q = A.g_algebra(relations={y1*x1:-x1*y1}, order='lex') |
| | 1125 | sage: Q.inject_variables() |
| | 1126 | Defining x1, y1, z1 |
| | 1127 | |
| | 1128 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1129 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1130 | sage: P.inject_variables() |
| | 1131 | Defining x, y, z |
| | 1132 | |
| | 1133 | ## sage: P.monomial_pairwise_prime(x^2*z^3, x1^4) |
| | 1134 | ## True |
| | 1135 | |
| | 1136 | ## sage: P.monomial_pairwise_prime((2)*x^3*y^2, Q.zero_element()) |
| | 1137 | ## True |
| | 1138 | |
| | 1139 | sage: P.monomial_pairwise_prime(2*P.one_element(),x) |
| | 1140 | False |
| | 1141 | """ |
| | 1142 | cdef int i |
| | 1143 | cdef ring *r |
| | 1144 | cdef poly *p, *q |
| | 1145 | |
| | 1146 | if h._parent is not g._parent: |
| | 1147 | g = (<NCPolynomialRing_plural>h._parent)._coerce_c(g) |
| | 1148 | |
| | 1149 | r = (<NCPolynomialRing_plural>h._parent)._ring |
| | 1150 | p = g._poly |
| | 1151 | q = h._poly |
| | 1152 | |
| | 1153 | if p == NULL: |
| | 1154 | if q == NULL: |
| | 1155 | return False #GCD(0,0) = 0 |
| | 1156 | else: |
| | 1157 | return True #GCD(x,0) = 1 |
| | 1158 | |
| | 1159 | elif q == NULL: |
| | 1160 | return True # GCD(0,x) = 1 |
| | 1161 | |
| | 1162 | elif p_IsConstant(p,r) or p_IsConstant(q,r): # assuming a base field |
| | 1163 | return False |
| | 1164 | |
| | 1165 | for i from 1 <= i <= r.N: |
| | 1166 | if p_GetExp(p,i,r) and p_GetExp(q,i,r): |
| | 1167 | return False |
| | 1168 | return True |
| | 1169 | |
| | 1170 | def monomial_all_divisors(self, NCPolynomial_plural t): |
| | 1171 | """ |
| | 1172 | Return a list of all monomials that divide ``t``. |
| | 1173 | |
| | 1174 | Coefficients are ignored. |
| | 1175 | |
| | 1176 | INPUT: |
| | 1177 | |
| | 1178 | - ``t`` - a monomial |
| | 1179 | |
| | 1180 | OUTPUT: |
| | 1181 | a list of monomials |
| | 1182 | |
| | 1183 | |
| | 1184 | EXAMPLES:: |
| | 1185 | |
| | 1186 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1187 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1188 | sage: P.inject_variables() |
| | 1189 | Defining x, y, z |
| | 1190 | |
| | 1191 | sage: P.monomial_all_divisors(x^2*z^3) |
| | 1192 | [x, x^2, z, x*z, x^2*z, z^2, x*z^2, x^2*z^2, z^3, x*z^3, x^2*z^3] |
| | 1193 | |
| | 1194 | ALGORITHM: addwithcarry idea by Toon Segers |
| | 1195 | """ |
| | 1196 | |
| | 1197 | M = list() |
| | 1198 | |
| | 1199 | cdef ring *_ring = self._ring |
| | 1200 | cdef poly *maxvector = t._poly |
| | 1201 | cdef poly *tempvector = p_ISet(1, _ring) |
| | 1202 | |
| | 1203 | pos = 1 |
| | 1204 | |
| | 1205 | while not p_ExpVectorEqual(tempvector, maxvector, _ring): |
| | 1206 | tempvector = addwithcarry(tempvector, maxvector, pos, _ring) |
| | 1207 | M.append(new_NCP(self, p_Copy(tempvector,_ring))) |
| | 1208 | return M |
| | 1209 | |
| | 1210 | |
| | 1211 | |
| | 1212 | cdef class NCPolynomial_plural(RingElement): |
| | 1213 | """ |
| | 1214 | A noncommutative multivariate polynomial implemented using libSINGULAR. |
| | 1215 | """ |
| | 1216 | def __init__(self, NCPolynomialRing_plural parent): |
| | 1217 | """ |
| | 1218 | Construct a zero element in parent. |
| | 1219 | |
| | 1220 | EXAMPLES:: |
| | 1221 | |
| | 1222 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1223 | sage: H = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1224 | sage: from sage.rings.polynomial.plural import NCPolynomial_plural |
| | 1225 | sage: NCPolynomial_plural(H) |
| | 1226 | 0 |
| | 1227 | """ |
| | 1228 | self._poly = NULL |
| | 1229 | self._parent = <ParentWithBase>parent |
| | 1230 | |
| | 1231 | def __dealloc__(self): |
| | 1232 | # TODO: Warn otherwise! |
| | 1233 | # for some mysterious reason, various things may be NULL in some cases |
| | 1234 | if self._parent is not <ParentWithBase>None and (<NCPolynomialRing_plural>self._parent)._ring != NULL and self._poly != NULL: |
| | 1235 | p_Delete(&self._poly, (<NCPolynomialRing_plural>self._parent)._ring) |
| | 1236 | |
| | 1237 | # def __call__(self, *x, **kwds): # ? |
| | 1238 | |
| | 1239 | # you may have to replicate this boilerplate code in derived classes if you override |
| | 1240 | # __richcmp__. The python documentation at http://docs.python.org/api/type-structs.html |
| | 1241 | # explains how __richcmp__, __hash__, and __cmp__ are tied together. |
| | 1242 | def __hash__(self): |
| | 1243 | """ |
| | 1244 | This hash incorporates the variable name in an effort to |
| | 1245 | respect the obvious inclusions into multi-variable polynomial |
| | 1246 | rings. |
| | 1247 | |
| | 1248 | The tuple algorithm is borrowed from http://effbot.org/zone/python-hash.htm. |
| | 1249 | |
| | 1250 | EXAMPLES:: |
| | 1251 | |
| | 1252 | sage: R.<x>=QQ[] |
| | 1253 | sage: S.<x,y>=QQ[] |
| | 1254 | sage: hash(S(1/2))==hash(1/2) # respect inclusions of the rationals |
| | 1255 | True |
| | 1256 | sage: hash(S.0)==hash(R.0) # respect inclusions into mpoly rings |
| | 1257 | True |
| | 1258 | sage: # the point is to make for more flexible dictionary look ups |
| | 1259 | sage: d={S.0:12} |
| | 1260 | sage: d[R.0] |
| | 1261 | 12 |
| | 1262 | """ |
| | 1263 | return self._hash_c() |
| | 1264 | |
| | 1265 | def __richcmp__(left, right, int op): |
| | 1266 | """ |
| | 1267 | Compare left and right and return -1, 0, and 1 for <,==, and > |
| | 1268 | respectively. |
| | 1269 | |
| | 1270 | EXAMPLES:: |
| | 1271 | |
| | 1272 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1273 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1274 | sage: P.inject_variables() |
| | 1275 | Defining x, z, y |
| | 1276 | |
| | 1277 | sage: x == x |
| | 1278 | True |
| | 1279 | |
| | 1280 | sage: x > y |
| | 1281 | True |
| | 1282 | sage: y^2 > x |
| | 1283 | False |
| | 1284 | |
| | 1285 | ## sage: (2/3*x^2 + 1/2*y + 3) > (2/3*x^2 + 1/4*y + 10) |
| | 1286 | # True |
| | 1287 | |
| | 1288 | TESTS:: |
| | 1289 | |
| | 1290 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1291 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1292 | sage: P.inject_variables() |
| | 1293 | Defining x, z, y |
| | 1294 | |
| | 1295 | sage: x > P(0) |
| | 1296 | True |
| | 1297 | |
| | 1298 | sage: P(0) == P(0) |
| | 1299 | True |
| | 1300 | |
| | 1301 | sage: P(0) < P(1) |
| | 1302 | True |
| | 1303 | |
| | 1304 | sage: x > P(1) |
| | 1305 | True |
| | 1306 | |
| | 1307 | sage: 1/2*x < 3/4*x |
| | 1308 | True |
| | 1309 | |
| | 1310 | sage: (x+1) > x |
| | 1311 | True |
| | 1312 | |
| | 1313 | # sage: f = 3/4*x^2*y + 1/2*x + 2/7 |
| | 1314 | # sage: f > f |
| | 1315 | # False |
| | 1316 | # sage: f < f |
| | 1317 | # False |
| | 1318 | # sage: f == f |
| | 1319 | # True |
| | 1320 | |
| | 1321 | # sage: P.<x,y,z> = PolynomialRing(GF(127), order='degrevlex') |
| | 1322 | # sage: (66*x^2 + 23) > (66*x^2 + 2) |
| | 1323 | # True |
| | 1324 | """ |
| | 1325 | return (<Element>left)._richcmp(right, op) |
| | 1326 | |
| | 1327 | cdef int _cmp_c_impl(left, Element right) except -2: |
| | 1328 | if left is right: |
| | 1329 | return 0 |
| | 1330 | cdef poly *p = (<NCPolynomial_plural>left)._poly |
| | 1331 | cdef poly *q = (<NCPolynomial_plural>right)._poly |
| | 1332 | cdef ring *r = (<NCPolynomialRing_plural>left._parent)._ring |
| | 1333 | return singular_polynomial_cmp(p, q, r) |
| | 1334 | |
| | 1335 | cpdef ModuleElement _add_( left, ModuleElement right): |
| | 1336 | """ |
| | 1337 | Adds left and right. |
| | 1338 | |
| | 1339 | EXAMPLES:: |
| | 1340 | |
| | 1341 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1342 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1343 | sage: P.inject_variables() |
| | 1344 | Defining x, z, y |
| | 1345 | sage: 3/2*x + 1/2*y + 1 # indirect doctest |
| | 1346 | 3/2*x + 1/2*y + 1 |
| | 1347 | """ |
| | 1348 | cdef poly *_p |
| | 1349 | singular_polynomial_add(&_p, left._poly, |
| | 1350 | (<NCPolynomial_plural>right)._poly, |
| | 1351 | (<NCPolynomialRing_plural>left._parent)._ring) |
| | 1352 | return new_NCP((<NCPolynomialRing_plural>left._parent), _p) |
| | 1353 | |
| | 1354 | cpdef ModuleElement _sub_( left, ModuleElement right): |
| | 1355 | """ |
| | 1356 | Subtract left and right. |
| | 1357 | |
| | 1358 | EXAMPLES:: |
| | 1359 | |
| | 1360 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1361 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1362 | sage: P.inject_variables() |
| | 1363 | Defining x, z, y |
| | 1364 | sage: 3/2*x - 1/2*y - 1 # indirect doctest |
| | 1365 | 3/2*x - 1/2*y - 1 |
| | 1366 | |
| | 1367 | """ |
| | 1368 | cdef ring *_ring = (<NCPolynomialRing_plural>left._parent)._ring |
| | 1369 | |
| | 1370 | cdef poly *_p |
| | 1371 | singular_polynomial_sub(&_p, left._poly, |
| | 1372 | (<NCPolynomial_plural>right)._poly, |
| | 1373 | _ring) |
| | 1374 | return new_NCP((<NCPolynomialRing_plural>left._parent), _p) |
| | 1375 | |
| | 1376 | cpdef ModuleElement _rmul_(self, RingElement left): |
| | 1377 | """ |
| | 1378 | Multiply self with a base ring element. |
| | 1379 | |
| | 1380 | EXAMPLES:: |
| | 1381 | |
| | 1382 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1383 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1384 | sage: P.inject_variables() |
| | 1385 | Defining x, z, y |
| | 1386 | sage: 3/2*x # indirect doctest |
| | 1387 | 3/2*x |
| | 1388 | """ |
| | 1389 | |
| | 1390 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1391 | if not left: |
| | 1392 | return (<NCPolynomialRing_plural>self._parent)._zero_element |
| | 1393 | cdef poly *_p |
| | 1394 | singular_polynomial_rmul(&_p, self._poly, left, _ring) |
| | 1395 | return new_NCP((<NCPolynomialRing_plural>self._parent),_p) |
| | 1396 | |
| | 1397 | cpdef ModuleElement _lmul_(self, RingElement right): |
| | 1398 | """ |
| | 1399 | Multiply self with a base ring element. |
| | 1400 | |
| | 1401 | EXAMPLES:: |
| | 1402 | |
| | 1403 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1404 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1405 | sage: P.inject_variables() |
| | 1406 | Defining x, z, y |
| | 1407 | sage: x* (2/3) # indirect doctest |
| | 1408 | 2/3*x |
| | 1409 | """ |
| | 1410 | return self._rmul_(right) |
| | 1411 | |
| | 1412 | cpdef RingElement _mul_(left, RingElement right): |
| | 1413 | """ |
| | 1414 | Multiply left and right. |
| | 1415 | |
| | 1416 | EXAMPLES:: |
| | 1417 | |
| | 1418 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1419 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1420 | sage: P.inject_variables() |
| | 1421 | Defining x, z, y |
| | 1422 | sage: (3/2*x - 1/2*y - 1) * (3/2*x + 1/2*y + 1) # indirect doctest |
| | 1423 | 9/4*x^2 + 3/2*x*y - 3/4*z - 1/4*y^2 - y - 1 |
| | 1424 | |
| | 1425 | TEST:: |
| | 1426 | |
| | 1427 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1428 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1429 | sage: P.inject_variables() |
| | 1430 | Defining x, z, y |
| | 1431 | sage: (x^2^30) * x^2^30 |
| | 1432 | Traceback (most recent call last): |
| | 1433 | ... |
| | 1434 | OverflowError: Exponent overflow (...). |
| | 1435 | """ |
| | 1436 | # all currently implemented rings are commutative |
| | 1437 | cdef poly *_p |
| | 1438 | singular_polynomial_mul(&_p, left._poly, |
| | 1439 | (<NCPolynomial_plural>right)._poly, |
| | 1440 | (<NCPolynomialRing_plural>left._parent)._ring) |
| | 1441 | return new_NCP((<NCPolynomialRing_plural>left._parent),_p) |
| | 1442 | |
| | 1443 | cpdef RingElement _div_(left, RingElement right): |
| | 1444 | """ |
| | 1445 | Divide left by right |
| | 1446 | |
| | 1447 | EXAMPLES:: |
| | 1448 | |
| | 1449 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1450 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1451 | sage: R.inject_variables() |
| | 1452 | Defining x, z, y |
| | 1453 | sage: f = (x + y)/3 # indirect doctest |
| | 1454 | sage: f.parent() |
| | 1455 | Noncommutative Multivariate Polynomial Ring in x, z, y over Rational Field, nc-relations: {y*x: -x*y + z} |
| | 1456 | |
| | 1457 | TESTS:: |
| | 1458 | |
| | 1459 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1460 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1461 | sage: R.inject_variables() |
| | 1462 | Defining x, z, y |
| | 1463 | sage: x/0 |
| | 1464 | Traceback (most recent call last): |
| | 1465 | ... |
| | 1466 | ZeroDivisionError: rational division by zero |
| | 1467 | """ |
| | 1468 | cdef poly *p |
| | 1469 | cdef bint is_field = left._parent._base.is_field() |
| | 1470 | if p_IsConstant((<NCPolynomial_plural>right)._poly, (<NCPolynomialRing_plural>right._parent)._ring): |
| | 1471 | if is_field: |
| | 1472 | singular_polynomial_div_coeff(&p, left._poly, (<NCPolynomial_plural>right)._poly, (<NCPolynomialRing_plural>right._parent)._ring) |
| | 1473 | return new_NCP(left._parent, p) |
| | 1474 | else: |
| | 1475 | return left.change_ring(left.base_ring().fraction_field())/right |
| | 1476 | else: |
| | 1477 | return (<NCPolynomialRing_plural>left._parent).fraction_field()(left,right) |
| | 1478 | |
| | 1479 | def __pow__(NCPolynomial_plural self, exp, ignored): |
| | 1480 | """ |
| | 1481 | Return ``self**(exp)``. |
| | 1482 | |
| | 1483 | The exponent must be an integer. |
| | 1484 | |
| | 1485 | EXAMPLES:: |
| | 1486 | |
| | 1487 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1488 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1489 | sage: R.inject_variables() |
| | 1490 | Defining x, z, y |
| | 1491 | sage: f = x^3 + y |
| | 1492 | sage: f^2 |
| | 1493 | x^6 + x^2*z + y^2 |
| | 1494 | |
| | 1495 | TESTS:: |
| | 1496 | |
| | 1497 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1498 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1499 | sage: P.inject_variables() |
| | 1500 | Defining x, z, y |
| | 1501 | sage: (x+y^2^30)^10 |
| | 1502 | Traceback (most recent call last): |
| | 1503 | .... |
| | 1504 | OverflowError: Exponent overflow (...). |
| | 1505 | """ |
| | 1506 | if not PY_TYPE_CHECK_EXACT(exp, Integer) or \ |
| | 1507 | PY_TYPE_CHECK_EXACT(exp, int): |
| | 1508 | try: |
| | 1509 | exp = Integer(exp) |
| | 1510 | except TypeError: |
| | 1511 | raise TypeError, "non-integral exponents not supported" |
| | 1512 | |
| | 1513 | if exp < 0: |
| | 1514 | return 1/(self**(-exp)) |
| | 1515 | elif exp == 0: |
| | 1516 | return (<NCPolynomialRing_plural>self._parent)._one_element |
| | 1517 | |
| | 1518 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1519 | cdef poly *_p |
| | 1520 | singular_polynomial_pow(&_p, self._poly, exp, _ring) |
| | 1521 | return new_NCP((<NCPolynomialRing_plural>self._parent),_p) |
| | 1522 | |
| | 1523 | def __neg__(self): |
| | 1524 | """ |
| | 1525 | Return ``-self``. |
| | 1526 | |
| | 1527 | EXAMPLES:: |
| | 1528 | |
| | 1529 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1530 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1531 | sage: R.inject_variables() |
| | 1532 | Defining x, z, y |
| | 1533 | sage: f = x^3 + y |
| | 1534 | sage: -f |
| | 1535 | -x^3 - y |
| | 1536 | """ |
| | 1537 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1538 | |
| | 1539 | cdef poly *p |
| | 1540 | singular_polynomial_neg(&p, self._poly, _ring) |
| | 1541 | return new_NCP((<NCPolynomialRing_plural>self._parent), p) |
| | 1542 | |
| | 1543 | def _repr_(self): |
| | 1544 | """ |
| | 1545 | EXAMPLES:: |
| | 1546 | |
| | 1547 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1548 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1549 | sage: R.inject_variables() |
| | 1550 | Defining x, z, y |
| | 1551 | sage: f = x^3 + y*x*z + z |
| | 1552 | sage: f # indirect doctest |
| | 1553 | x^3 - x*z*y + z^2 + z |
| | 1554 | """ |
| | 1555 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1556 | s = singular_polynomial_str(self._poly, _ring) |
| | 1557 | return s |
| | 1558 | |
| | 1559 | cpdef _repr_short_(self): |
| | 1560 | """ |
| | 1561 | This is a faster but less pretty way to print polynomials. If |
| | 1562 | available it uses the short SINGULAR notation. |
| | 1563 | |
| | 1564 | EXAMPLES:: |
| | 1565 | |
| | 1566 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1567 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1568 | sage: R.inject_variables() |
| | 1569 | Defining x, z, y |
| | 1570 | sage: f = x^3 + y |
| | 1571 | sage: f._repr_short_() |
| | 1572 | 'x3+y' |
| | 1573 | """ |
| | 1574 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1575 | rChangeCurrRing(_ring) |
| | 1576 | if _ring.CanShortOut: |
| | 1577 | _ring.ShortOut = 1 |
| | 1578 | s = p_String(self._poly, _ring, _ring) |
| | 1579 | _ring.ShortOut = 0 |
| | 1580 | else: |
| | 1581 | s = p_String(self._poly, _ring, _ring) |
| | 1582 | return s |
| | 1583 | |
| | 1584 | def _latex_(self): |
| | 1585 | """ |
| | 1586 | Return a polynomial LaTeX representation of this polynomial. |
| | 1587 | |
| | 1588 | EXAMPLES:: |
| | 1589 | |
| | 1590 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1591 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1592 | sage: R.inject_variables() |
| | 1593 | Defining x, z, y |
| | 1594 | sage: f = - 1*x^2*y - 25/27 * y^3 - z^2 |
| | 1595 | sage: latex(f) # indirect doctest |
| | 1596 | - x^{2} y - z^{2} - \frac{25}{27} y^{3} |
| | 1597 | """ |
| | 1598 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1599 | gens = self.parent().latex_variable_names() |
| | 1600 | base = self.parent().base() |
| | 1601 | return singular_polynomial_latex(self._poly, _ring, base, gens) |
| | 1602 | |
| | 1603 | def _repr_with_changed_varnames(self, varnames): |
| | 1604 | """ |
| | 1605 | Return string representing this polynomial but change the |
| | 1606 | variable names to ``varnames``. |
| | 1607 | |
| | 1608 | EXAMPLES:: |
| | 1609 | |
| | 1610 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1611 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1612 | sage: R.inject_variables() |
| | 1613 | Defining x, z, y |
| | 1614 | sage: f = - 1*x^2*y - 25/27 * y^3 - z^2 |
| | 1615 | sage: print f._repr_with_changed_varnames(['FOO', 'BAR', 'FOOBAR']) |
| | 1616 | -FOO^2*FOOBAR - BAR^2 - 25/27*FOOBAR^3 |
| | 1617 | """ |
| | 1618 | return singular_polynomial_str_with_changed_varnames(self._poly, (<NCPolynomialRing_plural>self._parent)._ring, varnames) |
| | 1619 | |
| | 1620 | def degree(self, NCPolynomial_plural x=None): |
| | 1621 | """ |
| | 1622 | Return the maximal degree of this polynomial in ``x``, where |
| | 1623 | ``x`` must be one of the generators for the parent of this |
| | 1624 | polynomial. |
| | 1625 | |
| | 1626 | INPUT: |
| | 1627 | |
| | 1628 | - ``x`` - multivariate polynomial (a generator of the parent of |
| | 1629 | self) If x is not specified (or is ``None``), return the total |
| | 1630 | degree, which is the maximum degree of any monomial. |
| | 1631 | |
| | 1632 | OUTPUT: |
| | 1633 | integer |
| | 1634 | |
| | 1635 | EXAMPLES:: |
| | 1636 | |
| | 1637 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1638 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1639 | sage: R.inject_variables() |
| | 1640 | Defining x, z, y |
| | 1641 | sage: f = y^2 - x^9 - x |
| | 1642 | sage: f.degree(x) |
| | 1643 | 9 |
| | 1644 | sage: f.degree(y) |
| | 1645 | 2 |
| | 1646 | sage: (y^10*x - 7*x^2*y^5 + 5*x^3).degree(x) |
| | 1647 | 3 |
| | 1648 | sage: (y^10*x - 7*x^2*y^5 + 5*x^3).degree(y) |
| | 1649 | 10 |
| | 1650 | |
| | 1651 | TESTS:: |
| | 1652 | |
| | 1653 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1654 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1655 | sage: P.inject_variables() |
| | 1656 | Defining x, z, y |
| | 1657 | sage: P(0).degree(x) |
| | 1658 | -1 |
| | 1659 | sage: P(1).degree(x) |
| | 1660 | 0 |
| | 1661 | |
| | 1662 | """ |
| | 1663 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1664 | cdef poly *p = self._poly |
| | 1665 | if not x: |
| | 1666 | return singular_polynomial_deg(p,NULL,r) |
| | 1667 | |
| | 1668 | # TODO: we can do this faster |
| | 1669 | if not x in self._parent.gens(): |
| | 1670 | raise TypeError("x must be one of the generators of the parent.") |
| | 1671 | |
| | 1672 | return singular_polynomial_deg(p, (<NCPolynomial_plural>x)._poly, r) |
| | 1673 | |
| | 1674 | def total_degree(self): |
| | 1675 | """ |
| | 1676 | Return the total degree of ``self``, which is the maximum degree |
| | 1677 | of all monomials in ``self``. |
| | 1678 | |
| | 1679 | EXAMPLES:: |
| | 1680 | |
| | 1681 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1682 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1683 | sage: R.inject_variables() |
| | 1684 | Defining x, z, y |
| | 1685 | sage: f=2*x*y^3*z^2 |
| | 1686 | sage: f.total_degree() |
| | 1687 | 6 |
| | 1688 | sage: f=4*x^2*y^2*z^3 |
| | 1689 | sage: f.total_degree() |
| | 1690 | 7 |
| | 1691 | sage: f=99*x^6*y^3*z^9 |
| | 1692 | sage: f.total_degree() |
| | 1693 | 18 |
| | 1694 | sage: f=x*y^3*z^6+3*x^2 |
| | 1695 | sage: f.total_degree() |
| | 1696 | 10 |
| | 1697 | sage: f=z^3+8*x^4*y^5*z |
| | 1698 | sage: f.total_degree() |
| | 1699 | 10 |
| | 1700 | sage: f=z^9+10*x^4+y^8*x^2 |
| | 1701 | sage: f.total_degree() |
| | 1702 | 10 |
| | 1703 | |
| | 1704 | TESTS:: |
| | 1705 | |
| | 1706 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1707 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1708 | sage: R.inject_variables() |
| | 1709 | Defining x, z, y |
| | 1710 | sage: R(0).total_degree() |
| | 1711 | -1 |
| | 1712 | sage: R(1).total_degree() |
| | 1713 | 0 |
| | 1714 | """ |
| | 1715 | cdef poly *p = self._poly |
| | 1716 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1717 | return singular_polynomial_deg(p,NULL,r) |
| | 1718 | |
| | 1719 | def degrees(self): |
| | 1720 | """ |
| | 1721 | Returns a tuple with the maximal degree of each variable in |
| | 1722 | this polynomial. The list of degrees is ordered by the order |
| | 1723 | of the generators. |
| | 1724 | |
| | 1725 | EXAMPLES:: |
| | 1726 | |
| | 1727 | sage: A.<y0,y1,y2> = FreeAlgebra(QQ, 3) |
| | 1728 | sage: R = A.g_algebra(relations={y1*y0:-y0*y1 + y2}, order='lex') |
| | 1729 | sage: R.inject_variables() |
| | 1730 | Defining y0, y1, y2 |
| | 1731 | sage: q = 3*y0*y1*y1*y2; q |
| | 1732 | 3*y0*y1^2*y2 |
| | 1733 | sage: q.degrees() |
| | 1734 | (1, 2, 1) |
| | 1735 | sage: (q + y0^5).degrees() |
| | 1736 | (5, 2, 1) |
| | 1737 | """ |
| | 1738 | cdef poly *p = self._poly |
| | 1739 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1740 | cdef int i |
| | 1741 | cdef list d = [0 for _ in range(r.N)] |
| | 1742 | while p: |
| | 1743 | for i from 0 <= i < r.N: |
| | 1744 | d[i] = max(d[i],p_GetExp(p, i+1, r)) |
| | 1745 | p = pNext(p) |
| | 1746 | return tuple(d) |
| | 1747 | |
| | 1748 | |
| | 1749 | def coefficient(self, degrees): |
| | 1750 | """ |
| | 1751 | Return the coefficient of the variables with the degrees |
| | 1752 | specified in the python dictionary ``degrees``. |
| | 1753 | Mathematically, this is the coefficient in the base ring |
| | 1754 | adjoined by the variables of this ring not listed in |
| | 1755 | ``degrees``. However, the result has the same parent as this |
| | 1756 | polynomial. |
| | 1757 | |
| | 1758 | This function contrasts with the function |
| | 1759 | ``monomial_coefficient`` which returns the coefficient in the |
| | 1760 | base ring of a monomial. |
| | 1761 | |
| | 1762 | INPUT: |
| | 1763 | |
| | 1764 | - ``degrees`` - Can be any of: |
| | 1765 | - a dictionary of degree restrictions |
| | 1766 | - a list of degree restrictions (with None in the unrestricted variables) |
| | 1767 | - a monomial (very fast, but not as flexible) |
| | 1768 | |
| | 1769 | OUTPUT: |
| | 1770 | element of the parent of this element. |
| | 1771 | |
| | 1772 | .. note:: |
| | 1773 | |
| | 1774 | For coefficients of specific monomials, look at :meth:`monomial_coefficient`. |
| | 1775 | |
| | 1776 | EXAMPLES:: |
| | 1777 | |
| | 1778 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1779 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1780 | sage: R.inject_variables() |
| | 1781 | Defining x, z, y |
| | 1782 | sage: f=x*y+y+5 |
| | 1783 | sage: f.coefficient({x:0,y:1}) |
| | 1784 | 1 |
| | 1785 | sage: f.coefficient({x:0}) |
| | 1786 | y + 5 |
| | 1787 | sage: f=(1+y+y^2)*(1+x+x^2) |
| | 1788 | sage: f.coefficient({x:0}) |
| | 1789 | z + y^2 + y + 1 |
| | 1790 | |
| | 1791 | sage: f.coefficient(x) |
| | 1792 | y^2 - y + 1 |
| | 1793 | |
| | 1794 | # f.coefficient([0,None]) # y^2 + y + 1 |
| | 1795 | |
| | 1796 | Be aware that this may not be what you think! The physical |
| | 1797 | appearance of the variable x is deceiving -- particularly if |
| | 1798 | the exponent would be a variable. :: |
| | 1799 | |
| | 1800 | sage: f.coefficient(x^0) # outputs the full polynomial |
| | 1801 | x^2*y^2 + x^2*y + x^2 + x*y^2 - x*y + x + z + y^2 + y + 1 |
| | 1802 | |
| | 1803 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 1804 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1805 | sage: R.inject_variables() |
| | 1806 | Defining x, z, y |
| | 1807 | sage: f=x*y+5 |
| | 1808 | sage: c=f.coefficient({x:0,y:0}); c |
| | 1809 | 5 |
| | 1810 | sage: parent(c) |
| | 1811 | Noncommutative Multivariate Polynomial Ring in x, z, y over Finite Field of size 389, nc-relations: {y*x: -x*y + z} |
| | 1812 | |
| | 1813 | AUTHOR: |
| | 1814 | |
| | 1815 | - Joel B. Mohler (2007.10.31) |
| | 1816 | """ |
| | 1817 | cdef poly *_degrees = <poly*>0 |
| | 1818 | cdef poly *p = self._poly |
| | 1819 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1820 | cdef poly *newp = p_ISet(0,r) |
| | 1821 | cdef poly *newptemp |
| | 1822 | cdef int i |
| | 1823 | cdef int flag |
| | 1824 | cdef int gens = self._parent.ngens() |
| | 1825 | cdef int *exps = <int*>sage_malloc(sizeof(int)*gens) |
| | 1826 | for i from 0<=i<gens: |
| | 1827 | exps[i] = -1 |
| | 1828 | |
| | 1829 | if PY_TYPE_CHECK(degrees, NCPolynomial_plural) and self._parent is (<NCPolynomial_plural>degrees)._parent: |
| | 1830 | _degrees = (<NCPolynomial_plural>degrees)._poly |
| | 1831 | if pLength(_degrees) != 1: |
| | 1832 | raise TypeError, "degrees must be a monomial" |
| | 1833 | for i from 0<=i<gens: |
| | 1834 | if p_GetExp(_degrees,i+1,r)!=0: |
| | 1835 | exps[i] = p_GetExp(_degrees,i+1,r) |
| | 1836 | elif type(degrees) is list: |
| | 1837 | for i from 0<=i<gens: |
| | 1838 | if degrees[i] is None: |
| | 1839 | exps[i] = -1 |
| | 1840 | else: |
| | 1841 | exps[i] = int(degrees[i]) |
| | 1842 | elif type(degrees) is dict: |
| | 1843 | # Extract the ordered list of degree specifications from the dictionary |
| | 1844 | poly_vars = self.parent().gens() |
| | 1845 | for i from 0<=i<gens: |
| | 1846 | try: |
| | 1847 | exps[i] = degrees[poly_vars[i]] |
| | 1848 | except KeyError: |
| | 1849 | pass |
| | 1850 | else: |
| | 1851 | raise TypeError, "The input degrees must be a dictionary of variables to exponents." |
| | 1852 | |
| | 1853 | # Extract the monomials that match the specifications |
| | 1854 | while(p): |
| | 1855 | flag = 0 |
| | 1856 | for i from 0<=i<gens: |
| | 1857 | if exps[i] != -1 and p_GetExp(p,i+1,r)!=exps[i]: |
| | 1858 | #print i, p_GetExp(p,i+1,r), exps[i] |
| | 1859 | flag = 1 |
| | 1860 | if flag == 0: |
| | 1861 | newptemp = p_LmInit(p,r) |
| | 1862 | p_SetCoeff(newptemp,n_Copy(p_GetCoeff(p,r),r),r) |
| | 1863 | for i from 0<=i<gens: |
| | 1864 | if exps[i] != -1: |
| | 1865 | p_SetExp(newptemp,i+1,0,r) |
| | 1866 | p_Setm(newptemp,r) |
| | 1867 | newp = p_Add_q(newp,newptemp,r) |
| | 1868 | p = pNext(p) |
| | 1869 | |
| | 1870 | sage_free(exps) |
| | 1871 | |
| | 1872 | return new_NCP(self.parent(),newp) |
| | 1873 | |
| | 1874 | def monomial_coefficient(self, NCPolynomial_plural mon): |
| | 1875 | """ |
| | 1876 | Return the coefficient in the base ring of the monomial mon in |
| | 1877 | ``self``, where mon must have the same parent as self. |
| | 1878 | |
| | 1879 | This function contrasts with the function ``coefficient`` |
| | 1880 | which returns the coefficient of a monomial viewing this |
| | 1881 | polynomial in a polynomial ring over a base ring having fewer |
| | 1882 | variables. |
| | 1883 | |
| | 1884 | INPUT: |
| | 1885 | |
| | 1886 | - ``mon`` - a monomial |
| | 1887 | |
| | 1888 | OUTPUT: |
| | 1889 | coefficient in base ring |
| | 1890 | |
| | 1891 | SEE ALSO: |
| | 1892 | For coefficients in a base ring of fewer variables, look at ``coefficient``. |
| | 1893 | |
| | 1894 | EXAMPLES:: |
| | 1895 | |
| | 1896 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 1897 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1898 | sage: P.inject_variables() |
| | 1899 | Defining x, z, y |
| | 1900 | |
| | 1901 | The parent of the return is a member of the base ring. |
| | 1902 | sage: f = 2 * x * y |
| | 1903 | sage: c = f.monomial_coefficient(x*y); c |
| | 1904 | 2 |
| | 1905 | sage: c.parent() |
| | 1906 | Finite Field of size 389 |
| | 1907 | |
| | 1908 | sage: f = y^2 + y^2*x - x^9 - 7*x + 5*x*y |
| | 1909 | sage: f.monomial_coefficient(y^2) |
| | 1910 | 1 |
| | 1911 | sage: f.monomial_coefficient(x*y) |
| | 1912 | 5 |
| | 1913 | sage: f.monomial_coefficient(x^9) |
| | 1914 | 388 |
| | 1915 | sage: f.monomial_coefficient(x^10) |
| | 1916 | 0 |
| | 1917 | """ |
| | 1918 | cdef poly *p = self._poly |
| | 1919 | cdef poly *m = mon._poly |
| | 1920 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1921 | |
| | 1922 | if not mon._parent is self._parent: |
| | 1923 | raise TypeError("mon must have same parent as self.") |
| | 1924 | |
| | 1925 | while(p): |
| | 1926 | if p_ExpVectorEqual(p, m, r) == 1: |
| | 1927 | return si2sa(p_GetCoeff(p, r), r, (<NCPolynomialRing_plural>self._parent)._base) |
| | 1928 | p = pNext(p) |
| | 1929 | |
| | 1930 | return (<NCPolynomialRing_plural>self._parent)._base._zero_element |
| | 1931 | |
| | 1932 | def dict(self): |
| | 1933 | """ |
| | 1934 | Return a dictionary representing self. This dictionary is in |
| | 1935 | the same format as the generic MPolynomial: The dictionary |
| | 1936 | consists of ``ETuple:coefficient`` pairs. |
| | 1937 | |
| | 1938 | EXAMPLES:: |
| | 1939 | |
| | 1940 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 1941 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1942 | sage: R.inject_variables() |
| | 1943 | Defining x, z, y |
| | 1944 | |
| | 1945 | sage: f = (2*x*y^3*z^2 + (7)*x^2 + (3)) |
| | 1946 | sage: f.dict() |
| | 1947 | {(0, 0, 0): 3, (2, 0, 0): 7, (1, 2, 3): 2} |
| | 1948 | """ |
| | 1949 | cdef poly *p |
| | 1950 | cdef ring *r |
| | 1951 | cdef int n |
| | 1952 | cdef int v |
| | 1953 | r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1954 | if r!=currRing: rChangeCurrRing(r) |
| | 1955 | base = (<NCPolynomialRing_plural>self._parent)._base |
| | 1956 | p = self._poly |
| | 1957 | pd = dict() |
| | 1958 | while p: |
| | 1959 | d = dict() |
| | 1960 | for v from 1 <= v <= r.N: |
| | 1961 | n = p_GetExp(p,v,r) |
| | 1962 | if n!=0: |
| | 1963 | d[v-1] = n |
| | 1964 | |
| | 1965 | pd[ETuple(d,r.N)] = si2sa(p_GetCoeff(p, r), r, base) |
| | 1966 | |
| | 1967 | p = pNext(p) |
| | 1968 | return pd |
| | 1969 | |
| | 1970 | |
| | 1971 | cdef long _hash_c(self): |
| | 1972 | """ |
| | 1973 | See ``self.__hash__`` |
| | 1974 | """ |
| | 1975 | cdef poly *p |
| | 1976 | cdef ring *r |
| | 1977 | cdef int n |
| | 1978 | cdef int v |
| | 1979 | r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1980 | if r!=currRing: rChangeCurrRing(r) |
| | 1981 | base = (<NCPolynomialRing_plural>self._parent)._base |
| | 1982 | p = self._poly |
| | 1983 | cdef long result = 0 # store it in a c-int and just let the overflowing additions wrap |
| | 1984 | cdef long result_mon |
| | 1985 | var_name_hash = [hash(vn) for vn in self._parent.variable_names()] |
| | 1986 | cdef long c_hash |
| | 1987 | while p: |
| | 1988 | c_hash = hash(si2sa(p_GetCoeff(p, r), r, base)) |
| | 1989 | if c_hash != 0: # this is always going to be true, because we are sparse (correct?) |
| | 1990 | # Hash (self[i], gen_a, exp_a, gen_b, exp_b, gen_c, exp_c, ...) as a tuple according to the algorithm. |
| | 1991 | # I omit gen,exp pairs where the exponent is zero. |
| | 1992 | result_mon = c_hash |
| | 1993 | for v from 1 <= v <= r.N: |
| | 1994 | n = p_GetExp(p,v,r) |
| | 1995 | if n!=0: |
| | 1996 | result_mon = (1000003 * result_mon) ^ var_name_hash[v-1] |
| | 1997 | result_mon = (1000003 * result_mon) ^ n |
| | 1998 | result += result_mon |
| | 1999 | |
| | 2000 | p = pNext(p) |
| | 2001 | if result == -1: |
| | 2002 | return -2 |
| | 2003 | return result |
| | 2004 | |
| | 2005 | def __getitem__(self,x): |
| | 2006 | """ |
| | 2007 | Same as ``self.monomial_coefficent`` but for exponent vectors. |
| | 2008 | |
| | 2009 | INPUT: |
| | 2010 | |
| | 2011 | - ``x`` - a tuple or, in case of a single-variable MPolynomial |
| | 2012 | ring x can also be an integer. |
| | 2013 | |
| | 2014 | EXAMPLES:: |
| | 2015 | |
| | 2016 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2017 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2018 | sage: R.inject_variables() |
| | 2019 | Defining x, z, y |
| | 2020 | sage: f = (-10*x^3*y + 17*x*y)* ( 15*z^3 + 2*x*y*z - 1); f |
| | 2021 | 20*x^4*z*y^2 - 150*x^3*z^3*y - 20*x^3*z^2*y + 10*x^3*y - 34*x^2*z*y^2 - 134*x*z^3*y + 34*x*z^2*y - 17*x*y |
| | 2022 | sage: f[4,1,2] |
| | 2023 | 20 |
| | 2024 | sage: f[1,0,1] |
| | 2025 | 372 |
| | 2026 | sage: f[0,0,0] |
| | 2027 | 0 |
| | 2028 | |
| | 2029 | sage: R.<x> = PolynomialRing(GF(7),1); R |
| | 2030 | Multivariate Polynomial Ring in x over Finite Field of size 7 |
| | 2031 | sage: f = 5*x^2 + 3; f |
| | 2032 | -2*x^2 + 3 |
| | 2033 | sage: f[2] |
| | 2034 | 5 |
| | 2035 | """ |
| | 2036 | cdef poly *m |
| | 2037 | cdef poly *p = self._poly |
| | 2038 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2039 | cdef int i |
| | 2040 | |
| | 2041 | if PY_TYPE_CHECK(x, NCPolynomial_plural): |
| | 2042 | return self.monomial_coefficient(x) |
| | 2043 | if not PY_TYPE_CHECK(x, tuple): |
| | 2044 | try: |
| | 2045 | x = tuple(x) |
| | 2046 | except TypeError: |
| | 2047 | x = (x,) |
| | 2048 | |
| | 2049 | if len(x) != (<NCPolynomialRing_plural>self._parent).__ngens: |
| | 2050 | raise TypeError, "x must have length self.ngens()" |
| | 2051 | |
| | 2052 | m = p_ISet(1,r) |
| | 2053 | i = 1 |
| | 2054 | for e in x: |
| | 2055 | overflow_check(e, r) |
| | 2056 | p_SetExp(m, i, int(e), r) |
| | 2057 | i += 1 |
| | 2058 | p_Setm(m, r) |
| | 2059 | |
| | 2060 | while(p): |
| | 2061 | if p_ExpVectorEqual(p, m, r) == 1: |
| | 2062 | p_Delete(&m,r) |
| | 2063 | return si2sa(p_GetCoeff(p, r), r, (<NCPolynomialRing_plural>self._parent)._base) |
| | 2064 | p = pNext(p) |
| | 2065 | |
| | 2066 | p_Delete(&m,r) |
| | 2067 | return (<NCPolynomialRing_plural>self._parent)._base._zero_element |
| | 2068 | |
| | 2069 | def exponents(self, as_ETuples=True): |
| | 2070 | """ |
| | 2071 | Return the exponents of the monomials appearing in this polynomial. |
| | 2072 | |
| | 2073 | INPUT: |
| | 2074 | |
| | 2075 | - ``as_ETuples`` - (default: ``True``) if true returns the result as an list of ETuples |
| | 2076 | otherwise returns a list of tuples |
| | 2077 | |
| | 2078 | |
| | 2079 | EXAMPLES:: |
| | 2080 | |
| | 2081 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2082 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2083 | sage: R.inject_variables() |
| | 2084 | Defining x, z, y |
| | 2085 | sage: f = x^3 + y + 2*z^2 |
| | 2086 | sage: f.exponents() |
| | 2087 | [(3, 0, 0), (0, 2, 0), (0, 0, 1)] |
| | 2088 | sage: f.exponents(as_ETuples=False) |
| | 2089 | [(3, 0, 0), (0, 2, 0), (0, 0, 1)] |
| | 2090 | """ |
| | 2091 | cdef poly *p |
| | 2092 | cdef ring *r |
| | 2093 | cdef int v |
| | 2094 | cdef list pl, ml |
| | 2095 | |
| | 2096 | r = (< NCPolynomialRing_plural>self._parent)._ring |
| | 2097 | p = self._poly |
| | 2098 | |
| | 2099 | pl = list() |
| | 2100 | ml = range(r.N) |
| | 2101 | while p: |
| | 2102 | for v from 1 <= v <= r.N: |
| | 2103 | ml[v-1] = p_GetExp(p,v,r) |
| | 2104 | |
| | 2105 | if as_ETuples: |
| | 2106 | pl.append(ETuple(ml)) |
| | 2107 | else: |
| | 2108 | pl.append(tuple(ml)) |
| | 2109 | |
| | 2110 | p = pNext(p) |
| | 2111 | return pl |
| | 2112 | |
| | 2113 | def is_homogeneous(self): |
| | 2114 | """ |
| | 2115 | Return ``True`` if this polynomial is homogeneous. |
| | 2116 | |
| | 2117 | EXAMPLES:: |
| | 2118 | |
| | 2119 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2120 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2121 | sage: P.inject_variables() |
| | 2122 | Defining x, z, y |
| | 2123 | sage: (x+y+z).is_homogeneous() |
| | 2124 | True |
| | 2125 | sage: (x.parent()(0)).is_homogeneous() |
| | 2126 | True |
| | 2127 | sage: (x+y^2+z^3).is_homogeneous() |
| | 2128 | False |
| | 2129 | sage: (x^2 + y^2).is_homogeneous() |
| | 2130 | True |
| | 2131 | sage: (x^2 + y^2*x).is_homogeneous() |
| | 2132 | False |
| | 2133 | sage: (x^2*y + y^2*x).is_homogeneous() |
| | 2134 | True |
| | 2135 | """ |
| | 2136 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2137 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 2138 | return bool(pIsHomogeneous(self._poly)) |
| | 2139 | |
| | 2140 | |
| | 2141 | def is_monomial(self): |
| | 2142 | """ |
| | 2143 | Return ``True`` if this polynomial is a monomial. A monomial |
| | 2144 | is defined to be a product of generators with coefficient 1. |
| | 2145 | |
| | 2146 | EXAMPLES:: |
| | 2147 | |
| | 2148 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2149 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2150 | sage: P.inject_variables() |
| | 2151 | Defining x, z, y |
| | 2152 | sage: x.is_monomial() |
| | 2153 | True |
| | 2154 | sage: (2*x).is_monomial() |
| | 2155 | False |
| | 2156 | sage: (x*y).is_monomial() |
| | 2157 | True |
| | 2158 | sage: (x*y + x).is_monomial() |
| | 2159 | False |
| | 2160 | """ |
| | 2161 | cdef poly *_p |
| | 2162 | cdef ring *_ring |
| | 2163 | cdef number *_n |
| | 2164 | _ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2165 | |
| | 2166 | if self._poly == NULL: |
| | 2167 | return True |
| | 2168 | |
| | 2169 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 2170 | |
| | 2171 | _p = p_Head(self._poly, _ring) |
| | 2172 | _n = p_GetCoeff(_p, _ring) |
| | 2173 | |
| | 2174 | ret = (not self._poly.next) and n_IsOne(_n, _ring) |
| | 2175 | |
| | 2176 | p_Delete(&_p, _ring) |
| | 2177 | return ret |
| | 2178 | |
| | 2179 | def monomials(self): |
| | 2180 | """ |
| | 2181 | Return the list of monomials in self. The returned list is |
| | 2182 | decreasingly ordered by the term ordering of |
| | 2183 | ``self.parent()``. |
| | 2184 | |
| | 2185 | EXAMPLES:: |
| | 2186 | |
| | 2187 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2188 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2189 | sage: P.inject_variables() |
| | 2190 | Defining x, z, y |
| | 2191 | sage: f = x + (3*2)*y*z^2 + (2+3) |
| | 2192 | sage: f.monomials() |
| | 2193 | [x, z^2*y, 1] |
| | 2194 | sage: f = P(3^2) |
| | 2195 | sage: f.monomials() |
| | 2196 | [1] |
| | 2197 | |
| | 2198 | TESTS:: |
| | 2199 | |
| | 2200 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2201 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2202 | sage: P.inject_variables() |
| | 2203 | Defining x, z, y |
| | 2204 | sage: f = x |
| | 2205 | sage: f.monomials() |
| | 2206 | [x] |
| | 2207 | sage: f = P(0) |
| | 2208 | sage: f.monomials() |
| | 2209 | [0] |
| | 2210 | |
| | 2211 | Check if #7152 is fixed:: |
| | 2212 | |
| | 2213 | sage: x=var('x') |
| | 2214 | sage: K.<rho> = NumberField(x**2 + 1) |
| | 2215 | sage: R.<x,y> = QQ[] |
| | 2216 | sage: p = rho*x |
| | 2217 | sage: q = x |
| | 2218 | sage: p.monomials() |
| | 2219 | [x] |
| | 2220 | sage: q.monomials() |
| | 2221 | [x] |
| | 2222 | sage: p.monomials() |
| | 2223 | [x] |
| | 2224 | """ |
| | 2225 | l = list() |
| | 2226 | cdef NCPolynomialRing_plural parent = <NCPolynomialRing_plural>self._parent |
| | 2227 | cdef ring *_ring = parent._ring |
| | 2228 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 2229 | cdef poly *p = p_Copy(self._poly, _ring) |
| | 2230 | cdef poly *t |
| | 2231 | |
| | 2232 | if p == NULL: |
| | 2233 | return [parent._zero_element] |
| | 2234 | |
| | 2235 | while p: |
| | 2236 | t = pNext(p) |
| | 2237 | p.next = NULL |
| | 2238 | p_SetCoeff(p, n_Init(1,_ring), _ring) |
| | 2239 | p_Setm(p, _ring) |
| | 2240 | l.append( new_NCP(parent,p) ) |
| | 2241 | p = t |
| | 2242 | |
| | 2243 | return l |
| | 2244 | |
| | 2245 | def constant_coefficient(self): |
| | 2246 | """ |
| | 2247 | Return the constant coefficient of this multivariate |
| | 2248 | polynomial. |
| | 2249 | |
| | 2250 | EXAMPLES:: |
| | 2251 | |
| | 2252 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2253 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2254 | sage: P.inject_variables() |
| | 2255 | Defining x, z, y |
| | 2256 | sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5 |
| | 2257 | sage: f.constant_coefficient() |
| | 2258 | 5 |
| | 2259 | sage: f = 3*x^2 |
| | 2260 | sage: f.constant_coefficient() |
| | 2261 | 0 |
| | 2262 | """ |
| | 2263 | cdef poly *p = self._poly |
| | 2264 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2265 | if p == NULL: |
| | 2266 | return (<NCPolynomialRing_plural>self._parent)._base._zero_element |
| | 2267 | |
| | 2268 | while p.next: |
| | 2269 | p = pNext(p) |
| | 2270 | |
| | 2271 | if p_LmIsConstant(p, r): |
| | 2272 | return si2sa( p_GetCoeff(p, r), r, (<NCPolynomialRing_plural>self._parent)._base ) |
| | 2273 | else: |
| | 2274 | return (<NCPolynomialRing_plural>self._parent)._base._zero_element |
| | 2275 | |
| | 2276 | cpdef is_constant(self): |
| | 2277 | """ |
| | 2278 | Return ``True`` if this polynomial is constant. |
| | 2279 | |
| | 2280 | EXAMPLES:: |
| | 2281 | |
| | 2282 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2283 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2284 | sage: P.inject_variables() |
| | 2285 | Defining x, z, y |
| | 2286 | sage: x.is_constant() |
| | 2287 | False |
| | 2288 | sage: P(1).is_constant() |
| | 2289 | True |
| | 2290 | """ |
| | 2291 | return bool(p_IsConstant(self._poly, (<NCPolynomialRing_plural>self._parent)._ring)) |
| | 2292 | |
| | 2293 | def lm(NCPolynomial_plural self): |
| | 2294 | """ |
| | 2295 | Returns the lead monomial of self with respect to the term |
| | 2296 | order of ``self.parent()``. In Sage a monomial is a product of |
| | 2297 | variables in some power without a coefficient. |
| | 2298 | |
| | 2299 | EXAMPLES:: |
| | 2300 | |
| | 2301 | sage: A.<x,y,z> = FreeAlgebra(GF(7), 3) |
| | 2302 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2303 | sage: R.inject_variables() |
| | 2304 | Defining x, y, z |
| | 2305 | sage: f = x^1*y^2 + y^3*z^4 |
| | 2306 | sage: f.lm() |
| | 2307 | x*y^2 |
| | 2308 | sage: f = x^3*y^2*z^4 + x^3*y^2*z^1 |
| | 2309 | sage: f.lm() |
| | 2310 | x^3*y^2*z^4 |
| | 2311 | |
| | 2312 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 2313 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='deglex') |
| | 2314 | sage: R.inject_variables() |
| | 2315 | Defining x, y, z |
| | 2316 | sage: f = x^1*y^2*z^3 + x^3*y^2*z^0 |
| | 2317 | sage: f.lm() |
| | 2318 | x*y^2*z^3 |
| | 2319 | sage: f = x^1*y^2*z^4 + x^1*y^1*z^5 |
| | 2320 | sage: f.lm() |
| | 2321 | x*y^2*z^4 |
| | 2322 | |
| | 2323 | sage: A.<x,y,z> = FreeAlgebra(GF(127), 3) |
| | 2324 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='degrevlex') |
| | 2325 | sage: R.inject_variables() |
| | 2326 | Defining x, y, z |
| | 2327 | sage: f = x^1*y^5*z^2 + x^4*y^1*z^3 |
| | 2328 | sage: f.lm() |
| | 2329 | x*y^5*z^2 |
| | 2330 | sage: f = x^4*y^7*z^1 + x^4*y^2*z^3 |
| | 2331 | sage: f.lm() |
| | 2332 | x^4*y^7*z |
| | 2333 | |
| | 2334 | """ |
| | 2335 | cdef poly *_p |
| | 2336 | cdef ring *_ring |
| | 2337 | _ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2338 | if self._poly == NULL: |
| | 2339 | return (<NCPolynomialRing_plural>self._parent)._zero_element |
| | 2340 | _p = p_Head(self._poly, _ring) |
| | 2341 | p_SetCoeff(_p, n_Init(1,_ring), _ring) |
| | 2342 | p_Setm(_p,_ring) |
| | 2343 | return new_NCP((<NCPolynomialRing_plural>self._parent), _p) |
| | 2344 | |
| | 2345 | def lc(NCPolynomial_plural self): |
| | 2346 | """ |
| | 2347 | Leading coefficient of this polynomial with respect to the |
| | 2348 | term order of ``self.parent()``. |
| | 2349 | |
| | 2350 | EXAMPLES:: |
| | 2351 | |
| | 2352 | sage: A.<x,y,z> = FreeAlgebra(GF(7), 3) |
| | 2353 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2354 | sage: R.inject_variables() |
| | 2355 | Defining x, y, z |
| | 2356 | |
| | 2357 | sage: f = 3*x^1*y^2 + 2*y^3*z^4 |
| | 2358 | sage: f.lc() |
| | 2359 | 3 |
| | 2360 | |
| | 2361 | sage: f = 5*x^3*y^2*z^4 + 4*x^3*y^2*z^1 |
| | 2362 | sage: f.lc() |
| | 2363 | 5 |
| | 2364 | """ |
| | 2365 | |
| | 2366 | cdef poly *_p |
| | 2367 | cdef ring *_ring |
| | 2368 | cdef number *_n |
| | 2369 | _ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2370 | |
| | 2371 | if self._poly == NULL: |
| | 2372 | return (<NCPolynomialRing_plural>self._parent)._base._zero_element |
| | 2373 | |
| | 2374 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 2375 | |
| | 2376 | _p = p_Head(self._poly, _ring) |
| | 2377 | _n = p_GetCoeff(_p, _ring) |
| | 2378 | |
| | 2379 | ret = si2sa(_n, _ring, (<NCPolynomialRing_plural>self._parent)._base) |
| | 2380 | p_Delete(&_p, _ring) |
| | 2381 | return ret |
| | 2382 | |
| | 2383 | def lt(NCPolynomial_plural self): |
| | 2384 | """ |
| | 2385 | Leading term of this polynomial. In Sage a term is a product |
| | 2386 | of variables in some power and a coefficient. |
| | 2387 | |
| | 2388 | EXAMPLES:: |
| | 2389 | |
| | 2390 | sage: A.<x,y,z> = FreeAlgebra(GF(7), 3) |
| | 2391 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2392 | sage: R.inject_variables() |
| | 2393 | Defining x, y, z |
| | 2394 | |
| | 2395 | sage: f = 3*x^1*y^2 + 2*y^3*z^4 |
| | 2396 | sage: f.lt() |
| | 2397 | 3*x*y^2 |
| | 2398 | |
| | 2399 | sage: f = 5*x^3*y^2*z^4 + 4*x^3*y^2*z^1 |
| | 2400 | sage: f.lt() |
| | 2401 | -2*x^3*y^2*z^4 |
| | 2402 | """ |
| | 2403 | if self._poly == NULL: |
| | 2404 | return (<NCPolynomialRing_plural>self._parent)._zero_element |
| | 2405 | |
| | 2406 | return new_NCP((<NCPolynomialRing_plural>self._parent), |
| | 2407 | p_Head(self._poly,(<NCPolynomialRing_plural>self._parent)._ring)) |
| | 2408 | |
| | 2409 | def is_zero(self): |
| | 2410 | """ |
| | 2411 | Return ``True`` if this polynomial is zero. |
| | 2412 | |
| | 2413 | EXAMPLES:: |
| | 2414 | |
| | 2415 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 2416 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2417 | sage: R.inject_variables() |
| | 2418 | Defining x, z, y |
| | 2419 | |
| | 2420 | sage: x.is_zero() |
| | 2421 | False |
| | 2422 | sage: (x-x).is_zero() |
| | 2423 | True |
| | 2424 | """ |
| | 2425 | if self._poly is NULL: |
| | 2426 | return True |
| | 2427 | else: |
| | 2428 | return False |
| | 2429 | |
| | 2430 | def __nonzero__(self): |
| | 2431 | """ |
| | 2432 | EXAMPLES:: |
| | 2433 | |
| | 2434 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 2435 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2436 | sage: R.inject_variables() |
| | 2437 | Defining x, z, y |
| | 2438 | |
| | 2439 | sage: bool(x) # indirect doctest |
| | 2440 | True |
| | 2441 | sage: bool(x-x) |
| | 2442 | False |
| | 2443 | """ |
| | 2444 | if self._poly: |
| | 2445 | return True |
| | 2446 | else: |
| | 2447 | return False |
| | 2448 | |
| | 2449 | |
| | 2450 | ##################################################################### |
| | 2451 | |
| | 2452 | |
| | 2453 | cdef inline NCPolynomial_plural new_NCP(NCPolynomialRing_plural parent, |
| | 2454 | poly *juice): |
| | 2455 | """ |
| | 2456 | Construct NCPolynomial_plural from parent and SINGULAR poly. |
| | 2457 | |
| | 2458 | EXAMPLES:: |
| | 2459 | |
| | 2460 | |
| | 2461 | """ |
| | 2462 | cdef NCPolynomial_plural p = PY_NEW(NCPolynomial_plural) |
| | 2463 | p._parent = <ParentWithBase>parent |
| | 2464 | p._poly = juice |
| | 2465 | p_Normalize(p._poly, parent._ring) |
| | 2466 | return p |
| | 2467 | |
| | 2468 | |
| | 2469 | |
| | 2470 | |
| | 2471 | cpdef MPolynomialRing_libsingular new_CRing(RingWrap rw, base_ring): |
| | 2472 | """ |
| | 2473 | Construct MPolynomialRing_libsingular from ringWrap, assumming the ground field to be base_ring |
| | 2474 | |
| | 2475 | EXAMPLES:: |
| | 2476 | sage: H.<x,y,z> = PolynomialRing(QQ, 3) |
| | 2477 | sage: from sage.libs.singular.function import singular_function |
| | 2478 | |
| | 2479 | sage: ringlist = singular_function('ringlist') |
| | 2480 | sage: ring = singular_function("ring") |
| | 2481 | |
| | 2482 | sage: L = ringlist(H, ring=H); L |
| | 2483 | [0, ['x', 'y', 'z'], [['dp', (1, 1, 1)], ['C', (0,)]], [0]] |
| | 2484 | |
| | 2485 | sage: len(L) |
| | 2486 | 4 |
| | 2487 | |
| | 2488 | sage: W = ring(L, ring=H); W |
| | 2489 | <RingWrap> |
| | 2490 | |
| | 2491 | sage: from sage.rings.polynomial.plural import new_CRing |
| | 2492 | sage: R = new_CRing(W, H.base_ring()) |
| | 2493 | sage: R # indirect doctest |
| | 2494 | Multivariate Polynomial Ring in x, y, z over Rational Field |
| | 2495 | """ |
| | 2496 | assert( rw.is_commutative() ) |
| | 2497 | |
| | 2498 | cdef MPolynomialRing_libsingular self = <MPolynomialRing_libsingular>PY_NEW(MPolynomialRing_libsingular) |
| | 2499 | |
| | 2500 | self._ring = rw._ring |
| | 2501 | self._ring.ShortOut = 0 |
| | 2502 | |
| | 2503 | self.__ngens = rw.ngens() |
| | 2504 | self.__term_order = TermOrder(rw.ordering_string(), force=True) |
| | 2505 | |
| | 2506 | ParentWithGens.__init__(self, base_ring, rw.var_names()) |
| | 2507 | # self._populate_coercion_lists_() # ??? |
| | 2508 | |
| | 2509 | #MPolynomialRing_generic.__init__(self, base_ring, n, names, order) |
| | 2510 | self._has_singular = True |
| | 2511 | # self._relations = self.relations() |
| | 2512 | |
| | 2513 | return self |
| | 2514 | |
| | 2515 | cpdef NCPolynomialRing_plural new_NRing(RingWrap rw, base_ring): |
| | 2516 | """ |
| | 2517 | Construct NCPolynomialRing_plural from ringWrap, assumming the ground field to be base_ring |
| | 2518 | |
| | 2519 | EXAMPLES:: |
| | 2520 | EXAMPLES:: |
| | 2521 | |
| | 2522 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 2523 | sage: H = A.g_algebra({y*x:x*y-1}) |
| | 2524 | sage: H.inject_variables() |
| | 2525 | Defining x, y, z |
| | 2526 | sage: z*x |
| | 2527 | x*z |
| | 2528 | sage: z*y |
| | 2529 | y*z |
| | 2530 | sage: y*x |
| | 2531 | x*y - 1 |
| | 2532 | sage: I = H.ideal([y^2, x^2, z^2-1]) |
| | 2533 | sage: I._groebner_basis_libsingular() |
| | 2534 | [1] |
| | 2535 | |
| | 2536 | sage: from sage.libs.singular.function import singular_function |
| | 2537 | |
| | 2538 | sage: ringlist = singular_function('ringlist') |
| | 2539 | sage: ring = singular_function("ring") |
| | 2540 | |
| | 2541 | sage: L = ringlist(H, ring=H); L |
| | 2542 | [0, ['x', 'y', 'z'], [['dp', (1, 1, 1)], ['C', (0,)]], [0], [0 1 1] |
| | 2543 | [0 0 1] |
| | 2544 | [0 0 0], [ 0 -1 0] |
| | 2545 | [ 0 0 0] |
| | 2546 | [ 0 0 0]] |
| | 2547 | |
| | 2548 | sage: len(L) |
| | 2549 | 6 |
| | 2550 | |
| | 2551 | sage: W = ring(L, ring=H); W |
| | 2552 | <noncommutative RingWrap> |
| | 2553 | |
| | 2554 | sage: from sage.rings.polynomial.plural import new_NRing |
| | 2555 | sage: R = new_NRing(W, H.base_ring()) |
| | 2556 | sage: R # indirect doctest |
| | 2557 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: x*y - 1} |
| | 2558 | """ |
| | 2559 | |
| | 2560 | assert( not rw.is_commutative() ) |
| | 2561 | |
| | 2562 | cdef NCPolynomialRing_plural self = <NCPolynomialRing_plural>PY_NEW(NCPolynomialRing_plural) |
| | 2563 | self._ring = rw._ring |
| | 2564 | self._ring.ShortOut = 0 |
| | 2565 | |
| | 2566 | self.__ngens = rw.ngens() |
| | 2567 | self.__term_order = TermOrder(rw.ordering_string(), force=True) |
| | 2568 | |
| | 2569 | ParentWithGens.__init__(self, base_ring, rw.var_names()) |
| | 2570 | # self._populate_coercion_lists_() # ??? |
| | 2571 | |
| | 2572 | #MPolynomialRing_generic.__init__(self, base_ring, n, names, order) |
| | 2573 | self._has_singular = True |
| | 2574 | self._relations = self.relations() |
| | 2575 | |
| | 2576 | return self |
| | 2577 | |
| | 2578 | |
| | 2579 | def new_Ring(RingWrap rw, base_ring): |
| | 2580 | """ |
| | 2581 | Constructs a Sage ring out of low level RingWrap, which wraps a pointer to a Singular ring. |
| | 2582 | The constructed ring is either commutative or noncommutative depending on the Singular ring. |
| | 2583 | |
| | 2584 | EXAMPLES:: |
| | 2585 | |
| | 2586 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 2587 | sage: H = A.g_algebra({y*x:x*y-1}) |
| | 2588 | sage: H.inject_variables() |
| | 2589 | Defining x, y, z |
| | 2590 | sage: z*x |
| | 2591 | x*z |
| | 2592 | sage: z*y |
| | 2593 | y*z |
| | 2594 | sage: y*x |
| | 2595 | x*y - 1 |
| | 2596 | sage: I = H.ideal([y^2, x^2, z^2-1]) |
| | 2597 | sage: I._groebner_basis_libsingular() |
| | 2598 | [1] |
| | 2599 | |
| | 2600 | sage: from sage.libs.singular.function import singular_function |
| | 2601 | |
| | 2602 | sage: ringlist = singular_function('ringlist') |
| | 2603 | sage: ring = singular_function("ring") |
| | 2604 | |
| | 2605 | sage: L = ringlist(H, ring=H); L |
| | 2606 | [0, ['x', 'y', 'z'], [['dp', (1, 1, 1)], ['C', (0,)]], [0], [0 1 1] |
| | 2607 | [0 0 1] |
| | 2608 | [0 0 0], [ 0 -1 0] |
| | 2609 | [ 0 0 0] |
| | 2610 | [ 0 0 0]] |
| | 2611 | |
| | 2612 | sage: len(L) |
| | 2613 | 6 |
| | 2614 | |
| | 2615 | sage: W = ring(L, ring=H); W |
| | 2616 | <noncommutative RingWrap> |
| | 2617 | |
| | 2618 | sage: from sage.rings.polynomial.plural import new_Ring |
| | 2619 | sage: R = new_Ring(W, H.base_ring()); R |
| | 2620 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: x*y - 1} |
| | 2621 | |
| | 2622 | """ |
| | 2623 | import warnings |
| | 2624 | # warnings.warn("This is a hack. Please, use it on your own risk...") |
| | 2625 | if rw.is_commutative(): |
| | 2626 | return new_CRing(rw, base_ring) |
| | 2627 | return new_NRing(rw, base_ring) |
| | 2628 | |
| | 2629 | |
| | 2630 | def SCA(base_ring, names, alt_vars, order='degrevlex'): |
| | 2631 | """ |
| | 2632 | Shortcut to construct a graded commutative algebra out of the following data: |
| | 2633 | |
| | 2634 | Input: |
| | 2635 | |
| | 2636 | - ``base_ring``: the ground field |
| | 2637 | - ``names``: a list of variable names |
| | 2638 | - ``alt_vars``: a list of indices of to be anti-commutative variables |
| | 2639 | - ``order``: orderig to be used for the constructed algebra |
| | 2640 | |
| | 2641 | EXAMPLES:: |
| | 2642 | |
| | 2643 | sage: from sage.rings.polynomial.plural import SCA |
| | 2644 | sage: E = SCA(QQ, ['x', 'y', 'z'], [0, 1], order = 'degrevlex') |
| | 2645 | sage: E |
| | 2646 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} |
| | 2647 | sage: E.inject_variables() |
| | 2648 | Defining x, y, z |
| | 2649 | sage: y*x |
| | 2650 | -x*y |
| | 2651 | sage: x^2 |
| | 2652 | 0 |
| | 2653 | sage: y^2 |
| | 2654 | 0 |
| | 2655 | sage: z^2 |
| | 2656 | z^2 |
| | 2657 | """ |
| | 2658 | n = len(names) |
| | 2659 | alt_start = min(alt_vars) |
| | 2660 | alt_end = max(alt_vars) |
| | 2661 | assert( alt_start >= 0 ) |
| | 2662 | assert( (alt_end >= alt_start) and (alt_end < n) ) |
| | 2663 | |
| | 2664 | relations = {} # {y*x:-x*y} |
| | 2665 | from sage.algebras.free_algebra import FreeAlgebra |
| | 2666 | A = FreeAlgebra(base_ring, n, names) |
| | 2667 | for r in range(0, n-1, 1): |
| | 2668 | for c in range(r+1, n, 1): |
| | 2669 | if (r in alt_vars) and (c in alt_vars): |
| | 2670 | relations[ A.gen(c) * A.gen(r) ] = - A.gen(r) * A.gen(c) |
| | 2671 | |
| | 2672 | H = A.g_algebra(relations=relations, order=order) |
| | 2673 | I = H.ideal([H.gen(i) *H.gen(i) for i in alt_vars]).twostd() |
| | 2674 | return H.quotient(I) |
| | 2675 | |
| | 2676 | cdef poly *addwithcarry(poly *tempvector, poly *maxvector, int pos, ring *_ring): |
| | 2677 | if p_GetExp(tempvector, pos, _ring) < p_GetExp(maxvector, pos, _ring): |
| | 2678 | p_SetExp(tempvector, pos, p_GetExp(tempvector, pos, _ring)+1, _ring) |
| | 2679 | else: |
| | 2680 | p_SetExp(tempvector, pos, 0, _ring) |
| | 2681 | tempvector = addwithcarry(tempvector, maxvector, pos + 1, _ring) |
| | 2682 | p_Setm(tempvector, _ring) |
| | 2683 | return tempvector |