001/* 002 * $Id: FactorAbsolute.java 5871 2018-07-20 15:58:45Z kredel $ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.Map; 011import java.util.SortedMap; 012import java.util.TreeMap; 013 014import org.apache.logging.log4j.Logger; 015import org.apache.logging.log4j.LogManager; 016 017import edu.jas.poly.AlgebraicNumber; 018import edu.jas.poly.AlgebraicNumberRing; 019import edu.jas.poly.GenPolynomial; 020import edu.jas.poly.GenPolynomialRing; 021import edu.jas.poly.PolyUtil; 022import edu.jas.structure.GcdRingElem; 023import edu.jas.structure.RingFactory; 024 025 026/** 027 * Absolute factorization algorithms class. This class contains implementations 028 * of methods for factorization over algebraically closed fields. The required 029 * field extension is computed along with the factors. The methods have been 030 * tested for prime fields of characteristic zero, that is for 031 * <code>BigRational</code>. It might eventually also be used for prime fields 032 * of non-zero characteristic, that is with <code>ModInteger</code>. The field 033 * extension may yet not be minimal. 034 * @author Heinz Kredel 035 * @param <C> coefficient type 036 */ 037 038public abstract class FactorAbsolute<C extends GcdRingElem<C>> extends FactorAbstract<C> { 039 040 041 private static final Logger logger = LogManager.getLogger(FactorAbsolute.class); 042 043 044 private static final boolean debug = logger.isDebugEnabled(); 045 046 047 /* 048 * Factorization engine for algebraic number coefficients. 049 */ 050 //not possible here because of recursion AN -> Int|Mod -> AN -> ... 051 //public final FactorAbstract<AlgebraicNumber<C>> aengine; 052 053 /** 054 * No argument constructor. <b>Note:</b> can't use this constructor. 055 */ 056 protected FactorAbsolute() { 057 throw new IllegalArgumentException("don't use this constructor"); 058 } 059 060 061 /** 062 * Constructor. 063 * @param cfac coefficient ring factory. 064 */ 065 public FactorAbsolute(RingFactory<C> cfac) { 066 super(cfac); 067 //GenPolynomialRing<C> fac = new GenPolynomialRing<C>(cfac,1); 068 //GenPolynomial<C> p = fac.univariate(0); 069 //AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(p); 070 //aengine = null; //FactorFactory.<C>getImplementation(afac); // hack 071 } 072 073 074 /** 075 * Get the String representation. 076 * @see java.lang.Object#toString() 077 */ 078 @Override 079 public String toString() { 080 return getClass().getName(); 081 } 082 083 084 /** 085 * GenPolynomial test if is absolute irreducible. 086 * @param P GenPolynomial. 087 * @return true if P is absolute irreducible, else false. 088 */ 089 public boolean isAbsoluteIrreducible(GenPolynomial<C> P) { 090 if (!isIrreducible(P)) { 091 return false; 092 } 093 Factors<C> F = factorsAbsoluteIrreducible(P); 094 if (F.afac == null) { 095 return true; 096 } else if (F.afactors.size() > 2) { 097 return false; 098 } else { //F.size() == 2 099 boolean cnst = false; 100 for (GenPolynomial<AlgebraicNumber<C>> p : F.afactors) { 101 if (p.isConstant()) { 102 cnst = true; 103 } 104 } 105 return cnst; 106 } 107 } 108 109 110 /** 111 * GenPolynomial absolute base factorization of a polynomial. 112 * @param P univariate GenPolynomial. 113 * @return factors map container: [p_1 -> e_1, ..., p_k -> e_k] with P 114 * = prod_{i=1,...,k} p_i**e_i. <b>Note:</b> K(alpha) not yet 115 * minimal. 116 */ 117 // @Override 118 public FactorsMap<C> baseFactorsAbsolute(GenPolynomial<C> P) { 119 if (P == null) { 120 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 121 } 122 SortedMap<GenPolynomial<C>, Long> factors = new TreeMap<GenPolynomial<C>, Long>(); 123 if (P.isZERO()) { 124 return new FactorsMap<C>(P, factors); 125 } 126 //System.out.println("\nP_base = " + P); 127 GenPolynomialRing<C> pfac = P.ring; // K[x] 128 if (pfac.nvar > 1) { 129 //System.out.println("\nfacs_base: univ"); 130 throw new IllegalArgumentException("only for univariate polynomials"); 131 } 132 if (!pfac.coFac.isField()) { 133 //System.out.println("\nfacs_base: field"); 134 throw new IllegalArgumentException("only for field coefficients"); 135 } 136 if (P.degree(0) <= 1) { 137 factors.put(P, 1L); 138 return new FactorsMap<C>(P, factors); 139 } 140 // factor over K (=C) 141 SortedMap<GenPolynomial<C>, Long> facs = baseFactors(P); 142 if (debug && !isFactorization(P, facs)) { 143 System.out.println("facs = " + facs); 144 throw new ArithmeticException("isFactorization = false"); 145 } 146 if (logger.isInfoEnabled()) { 147 logger.info("all K factors = " + facs); // Q[X] 148 //System.out.println("\nall K factors = " + facs); // Q[X] 149 } 150 // factor over some K(alpha) 151 SortedMap<Factors<C>, Long> afactors = new TreeMap<Factors<C>, Long>(); 152 for (Map.Entry<GenPolynomial<C>, Long> me : facs.entrySet()) { 153 GenPolynomial<C> p = me.getKey(); 154 Long e = me.getValue(); //facs.get(p); 155 if (p.degree(0) <= 1) { 156 factors.put(p, e); 157 } else { 158 Factors<C> afacs = baseFactorsAbsoluteIrreducible(p); 159 //System.out.println("afacs = " + afacs); 160 afactors.put(afacs, e); 161 } 162 } 163 //System.out.println("K(alpha) factors = " + factors); 164 return new FactorsMap<C>(P, factors, afactors); 165 } 166 167 168 /** 169 * GenPolynomial absolute base factorization of a squarefree polynomial. 170 * @param P squarefree and primitive univariate GenPolynomial. 171 * @return factors list container: [p_1,...,p_k] with P = prod_{i=1, ..., k} 172 * p_i. <b>Note:</b> K(alpha) not yet minimal. 173 */ 174 // @Override 175 public FactorsList<C> baseFactorsAbsoluteSquarefree(GenPolynomial<C> P) { 176 if (P == null) { 177 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 178 } 179 List<GenPolynomial<C>> factors = new ArrayList<GenPolynomial<C>>(); 180 if (P.isZERO()) { 181 return new FactorsList<C>(P, factors); 182 } 183 //System.out.println("\nP_base_sqf = " + P); 184 GenPolynomialRing<C> pfac = P.ring; // K[x] 185 if (pfac.nvar > 1) { 186 //System.out.println("facs_base_sqf: univ"); 187 throw new IllegalArgumentException("only for univariate polynomials"); 188 } 189 if (!pfac.coFac.isField()) { 190 //System.out.println("facs_base_sqf: field"); 191 throw new IllegalArgumentException("only for field coefficients"); 192 } 193 if (P.degree(0) <= 1) { 194 factors.add(P); 195 return new FactorsList<C>(P, factors); 196 } 197 // factor over K (=C) 198 List<GenPolynomial<C>> facs = baseFactorsSquarefree(P); 199 //System.out.println("facs_base_irred = " + facs); 200 if (debug && !isFactorization(P, facs)) { 201 throw new ArithmeticException("isFactorization = false"); 202 } 203 if (logger.isInfoEnabled()) { 204 logger.info("all K factors = " + facs); // Q[X] 205 //System.out.println("\nall K factors = " + facs); // Q[X] 206 } 207 // factor over K(alpha) 208 List<Factors<C>> afactors = new ArrayList<Factors<C>>(); 209 for (GenPolynomial<C> p : facs) { 210 //System.out.println("facs_base_sqf_p = " + p); 211 if (p.degree(0) <= 1) { 212 factors.add(p); 213 } else { 214 Factors<C> afacs = baseFactorsAbsoluteIrreducible(p); 215 //System.out.println("afacs_base_sqf = " + afacs); 216 if (logger.isInfoEnabled()) { 217 logger.info("K(alpha) factors = " + afacs); // K(alpha)[X] 218 } 219 afactors.add(afacs); 220 } 221 } 222 //System.out.println("K(alpha) factors = " + factors); 223 return new FactorsList<C>(P, factors, afactors); 224 } 225 226 227 /** 228 * GenPolynomial base absolute factorization of a irreducible polynomial. 229 * @param P irreducible! univariate GenPolynomial. 230 * @return factors container: [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i 231 * in K(alpha)[x] for suitable alpha and p_i irreducible over L[x], 232 * where K \subset K(alpha) \subset L is an algebraically closed 233 * field over K. <b>Note:</b> K(alpha) not yet minimal. 234 */ 235 public Factors<C> baseFactorsAbsoluteIrreducible(GenPolynomial<C> P) { 236 if (P == null) { 237 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 238 } 239 if (P.isZERO()) { 240 return new Factors<C>(P); 241 } 242 //System.out.println("\nP_base_irred = " + P); 243 GenPolynomialRing<C> pfac = P.ring; // K[x] 244 if (pfac.nvar > 1) { 245 //System.out.println("facs_base_irred: univ"); 246 throw new IllegalArgumentException("only for univariate polynomials"); 247 } 248 if (!pfac.coFac.isField()) { 249 //System.out.println("facs_base_irred: field"); 250 throw new IllegalArgumentException("only for field coefficients"); 251 } 252 if (P.degree(0) <= 1) { 253 return new Factors<C>(P); 254 } 255 // setup field extension K(alpha) where alpha = z_xx 256 //String[] vars = new String[] { "z_" + Math.abs(P.hashCode() % 1000) }; 257 String[] vars = pfac.newVars("z_"); 258 pfac = pfac.copy(); 259 vars = pfac.setVars(vars); 260 GenPolynomial<C> aP = pfac.copy(P); // hack to exchange the variables 261 AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(aP, true); // since irreducible 262 if (logger.isInfoEnabled()) { 263 logger.info("K(alpha) = " + afac); 264 logger.info("K(alpha) = " + afac.toScript()); 265 //System.out.println("K(alpha) = " + afac); 266 } 267 GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, 268 aP.ring.nvar, aP.ring.tord, /*old*/vars); 269 // convert to K(alpha) 270 GenPolynomial<AlgebraicNumber<C>> Pa = PolyUtil.<C> convertToAlgebraicCoefficients(pafac, P); 271 if (logger.isInfoEnabled()) { 272 logger.info("P over K(alpha) = " + Pa); 273 //logger.info("P over K(alpha) = " + Pa.toScript()); 274 //System.out.println("P in K(alpha) = " + Pa); 275 } 276 // factor over K(alpha) 277 FactorAbstract<AlgebraicNumber<C>> engine = FactorFactory.<C> getImplementation(afac); 278 //System.out.println("K(alpha) engine = " + engine); 279 List<GenPolynomial<AlgebraicNumber<C>>> factors = engine.baseFactorsSquarefree(Pa); 280 //System.out.println("factors = " + factors); 281 if (logger.isInfoEnabled()) { 282 logger.info("factors over K(alpha) = " + factors); 283 //System.out.println("factors over K(alpha) = " + factors); 284 } 285 List<GenPolynomial<AlgebraicNumber<C>>> faca = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>( 286 factors.size()); 287 List<Factors<AlgebraicNumber<C>>> facar = new ArrayList<Factors<AlgebraicNumber<C>>>(); 288 for (GenPolynomial<AlgebraicNumber<C>> fi : factors) { 289 if (fi.degree(0) <= 1) { 290 faca.add(fi); 291 } else { 292 //System.out.println("fi.deg > 1 = " + fi); 293 FactorAbsolute<AlgebraicNumber<C>> aengine = (FactorAbsolute<AlgebraicNumber<C>>) FactorFactory 294 .<C> getImplementation(afac); 295 Factors<AlgebraicNumber<C>> fif = aengine.baseFactorsAbsoluteIrreducible(fi); 296 //System.out.println("fif = " + fif); 297 facar.add(fif); 298 } 299 } 300 if (facar.size() == 0) { 301 facar = null; 302 } 303 // find minimal field extension K(beta) \subset K(alpha) 304 return new Factors<C>(P, afac, Pa, faca, facar); 305 } 306 307 308 /** 309 * Univariate GenPolynomial algebraic partial fraction decomposition, 310 * Absolute factorization for elementary integration algorithm to linear factors. 311 * @param A univariate GenPolynomial, deg(A) < deg(P). 312 * @param P univariate squarefree GenPolynomial, gcd(A,P) == 1. 313 * @return partial fraction container. 314 */ 315 public PartialFraction<C> baseAlgebraicPartialFraction(GenPolynomial<C> A, GenPolynomial<C> P) { 316 if (P == null || P.isZERO()) { 317 throw new IllegalArgumentException(" P == null or P == 0"); 318 } 319 if (A == null || A.isZERO()) { 320 throw new IllegalArgumentException(" A == null or A == 0"); 321 // PartialFraction(A,P,al,pl,empty,empty) 322 } 323 //System.out.println("\nP_base_algeb_part = " + P); 324 GenPolynomialRing<C> pfac = P.ring; // K[x] 325 if (pfac.nvar > 1) { 326 //System.out.println("facs_base_irred: univ"); 327 throw new IllegalArgumentException("only for univariate polynomials"); 328 } 329 if (!pfac.coFac.isField()) { 330 //System.out.println("facs_base_irred: field"); 331 throw new IllegalArgumentException("only for field coefficients"); 332 } 333 List<C> cfactors = new ArrayList<C>(); 334 List<GenPolynomial<C>> cdenom = new ArrayList<GenPolynomial<C>>(); 335 List<AlgebraicNumber<C>> afactors = new ArrayList<AlgebraicNumber<C>>(); 336 List<GenPolynomial<AlgebraicNumber<C>>> adenom = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>(); 337 338 // P linear 339 if (P.degree(0) <= 1) { 340 cfactors.add(A.leadingBaseCoefficient()); 341 cdenom.add(P); 342 return new PartialFraction<C>(A, P, cfactors, cdenom, afactors, adenom); 343 } 344 List<GenPolynomial<C>> Pfac = baseFactorsSquarefree(P); 345 //System.out.println("\nPfac = " + Pfac); 346 347 List<GenPolynomial<C>> Afac = engine.basePartialFraction(A, Pfac); 348 349 GenPolynomial<C> A0 = Afac.remove(0); 350 if (!A0.isZERO()) { 351 throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)"); 352 } 353 354 // algebraic and linear factors 355 int i = 0; 356 for (GenPolynomial<C> pi : Pfac) { 357 GenPolynomial<C> ai = Afac.get(i++); 358 if (pi.degree(0) <= 1) { 359 cfactors.add(ai.leadingBaseCoefficient()); 360 cdenom.add(pi); 361 continue; 362 } 363 PartialFraction<C> pf = baseAlgebraicPartialFractionIrreducibleAbsolute(ai, pi); 364 //PartialFraction<C> pf = baseAlgebraicPartialFractionIrreducible(ai,pi); 365 cfactors.addAll(pf.cfactors); 366 cdenom.addAll(pf.cdenom); 367 afactors.addAll(pf.afactors); 368 adenom.addAll(pf.adenom); 369 } 370 return new PartialFraction<C>(A, P, cfactors, cdenom, afactors, adenom); 371 } 372 373 374 /** 375 * Univariate GenPolynomial algebraic partial fraction decomposition, via 376 * absolute factorization to linear factors. 377 * @param A univariate GenPolynomial, deg(A) < deg(P). 378 * @param P univariate irreducible GenPolynomial, gcd(A,P) == 1. 379 * @return partial fraction container. 380 */ 381 @SuppressWarnings("cast") 382 public PartialFraction<C> baseAlgebraicPartialFractionIrreducibleAbsolute(GenPolynomial<C> A, 383 GenPolynomial<C> P) { 384 if (P == null || P.isZERO()) { 385 throw new IllegalArgumentException(" P == null or P == 0"); 386 } 387 //System.out.println("\nP_base_algeb_part = " + P); 388 GenPolynomialRing<C> pfac = P.ring; // K[x] 389 if (pfac.nvar > 1) { 390 //System.out.println("facs_base_irred: univ"); 391 throw new IllegalArgumentException("only for univariate polynomials"); 392 } 393 if (!pfac.coFac.isField()) { 394 //System.out.println("facs_base_irred: field"); 395 throw new IllegalArgumentException("only for field coefficients"); 396 } 397 List<C> cfactors = new ArrayList<C>(); 398 List<GenPolynomial<C>> cdenom = new ArrayList<GenPolynomial<C>>(); 399 List<AlgebraicNumber<C>> afactors = new ArrayList<AlgebraicNumber<C>>(); 400 List<GenPolynomial<AlgebraicNumber<C>>> adenom = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>(); 401 402 // P linear 403 if (P.degree(0) <= 1) { 404 cfactors.add(A.leadingBaseCoefficient()); 405 cdenom.add(P); 406 return new PartialFraction<C>(A, P, cfactors, cdenom, afactors, adenom); 407 } 408 409 // non linear case 410 Factors<C> afacs = factorsAbsoluteIrreducible(P); 411 //System.out.println("linear algebraic factors = " + afacs); 412 //System.out.println("afactors = " + afacs.afactors); 413 //System.out.println("arfactors = " + afacs.arfactors); 414 //System.out.println("arfactors pol = " + afacs.arfactors.get(0).poly); 415 //System.out.println("arfactors2 = " + afacs.arfactors.get(0).afactors); 416 417 List<GenPolynomial<AlgebraicNumber<C>>> fact = afacs.getFactors(); 418 //System.out.println("factors = " + fact); 419 GenPolynomial<AlgebraicNumber<C>> Pa = afacs.apoly; 420 GenPolynomial<AlgebraicNumber<C>> Aa = PolyUtil.<C> convertToRecAlgebraicCoefficients(1, Pa.ring, A); 421 422 GreatestCommonDivisorAbstract<AlgebraicNumber<C>> aengine = GCDFactory.getProxy(afacs.afac); 423 //System.out.println("denom = " + Pa); 424 //System.out.println("numer = " + Aa); 425 List<GenPolynomial<AlgebraicNumber<C>>> numers = aengine.basePartialFraction(Aa, fact); 426 //System.out.println("part frac = " + numers); 427 GenPolynomial<AlgebraicNumber<C>> A0 = numers.remove(0); 428 if (!A0.isZERO()) { 429 throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)"); 430 } 431 int i = 0; 432 for (GenPolynomial<AlgebraicNumber<C>> fa : fact) { 433 GenPolynomial<AlgebraicNumber<C>> an = numers.get(i++); 434 if (fa.degree(0) <= 1) { 435 afactors.add(an.leadingBaseCoefficient()); 436 adenom.add(fa); 437 continue; 438 } 439 System.out.println("fa = " + fa); 440 Factors<AlgebraicNumber<C>> faf = afacs.getFactor(fa); 441 System.out.println("faf = " + faf); 442 List<GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>>> fafact = faf.getFactors(); 443 GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>> Aaa = PolyUtil 444 .<AlgebraicNumber<C>> convertToRecAlgebraicCoefficients(1, faf.apoly.ring, an); 445 446 GreatestCommonDivisorAbstract<AlgebraicNumber<AlgebraicNumber<C>>> aaengine = GCDFactory 447 .getImplementation(faf.afac); 448 449 List<GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>>> anumers = aaengine 450 .basePartialFraction(Aaa, fafact); 451 System.out.println("algeb part frac = " + anumers); 452 GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>> A0a = anumers.remove(0); 453 if (!A0a.isZERO()) { 454 throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)"); 455 } 456 int k = 0; 457 for (GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>> faa : fafact) { 458 GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>> ana = anumers.get(k++); 459 System.out.println("faa = " + faa); 460 System.out.println("ana = " + ana); 461 if (faa.degree(0) > 1) { 462 throw new ArithmeticException(" faa not linear"); 463 } 464 GenPolynomial<AlgebraicNumber<C>> ana1 = (GenPolynomial<AlgebraicNumber<C>>) (GenPolynomial) ana; 465 GenPolynomial<AlgebraicNumber<C>> faa1 = (GenPolynomial<AlgebraicNumber<C>>) (GenPolynomial) faa; 466 467 afactors.add(ana1.leadingBaseCoefficient()); 468 adenom.add(faa1); 469 } 470 } 471 return new PartialFraction<C>(A, P, cfactors, cdenom, afactors, adenom); 472 } 473 474 475 /** 476 * GenPolynomial absolute factorization of a polynomial. 477 * @param P GenPolynomial. 478 * @return factors map container: [p_1 -> e_1, ..., p_k -> e_k] with P 479 * = prod_{i=1,...,k} p_i**e_i. <b>Note:</b> K(alpha) not yet 480 * minimal. 481 */ 482 public FactorsMap<C> factorsAbsolute(GenPolynomial<C> P) { 483 if (P == null) { 484 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 485 } 486 SortedMap<GenPolynomial<C>, Long> factors = new TreeMap<GenPolynomial<C>, Long>(); 487 if (P.isZERO()) { 488 return new FactorsMap<C>(P, factors); 489 } 490 //System.out.println("\nP_mult = " + P); 491 GenPolynomialRing<C> pfac = P.ring; // K[x] 492 if (pfac.nvar <= 1) { 493 return baseFactorsAbsolute(P); 494 } 495 if (!pfac.coFac.isField()) { 496 throw new IllegalArgumentException("only for field coefficients"); 497 } 498 if (P.degree() <= 1) { 499 factors.put(P, 1L); 500 return new FactorsMap<C>(P, factors); 501 } 502 // factor over K (=C) 503 SortedMap<GenPolynomial<C>, Long> facs = factors(P); 504 if (debug && !isFactorization(P, facs)) { 505 throw new ArithmeticException("isFactorization = false"); 506 } 507 if (logger.isInfoEnabled()) { 508 logger.info("all K factors = " + facs); // Q[X] 509 //System.out.println("\nall K factors = " + facs); // Q[X] 510 } 511 SortedMap<Factors<C>, Long> afactors = new TreeMap<Factors<C>, Long>(); 512 // factor over K(alpha) 513 for (Map.Entry<GenPolynomial<C>, Long> me : facs.entrySet()) { 514 GenPolynomial<C> p = me.getKey(); 515 Long e = me.getValue(); //facs.get(p); 516 if (p.degree() <= 1) { 517 factors.put(p, e); 518 } else { 519 Factors<C> afacs = factorsAbsoluteIrreducible(p); 520 if (afacs.afac == null) { // absolute irreducible 521 factors.put(p, e); 522 } else { 523 afactors.put(afacs, e); 524 } 525 } 526 } 527 //System.out.println("K(alpha) factors multi = " + factors); 528 return new FactorsMap<C>(P, factors, afactors); 529 } 530 531 532 /** 533 * GenPolynomial absolute factorization of a squarefree polynomial. 534 * @param P squarefree and primitive GenPolynomial. 535 * @return factors list container: [p_1,...,p_k] with P = prod_{i=1, ..., k} 536 * p_i. <b>Note:</b> K(alpha) not yet minimal. 537 */ 538 // @Override 539 public FactorsList<C> factorsAbsoluteSquarefree(GenPolynomial<C> P) { 540 if (P == null) { 541 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 542 } 543 List<GenPolynomial<C>> factors = new ArrayList<GenPolynomial<C>>(); 544 if (P.isZERO()) { 545 return new FactorsList<C>(P, factors); 546 } 547 //System.out.println("\nP = " + P); 548 GenPolynomialRing<C> pfac = P.ring; // K[x] 549 if (pfac.nvar <= 1) { 550 return baseFactorsAbsoluteSquarefree(P); 551 } 552 if (!pfac.coFac.isField()) { 553 throw new IllegalArgumentException("only for field coefficients"); 554 } 555 if (P.degree() <= 1) { 556 factors.add(P); 557 return new FactorsList<C>(P, factors); 558 } 559 // factor over K (=C) 560 List<GenPolynomial<C>> facs = factorsSquarefree(P); 561 if (debug && !isFactorization(P, facs)) { 562 throw new ArithmeticException("isFactorization = false"); 563 } 564 if (logger.isInfoEnabled()) { 565 logger.info("all K factors = " + facs); // Q[X] 566 //System.out.println("\nall K factors = " + facs); // Q[X] 567 } 568 List<Factors<C>> afactors = new ArrayList<Factors<C>>(); 569 // factor over K(alpha) 570 for (GenPolynomial<C> p : facs) { 571 if (p.degree() <= 1) { 572 factors.add(p); 573 } else { 574 Factors<C> afacs = factorsAbsoluteIrreducible(p); 575 if (debug) { 576 logger.info("K(alpha) factors = " + afacs); // K(alpha)[X] 577 } 578 if (afacs.afac == null) { // absolute irreducible 579 factors.add(p); 580 } else { 581 afactors.add(afacs); 582 } 583 } 584 } 585 //System.out.println("K(alpha) factors = " + factors); 586 return new FactorsList<C>(P, factors, afactors); 587 } 588 589 590 /** 591 * GenPolynomial absolute factorization of a irreducible polynomial. 592 * @param P irreducible! GenPolynomial. 593 * @return factors container: [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i 594 * in K(alpha)[x] for suitable alpha and p_i irreducible over L[x], 595 * where K \subset K(alpha) \subset L is an algebraically closed 596 * field over K. <b>Note:</b> K(alpha) not yet minimal. 597 */ 598 public Factors<C> factorsAbsoluteIrreducible(GenPolynomial<C> P) { 599 if (P == null) { 600 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 601 } 602 if (P.isZERO()) { 603 return new Factors<C>(P); 604 } 605 GenPolynomialRing<C> pfac = P.ring; // K[x] 606 if (pfac.nvar <= 1) { 607 return baseFactorsAbsoluteIrreducible(P); 608 } 609 if (!pfac.coFac.isField()) { 610 throw new IllegalArgumentException("only for field coefficients"); 611 } 612 //List<GenPolynomial<C>> factors = new ArrayList<GenPolynomial<C>>(); 613 if (P.degree() <= 1) { 614 return new Factors<C>(P); 615 } 616 // find field extension K(alpha) 617 GenPolynomial<C> up = P; 618 RingFactory<C> cf = pfac.coFac; 619 long cr = cf.characteristic().longValue(); // char might be larger 620 if (cr == 0L) { 621 cr = Long.MAX_VALUE; 622 } 623 long rp = 0L; 624 for (int i = 0; i < (pfac.nvar - 1); i++) { 625 rp = 0L; 626 GenPolynomialRing<C> nfac = pfac.contract(1); 627 String[] vn = new String[] { pfac.getVars()[pfac.nvar - 1] }; 628 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(nfac, 1, 629 pfac.tord, vn); 630 GenPolynomial<GenPolynomial<C>> upr = PolyUtil.<C> recursive(rfac, up); 631 //System.out.println("upr = " + upr); 632 GenPolynomial<C> ep; 633 do { 634 if (rp >= cr) { 635 throw new ArithmeticException("elements of prime field exhausted: " + cr); 636 } 637 C r = cf.fromInteger(rp); //cf.random(rp); 638 //System.out.println("r = " + r); 639 ep = PolyUtil.<C> evaluateMainRecursive(nfac, upr, r); 640 //System.out.println("ep = " + ep); 641 rp++; 642 } while (!isSquarefree(ep) /*todo: || ep.degree() <= 1*/); // max deg 643 up = ep; 644 pfac = nfac; 645 } 646 up = up.monic(); 647 if (debug) { 648 logger.info("P(" + rp + ") = " + up); 649 //System.out.println("up = " + up); 650 } 651 if (debug && !isSquarefree(up)) { 652 throw new ArithmeticException("not irreducible up = " + up); 653 } 654 if (up.degree(0) <= 1) { 655 return new Factors<C>(P); 656 } 657 // find irreducible factor of up 658 List<GenPolynomial<C>> UF = baseFactorsSquarefree(up); 659 //System.out.println("UF = " + UF); 660 FactorsList<C> aUF = baseFactorsAbsoluteSquarefree(up); 661 //System.out.println("aUF = " + aUF); 662 AlgebraicNumberRing<C> arfac = aUF.findExtensionField(); 663 //System.out.println("arfac = " + arfac); 664 665 long e = up.degree(0); 666 // search factor polynomial with smallest degree 667 for (int i = 0; i < UF.size(); i++) { 668 GenPolynomial<C> upi = UF.get(i); 669 long d = upi.degree(0); 670 if (1 <= d && d <= e) { 671 up = upi; 672 e = up.degree(0); 673 } 674 } 675 if (up.degree(0) <= 1) { 676 return new Factors<C>(P); 677 } 678 if (debug) { 679 logger.info("field extension by " + up); 680 } 681 682 List<GenPolynomial<AlgebraicNumber<C>>> afactors = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>(); 683 684 // setup field extension K(alpha) 685 //String[] vars = new String[] { "z_" + Math.abs(up.hashCode() % 1000) }; 686 String[] vars = pfac.newVars("z_"); 687 pfac = pfac.copy(); 688 //String[] ovars = 689 pfac.setVars(vars); // side effects! 690 //GenPolynomial<C> aup = pfac.copy(up); // hack to exchange the variables 691 //AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(aup,true); // since irreducible 692 AlgebraicNumberRing<C> afac = arfac; 693 int depth = afac.depth(); 694 //System.out.println("afac = " + afac); 695 GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, 696 P.ring.nvar, P.ring.tord, P.ring.getVars()); 697 //System.out.println("pafac = " + pafac); 698 // convert to K(alpha) 699 GenPolynomial<AlgebraicNumber<C>> Pa = PolyUtil.<C> convertToRecAlgebraicCoefficients(depth, pafac, 700 P); 701 //System.out.println("Pa = " + Pa); 702 // factor over K(alpha) 703 FactorAbstract<AlgebraicNumber<C>> engine = FactorFactory.<C> getImplementation(afac); 704 afactors = engine.factorsSquarefree(Pa); 705 if (debug) { 706 logger.info("K(alpha) factors multi = " + afactors); 707 //System.out.println("K(alpha) factors = " + afactors); 708 } 709 if (afactors.size() <= 1) { 710 return new Factors<C>(P); 711 } 712 // normalize first factor to monic 713 GenPolynomial<AlgebraicNumber<C>> p1 = afactors.get(0); 714 AlgebraicNumber<C> p1c = p1.leadingBaseCoefficient(); 715 if (!p1c.isONE()) { 716 GenPolynomial<AlgebraicNumber<C>> p2 = afactors.get(1); 717 afactors.remove(p1); 718 afactors.remove(p2); 719 p1 = p1.divide(p1c); 720 p2 = p2.multiply(p1c); 721 afactors.add(p1); 722 afactors.add(p2); 723 } 724 // recursion for splitting field 725 // find minimal field extension K(beta) \subset K(alpha) 726 return new Factors<C>(P, afac, Pa, afactors); 727 } 728 729 730 /** 731 * GenPolynomial is absolute factorization. 732 * @param facs factors container. 733 * @return true if P = prod_{i=1,...,r} p_i, else false. 734 */ 735 public boolean isAbsoluteFactorization(Factors<C> facs) { 736 if (facs == null) { 737 throw new IllegalArgumentException("facs may not be null"); 738 } 739 if (facs.afac == null) { 740 return true; 741 } 742 GenPolynomial<AlgebraicNumber<C>> fa = facs.apoly; 743 GenPolynomialRing<AlgebraicNumber<C>> pafac = fa.ring; 744 GenPolynomial<AlgebraicNumber<C>> t = pafac.getONE(); 745 for (GenPolynomial<AlgebraicNumber<C>> f : facs.afactors) { 746 t = t.multiply(f); 747 } 748 //return fa.equals(t) || fa.equals(t.negate()); 749 boolean b = fa.equals(t) || fa.equals(t.negate()); 750 if (b) { 751 return b; 752 } 753 if (facs.arfactors == null) { 754 return false; 755 } 756 for (Factors<AlgebraicNumber<C>> arp : facs.arfactors) { 757 t = t.multiply(arp.poly); 758 } 759 b = fa.equals(t) || fa.equals(t.negate()); 760 if (!b) { 761 System.out.println("\nFactors: " + facs); 762 System.out.println("fa = " + fa); 763 System.out.println("t = " + t); 764 } 765 return b; 766 } 767 768 769 /** 770 * GenPolynomial is absolute factorization. 771 * @param facs factors list container. 772 * @return true if P = prod_{i=1,...,r} p_i, else false. 773 */ 774 public boolean isAbsoluteFactorization(FactorsList<C> facs) { 775 if (facs == null) { 776 throw new IllegalArgumentException("facs may not be null"); 777 } 778 GenPolynomial<C> P = facs.poly; 779 GenPolynomial<C> t = P.ring.getONE(); 780 for (GenPolynomial<C> f : facs.factors) { 781 t = t.multiply(f); 782 } 783 if (P.equals(t) || P.equals(t.negate())) { 784 return true; 785 } 786 if (facs.afactors == null) { 787 return false; 788 } 789 for (Factors<C> fs : facs.afactors) { 790 if (!isAbsoluteFactorization(fs)) { 791 return false; 792 } 793 t = t.multiply(facs.poly); 794 } 795 //return P.equals(t) || P.equals(t.negate()); 796 boolean b = P.equals(t) || P.equals(t.negate()); 797 if (!b) { 798 System.out.println("\nFactorsList: " + facs); 799 System.out.println("P = " + P); 800 System.out.println("t = " + t); 801 } 802 return b; 803 } 804 805 806 /** 807 * GenPolynomial is absolute factorization. 808 * @param facs factors map container. 809 * @return true if P = prod_{i=1,...,k} p_i**e_i , else false. 810 */ 811 public boolean isAbsoluteFactorization(FactorsMap<C> facs) { 812 if (facs == null) { 813 throw new IllegalArgumentException("facs may not be null"); 814 } 815 GenPolynomial<C> P = facs.poly; 816 GenPolynomial<C> t = P.ring.getONE(); 817 for (Map.Entry<GenPolynomial<C>, Long> me : facs.factors.entrySet()) { 818 GenPolynomial<C> f = me.getKey(); 819 long e = me.getValue(); 820 GenPolynomial<C> g = f.power(e); 821 t = t.multiply(g); 822 } 823 if (P.equals(t) || P.equals(t.negate())) { 824 return true; 825 } 826 if (facs.afactors == null) { 827 return false; 828 } 829 for (Map.Entry<Factors<C>, Long> me : facs.afactors.entrySet()) { 830 Factors<C> fs = me.getKey(); 831 if (!isAbsoluteFactorization(fs)) { 832 return false; 833 } 834 long e = me.getValue(); 835 GenPolynomial<C> g = fs.poly.power(e); 836 t = t.multiply(g); 837 } 838 boolean b = P.equals(t) || P.equals(t.negate()); 839 if (!b) { 840 System.out.println("\nFactorsMap: " + facs); 841 System.out.println("P = " + P); 842 System.out.println("t = " + t); 843 } 844 return b; 845 } 846 847}