001/* 002 * $Id: SolvableGroebnerBasePseudoRecSeq.java 5841 2018-05-20 21:26:13Z kredel $ 003 */ 004 005package edu.jas.gbufd; 006 007 008import java.util.ArrayList; 009import java.util.Collections; 010import java.util.List; 011 012import org.apache.log4j.Logger; 013 014import edu.jas.gb.OrderedPairlist; 015import edu.jas.gb.Pair; 016import edu.jas.gb.PairList; 017import edu.jas.gb.SolvableExtendedGB; 018import edu.jas.gb.SolvableGroebnerBaseAbstract; 019import edu.jas.poly.GenPolynomial; 020import edu.jas.poly.GenPolynomialRing; 021import edu.jas.poly.GenSolvablePolynomial; 022import edu.jas.poly.GenSolvablePolynomialRing; 023import edu.jas.poly.QLRSolvablePolynomialRing; 024import edu.jas.poly.PolyUtil; 025import edu.jas.poly.PolynomialList; 026import edu.jas.structure.GcdRingElem; 027import edu.jas.structure.RingFactory; 028import edu.jas.ufd.GCDFactory; 029import edu.jas.ufd.GreatestCommonDivisorAbstract; 030import edu.jas.ufd.GreatestCommonDivisorFake; 031 032 033/** 034 * Solvable Groebner Base with pseudo reduction sequential algorithm. Implements 035 * coefficient fraction free Groebner bases. Coefficients can for example be 036 * (commutative) multivariate polynomials. 037 * @param <C> coefficient type 038 * @author Heinz Kredel 039 * 040 * @see edu.jas.application.GBAlgorithmBuilder 041 * @see edu.jas.gbufd.GBFactory 042 */ 043 044public class SolvableGroebnerBasePseudoRecSeq<C extends GcdRingElem<C>> extends 045 SolvableGroebnerBaseAbstract<GenPolynomial<C>> { 046 047 048 private static final Logger logger = Logger.getLogger(SolvableGroebnerBasePseudoRecSeq.class); 049 050 051 private static final boolean debug = logger.isDebugEnabled(); 052 053 054 /** 055 * Greatest common divisor engine for coefficient content and primitive 056 * parts. 057 */ 058 protected final GreatestCommonDivisorAbstract<C> engine; 059 060 061 /** 062 * Pseudo reduction engine. 063 */ 064 protected final SolvablePseudoReduction<C> sredRec; 065 066 067 /** 068 * Pseudo reduction engine. 069 */ 070 protected final SolvablePseudoReduction<GenPolynomial<C>> sred; 071 072 073 /** 074 * Coefficient ring factory. 075 */ 076 //protected final RingFactory<C> cofac; 077 protected final GenPolynomialRing<C> cofac; 078 079 080 /** 081 * Constructor. 082 * @param rf coefficient ring factory. 083 */ 084 public SolvableGroebnerBasePseudoRecSeq(RingFactory<GenPolynomial<C>> rf) { 085 this(rf, new SolvablePseudoReductionSeq<C>()); 086 } 087 088 089 /** 090 * Constructor. 091 * @param rf coefficient ring factory. 092 * @param pl pair selection strategy 093 */ 094 public SolvableGroebnerBasePseudoRecSeq(RingFactory<GenPolynomial<C>> rf, PairList<GenPolynomial<C>> pl) { 095 this(rf, new SolvablePseudoReductionSeq<C>(), pl); 096 } 097 098 099 /** 100 * Constructor. 101 * @param rf coefficient ring factory. 102 * @param red pseudo reduction engine. <b>Note:</b> red must be an instance 103 * of PseudoReductionSeq. 104 */ 105 public SolvableGroebnerBasePseudoRecSeq(RingFactory<GenPolynomial<C>> rf, SolvablePseudoReduction<C> red) { 106 this(rf, red, new OrderedPairlist<GenPolynomial<C>>()); 107 } 108 109 110 /** 111 * Constructor. 112 * @param rf coefficient ring factory. 113 * @param red pseudo reduction engine. <b>Note:</b> red must be an instance 114 * of PseudoReductionSeq. 115 * @param pl pair selection strategy 116 */ 117 @SuppressWarnings({ "cast", "unchecked" }) 118 public SolvableGroebnerBasePseudoRecSeq(RingFactory<GenPolynomial<C>> rf, SolvablePseudoReduction<C> red, 119 PairList<GenPolynomial<C>> pl) { 120 super((SolvablePseudoReduction<GenPolynomial<C>>) (SolvablePseudoReduction) red, pl); 121 this.sred = (SolvablePseudoReduction<GenPolynomial<C>>) (SolvablePseudoReduction) red; 122 sredRec = red; 123 //this.red = sred; 124 cofac = (GenPolynomialRing<C>) rf; 125 if (!cofac.isCommutative()) { 126 logger.warn("right reduction not correct for " + cofac.toScript()); 127 engine = new GreatestCommonDivisorFake<C>(); 128 // TODO check that also coeffTable is empty for recursive solvable poly ring 129 } else { 130 //engine = GCDFactory.<C> getImplementation(cofac.coFac); 131 engine = GCDFactory.<C> getProxy(cofac.coFac); 132 } 133 } 134 135 136 /** 137 * Left Groebner base using pairlist class. 138 * @param modv module variable number. 139 * @param F polynomial list. 140 * @return GB(F) a Groebner base of F. 141 */ 142 @Override 143 public List<GenSolvablePolynomial<GenPolynomial<C>>> leftGB(int modv, 144 List<GenSolvablePolynomial<GenPolynomial<C>>> F) { 145 List<GenSolvablePolynomial<GenPolynomial<C>>> G = normalizeZerosOnes(F); 146 G = PolynomialList.<GenPolynomial<C>> castToSolvableList(PolyUtil.<C> monicRec(engine 147 .recursivePrimitivePart(PolynomialList.<GenPolynomial<C>> castToList(G)))); 148 if (G.size() <= 1) { 149 return G; 150 } 151 GenSolvablePolynomialRing<GenPolynomial<C>> ring = G.get(0).ring; 152 if (ring.coFac.isField()) { // remove ? 153 throw new IllegalArgumentException("coefficients from a field"); 154 } 155 PairList<GenPolynomial<C>> pairlist = strategy.create(modv, ring); 156 pairlist.put(PolynomialList.<GenPolynomial<C>> castToList(G)); 157 logger.info("leftGB start " + pairlist); 158 159 Pair<GenPolynomial<C>> pair; 160 GenSolvablePolynomial<GenPolynomial<C>> pi, pj, S, H; 161 while (pairlist.hasNext()) { 162 pair = pairlist.removeNext(); 163 if (pair == null) 164 continue; 165 166 pi = (GenSolvablePolynomial<GenPolynomial<C>>) pair.pi; 167 pj = (GenSolvablePolynomial<GenPolynomial<C>>) pair.pj; 168 if (debug) { 169 logger.debug("pi = " + pi); 170 logger.debug("pj = " + pj); 171 } 172 173 S = sred.leftSPolynomial(pi, pj); 174 if (S.isZERO()) { 175 pair.setZero(); 176 continue; 177 } 178 if (debug) { 179 logger.info("ht(S) = " + S.leadingExpVector()); 180 } 181 182 H = sredRec.leftNormalformRecursive(G, S); 183 if (H.isZERO()) { 184 pair.setZero(); 185 continue; 186 } 187 if (debug) { 188 logger.info("ht(H) = " + H.leadingExpVector() + ", #(H) = " + H.length()); 189 } 190 H = (GenSolvablePolynomial<GenPolynomial<C>>) engine.recursivePrimitivePart(H); 191 H = PolyUtil.<C> monic(H); 192 if (H.isConstant()) { 193 G.clear(); 194 G.add(H); 195 return G; // since no threads are activated 196 } 197 if (debug) { 198 logger.info("lc(pp(H)) = " + H.leadingBaseCoefficient().toScript()); 199 } 200 if (H.length() > 0) { 201 G.add(H); 202 pairlist.put(H); 203 } 204 } 205 logger.debug("#sequential list = " + G.size()); 206 G = leftMinimalGB(G); 207 logger.info("leftGB end " + pairlist); 208 return G; 209 } 210 211 212 /** 213 * Minimal ordered Solvable Groebner basis. 214 * @param Gp a Solvable Groebner base. 215 * @return a reduced Solvable Groebner base of Gp. 216 */ 217 @Override 218 public List<GenSolvablePolynomial<GenPolynomial<C>>> leftMinimalGB( 219 List<GenSolvablePolynomial<GenPolynomial<C>>> Gp) { 220 List<GenSolvablePolynomial<GenPolynomial<C>>> G = normalizeZerosOnes(Gp); 221 if (G.size() <= 1) { 222 return G; 223 } 224 // remove top reducible polynomials 225 GenSolvablePolynomial<GenPolynomial<C>> a; 226 List<GenSolvablePolynomial<GenPolynomial<C>>> F = new ArrayList<GenSolvablePolynomial<GenPolynomial<C>>>( 227 G.size()); 228 while (G.size() > 0) { 229 a = G.remove(0); 230 if (sred.isTopReducible(G, a) || sred.isTopReducible(F, a)) { 231 // drop polynomial 232 if (debug) { 233 System.out.println("dropped " + a); 234 List<GenSolvablePolynomial<GenPolynomial<C>>> ff; 235 ff = new ArrayList<GenSolvablePolynomial<GenPolynomial<C>>>(G); 236 ff.addAll(F); 237 a = sredRec.leftNormalformRecursive(ff, a); 238 if (!a.isZERO()) { 239 System.out.println("error, nf(a) " + a); 240 } 241 } 242 } else { 243 F.add(a); 244 } 245 } 246 G = F; 247 if (G.size() <= 1) { 248 return G; 249 } 250 Collections.reverse(G); // important for lex GB 251 // reduce remaining polynomials 252 int len = G.size(); 253 int i = 0; 254 while (i < len) { 255 a = G.remove(0); 256 //System.out.println("doing " + a.length()); 257 a = sredRec.leftNormalformRecursive(G, a); 258 a = (GenSolvablePolynomial<GenPolynomial<C>>) engine.recursivePrimitivePart(a); //a.monic(); not possible 259 a = PolyUtil.<C> monic(a); 260 G.add(a); // adds as last 261 i++; 262 } 263 return G; 264 } 265 266 267 /** 268 * Twosided Solvable Groebner base using pairlist class. 269 * @param modv number of module variables. 270 * @param Fp solvable polynomial list. 271 * @return tsGB(Fp) a twosided Groebner base of Fp. 272 */ 273 @Override 274 public List<GenSolvablePolynomial<GenPolynomial<C>>> twosidedGB(int modv, 275 List<GenSolvablePolynomial<GenPolynomial<C>>> Fp) { 276 List<GenSolvablePolynomial<GenPolynomial<C>>> G = normalizeZerosOnes(Fp); 277 G = PolynomialList.<GenPolynomial<C>> castToSolvableList(PolyUtil.<C> monicRec(engine 278 .recursivePrimitivePart(PolynomialList.<GenPolynomial<C>> castToList(G)))); 279 if (G.size() < 1) { // two-sided! 280 return G; 281 } 282 //System.out.println("G = " + G); 283 GenSolvablePolynomialRing<GenPolynomial<C>> ring = G.get(0).ring; // assert != null 284 if (ring.coFac.isField()) { // remove ? 285 throw new IllegalArgumentException("coefficients from a field"); 286 } 287 // add also coefficient generators 288 List<GenSolvablePolynomial<GenPolynomial<C>>> X; 289 X = PolynomialList.castToSolvableList(ring.generators(modv)); 290 logger.info("right multipliers = " + X); 291 List<GenSolvablePolynomial<GenPolynomial<C>>> F = new ArrayList<GenSolvablePolynomial<GenPolynomial<C>>>( 292 G.size() * (1 + X.size())); 293 F.addAll(G); 294 GenSolvablePolynomial<GenPolynomial<C>> p, x, q; 295 for (int i = 0; i < F.size(); i++) { // F changes 296 p = F.get(i); 297 for (int j = 0; j < X.size(); j++) { 298 x = X.get(j); 299 if (x.isONE()) { 300 continue; 301 } 302 q = p.multiply(x); 303 q = sredRec.leftNormalformRecursive(F, q); 304 if (!q.isZERO()) { 305 q = (GenSolvablePolynomial<GenPolynomial<C>>) engine.recursivePrimitivePart(q); 306 q = PolyUtil.<C> monic(q); 307 F.add(q); 308 } 309 } 310 } 311 G = F; 312 //System.out.println("G generated = " + G); 313 PairList<GenPolynomial<C>> pairlist = strategy.create(modv, ring); 314 pairlist.put(PolynomialList.<GenPolynomial<C>> castToList(G)); 315 logger.info("twosidedGB start " + pairlist); 316 317 Pair<GenPolynomial<C>> pair; 318 GenSolvablePolynomial<GenPolynomial<C>> pi, pj, S, H; 319 while (pairlist.hasNext()) { 320 pair = pairlist.removeNext(); 321 if (pair == null) { 322 continue; 323 } 324 325 pi = (GenSolvablePolynomial<GenPolynomial<C>>) pair.pi; 326 pj = (GenSolvablePolynomial<GenPolynomial<C>>) pair.pj; 327 if (debug) { 328 logger.debug("pi = " + pi); 329 logger.debug("pj = " + pj); 330 } 331 332 S = sred.leftSPolynomial(pi, pj); 333 if (S.isZERO()) { 334 pair.setZero(); 335 continue; 336 } 337 if (debug) { 338 logger.info("ht(S) = " + S.leadingExpVector()); 339 } 340 341 H = sredRec.leftNormalformRecursive(G, S); 342 if (H.isZERO()) { 343 pair.setZero(); 344 continue; 345 } 346 if (debug) { 347 logger.info("ht(H) = " + H.leadingExpVector()); 348 } 349 350 H = (GenSolvablePolynomial<GenPolynomial<C>>) engine.recursivePrimitivePart(H); 351 H = PolyUtil.<C> monic(H); 352 if (H.isONE()) { 353 G.clear(); 354 G.add(H); 355 return G; // since no threads are activated 356 } 357 if (debug) { 358 logger.info("lc(pp(H)) = " + H.leadingBaseCoefficient()); 359 } 360 if (H.length() > 0) { 361 G.add(H); 362 pairlist.put(H); 363 for (int j = 0; j < X.size(); j++) { 364 x = X.get(j); 365 if (x.isONE()) { 366 continue; 367 } 368 p = H.multiply(x); 369 p = sredRec.leftNormalformRecursive(G, p); 370 if (!p.isZERO()) { 371 p = (GenSolvablePolynomial<GenPolynomial<C>>) engine.recursivePrimitivePart(p); 372 p = PolyUtil.<C> monic(p); 373 if (p.isONE()) { 374 G.clear(); 375 G.add(p); 376 return G; // since no threads are activated 377 } 378 G.add(p); 379 pairlist.put(p); 380 } 381 } 382 } 383 } 384 logger.debug("#sequential list = " + G.size()); 385 G = leftMinimalGB(G); 386 logger.info("twosidedGB end " + pairlist); 387 return G; 388 } 389 390 391 /** 392 * Left Groebner base test. 393 * @param modv number of module variables. 394 * @param F solvable polynomial list. 395 * @return true, if F is a left Groebner base, else false. 396 */ 397 @Override 398 public boolean isLeftGBsimple(int modv, List<GenSolvablePolynomial<GenPolynomial<C>>> F) { 399 //System.out.println("F to left check = " + F); 400 GenSolvablePolynomial<GenPolynomial<C>> pi, pj, s, h; 401 for (int i = 0; i < F.size(); i++) { 402 pi = F.get(i); 403 for (int j = i + 1; j < F.size(); j++) { 404 pj = F.get(j); 405 if (!red.moduleCriterion(modv, pi, pj)) { 406 continue; 407 } 408 // if ( ! red.criterion4( pi, pj ) ) { continue; } 409 s = sred.leftSPolynomial(pi, pj); 410 if (s.isZERO()) { 411 continue; 412 } 413 h = sredRec.leftNormalformRecursive(F, s); 414 if (!h.isZERO()) { 415 return false; 416 } 417 } 418 } 419 return true; 420 } 421 422 423 /** 424 * Left Groebner base idempotence test. 425 * @param modv module variable number. 426 * @param F solvable polynomial list. 427 * @return true, if F is equal to GB(F), else false. 428 */ 429 @Override 430 public boolean isLeftGBidem(int modv, List<GenSolvablePolynomial<GenPolynomial<C>>> F) { 431 if (F == null || F.isEmpty()) { 432 return true; 433 } 434 GenSolvablePolynomialRing<GenPolynomial<C>> pring = F.get(0).ring; 435 List<GenSolvablePolynomial<GenPolynomial<C>>> G = leftGB(modv, F); 436 PolynomialList<GenPolynomial<C>> Fp = new PolynomialList<GenPolynomial<C>>(pring, F); 437 PolynomialList<GenPolynomial<C>> Gp = new PolynomialList<GenPolynomial<C>>(pring, G); 438 return Fp.compareTo(Gp) == 0; 439 } 440 441 442 /** 443 * Twosided Groebner base test. 444 * @param modv number of module variables. 445 * @param Fp solvable polynomial list. 446 * @return true, if Fp is a two-sided Groebner base, else false. 447 */ 448 @Override 449 public boolean isTwosidedGB(int modv, List<GenSolvablePolynomial<GenPolynomial<C>>> Fp) { 450 //System.out.println("F to twosided check = " + Fp); 451 if (Fp == null || Fp.size() == 0) { // 0 not 1 452 return true; 453 } 454 GenSolvablePolynomialRing<GenPolynomial<C>> ring = Fp.get(0).ring; // assert != null 455 //List<GenSolvablePolynomial<C>> X = generateUnivar( modv, Fp ); 456 List<GenSolvablePolynomial<GenPolynomial<C>>> X, Y; 457 X = PolynomialList.castToSolvableList(ring.generators()); // todo use modv? 458 Y = new ArrayList<GenSolvablePolynomial<GenPolynomial<C>>>(); 459 for (GenSolvablePolynomial<GenPolynomial<C>> x : X) { 460 if (x.isConstant()) { 461 Y.add(x); 462 } 463 } 464 X = Y; 465 X.addAll(ring.univariateList(modv)); 466 logger.info("right multipliers = " + X); 467 List<GenSolvablePolynomial<GenPolynomial<C>>> F = new ArrayList<GenSolvablePolynomial<GenPolynomial<C>>>( 468 Fp.size() * (1 + X.size())); 469 F.addAll(Fp); 470 GenSolvablePolynomial<GenPolynomial<C>> p, x, pi, pj, s, h; 471 for (int i = 0; i < Fp.size(); i++) { 472 p = Fp.get(i); 473 for (int j = 0; j < X.size(); j++) { 474 x = X.get(j); 475 if (x.isONE()) { 476 continue; 477 } 478 p = p.multiply(x); 479 p = sredRec.leftNormalformRecursive(F, p); 480 if (!p.isZERO()) { 481 return false; 482 //F.add(p); 483 } 484 } 485 } 486 //System.out.println("F to check = " + F); 487 for (int i = 0; i < F.size(); i++) { 488 pi = F.get(i); 489 for (int j = i + 1; j < F.size(); j++) { 490 pj = F.get(j); 491 if (!red.moduleCriterion(modv, pi, pj)) { 492 continue; 493 } 494 // if ( ! red.criterion4( pi, pj ) ) { continue; } 495 s = sred.leftSPolynomial(pi, pj); 496 if (s.isZERO()) { 497 continue; 498 } 499 h = sredRec.leftNormalformRecursive(F, s); 500 if (!h.isZERO()) { 501 logger.info("is not TwosidedGB: " + h); 502 return false; 503 } 504 } 505 } 506 return true; 507 } 508 509 510 /** 511 * Solvable Extended Groebner base using critical pair class. 512 * @param modv module variable number. 513 * @param F solvable polynomial list. 514 * @return a container for an extended left Groebner base of F. <b>Note: 515 * </b> not implemented; 516 */ 517 //@SuppressWarnings("unchecked") 518 @Override 519 public SolvableExtendedGB<GenPolynomial<C>> extLeftGB(int modv, 520 List<GenSolvablePolynomial<GenPolynomial<C>>> F) { 521 throw new UnsupportedOperationException(); // TODO 522 } 523 524}