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