001/* 002 * $Id$ 003 */ 004 005package edu.jas.gbufd; 006 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.Map; 011 012import org.apache.logging.log4j.LogManager; 013import org.apache.logging.log4j.Logger; 014 015import edu.jas.gb.GroebnerBaseAbstract; 016import edu.jas.gb.ReductionAbstract; 017import edu.jas.gb.ReductionSeq; 018import edu.jas.gb.SolvableGroebnerBaseAbstract; 019import edu.jas.gb.SolvableReductionAbstract; 020import edu.jas.gb.SolvableReductionSeq; 021import edu.jas.gb.WordGroebnerBaseAbstract; 022import edu.jas.gb.WordGroebnerBaseSeq; 023import edu.jas.poly.ExpVector; 024import edu.jas.poly.GenPolynomial; 025import edu.jas.poly.GenPolynomialRing; 026import edu.jas.poly.GenSolvablePolynomial; 027import edu.jas.poly.GenSolvablePolynomialRing; 028import edu.jas.poly.GenWordPolynomial; 029import edu.jas.poly.GenWordPolynomialRing; 030import edu.jas.poly.PolyUtil; 031import edu.jas.structure.GcdRingElem; 032import edu.jas.structure.RingElem; 033 034 035/** 036 * Package gbufd utilities. 037 * @author Heinz Kredel 038 */ 039 040public class PolyGBUtil { 041 042 043 private static final Logger logger = LogManager.getLogger(PolyGBUtil.class); 044 045 046 private static final boolean debug = logger.isDebugEnabled(); 047 048 049 /** 050 * Test for resultant. 051 * @param A generic polynomial. 052 * @param B generic polynomial. 053 * @param r generic polynomial. 054 * @return true if res(A,B) isContained in ideal(A,B), else false. 055 */ 056 public static <C extends GcdRingElem<C>> boolean isResultant(GenPolynomial<C> A, GenPolynomial<C> B, 057 GenPolynomial<C> r) { 058 if (r == null || r.isZERO()) { 059 return true; 060 } 061 GroebnerBaseAbstract<C> bb = GBFactory.<C> getImplementation(r.ring.coFac); 062 List<GenPolynomial<C>> F = new ArrayList<GenPolynomial<C>>(2); 063 F.add(A); 064 F.add(B); 065 List<GenPolynomial<C>> G = bb.GB(F); 066 //System.out.println("G = " + G); 067 GenPolynomial<C> n = bb.red.normalform(G, r); 068 //System.out.println("n = " + n); 069 return n.isZERO(); 070 } 071 072 073 /** 074 * Top pseudo reduction wrt the main variables. 075 * @param P generic polynomial. 076 * @param A list of generic polynomials sorted according to appearing main 077 * variables. 078 * @return top pseudo remainder of P wrt. A for the appearing variables. 079 */ 080 public static <C extends RingElem<C>> GenPolynomial<C> topPseudoRemainder(List<GenPolynomial<C>> A, 081 GenPolynomial<C> P) { 082 if (A == null || A.isEmpty()) { 083 return P.monic(); 084 } 085 if (P.isZERO()) { 086 return P; 087 } 088 //System.out.println("remainder, P = " + P); 089 GenPolynomialRing<C> pfac = A.get(0).ring; 090 if (pfac.nvar <= 1) { // recursion base 091 GenPolynomial<C> R = PolyUtil.<C> baseSparsePseudoRemainder(P, A.get(0)); 092 return R.monic(); 093 } 094 // select polynomials according to the main variable 095 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 096 GenPolynomial<C> Q = A.get(0); // wrong, must eventually search polynomial 097 GenPolynomial<GenPolynomial<C>> qr = PolyUtil.<C> recursive(rfac, Q); 098 GenPolynomial<GenPolynomial<C>> pr = PolyUtil.<C> recursive(rfac, P); 099 GenPolynomial<GenPolynomial<C>> rr; 100 if (qr.isONE()) { 101 return P.ring.getZERO(); 102 } 103 if (qr.degree(0) > 0) { 104 rr = PolyUtil.<C> recursiveSparsePseudoRemainder(pr, qr); 105 //System.out.println("remainder, pr = " + pr); 106 //System.out.println("remainder, qr = " + qr); 107 //System.out.println("remainder, rr = " + rr); 108 } else { 109 rr = pr; 110 } 111 if (rr.degree(0) > 0) { 112 GenPolynomial<C> R = PolyUtil.<C> distribute(pfac, rr); 113 return R.monic(); 114 // not further reduced wrt. other variables = top-reduction only 115 } 116 List<GenPolynomial<C>> zeroDeg = zeroDegrees(A); 117 GenPolynomial<C> R = topPseudoRemainder(zeroDeg, rr.leadingBaseCoefficient()); 118 R = R.extend(pfac, 0, 0L); 119 return R.monic(); 120 } 121 122 123 /** 124 * Top coefficient pseudo remainder of the leading coefficient of P wrt A in 125 * the main variables. 126 * @param P generic polynomial in n+1 variables. 127 * @param A list of generic polynomials in n variables sorted according to 128 * appearing main variables. 129 * @return pseudo remainder of the leading coefficient of P wrt A. 130 */ 131 public static <C extends RingElem<C>> GenPolynomial<C> topCoefficientPseudoRemainder( 132 List<GenPolynomial<C>> A, GenPolynomial<C> P) { 133 if (A == null || A.isEmpty()) { 134 return P.monic(); 135 } 136 if (P.isZERO()) { 137 return P; 138 } 139 GenPolynomialRing<C> pfac = P.ring; 140 GenPolynomialRing<C> pfac1 = A.get(0).ring; 141 if (pfac1.nvar <= 1) { // recursion base 142 GenPolynomial<C> a = A.get(0); 143 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(pfac.nvar - 1); 144 GenPolynomial<GenPolynomial<C>> pr = PolyUtil.<C> recursive(rfac, P); 145 // ldcf(P,x_m) = q a + r 146 GenPolynomial<GenPolynomial<C>> rr = PolyGBUtil.<C> coefficientPseudoRemainderBase(pr, a); 147 GenPolynomial<C> R = PolyUtil.<C> distribute(pfac, rr); 148 return R.monic(); 149 } 150 // select polynomials according to the main variable 151 GenPolynomialRing<GenPolynomial<C>> rfac1 = pfac1.recursive(1); 152 int nv = pfac.nvar - pfac1.nvar; 153 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1 + nv); 154 GenPolynomialRing<GenPolynomial<GenPolynomial<C>>> rfac2 = rfac.recursive(nv); 155 if (debug) { 156 logger.info("rfac =" + rfac); 157 } 158 GenPolynomial<GenPolynomial<C>> pr = PolyUtil.<C> recursive(rfac, P); 159 GenPolynomial<GenPolynomial<GenPolynomial<C>>> pr2 = PolyUtil.<GenPolynomial<C>> recursive(rfac2, pr); 160 //System.out.println("recursion, pr2 = " + pr2); 161 GenPolynomial<C> Q = A.get(0); 162 GenPolynomial<GenPolynomial<C>> qr = PolyUtil.<C> recursive(rfac1, Q); 163 GenPolynomial<GenPolynomial<GenPolynomial<C>>> rr; 164 if (qr.isONE()) { 165 return P.ring.getZERO(); 166 } 167 if (qr.degree(0) > 0) { 168 // pseudo remainder: ldcf(P,x_m) = a q + r 169 rr = PolyGBUtil.<C> coefficientPseudoRemainder(pr2, qr); 170 //System.out.println("recursion, qr = " + qr); 171 //System.out.println("recursion, pr = " + pr2); 172 //System.out.println("recursion, rr = " + rr); 173 } else { 174 rr = pr2; 175 } 176 // reduction wrt. the other variables 177 List<GenPolynomial<C>> zeroDeg = zeroDegrees(A); 178 GenPolynomial<GenPolynomial<C>> Rr = PolyUtil.<GenPolynomial<C>> distribute(rfac, rr); 179 GenPolynomial<C> R = PolyUtil.<C> distribute(pfac, Rr); 180 R = topCoefficientPseudoRemainder(zeroDeg, R); 181 return R.monic(); 182 } 183 184 185 /** 186 * Polynomial leading coefficient pseudo remainder. 187 * @param P generic polynomial in n+1 variables. 188 * @param A generic polynomial in n variables. 189 * @return pseudo remainder of the leading coefficient of P wrt A, with 190 * ldcf(A)<sup>m'</sup> P = quotient * A + remainder. 191 */ 192 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<GenPolynomial<C>>> coefficientPseudoRemainder( 193 GenPolynomial<GenPolynomial<GenPolynomial<C>>> P, GenPolynomial<GenPolynomial<C>> A) { 194 if (A == null || A.isZERO()) { // findbugs 195 throw new ArithmeticException(P + " division by zero " + A); 196 } 197 if (A.isONE()) { 198 return P.ring.getZERO(); 199 } 200 if (P.isZERO() || P.isONE()) { 201 return P; 202 } 203 GenPolynomialRing<GenPolynomial<GenPolynomial<C>>> pfac = P.ring; 204 GenPolynomialRing<GenPolynomial<C>> afac = A.ring; // == pfac.coFac 205 GenPolynomial<GenPolynomial<GenPolynomial<C>>> r = P; 206 GenPolynomial<GenPolynomial<C>> h; 207 GenPolynomial<GenPolynomial<GenPolynomial<C>>> hr; 208 GenPolynomial<GenPolynomial<C>> ldcf = P.leadingBaseCoefficient(); 209 long m = ldcf.degree(0); 210 long n = A.degree(0); 211 GenPolynomial<C> c = A.leadingBaseCoefficient(); 212 GenPolynomial<GenPolynomial<C>> cc = afac.getZERO().sum(c); 213 //System.out.println("cc = " + cc); 214 ExpVector e = A.leadingExpVector(); 215 for (long i = m; i >= n; i--) { 216 if (r.isZERO()) { 217 return r; 218 } 219 GenPolynomial<GenPolynomial<C>> p = r.leadingBaseCoefficient(); 220 ExpVector g = r.leadingExpVector(); 221 long k = p.degree(0); 222 if (i == k) { 223 GenPolynomial<C> pl = p.leadingBaseCoefficient(); 224 ExpVector f = p.leadingExpVector(); 225 f = f.subtract(e); 226 r = r.multiply(cc); // coeff cc 227 h = A.multiply(pl, f); // coeff ac 228 hr = new GenPolynomial<GenPolynomial<GenPolynomial<C>>>(pfac, h, g); 229 r = r.subtract(hr); 230 } else { 231 r = r.multiply(cc); 232 } 233 //System.out.println("r = " + r); 234 } 235 if (r.degree(0) < P.degree(0)) { // recursion for degree 236 r = coefficientPseudoRemainder(r, A); 237 } 238 return r; 239 } 240 241 242 /** 243 * Polynomial leading coefficient pseudo remainder, base case. 244 * @param P generic polynomial in 1+1 variables. 245 * @param A generic polynomial in 1 variable. 246 * @return pseudo remainder of the leading coefficient of P wrt. A, with 247 * ldcf(A)<sup>m'</sup> P = quotient * A + remainder. 248 */ 249 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> coefficientPseudoRemainderBase( 250 GenPolynomial<GenPolynomial<C>> P, GenPolynomial<C> A) { 251 if (A == null || A.isZERO()) { // findbugs 252 throw new ArithmeticException(P + " division by zero " + A); 253 } 254 if (A.isONE()) { 255 return P.ring.getZERO(); 256 } 257 if (P.isZERO() || P.isONE()) { 258 return P; 259 } 260 GenPolynomialRing<GenPolynomial<C>> pfac = P.ring; 261 GenPolynomialRing<C> afac = A.ring; // == pfac.coFac 262 GenPolynomial<GenPolynomial<C>> r = P; 263 GenPolynomial<C> h; 264 GenPolynomial<GenPolynomial<C>> hr; 265 GenPolynomial<C> ldcf = P.leadingBaseCoefficient(); 266 long m = ldcf.degree(0); 267 long n = A.degree(0); 268 C c = A.leadingBaseCoefficient(); 269 GenPolynomial<C> cc = afac.getZERO().sum(c); 270 //System.out.println("cc = " + cc); 271 ExpVector e = A.leadingExpVector(); 272 for (long i = m; i >= n; i--) { 273 if (r.isZERO()) { 274 return r; 275 } 276 GenPolynomial<C> p = r.leadingBaseCoefficient(); 277 ExpVector g = r.leadingExpVector(); 278 long k = p.degree(0); 279 if (i == k) { 280 C pl = p.leadingBaseCoefficient(); 281 ExpVector f = p.leadingExpVector(); 282 f = f.subtract(e); 283 r = r.multiply(cc); // coeff cc 284 h = A.multiply(pl, f); // coeff ac 285 hr = new GenPolynomial<GenPolynomial<C>>(pfac, h, g); 286 r = r.subtract(hr); 287 } else { 288 r = r.multiply(cc); 289 } 290 //System.out.println("r = " + r); 291 } 292 if (r.degree(0) < P.degree(0)) { // recursion for degree 293 r = coefficientPseudoRemainderBase(r, A); 294 } 295 return r; 296 } 297 298 299 /** 300 * Extract polynomials with degree zero in the main variable. 301 * @param A list of generic polynomials in n variables. 302 * @return Z = [a_i] with deg(a_i,x_n) = 0 and in n-1 variables. 303 */ 304 public static <C extends RingElem<C>> List<GenPolynomial<C>> zeroDegrees(List<GenPolynomial<C>> A) { 305 if (A == null || A.isEmpty()) { 306 return A; 307 } 308 GenPolynomialRing<C> pfac = A.get(0).ring; 309 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 310 List<GenPolynomial<C>> zeroDeg = new ArrayList<GenPolynomial<C>>(A.size()); 311 for (int i = 0; i < A.size(); i++) { 312 GenPolynomial<C> q = A.get(i); 313 GenPolynomial<GenPolynomial<C>> fr = PolyUtil.<C> recursive(rfac, q); 314 if (fr.degree(0) == 0) { 315 zeroDeg.add(fr.leadingBaseCoefficient()); 316 } 317 } 318 return zeroDeg; 319 } 320 321 322 /** 323 * Intersection. Generators for the intersection of ideals. 324 * @param pfac polynomial ring 325 * @param A list of polynomials 326 * @param B list of polynomials 327 * @return generators for (A \cap B) 328 */ 329 public static <C extends GcdRingElem<C>> List<GenPolynomial<C>> intersect(GenPolynomialRing<C> pfac, 330 List<GenPolynomial<C>> A, List<GenPolynomial<C>> B) { 331 if (A == null || A.isEmpty()) { // (0) 332 return B; 333 } 334 if (B == null || B.isEmpty()) { // (0) 335 return A; 336 } 337 int s = A.size() + B.size(); 338 List<GenPolynomial<C>> c = new ArrayList<GenPolynomial<C>>(s); 339 GenPolynomialRing<C> tfac = pfac.extend(1); 340 // term order is also adjusted 341 for (GenPolynomial<C> p : A) { 342 p = p.extend(tfac, 0, 1L); // t*p 343 c.add(p); 344 } 345 for (GenPolynomial<C> p : B) { 346 GenPolynomial<C> q = p.extend(tfac, 0, 1L); 347 GenPolynomial<C> r = p.extend(tfac, 0, 0L); 348 p = r.subtract(q); // (1-t)*p 349 c.add(p); 350 } 351 GroebnerBaseAbstract<C> bb = GBFactory.<C> getImplementation(tfac.coFac); 352 logger.warn("intersect computing GB"); 353 List<GenPolynomial<C>> G = bb.GB(c); 354 if (debug) { 355 logger.debug("intersect GB = " + G); 356 } 357 List<GenPolynomial<C>> I = PolyUtil.<C> intersect(pfac, G); 358 return I; 359 } 360 361 362 /** 363 * Intersection. Generators for the intersection of ideals. 364 * @param pfac solvable polynomial ring 365 * @param A list of polynomials 366 * @param B list of polynomials 367 * @return generators for (A \cap B) 368 */ 369 public static <C extends GcdRingElem<C>> List<GenSolvablePolynomial<C>> intersect( 370 GenSolvablePolynomialRing<C> pfac, List<GenSolvablePolynomial<C>> A, 371 List<GenSolvablePolynomial<C>> B) { 372 if (A == null || A.isEmpty()) { // (0) 373 return B; 374 } 375 if (B == null || B.isEmpty()) { // (0) 376 return A; 377 } 378 int s = A.size() + B.size(); 379 List<GenSolvablePolynomial<C>> c = new ArrayList<GenSolvablePolynomial<C>>(s); 380 GenSolvablePolynomialRing<C> tfac = pfac.extend(1); 381 // term order is also adjusted 382 for (GenSolvablePolynomial<C> p : A) { 383 p = (GenSolvablePolynomial<C>) p.extend(tfac, 0, 1L); // t*p 384 c.add(p); 385 } 386 for (GenSolvablePolynomial<C> p : B) { 387 GenSolvablePolynomial<C> q = (GenSolvablePolynomial<C>) p.extend(tfac, 0, 1L); 388 GenSolvablePolynomial<C> r = (GenSolvablePolynomial<C>) p.extend(tfac, 0, 0L); 389 p = (GenSolvablePolynomial<C>) r.subtract(q); // (1-t)*p 390 c.add(p); 391 } 392 SolvableGroebnerBaseAbstract<C> sbb = SGBFactory.<C> getImplementation(tfac.coFac); 393 //new SolvableGroebnerBaseSeq<C>(); 394 logger.warn("intersect computing GB"); 395 List<GenSolvablePolynomial<C>> g = sbb.leftGB(c); 396 //List<GenSolvablePolynomial<C>> g = sbb.twosidedGB(c); 397 if (debug) { 398 logger.debug("intersect GB = " + g); 399 } 400 List<GenSolvablePolynomial<C>> I = PolyUtil.<C> intersect(pfac, g); 401 return I; 402 } 403 404 405 /** 406 * Intersection. Generators for the intersection of word ideals. 407 * @param pfac word polynomial ring 408 * @param A list of word polynomials 409 * @param B list of word polynomials 410 * @return generators for (A \cap B) if it exists 411 */ 412 public static <C extends GcdRingElem<C>> List<GenWordPolynomial<C>> intersect( 413 GenWordPolynomialRing<C> pfac, List<GenWordPolynomial<C>> A, 414 List<GenWordPolynomial<C>> B) { 415 if (A == null || A.isEmpty()) { // (0) 416 return B; 417 } 418 if (B == null || B.isEmpty()) { // (0) 419 return A; 420 } 421 int s = A.size() + B.size(); 422 List<GenWordPolynomial<C>> L = new ArrayList<GenWordPolynomial<C>>(s); 423 GenWordPolynomialRing<C> tfac = pfac.extend(1); 424 List<GenWordPolynomial<C>> gens = tfac.univariateList(); 425 //System.out.println("gens = " + gens); 426 GenWordPolynomial<C> t = gens.get(gens.size() - 1); 427 //System.out.println("t = " + t); 428 // make t commute with other variables 429 for (GenWordPolynomial<C> p : gens) { 430 if (t == p) { 431 continue; 432 } 433 GenWordPolynomial<C> c = t.multiply(p).subtract(p.multiply(t)); // t p - p t 434 L.add(c); 435 } 436 for (GenWordPolynomial<C> p : A) { 437 p = tfac.valueOf(p).multiply(t); // t p 438 L.add(p); 439 } 440 for (GenWordPolynomial<C> p : B) { 441 GenWordPolynomial<C> q = tfac.valueOf(p).multiply(t); 442 GenWordPolynomial<C> r = tfac.valueOf(p); 443 p = r.subtract(q); // (1-t) p 444 L.add(p); 445 } 446 //System.out.println("L = " + L); 447 WordGroebnerBaseAbstract<C> bb = new WordGroebnerBaseSeq<C>(); 448 logger.warn("intersect computing GB"); 449 List<GenWordPolynomial<C>> G = bb.GB(L); 450 //System.out.println("G = " + G); 451 if (debug) { 452 logger.debug("intersect GB = " + G); 453 } 454 List<GenWordPolynomial<C>> I = PolyUtil.<C> intersect(pfac, G); 455 return I; 456 } 457 458 459 /** 460 * Solvable quotient and remainder via reduction. 461 * @param n first solvable polynomial. 462 * @param d second solvable polynomial. 463 * @return [ n/d, n - (n/d)*d ] 464 */ 465 @SuppressWarnings("unchecked") 466 public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C>[] quotientRemainder( 467 GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) { 468 GenSolvablePolynomial<C>[] res = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[2]; 469 if (d.isZERO()) { 470 throw new RuntimeException("division by zero: " + n + "/" + d); 471 } 472 if (n.isZERO()) { 473 res[0] = n; 474 res[1] = n; 475 return res; 476 } 477 GenSolvablePolynomialRing<C> r = n.ring; 478 if (d.isONE()) { 479 res[0] = n; 480 res[1] = r.getZERO(); 481 return res; 482 } 483 // divide 484 List<GenSolvablePolynomial<C>> Q = new ArrayList<GenSolvablePolynomial<C>>(1); 485 Q.add(r.getZERO()); 486 List<GenSolvablePolynomial<C>> D = new ArrayList<GenSolvablePolynomial<C>>(1); 487 D.add(d); 488 SolvableReductionAbstract<C> sred = new SolvableReductionSeq<C>(); 489 res[1] = sred.rightNormalform(Q, D, n); // left 490 res[0] = Q.get(0); 491 return res; 492 } 493 494 495 /** 496 * Subring generators. 497 * @param A list of polynomials in n variables. 498 * @return a Groebner base of polynomials in m > n variables generating the subring of K[A]. 499 */ 500 public static <C extends GcdRingElem<C>> List<GenPolynomial<C>> subRing(List<GenPolynomial<C>> A) { 501 if (A == null || A.isEmpty()) { 502 return A; 503 } 504 GenPolynomialRing<C> pfac = A.get(0).ring; 505 logger.debug("pfac = " + pfac.toScript()); 506 int n = pfac.nvar; 507 List<GenPolynomial<C>> Ap = new ArrayList<GenPolynomial<C>>(); 508 for (GenPolynomial<C> a : A) { 509 if (a == null || a.isZERO() || a.isONE()) { 510 continue; 511 } 512 Ap.add(a); 513 } 514 int k = Ap.size(); 515 if (k == 0) { 516 return Ap; 517 } 518 GenPolynomialRing<C> rfac = pfac.extendLower(k); 519 logger.debug("rfac = " + rfac.toScript()); 520 assert rfac.nvar == n + k : "rfac.nvar == n+k"; 521 List<GenPolynomial<C>> sr = new ArrayList<GenPolynomial<C>>(); 522 int i = 0; 523 for (GenPolynomial<C> a : Ap) { 524 GenPolynomial<C> b = a.extendLower(rfac, 0, 0L); 525 b = b.subtract(pfac.getONE().extendLower(rfac, i++, 1L)); 526 //System.out.println("a = " + a); 527 //System.out.println("b = " + b); 528 sr.add(b); 529 } 530 GroebnerBaseAbstract<C> bb = GBFactory.<C> getImplementation(pfac.coFac); 531 List<GenPolynomial<C>> srg = bb.GB(sr); 532 return srg; 533 } 534 535 536 /** 537 * Subring membership. 538 * @param A Groebner base of polynomials in m > n variables generating the subring of elements of K[A]. 539 * @param g polynomial in n variables. 540 * @return true, if g \in K[A], else false. 541 */ 542 public static <C extends GcdRingElem<C>> boolean subRingMember(List<GenPolynomial<C>> A, 543 GenPolynomial<C> g) { 544 if (A == null || A.isEmpty()) { 545 return true; 546 } 547 GenPolynomialRing<C> pfac = A.get(0).ring; 548 GenPolynomial<C> m = g; 549 if (pfac.nvar != g.ring.nvar) { 550 m = m.extendLower(pfac, 0, 0L); 551 } else { 552 throw new IllegalArgumentException("g must be extended: " + pfac.nvar + " == " + g.ring.nvar 553 + " did you mean method subRingAndMember()?"); 554 } 555 //ReductionAbstract<C> red = new ReductionSeq<C>(); 556 GroebnerBaseAbstract<C> bb = GBFactory.<C> getImplementation(pfac.coFac); 557 GenPolynomial<C> r = bb.red.normalform(A, m); 558 //System.out.println("r = " + r); 559 GenPolynomialRing<C> cfac = pfac.contract(g.ring.nvar); 560 logger.debug("cfac = " + cfac.toScript()); 561 Map<ExpVector, GenPolynomial<C>> map = r.contract(cfac); 562 //System.out.println("map = " + map); 563 return map.size() == 1 && map.keySet().contains(g.ring.evzero); 564 } 565 566 567 /** 568 * Subring and membership test. 569 * @param A list of polynomials in n variables. 570 * @param g polynomial in n variables. 571 * @return true, if g \in K[A], else false. 572 */ 573 public static <C extends GcdRingElem<C>> boolean subRingAndMember(List<GenPolynomial<C>> A, 574 GenPolynomial<C> g) { 575 if (A == null || A.isEmpty()) { 576 return true; 577 } 578 List<GenPolynomial<C>> srg = PolyGBUtil.<C> subRing(A); 579 return PolyGBUtil.<C> subRingMember(srg, g); 580 } 581 582}