001/* 002 * $Id: FactorAbsolute.java 5047 2014-12-30 17:44:11Z 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.Power; 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 = Logger.getLogger(FactorAbsolute.class); 042 043 044 private 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 or Rothstein-Trager algorithm. 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, 376 * Rothstein-Trager algorithm. 377 * @param A univariate GenPolynomial, deg(A) < deg(P). 378 * @param P univariate squarefree GenPolynomial, gcd(A,P) == 1. 379 * @return partial fraction container. 380 */ 381 @Deprecated 382 public PartialFraction<C> baseAlgebraicPartialFractionIrreducible(GenPolynomial<C> A, 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 // deriviative 409 GenPolynomial<C> Pp = PolyUtil.<C> baseDeriviative(P); 410 //no: Pp = Pp.monic(); 411 //System.out.println("\nP = " + P); 412 //System.out.println("Pp = " + Pp); 413 414 // Q[t] 415 String[] vars = new String[] { "t" }; 416 GenPolynomialRing<C> cfac = new GenPolynomialRing<C>(pfac.coFac, 1, pfac.tord, vars); 417 GenPolynomial<C> t = cfac.univariate(0); 418 //System.out.println("t = " + t); 419 420 // Q[x][t] 421 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(pfac, cfac); // sic 422 //System.out.println("rfac = " + rfac.toScript()); 423 424 // transform polynomials to bi-variate polynomial 425 GenPolynomial<GenPolynomial<C>> Ac = PolyUfdUtil.<C> introduceLowerVariable(rfac, A); 426 //System.out.println("Ac = " + Ac); 427 GenPolynomial<GenPolynomial<C>> Pc = PolyUfdUtil.<C> introduceLowerVariable(rfac, P); 428 //System.out.println("Pc = " + Pc); 429 GenPolynomial<GenPolynomial<C>> Pcp = PolyUfdUtil.<C> introduceLowerVariable(rfac, Pp); 430 //System.out.println("Pcp = " + Pcp); 431 432 // Q[t][x] 433 GenPolynomialRing<GenPolynomial<C>> rfac1 = Pc.ring; 434 //System.out.println("rfac1 = " + rfac1.toScript()); 435 436 // A - t P' 437 GenPolynomial<GenPolynomial<C>> tc = rfac1.getONE().multiply(t); 438 //System.out.println("tc = " + tc); 439 GenPolynomial<GenPolynomial<C>> At = Ac.subtract(tc.multiply(Pcp)); 440 //System.out.println("At = " + At); 441 442 GreatestCommonDivisorSubres<C> engine = new GreatestCommonDivisorSubres<C>(); 443 // = GCDFactory.<C>getImplementation( cfac.coFac ); 444 GreatestCommonDivisorAbstract<AlgebraicNumber<C>> aengine = null; 445 446 GenPolynomial<GenPolynomial<C>> Rc = engine.recursiveUnivariateResultant(Pc, At); 447 //System.out.println("Rc = " + Rc); 448 GenPolynomial<C> res = Rc.leadingBaseCoefficient(); 449 //no: res = res.monic(); 450 //System.out.println("\nres = " + res); 451 452 SortedMap<GenPolynomial<C>, Long> resfac = baseFactors(res); 453 //System.out.println("resfac = " + resfac + "\n"); 454 455 for (GenPolynomial<C> r : resfac.keySet()) { 456 //System.out.println("\nr(t) = " + r); 457 if (r.isConstant()) { 458 continue; 459 } 460 // if ( r.degree(0) <= 1L ) { 461 // System.out.println("warning linear factor in resultant ignored"); 462 // continue; 463 // //throw new ArithmeticException("input not irreducible"); 464 // } 465 //vars = new String[] { "z_" + Math.abs(r.hashCode() % 1000) }; 466 vars = pfac.newVars("z_"); 467 pfac = pfac.copy(); 468 //String[] ovars = 469 pfac.setVars(vars); 470 r = pfac.copy(r); // hack to exchange the variables 471 //System.out.println("r(z_) = " + r); 472 AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(r, true); // since irreducible 473 logger.debug("afac = " + afac.toScript()); 474 AlgebraicNumber<C> a = afac.getGenerator(); 475 //no: a = a.negate(); 476 //System.out.println("a = " + a); 477 478 // K(alpha)[x] 479 GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, 480 Pc.ring); 481 //System.out.println("pafac = " + pafac.toScript()); 482 483 // convert to K(alpha)[x] 484 GenPolynomial<AlgebraicNumber<C>> Pa = PolyUtil.<C> convertToAlgebraicCoefficients(pafac, P); 485 //System.out.println("Pa = " + Pa); 486 GenPolynomial<AlgebraicNumber<C>> Pap = PolyUtil.<C> convertToAlgebraicCoefficients(pafac, Pp); 487 //System.out.println("Pap = " + Pap); 488 GenPolynomial<AlgebraicNumber<C>> Aa = PolyUtil.<C> convertToAlgebraicCoefficients(pafac, A); 489 //System.out.println("Aa = " + Aa); 490 491 // A - a P' 492 GenPolynomial<AlgebraicNumber<C>> Ap = Aa.subtract(Pap.multiply(a)); 493 //System.out.println("Ap = " + Ap); 494 495 if (aengine == null) { 496 aengine = GCDFactory.<AlgebraicNumber<C>> getImplementation(afac); 497 //System.out.println("aengine = " + aengine); 498 } 499 GenPolynomial<AlgebraicNumber<C>> Ga = aengine.baseGcd(Pa, Ap); 500 //System.out.println("Ga = " + Ga); 501 if (Ga.isConstant()) { 502 //System.out.println("warning constant gcd ignored"); 503 continue; 504 } 505 afactors.add(a); 506 adenom.add(Ga); 507 // quadratic case 508 if (P.degree(0) == 2 && Ga.degree(0) == 1) { 509 GenPolynomial<AlgebraicNumber<C>>[] qra = PolyUtil 510 .<AlgebraicNumber<C>> basePseudoQuotientRemainder(Pa, Ga); 511 GenPolynomial<AlgebraicNumber<C>> Qa = qra[0]; 512 if (!qra[1].isZERO()) { 513 throw new ArithmeticException("remainder not zero"); 514 } 515 //System.out.println("Qa = " + Qa); 516 afactors.add(a.negate()); 517 adenom.add(Qa); 518 } 519 // if (P.degree(0) == 3 && Ga.degree(0) == 1) { 520 // GenPolynomial<AlgebraicNumber<C>>[] qra = PolyUtil 521 // .<AlgebraicNumber<C>> basePseudoQuotientRemainder(Pa, Ga); 522 // GenPolynomial<AlgebraicNumber<C>> Qa = qra[0]; 523 // if (!qra[1].isZERO()) { 524 // throw new ArithmeticException("remainder not zero"); 525 // } 526 // System.out.println("Qa3 = " + Qa); 527 // //afactors.add( a.negate() ); 528 // //adenom.add( Qa ); 529 // } 530 } 531 return new PartialFraction<C>(A, P, cfactors, cdenom, afactors, adenom); 532 } 533 534 535 /** 536 * Univariate GenPolynomial algebraic partial fraction decomposition, via 537 * absolute factorization to linear factors. 538 * @param A univariate GenPolynomial, deg(A) < deg(P). 539 * @param P univariate squarefree GenPolynomial, gcd(A,P) == 1. 540 * @return partial fraction container. 541 */ 542 @SuppressWarnings("cast") 543 public PartialFraction<C> baseAlgebraicPartialFractionIrreducibleAbsolute(GenPolynomial<C> A, 544 GenPolynomial<C> P) { 545 if (P == null || P.isZERO()) { 546 throw new IllegalArgumentException(" P == null or P == 0"); 547 } 548 //System.out.println("\nP_base_algeb_part = " + P); 549 GenPolynomialRing<C> pfac = P.ring; // K[x] 550 if (pfac.nvar > 1) { 551 //System.out.println("facs_base_irred: univ"); 552 throw new IllegalArgumentException("only for univariate polynomials"); 553 } 554 if (!pfac.coFac.isField()) { 555 //System.out.println("facs_base_irred: field"); 556 throw new IllegalArgumentException("only for field coefficients"); 557 } 558 List<C> cfactors = new ArrayList<C>(); 559 List<GenPolynomial<C>> cdenom = new ArrayList<GenPolynomial<C>>(); 560 List<AlgebraicNumber<C>> afactors = new ArrayList<AlgebraicNumber<C>>(); 561 List<GenPolynomial<AlgebraicNumber<C>>> adenom = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>(); 562 563 // P linear 564 if (P.degree(0) <= 1) { 565 cfactors.add(A.leadingBaseCoefficient()); 566 cdenom.add(P); 567 return new PartialFraction<C>(A, P, cfactors, cdenom, afactors, adenom); 568 } 569 570 // non linear case 571 Factors<C> afacs = factorsAbsoluteIrreducible(P); 572 //System.out.println("linear algebraic factors = " + afacs); 573 574 //System.out.println("afactors = " + afacs.afactors); 575 //System.out.println("arfactors = " + afacs.arfactors); 576 //System.out.println("arfactors pol = " + afacs.arfactors.get(0).poly); 577 //System.out.println("arfactors2 = " + afacs.arfactors.get(0).afactors); 578 579 List<GenPolynomial<AlgebraicNumber<C>>> fact = afacs.getFactors(); 580 //System.out.println("factors = " + fact); 581 GenPolynomial<AlgebraicNumber<C>> Pa = afacs.apoly; 582 583 GenPolynomial<AlgebraicNumber<C>> Aa = PolyUtil.<C> convertToRecAlgebraicCoefficients(1, Pa.ring, A); 584 585 586 GreatestCommonDivisorAbstract<AlgebraicNumber<C>> aengine = GCDFactory.getProxy(afacs.afac); 587 588 //System.out.println("denom = " + Pa); 589 //System.out.println("numer = " + Aa); 590 591 List<GenPolynomial<AlgebraicNumber<C>>> numers = aengine.basePartialFraction(Aa, fact); 592 //System.out.println("part frac = " + numers); 593 GenPolynomial<AlgebraicNumber<C>> A0 = numers.remove(0); 594 if (!A0.isZERO()) { 595 throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)"); 596 } 597 int i = 0; 598 for (GenPolynomial<AlgebraicNumber<C>> fa : fact) { 599 GenPolynomial<AlgebraicNumber<C>> an = numers.get(i++); 600 if (fa.degree(0) <= 1) { 601 afactors.add(an.leadingBaseCoefficient()); 602 adenom.add(fa); 603 continue; 604 } 605 System.out.println("fa = " + fa); 606 Factors<AlgebraicNumber<C>> faf = afacs.getFactor(fa); 607 System.out.println("faf = " + faf); 608 List<GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>>> fafact = faf.getFactors(); 609 GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>> Aaa = PolyUtil 610 .<AlgebraicNumber<C>> convertToRecAlgebraicCoefficients(1, faf.apoly.ring, an); 611 612 GreatestCommonDivisorAbstract<AlgebraicNumber<AlgebraicNumber<C>>> aaengine = GCDFactory 613 .getImplementation(faf.afac); 614 615 List<GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>>> anumers = aaengine.basePartialFraction( 616 Aaa, fafact); 617 System.out.println("algeb part frac = " + anumers); 618 GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>> A0a = anumers.remove(0); 619 if (!A0a.isZERO()) { 620 throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)"); 621 } 622 int k = 0; 623 for (GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>> faa : fafact) { 624 GenPolynomial<AlgebraicNumber<AlgebraicNumber<C>>> ana = anumers.get(k++); 625 System.out.println("faa = " + faa); 626 System.out.println("ana = " + ana); 627 if (faa.degree(0) > 1) { 628 throw new ArithmeticException(" faa not linear"); 629 } 630 GenPolynomial<AlgebraicNumber<C>> ana1 = (GenPolynomial<AlgebraicNumber<C>>) (GenPolynomial) ana; 631 GenPolynomial<AlgebraicNumber<C>> faa1 = (GenPolynomial<AlgebraicNumber<C>>) (GenPolynomial) faa; 632 633 634 afactors.add(ana1.leadingBaseCoefficient()); 635 adenom.add(faa1); 636 } 637 } 638 return new PartialFraction<C>(A, P, cfactors, cdenom, afactors, adenom); 639 } 640 641 642 /** 643 * GenPolynomial absolute factorization of a polynomial. 644 * @param P GenPolynomial. 645 * @return factors map container: [p_1 -> e_1, ..., p_k -> e_k] with P 646 * = prod_{i=1,...,k} p_i**e_i. <b>Note:</b> K(alpha) not yet 647 * minimal. 648 */ 649 public FactorsMap<C> factorsAbsolute(GenPolynomial<C> P) { 650 if (P == null) { 651 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 652 } 653 SortedMap<GenPolynomial<C>, Long> factors = new TreeMap<GenPolynomial<C>, Long>(); 654 if (P.isZERO()) { 655 return new FactorsMap<C>(P, factors); 656 } 657 //System.out.println("\nP_mult = " + P); 658 GenPolynomialRing<C> pfac = P.ring; // K[x] 659 if (pfac.nvar <= 1) { 660 return baseFactorsAbsolute(P); 661 } 662 if (!pfac.coFac.isField()) { 663 throw new IllegalArgumentException("only for field coefficients"); 664 } 665 if (P.degree() <= 1) { 666 factors.put(P, 1L); 667 return new FactorsMap<C>(P, factors); 668 } 669 // factor over K (=C) 670 SortedMap<GenPolynomial<C>, Long> facs = factors(P); 671 if (debug && !isFactorization(P, facs)) { 672 throw new ArithmeticException("isFactorization = false"); 673 } 674 if (logger.isInfoEnabled()) { 675 logger.info("all K factors = " + facs); // Q[X] 676 //System.out.println("\nall K factors = " + facs); // Q[X] 677 } 678 SortedMap<Factors<C>, Long> afactors = new TreeMap<Factors<C>, Long>(); 679 // factor over K(alpha) 680 for (Map.Entry<GenPolynomial<C>, Long> me : facs.entrySet()) { 681 GenPolynomial<C> p = me.getKey(); 682 Long e = me.getValue(); //facs.get(p); 683 if (p.degree() <= 1) { 684 factors.put(p, e); 685 } else { 686 Factors<C> afacs = factorsAbsoluteIrreducible(p); 687 if (afacs.afac == null) { // absolute irreducible 688 factors.put(p, e); 689 } else { 690 afactors.put(afacs, e); 691 } 692 } 693 } 694 //System.out.println("K(alpha) factors multi = " + factors); 695 return new FactorsMap<C>(P, factors, afactors); 696 } 697 698 699 /** 700 * GenPolynomial absolute factorization of a squarefree polynomial. 701 * @param P squarefree and primitive GenPolynomial. 702 * @return factors list container: [p_1,...,p_k] with P = prod_{i=1, ..., k} 703 * p_i. <b>Note:</b> K(alpha) not yet minimal. 704 */ 705 // @Override 706 public FactorsList<C> factorsAbsoluteSquarefree(GenPolynomial<C> P) { 707 if (P == null) { 708 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 709 } 710 List<GenPolynomial<C>> factors = new ArrayList<GenPolynomial<C>>(); 711 if (P.isZERO()) { 712 return new FactorsList<C>(P, factors); 713 } 714 //System.out.println("\nP = " + P); 715 GenPolynomialRing<C> pfac = P.ring; // K[x] 716 if (pfac.nvar <= 1) { 717 return baseFactorsAbsoluteSquarefree(P); 718 } 719 if (!pfac.coFac.isField()) { 720 throw new IllegalArgumentException("only for field coefficients"); 721 } 722 if (P.degree() <= 1) { 723 factors.add(P); 724 return new FactorsList<C>(P, factors); 725 } 726 // factor over K (=C) 727 List<GenPolynomial<C>> facs = factorsSquarefree(P); 728 if (debug && !isFactorization(P, facs)) { 729 throw new ArithmeticException("isFactorization = false"); 730 } 731 if (logger.isInfoEnabled()) { 732 logger.info("all K factors = " + facs); // Q[X] 733 //System.out.println("\nall K factors = " + facs); // Q[X] 734 } 735 List<Factors<C>> afactors = new ArrayList<Factors<C>>(); 736 // factor over K(alpha) 737 for (GenPolynomial<C> p : facs) { 738 if (p.degree() <= 1) { 739 factors.add(p); 740 } else { 741 Factors<C> afacs = factorsAbsoluteIrreducible(p); 742 if (debug) { 743 logger.info("K(alpha) factors = " + afacs); // K(alpha)[X] 744 } 745 if (afacs.afac == null) { // absolute irreducible 746 factors.add(p); 747 } else { 748 afactors.add(afacs); 749 } 750 } 751 } 752 //System.out.println("K(alpha) factors = " + factors); 753 return new FactorsList<C>(P, factors, afactors); 754 } 755 756 757 /** 758 * GenPolynomial absolute factorization of a irreducible polynomial. 759 * @param P irreducible! GenPolynomial. 760 * @return factors container: [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i 761 * in K(alpha)[x] for suitable alpha and p_i irreducible over L[x], 762 * where K \subset K(alpha) \subset L is an algebraically closed 763 * field over K. <b>Note:</b> K(alpha) not yet minimal. 764 */ 765 public Factors<C> factorsAbsoluteIrreducible(GenPolynomial<C> P) { 766 if (P == null) { 767 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 768 } 769 if (P.isZERO()) { 770 return new Factors<C>(P); 771 } 772 GenPolynomialRing<C> pfac = P.ring; // K[x] 773 if (pfac.nvar <= 1) { 774 return baseFactorsAbsoluteIrreducible(P); 775 } 776 if (!pfac.coFac.isField()) { 777 throw new IllegalArgumentException("only for field coefficients"); 778 } 779 //List<GenPolynomial<C>> factors = new ArrayList<GenPolynomial<C>>(); 780 if (P.degree() <= 1) { 781 return new Factors<C>(P); 782 } 783 // find field extension K(alpha) 784 GenPolynomial<C> up = P; 785 RingFactory<C> cf = pfac.coFac; 786 long cr = cf.characteristic().longValue(); // char might be larger 787 if (cr == 0L) { 788 cr = Long.MAX_VALUE; 789 } 790 long rp = 0L; 791 for (int i = 0; i < (pfac.nvar - 1); i++) { 792 rp = 0L; 793 GenPolynomialRing<C> nfac = pfac.contract(1); 794 String[] vn = new String[] { pfac.getVars()[pfac.nvar - 1] }; 795 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(nfac, 1, 796 pfac.tord, vn); 797 GenPolynomial<GenPolynomial<C>> upr = PolyUtil.<C> recursive(rfac, up); 798 //System.out.println("upr = " + upr); 799 GenPolynomial<C> ep; 800 do { 801 if (rp >= cr) { 802 throw new ArithmeticException("elements of prime field exhausted: " + cr); 803 } 804 C r = cf.fromInteger(rp); //cf.random(rp); 805 //System.out.println("r = " + r); 806 ep = PolyUtil.<C> evaluateMainRecursive(nfac, upr, r); 807 //System.out.println("ep = " + ep); 808 rp++; 809 } while (!isSquarefree(ep) /*todo: || ep.degree() <= 1*/); // max deg 810 up = ep; 811 pfac = nfac; 812 } 813 up = up.monic(); 814 if (debug) { 815 logger.info("P(" + rp + ") = " + up); 816 //System.out.println("up = " + up); 817 } 818 if (debug && !isSquarefree(up)) { 819 throw new ArithmeticException("not irreducible up = " + up); 820 } 821 if (up.degree(0) <= 1) { 822 return new Factors<C>(P); 823 } 824 // find irreducible factor of up 825 List<GenPolynomial<C>> UF = baseFactorsSquarefree(up); 826 //System.out.println("UF = " + UF); 827 FactorsList<C> aUF = baseFactorsAbsoluteSquarefree(up); 828 //System.out.println("aUF = " + aUF); 829 AlgebraicNumberRing<C> arfac = aUF.findExtensionField(); 830 //System.out.println("arfac = " + arfac); 831 832 long e = up.degree(0); 833 // search factor polynomial with smallest degree 834 for (int i = 0; i < UF.size(); i++) { 835 GenPolynomial<C> upi = UF.get(i); 836 long d = upi.degree(0); 837 if (1 <= d && d <= e) { 838 up = upi; 839 e = up.degree(0); 840 } 841 } 842 if (up.degree(0) <= 1) { 843 return new Factors<C>(P); 844 } 845 if (debug) { 846 logger.info("field extension by " + up); 847 } 848 849 List<GenPolynomial<AlgebraicNumber<C>>> afactors = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>(); 850 851 // setup field extension K(alpha) 852 //String[] vars = new String[] { "z_" + Math.abs(up.hashCode() % 1000) }; 853 String[] vars = pfac.newVars("z_"); 854 pfac = pfac.copy(); 855 //String[] ovars = 856 pfac.setVars(vars); // side effects! 857 //GenPolynomial<C> aup = pfac.copy(up); // hack to exchange the variables 858 //AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(aup,true); // since irreducible 859 AlgebraicNumberRing<C> afac = arfac; 860 int depth = afac.depth(); 861 //System.out.println("afac = " + afac); 862 GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, 863 P.ring.nvar, P.ring.tord, P.ring.getVars()); 864 //System.out.println("pafac = " + pafac); 865 // convert to K(alpha) 866 GenPolynomial<AlgebraicNumber<C>> Pa = PolyUtil 867 .<C> convertToRecAlgebraicCoefficients(depth, pafac, P); 868 //System.out.println("Pa = " + Pa); 869 // factor over K(alpha) 870 FactorAbstract<AlgebraicNumber<C>> engine = FactorFactory.<C> getImplementation(afac); 871 afactors = engine.factorsSquarefree(Pa); 872 if (debug) { 873 logger.info("K(alpha) factors multi = " + afactors); 874 //System.out.println("K(alpha) factors = " + afactors); 875 } 876 if (afactors.size() <= 1) { 877 return new Factors<C>(P); 878 } 879 // normalize first factor to monic 880 GenPolynomial<AlgebraicNumber<C>> p1 = afactors.get(0); 881 AlgebraicNumber<C> p1c = p1.leadingBaseCoefficient(); 882 if (!p1c.isONE()) { 883 GenPolynomial<AlgebraicNumber<C>> p2 = afactors.get(1); 884 afactors.remove(p1); 885 afactors.remove(p2); 886 p1 = p1.divide(p1c); 887 p2 = p2.multiply(p1c); 888 afactors.add(p1); 889 afactors.add(p2); 890 } 891 // recursion for splitting field 892 // find minimal field extension K(beta) \subset K(alpha) 893 return new Factors<C>(P, afac, Pa, afactors); 894 } 895 896 897 /** 898 * GenPolynomial is absolute factorization. 899 * @param facs factors container. 900 * @return true if P = prod_{i=1,...,r} p_i, else false. 901 */ 902 public boolean isAbsoluteFactorization(Factors<C> facs) { 903 if (facs == null) { 904 throw new IllegalArgumentException("facs may not be null"); 905 } 906 if (facs.afac == null) { 907 return true; 908 } 909 GenPolynomial<AlgebraicNumber<C>> fa = facs.apoly; 910 GenPolynomialRing<AlgebraicNumber<C>> pafac = fa.ring; 911 GenPolynomial<AlgebraicNumber<C>> t = pafac.getONE(); 912 for (GenPolynomial<AlgebraicNumber<C>> f : facs.afactors) { 913 t = t.multiply(f); 914 } 915 //return fa.equals(t) || fa.equals(t.negate()); 916 boolean b = fa.equals(t) || fa.equals(t.negate()); 917 if (b) { 918 return b; 919 } 920 if (facs.arfactors == null) { 921 return false; 922 } 923 for (Factors<AlgebraicNumber<C>> arp : facs.arfactors) { 924 t = t.multiply(arp.poly); 925 } 926 b = fa.equals(t) || fa.equals(t.negate()); 927 if (!b) { 928 System.out.println("\nFactors: " + facs); 929 System.out.println("fa = " + fa); 930 System.out.println("t = " + t); 931 } 932 return b; 933 } 934 935 936 /** 937 * GenPolynomial is absolute factorization. 938 * @param facs factors list container. 939 * @return true if P = prod_{i=1,...,r} p_i, else false. 940 */ 941 public boolean isAbsoluteFactorization(FactorsList<C> facs) { 942 if (facs == null) { 943 throw new IllegalArgumentException("facs may not be null"); 944 } 945 GenPolynomial<C> P = facs.poly; 946 GenPolynomial<C> t = P.ring.getONE(); 947 for (GenPolynomial<C> f : facs.factors) { 948 t = t.multiply(f); 949 } 950 if (P.equals(t) || P.equals(t.negate())) { 951 return true; 952 } 953 if (facs.afactors == null) { 954 return false; 955 } 956 for (Factors<C> fs : facs.afactors) { 957 if (!isAbsoluteFactorization(fs)) { 958 return false; 959 } 960 t = t.multiply(facs.poly); 961 } 962 //return P.equals(t) || P.equals(t.negate()); 963 boolean b = P.equals(t) || P.equals(t.negate()); 964 if (!b) { 965 System.out.println("\nFactorsList: " + facs); 966 System.out.println("P = " + P); 967 System.out.println("t = " + t); 968 } 969 return b; 970 } 971 972 973 /** 974 * GenPolynomial is absolute factorization. 975 * @param facs factors map container. 976 * @return true if P = prod_{i=1,...,k} p_i**e_i , else false. 977 */ 978 public boolean isAbsoluteFactorization(FactorsMap<C> facs) { 979 if (facs == null) { 980 throw new IllegalArgumentException("facs may not be null"); 981 } 982 GenPolynomial<C> P = facs.poly; 983 GenPolynomial<C> t = P.ring.getONE(); 984 for (Map.Entry<GenPolynomial<C>, Long> me : facs.factors.entrySet()) { 985 GenPolynomial<C> f = me.getKey(); 986 long e = me.getValue(); //facs.factors.get(f); 987 GenPolynomial<C> g = Power.<GenPolynomial<C>> positivePower(f, e); 988 t = t.multiply(g); 989 } 990 if (P.equals(t) || P.equals(t.negate())) { 991 return true; 992 } 993 if (facs.afactors == null) { 994 return false; 995 } 996 for (Map.Entry<Factors<C>, Long> me : facs.afactors.entrySet()) { 997 Factors<C> fs = me.getKey(); 998 if (!isAbsoluteFactorization(fs)) { 999 return false; 1000 } 1001 long e = me.getValue(); // facs.afactors.get(fs); 1002 GenPolynomial<C> g = Power.<GenPolynomial<C>> positivePower(fs.poly, e); 1003 t = t.multiply(g); 1004 } 1005 boolean b = P.equals(t) || P.equals(t.negate()); 1006 if (!b) { 1007 System.out.println("\nFactorsMap: " + facs); 1008 System.out.println("P = " + P); 1009 System.out.println("t = " + t); 1010 } 1011 return b; 1012 } 1013 1014}