001/* 002 * $Id$ 003 */ 004 005package edu.jas.gb; 006 007 008import java.util.ArrayList; 009import java.util.Iterator; 010import java.util.List; 011import java.util.Map; 012 013import org.apache.logging.log4j.LogManager; 014import org.apache.logging.log4j.Logger; 015 016import edu.jas.poly.ExpVector; 017import edu.jas.poly.GenSolvablePolynomial; 018import edu.jas.poly.GenSolvablePolynomialRing; 019import edu.jas.poly.ModuleList; 020import edu.jas.poly.PolynomialList; 021import edu.jas.structure.RingElem; 022 023 024/** 025 * Solvable polynomial Reduction abstract class. Implements common left, right 026 * S-Polynomial, left normalform and left irreducible set. 027 * @param <C> coefficient type 028 * @author Heinz Kredel 029 */ 030 031public abstract class SolvableReductionAbstract<C extends RingElem<C>> implements SolvableReduction<C> { 032 033 034 private static final Logger logger = LogManager.getLogger(SolvableReductionAbstract.class); 035 036 037 private static final boolean debug = logger.isDebugEnabled(); 038 039 040 /** 041 * Constructor. 042 */ 043 public SolvableReductionAbstract() { 044 } 045 046 047 /** 048 * Left S-Polynomial. 049 * @param Ap solvable polynomial. 050 * @param Bp solvable polynomial. 051 * @return left-spol(Ap,Bp) the left S-polynomial of Ap and Bp. 052 */ 053 public GenSolvablePolynomial<C> leftSPolynomial(GenSolvablePolynomial<C> Ap, 054 GenSolvablePolynomial<C> Bp) { 055 if (logger.isInfoEnabled()) { 056 if (Bp == null || Bp.isZERO()) { 057 if (Ap != null) { 058 return Ap.ring.getZERO(); 059 } 060 return null; 061 } 062 if (Ap == null || Ap.isZERO()) { 063 return Bp.ring.getZERO(); 064 } 065 if (!Ap.ring.equals(Bp.ring)) { 066 logger.error("rings not equal"); 067 } 068 } 069 Map.Entry<ExpVector, C> ma = Ap.leadingMonomial(); 070 Map.Entry<ExpVector, C> mb = Bp.leadingMonomial(); 071 072 ExpVector e = ma.getKey(); 073 ExpVector f = mb.getKey(); 074 075 ExpVector g = e.lcm(f); 076 ExpVector e1 = g.subtract(e); 077 ExpVector f1 = g.subtract(f); 078 079 C a = ma.getValue(); 080 C b = mb.getValue(); 081 082 GenSolvablePolynomial<C> App = Ap.multiplyLeft(b, e1); 083 GenSolvablePolynomial<C> Bpp = Bp.multiplyLeft(a, f1); 084 GenSolvablePolynomial<C> Cp = (GenSolvablePolynomial<C>) App.subtract(Bpp); 085 return Cp; 086 } 087 088 089 /** 090 * S-Polynomial with recording. 091 * @param S recording matrix, is modified. 092 * @param i index of Ap in basis list. 093 * @param Ap a polynomial. 094 * @param j index of Bp in basis list. 095 * @param Bp a polynomial. 096 * @return leftSpol(Ap, Bp), the left S-Polynomial for Ap and Bp. 097 */ 098 public GenSolvablePolynomial<C> leftSPolynomial(List<GenSolvablePolynomial<C>> S, int i, 099 GenSolvablePolynomial<C> Ap, int j, GenSolvablePolynomial<C> Bp) { 100 if (debug /*logger.isInfoEnabled()*/) { 101 if (Bp == null || Bp.isZERO()) { 102 throw new ArithmeticException("Spol B is zero"); 103 } 104 if (Ap == null || Ap.isZERO()) { 105 throw new ArithmeticException("Spol A is zero"); 106 } 107 if (!Ap.ring.equals(Bp.ring)) { 108 logger.error("rings not equal"); 109 } 110 } 111 Map.Entry<ExpVector, C> ma = Ap.leadingMonomial(); 112 Map.Entry<ExpVector, C> mb = Bp.leadingMonomial(); 113 114 ExpVector e = ma.getKey(); 115 ExpVector f = mb.getKey(); 116 117 ExpVector g = e.lcm(f); 118 ExpVector e1 = g.subtract(e); 119 ExpVector f1 = g.subtract(f); 120 121 C a = ma.getValue(); 122 C b = mb.getValue(); 123 124 GenSolvablePolynomial<C> App = Ap.multiplyLeft(b, e1); 125 GenSolvablePolynomial<C> Bpp = Bp.multiplyLeft(a, f1); 126 GenSolvablePolynomial<C> Cp = (GenSolvablePolynomial<C>) App.subtract(Bpp); 127 128 GenSolvablePolynomial<C> zero = Ap.ring.getZERO(); 129 GenSolvablePolynomial<C> As = (GenSolvablePolynomial<C>) zero.sum(b.negate(), e1); 130 GenSolvablePolynomial<C> Bs = (GenSolvablePolynomial<C>) zero.sum(a, f1); 131 S.set(i, As); 132 S.set(j, Bs); 133 return Cp; 134 } 135 136 137 /** 138 * Left Normalform Set. 139 * @param Ap solvable polynomial list. 140 * @param Pp solvable polynomial list. 141 * @return list of left-nf(a) with respect to Pp for all a in Ap. 142 */ 143 public List<GenSolvablePolynomial<C>> leftNormalform(List<GenSolvablePolynomial<C>> Pp, 144 List<GenSolvablePolynomial<C>> Ap) { 145 if (Pp == null || Pp.isEmpty()) { 146 return Ap; 147 } 148 if (Ap == null || Ap.isEmpty()) { 149 return Ap; 150 } 151 ArrayList<GenSolvablePolynomial<C>> red = new ArrayList<GenSolvablePolynomial<C>>(); 152 for (GenSolvablePolynomial<C> A : Ap) { 153 A = leftNormalform(Pp, A); 154 red.add(A); 155 } 156 return red; 157 } 158 159 160 /** 161 * Module left normalform set. 162 * @param Ap module list. 163 * @param Pp module list. 164 * @return list of left-nf(a) with respect to Pp for all a in Ap. 165 */ 166 public ModuleList<C> leftNormalform(ModuleList<C> Pp, ModuleList<C> Ap) { 167 return leftNormalform(Pp, Ap, false); 168 } 169 170 171 /** 172 * Module left normalform set. 173 * @param Ap module list. 174 * @param Pp module list. 175 * @param top true for TOP term order, false for POT term order. 176 * @return list of left-nf(a) with respect to Pp for all a in Ap. 177 */ 178 public ModuleList<C> leftNormalform(ModuleList<C> Pp, ModuleList<C> Ap, boolean top) { 179 if (Pp == null || Pp.isEmpty()) { 180 return Ap; 181 } 182 if (Ap == null || Ap.isEmpty()) { 183 return Ap; 184 } 185 GenSolvablePolynomialRing<C> sring = (GenSolvablePolynomialRing<C>) Pp.ring; 186 int modv = Pp.cols; 187 GenSolvablePolynomialRing<C> pfac = sring.extend(modv, top); 188 logger.debug("extended ring = {}", pfac.toScript()); 189 //System.out.println("extended ring = " + pfac.toScript()); 190 PolynomialList<C> P = Pp.getPolynomialList(pfac); 191 PolynomialList<C> A = Ap.getPolynomialList(pfac); 192 //System.out.println("P = " + P.toScript()); 193 194 List<GenSolvablePolynomial<C>> red = leftNormalform(P.castToSolvableList(), A.castToSolvableList()); 195 PolynomialList<C> Fr = new PolynomialList<C>(pfac, red); 196 ModuleList<C> Nr = Fr.getModuleList(modv); 197 return Nr; 198 } 199 200 201 /** 202 * Left irreducible set. 203 * @param Pp solvable polynomial list. 204 * @return a list P of solvable polynomials which are in normalform wrt. P. 205 */ 206 public List<GenSolvablePolynomial<C>> leftIrreducibleSet(List<GenSolvablePolynomial<C>> Pp) { 207 ArrayList<GenSolvablePolynomial<C>> P = new ArrayList<GenSolvablePolynomial<C>>(); 208 for (GenSolvablePolynomial<C> a : Pp) { 209 if (a.length() != 0) { 210 a = a.monic(); 211 P.add(a); 212 } 213 } 214 int l = P.size(); 215 if (l <= 1) 216 return P; 217 218 int irr = 0; 219 ExpVector e; 220 ExpVector f; 221 GenSolvablePolynomial<C> a; 222 Iterator<GenSolvablePolynomial<C>> it; 223 logger.debug("irr = "); 224 while (irr != l) { 225 it = P.listIterator(); 226 a = it.next(); 227 P.remove(0); 228 e = a.leadingExpVector(); 229 a = leftNormalform(P, a); 230 logger.debug(String.valueOf(irr)); 231 if (a.length() == 0) { 232 l--; 233 if (l <= 1) { 234 return P; 235 } 236 } else { 237 f = a.leadingExpVector(); 238 if (f.signum() == 0) { 239 P = new ArrayList<GenSolvablePolynomial<C>>(); 240 P.add(a.monic()); 241 return P; 242 } 243 if (e.equals(f)) { 244 irr++; 245 } else { 246 irr = 0; 247 a = a.monic(); 248 } 249 P.add(a); 250 } 251 } 252 //System.out.println(); 253 return P; 254 } 255 256 257 /** 258 * Is reduction of normal form. 259 * @param row recording matrix. 260 * @param Pp a solvable polynomial list for reduction. 261 * @param Ap a solvable polynomial. 262 * @param Np nf(Pp,Ap), a left normal form of Ap wrt. Pp. 263 * @return true, if Np + sum( row[i]*Pp[i] ) == Ap, else false. 264 */ 265 @SuppressWarnings("unchecked") 266 public boolean isLeftReductionNF(List<GenSolvablePolynomial<C>> row, List<GenSolvablePolynomial<C>> Pp, 267 GenSolvablePolynomial<C> Ap, GenSolvablePolynomial<C> Np) { 268 if (row == null && Pp == null) { 269 if (Ap == null) { 270 return Np == null; 271 } 272 return Ap.equals(Np); 273 } 274 if (row == null || Pp == null) { 275 return false; 276 } 277 if (row.size() != Pp.size()) { 278 return false; 279 } 280 GenSolvablePolynomial<C> t = Np; 281 GenSolvablePolynomial<C> r; 282 GenSolvablePolynomial<C> p; 283 for (int m = 0; m < Pp.size(); m++) { 284 r = row.get(m); 285 p = Pp.get(m); 286 if (r != null && p != null) { 287 if (t == null) { 288 t = r.multiply(p); 289 } else { 290 t = (GenSolvablePolynomial<C>) t.sum(r.multiply(p)); 291 } 292 } 293 //System.out.println("r = " + r ); 294 //System.out.println("p = " + p ); 295 } 296 if (debug) { 297 logger.info("t = {}", t); 298 logger.info("a = {}", Ap); 299 } 300 if (t == null) { 301 if (Ap == null) { 302 return true; 303 } 304 return Ap.isZERO(); 305 } 306 t = (GenSolvablePolynomial<C>) t.subtract(Ap); 307 return t.isZERO(); 308 } 309 310 311 /** 312 * Right S-Polynomial. 313 * @param Ap solvable polynomial. 314 * @param Bp solvable polynomial. 315 * @return right-spol(Ap,Bp) the right S-polynomial of Ap and Bp. 316 */ 317 @SuppressWarnings("unchecked") 318 public GenSolvablePolynomial<C> rightSPolynomial(GenSolvablePolynomial<C> Ap, 319 GenSolvablePolynomial<C> Bp) { 320 if (logger.isInfoEnabled()) { 321 if (Bp == null || Bp.isZERO()) { 322 if (Ap != null) { 323 return Ap.ring.getZERO(); 324 } 325 return null; 326 } 327 if (Ap == null || Ap.isZERO()) { 328 return Bp.ring.getZERO(); 329 } 330 if (!Ap.ring.equals(Bp.ring)) { 331 logger.error("rings not equal"); 332 } 333 } 334 ExpVector e = Ap.leadingExpVector(); 335 ExpVector f = Bp.leadingExpVector(); 336 337 ExpVector g = e.lcm(f); 338 ExpVector e1 = g.subtract(e); 339 ExpVector f1 = g.subtract(f); 340 341 GenSolvablePolynomial<C> App = Ap.multiply(e1); 342 GenSolvablePolynomial<C> Bpp = Bp.multiply(f1); 343 344 C a = App.leadingBaseCoefficient(); 345 C b = Bpp.leadingBaseCoefficient(); 346 App = App.multiply(b); 347 Bpp = Bpp.multiply(a); 348 349 GenSolvablePolynomial<C> Cp = (GenSolvablePolynomial<C>) App.subtract(Bpp); 350 return Cp; 351 } 352 353 354 /** 355 * Is top reducible. Is left right symmetric. 356 * @param A solvable polynomial. 357 * @param P solvable polynomial list. 358 * @return true if A is top reducible with respect to P. 359 */ 360 public boolean isTopReducible(List<GenSolvablePolynomial<C>> P, GenSolvablePolynomial<C> A) { 361 if (P == null || P.isEmpty()) { 362 return false; 363 } 364 if (A == null || A.isZERO()) { 365 return false; 366 } 367 boolean mt = false; 368 ExpVector e = A.leadingExpVector(); 369 for (GenSolvablePolynomial<C> p : P) { 370 mt = e.multipleOf(p.leadingExpVector()); 371 if (mt) { 372 return true; 373 } 374 } 375 return false; 376 } 377 378 379 /** 380 * Is reducible. Is left right symmetric. 381 * @param Ap solvable polynomial. 382 * @param Pp solvable polynomial list. 383 * @return true if Ap is reducible with respect to Pp. 384 */ 385 public boolean isReducible(List<GenSolvablePolynomial<C>> Pp, GenSolvablePolynomial<C> Ap) { 386 return !isNormalform(Pp, Ap); 387 } 388 389 390 /** 391 * Is in Normalform. Is left right symmetric. 392 * @param Ap polynomial. 393 * @param Pp polynomial list. 394 * @return true if Ap is in normalform with respect to Pp. 395 */ 396 @SuppressWarnings("unchecked") 397 public boolean isNormalform(List<GenSolvablePolynomial<C>> Pp, GenSolvablePolynomial<C> Ap) { 398 if (Pp == null || Pp.isEmpty()) { 399 return true; 400 } 401 if (Ap == null || Ap.isZERO()) { 402 return true; 403 } 404 GenSolvablePolynomial<C>[] P = new GenSolvablePolynomial[0]; 405 synchronized (Pp) { 406 P = Pp.toArray(P); 407 } 408 int l = P.length; 409 ExpVector[] htl = new ExpVector[l]; 410 GenSolvablePolynomial<C>[] p = new GenSolvablePolynomial[l]; 411 ExpVector f; 412 int i; 413 int j = 0; 414 for (i = 0; i < l; i++) { 415 p[i] = P[i]; 416 f = p[i].leadingExpVector(); 417 if (f != null) { 418 p[j] = p[i]; 419 htl[j] = f; 420 j++; 421 } 422 } 423 l = j; 424 boolean mt = false; 425 for (ExpVector e : Ap.getMap().keySet()) { 426 for (i = 0; i < l; i++) { 427 mt = e.multipleOf(htl[i]); 428 if (mt) { 429 return false; 430 } 431 } 432 } 433 return true; 434 } 435 436 437 /** 438 * Is right reduction of normal form. 439 * @param row recording matrix. 440 * @param Pp a solvable polynomial list for reduction. 441 * @param Ap a solvable polynomial. 442 * @param Np nf(Pp,Ap), a left normal form of Ap wrt. Pp. 443 * @return true, if Np + sum( Pp[i]*row[i] ) == Ap, else false. 444 */ 445 @SuppressWarnings("unchecked") 446 public boolean isRightReductionNF(List<GenSolvablePolynomial<C>> row, List<GenSolvablePolynomial<C>> Pp, 447 GenSolvablePolynomial<C> Ap, GenSolvablePolynomial<C> Np) { 448 if (row == null && Pp == null) { 449 if (Ap == null) { 450 return Np == null; 451 } 452 return Ap.equals(Np); 453 } 454 if (row == null || Pp == null) { 455 return false; 456 } 457 if (row.size() != Pp.size()) { 458 return false; 459 } 460 GenSolvablePolynomial<C> t = Np; 461 GenSolvablePolynomial<C> r; 462 GenSolvablePolynomial<C> p; 463 for (int m = 0; m < Pp.size(); m++) { 464 r = row.get(m); 465 p = Pp.get(m); 466 if (r != null && p != null) { 467 if (t == null) { 468 t = p.multiply(r); //right 469 } else { 470 t = (GenSolvablePolynomial<C>) t.sum(p.multiply(r)); //right 471 } 472 } 473 //System.out.println("r = " + r ); 474 //System.out.println("p = " + p ); 475 } 476 if (debug) { 477 logger.info("t = {}", t); 478 logger.info("a = {}", Ap); 479 } 480 if (t == null) { 481 if (Ap == null) { 482 return true; 483 } 484 return Ap.isZERO(); 485 } 486 t = (GenSolvablePolynomial<C>) t.subtract(Ap); 487 return t.isZERO(); 488 } 489 490 491 /** 492 * Two-sided Normalform. 493 * @param Ap solvable polynomial. 494 * @param Pp solvable polynomial list. 495 * @return two-sided-nf(Ap) with respect to Pp. 496 */ 497 public GenSolvablePolynomial<C> normalform(List<GenSolvablePolynomial<C>> Pp, 498 GenSolvablePolynomial<C> Ap) { 499 throw new UnsupportedOperationException("two-sided normalform not implemented"); 500 } 501 502}