[Home] DMelt member access. Java source code: edu.jas.ufd.FactorAbsolute
/*
* $Id$
*/
package edu.jas.ufd;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.log4j.Logger;
import edu.jas.poly.AlgebraicNumber;
import edu.jas.poly.AlgebraicNumberRing;
import edu.jas.poly.GenPolynomial;
import edu.jas.poly.GenPolynomialRing;
import edu.jas.poly.PolyUtil;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.Power;
import edu.jas.structure.RingFactory;
/**
* Absolute factorization algorithms class. This class contains implementations
* of methods for factorization over algebraically closed fields. The required
* field extension is computed along with the factors. The methods have been
* tested for prime fields of characteristic zero, that is for
* BigRational. It might eventually also be used for prime
* fields of non-zero characteristic, that is with ModInteger.
* The field extension may yet not be minimal.
* @author Heinz Kredel
* @param coefficient type
*/
public abstract class FactorAbsolute> extends FactorAbstract {
private static final Logger logger = Logger.getLogger(FactorAbsolute.class);
private final boolean debug = logger.isDebugEnabled();
/*
* Factorization engine for algebraic number coefficients.
*/
//not possible here because of recursion AN -> Int|Mod -> AN -> ...
//public final FactorAbstract> aengine;
/**
* No argument constructor. Note: can't use this constructor.
*/
protected FactorAbsolute() {
throw new IllegalArgumentException("don't use this constructor");
}
/**
* Constructor.
* @param cfac coefficient ring factory.
*/
public FactorAbsolute(RingFactory cfac) {
super(cfac);
//GenPolynomialRing fac = new GenPolynomialRing(cfac,1);
//GenPolynomial p = fac.univariate(0);
//AlgebraicNumberRing afac = new AlgebraicNumberRing(p);
//aengine = null; //FactorFactory.getImplementation(afac); // hack
}
/**
* Get the String representation.
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getClass().getName();
}
/**
* GenPolynomial test if is absolute irreducible.
* @param P GenPolynomial.
* @return true if P is absolute irreducible, else false.
*/
public boolean isAbsoluteIrreducible(GenPolynomial P) {
if (!isIrreducible(P)) {
return false;
}
Factors F = factorsAbsoluteIrreducible(P);
if (F.afac == null) {
return true;
} else if (F.afactors.size() > 2) {
return false;
} else { //F.size() == 2
boolean cnst = false;
for (GenPolynomial> p : F.afactors) {
if (p.isConstant()) {
cnst = true;
}
}
return cnst;
}
}
/**
* GenPolynomial absolute base factorization of a polynomial.
* @param P univariate GenPolynomial.
* @return factors map container: [p_1 -> e_1, ..., p_k -> e_k] with P =
* prod_{i=1,...,k} p_i**e_i. Note: K(alpha) not yet
* minimal.
*/
// @Override
public FactorsMap baseFactorsAbsolute(GenPolynomial P) {
if (P == null) {
throw new IllegalArgumentException(this.getClass().getName() + " P == null");
}
SortedMap, Long> factors = new TreeMap, Long>();
if (P.isZERO()) {
return new FactorsMap(P, factors);
}
//System.out.println("\nP_base = " + P);
GenPolynomialRing pfac = P.ring; // K[x]
if (pfac.nvar > 1) {
//System.out.println("\nfacs_base: univ");
throw new IllegalArgumentException("only for univariate polynomials");
}
if (!pfac.coFac.isField()) {
//System.out.println("\nfacs_base: field");
throw new IllegalArgumentException("only for field coefficients");
}
if (P.degree(0) <= 1) {
factors.put(P, 1L);
return new FactorsMap(P, factors);
}
// factor over K (=C)
SortedMap, Long> facs = baseFactors(P);
if (debug && !isFactorization(P, facs)) {
System.out.println("facs = " + facs);
throw new ArithmeticException("isFactorization = false");
}
if (logger.isInfoEnabled()) {
logger.info("all K factors = " + facs); // Q[X]
//System.out.println("\nall K factors = " + facs); // Q[X]
}
// factor over some K(alpha)
SortedMap, Long> afactors = new TreeMap, Long>();
for ( Map.Entry,Long> me : facs.entrySet()) {
GenPolynomial p = me.getKey();
Long e = me.getValue(); //facs.get(p);
if (p.degree(0) <= 1) {
factors.put(p, e);
} else {
Factors afacs = baseFactorsAbsoluteIrreducible(p);
//System.out.println("afacs = " + afacs);
afactors.put(afacs, e);
}
}
//System.out.println("K(alpha) factors = " + factors);
return new FactorsMap(P, factors, afactors);
}
/**
* GenPolynomial absolute base factorization of a squarefree polynomial.
* @param P squarefree and primitive univariate GenPolynomial.
* @return factors list container: [p_1,...,p_k] with P = prod_{i=1, ..., k}
* p_i. Note: K(alpha) not yet minimal.
*/
// @Override
public FactorsList baseFactorsAbsoluteSquarefree(GenPolynomial P) {
if (P == null) {
throw new IllegalArgumentException(this.getClass().getName() + " P == null");
}
List> factors = new ArrayList>();
if (P.isZERO()) {
return new FactorsList(P, factors);
}
//System.out.println("\nP_base_sqf = " + P);
GenPolynomialRing pfac = P.ring; // K[x]
if (pfac.nvar > 1) {
//System.out.println("facs_base_sqf: univ");
throw new IllegalArgumentException("only for univariate polynomials");
}
if (!pfac.coFac.isField()) {
//System.out.println("facs_base_sqf: field");
throw new IllegalArgumentException("only for field coefficients");
}
if (P.degree(0) <= 1) {
factors.add(P);
return new FactorsList(P, factors);
}
// factor over K (=C)
List> facs = baseFactorsSquarefree(P);
//System.out.println("facs_base_irred = " + facs);
if (debug && !isFactorization(P, facs)) {
throw new ArithmeticException("isFactorization = false");
}
if (logger.isInfoEnabled()) {
logger.info("all K factors = " + facs); // Q[X]
//System.out.println("\nall K factors = " + facs); // Q[X]
}
// factor over K(alpha)
List> afactors = new ArrayList>();
for (GenPolynomial p : facs) {
//System.out.println("facs_base_sqf_p = " + p);
if (p.degree(0) <= 1) {
factors.add(p);
} else {
Factors afacs = baseFactorsAbsoluteIrreducible(p);
//System.out.println("afacs_base_sqf = " + afacs);
if (logger.isInfoEnabled()) {
logger.info("K(alpha) factors = " + afacs); // K(alpha)[X]
}
afactors.add(afacs);
}
}
//System.out.println("K(alpha) factors = " + factors);
return new FactorsList(P, factors, afactors);
}
/**
* GenPolynomial base absolute factorization of a irreducible polynomial.
* @param P irreducible! univariate GenPolynomial.
* @return factors container: [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i
* in K(alpha)[x] for suitable alpha and p_i irreducible over L[x],
* where K \subset K(alpha) \subset L is an algebraically closed
* field over K. Note: K(alpha) not yet minimal.
*/
public Factors baseFactorsAbsoluteIrreducible(GenPolynomial P) {
if (P == null) {
throw new IllegalArgumentException(this.getClass().getName() + " P == null");
}
if (P.isZERO()) {
return new Factors(P);
}
//System.out.println("\nP_base_irred = " + P);
GenPolynomialRing pfac = P.ring; // K[x]
if (pfac.nvar > 1) {
//System.out.println("facs_base_irred: univ");
throw new IllegalArgumentException("only for univariate polynomials");
}
if (!pfac.coFac.isField()) {
//System.out.println("facs_base_irred: field");
throw new IllegalArgumentException("only for field coefficients");
}
if (P.degree(0) <= 1) {
return new Factors(P);
}
// setup field extension K(alpha) where alpha = z_xx
//String[] vars = new String[] { "z_" + Math.abs(P.hashCode() % 1000) };
String[] vars = pfac.newVars( "z_" );
pfac = pfac.copy();
vars = pfac.setVars(vars);
GenPolynomial aP = pfac.copy(P); // hack to exchange the variables
AlgebraicNumberRing afac = new AlgebraicNumberRing(aP, true); // since irreducible
if (logger.isInfoEnabled()) {
logger.info("K(alpha) = " + afac);
logger.info("K(alpha) = " + afac.toScript());
//System.out.println("K(alpha) = " + afac);
}
GenPolynomialRing> pafac = new GenPolynomialRing>(afac,
aP.ring.nvar, aP.ring.tord, /*old*/vars);
// convert to K(alpha)
GenPolynomial> Pa = PolyUtil. convertToAlgebraicCoefficients(pafac, P);
if (logger.isInfoEnabled()) {
logger.info("P over K(alpha) = " + Pa);
//logger.info("P over K(alpha) = " + Pa.toScript());
//System.out.println("P in K(alpha) = " + Pa);
}
// factor over K(alpha)
FactorAbstract> engine = FactorFactory. getImplementation(afac);
//System.out.println("K(alpha) engine = " + engine);
List>> factors = engine.baseFactorsSquarefree(Pa);
//System.out.println("factors = " + factors);
if (logger.isInfoEnabled()) {
logger.info("factors over K(alpha) = " + factors);
//System.out.println("factors over K(alpha) = " + factors);
}
List>> faca = new ArrayList>>(
factors.size());
List>> facar = new ArrayList>>();
for (GenPolynomial> fi : factors) {
if (fi.degree(0) <= 1) {
faca.add(fi);
} else {
//System.out.println("fi.deg > 1 = " + fi);
FactorAbsolute> aengine = (FactorAbsolute>) FactorFactory
. getImplementation(afac);
Factors> fif = aengine.baseFactorsAbsoluteIrreducible(fi);
//System.out.println("fif = " + fif);
facar.add(fif);
}
}
if (facar.size() == 0) {
facar = null;
}
// find minimal field extension K(beta) \subset K(alpha)
return new Factors(P, afac, Pa, faca, facar);
}
/**
* Univariate GenPolynomial algebraic partial fraction decomposition,
* Absolute factorization or Rothstein-Trager algorithm.
* @param A univariate GenPolynomial, deg(A) < deg(P).
* @param P univariate squarefree GenPolynomial, gcd(A,P) == 1.
* @return partial fraction container.
*/
public PartialFraction baseAlgebraicPartialFraction(GenPolynomial A, GenPolynomial P) {
if (P == null || P.isZERO() ) {
throw new IllegalArgumentException(" P == null or P == 0");
}
if (A == null || A.isZERO() ) {
throw new IllegalArgumentException(" A == null or A == 0");
// PartialFraction(A,P,al,pl,empty,empty)
}
//System.out.println("\nP_base_algeb_part = " + P);
GenPolynomialRing pfac = P.ring; // K[x]
if (pfac.nvar > 1) {
//System.out.println("facs_base_irred: univ");
throw new IllegalArgumentException("only for univariate polynomials");
}
if (!pfac.coFac.isField()) {
//System.out.println("facs_base_irred: field");
throw new IllegalArgumentException("only for field coefficients");
}
List cfactors = new ArrayList();
List> cdenom = new ArrayList>();
List> afactors = new ArrayList>();
List>> adenom = new ArrayList>>();
// P linear
if (P.degree(0) <= 1) {
cfactors.add(A.leadingBaseCoefficient());
cdenom.add(P);
return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom);
}
List> Pfac = baseFactorsSquarefree(P);
//System.out.println("\nPfac = " + Pfac);
List> Afac = engine.basePartialFraction(A,Pfac);
GenPolynomial A0 = Afac.remove(0);
if ( !A0.isZERO() ) {
throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)");
}
// algebraic and linear factors
int i = 0;
for ( GenPolynomial pi : Pfac ) {
GenPolynomial ai = Afac.get(i++);
if ( pi.degree(0) <= 1 ) {
cfactors.add( ai.leadingBaseCoefficient() );
cdenom.add(pi);
continue;
}
PartialFraction pf = baseAlgebraicPartialFractionIrreducibleAbsolute(ai,pi);
//PartialFraction pf = baseAlgebraicPartialFractionIrreducible(ai,pi);
cfactors.addAll( pf.cfactors );
cdenom.addAll( pf.cdenom );
afactors.addAll( pf.afactors );
adenom.addAll( pf.adenom );
}
return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom);
}
/**
* Univariate GenPolynomial algebraic partial fraction decomposition,
* Rothstein-Trager algorithm.
* @param A univariate GenPolynomial, deg(A) < deg(P).
* @param P univariate squarefree GenPolynomial, gcd(A,P) == 1.
* @return partial fraction container.
*/
@Deprecated
public PartialFraction baseAlgebraicPartialFractionIrreducible(GenPolynomial A, GenPolynomial P) {
if (P == null || P.isZERO() ) {
throw new IllegalArgumentException(" P == null or P == 0");
}
//System.out.println("\nP_base_algeb_part = " + P);
GenPolynomialRing pfac = P.ring; // K[x]
if (pfac.nvar > 1) {
//System.out.println("facs_base_irred: univ");
throw new IllegalArgumentException("only for univariate polynomials");
}
if (!pfac.coFac.isField()) {
//System.out.println("facs_base_irred: field");
throw new IllegalArgumentException("only for field coefficients");
}
List cfactors = new ArrayList();
List> cdenom = new ArrayList>();
List> afactors = new ArrayList>();
List>> adenom = new ArrayList>>();
// P linear
if (P.degree(0) <= 1) {
cfactors.add(A.leadingBaseCoefficient());
cdenom.add(P);
return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom);
}
// deriviative
GenPolynomial Pp = PolyUtil. baseDeriviative(P);
//no: Pp = Pp.monic();
//System.out.println("\nP = " + P);
//System.out.println("Pp = " + Pp);
// Q[t]
String[] vars = new String[] { "t" };
GenPolynomialRing cfac = new GenPolynomialRing(pfac.coFac, 1, pfac.tord, vars);
GenPolynomial t = cfac.univariate(0);
//System.out.println("t = " + t);
// Q[x][t]
GenPolynomialRing> rfac = new GenPolynomialRing>(pfac, cfac); // sic
//System.out.println("rfac = " + rfac.toScript());
// transform polynomials to bi-variate polynomial
GenPolynomial> Ac = PolyUfdUtil. introduceLowerVariable(rfac, A);
//System.out.println("Ac = " + Ac);
GenPolynomial> Pc = PolyUfdUtil. introduceLowerVariable(rfac, P);
//System.out.println("Pc = " + Pc);
GenPolynomial> Pcp = PolyUfdUtil. introduceLowerVariable(rfac, Pp);
//System.out.println("Pcp = " + Pcp);
// Q[t][x]
GenPolynomialRing> rfac1 = Pc.ring;
//System.out.println("rfac1 = " + rfac1.toScript());
// A - t P'
GenPolynomial> tc = rfac1.getONE().multiply(t);
//System.out.println("tc = " + tc);
GenPolynomial> At = Ac.subtract( tc.multiply(Pcp) );
//System.out.println("At = " + At);
GreatestCommonDivisorSubres engine = new GreatestCommonDivisorSubres();
// = GCDFactory.getImplementation( cfac.coFac );
GreatestCommonDivisorAbstract> aengine = null;
GenPolynomial> Rc = engine.recursiveUnivariateResultant(Pc, At);
//System.out.println("Rc = " + Rc);
GenPolynomial res = Rc.leadingBaseCoefficient();
//no: res = res.monic();
//System.out.println("\nres = " + res);
SortedMap,Long> resfac = baseFactors(res);
//System.out.println("resfac = " + resfac + "\n");
for ( GenPolynomial r : resfac.keySet() ) {
//System.out.println("\nr(t) = " + r);
if ( r.isConstant() ) {
continue;
}
// if ( r.degree(0) <= 1L ) {
// System.out.println("warning linear factor in resultant ignored");
// continue;
// //throw new ArithmeticException("input not irreducible");
// }
//vars = new String[] { "z_" + Math.abs(r.hashCode() % 1000) };
vars = pfac.newVars( "z_" );
pfac = pfac.copy();
//String[] ovars =
pfac.setVars(vars);
r = pfac.copy(r); // hack to exchange the variables
//System.out.println("r(z_) = " + r);
AlgebraicNumberRing afac = new AlgebraicNumberRing(r, true); // since irreducible
logger.debug("afac = " + afac.toScript());
AlgebraicNumber a = afac.getGenerator();
//no: a = a.negate();
//System.out.println("a = " + a);
// K(alpha)[x]
GenPolynomialRing> pafac
= new GenPolynomialRing>(afac, Pc.ring);
//System.out.println("pafac = " + pafac.toScript());
// convert to K(alpha)[x]
GenPolynomial> Pa = PolyUtil. convertToAlgebraicCoefficients(pafac, P);
//System.out.println("Pa = " + Pa);
GenPolynomial> Pap = PolyUtil. convertToAlgebraicCoefficients(pafac, Pp);
//System.out.println("Pap = " + Pap);
GenPolynomial> Aa = PolyUtil. convertToAlgebraicCoefficients(pafac, A);
//System.out.println("Aa = " + Aa);
// A - a P'
GenPolynomial> Ap = Aa.subtract( Pap.multiply(a) );
//System.out.println("Ap = " + Ap);
if ( aengine == null ) {
aengine = GCDFactory.>getImplementation( afac );
//System.out.println("aengine = " + aengine);
}
GenPolynomial> Ga = aengine.baseGcd(Pa,Ap);
//System.out.println("Ga = " + Ga);
if ( Ga.isConstant() ) {
//System.out.println("warning constant gcd ignored");
continue;
}
afactors.add( a );
adenom.add( Ga );
// quadratic case
if ( P.degree(0) == 2 && Ga.degree(0) == 1 ) {
GenPolynomial>[] qra = PolyUtil.> basePseudoQuotientRemainder(Pa,Ga);
GenPolynomial> Qa = qra[0];
if ( !qra[1].isZERO() ) {
throw new ArithmeticException("remainder not zero");
}
//System.out.println("Qa = " + Qa);
afactors.add( a.negate() );
adenom.add( Qa );
}
if ( false && P.degree(0) == 3 && Ga.degree(0) == 1 ) {
GenPolynomial>[] qra = PolyUtil.> basePseudoQuotientRemainder(Pa,Ga);
GenPolynomial> Qa = qra[0];
if ( !qra[1].isZERO() ) {
throw new ArithmeticException("remainder not zero");
}
System.out.println("Qa3 = " + Qa);
//afactors.add( a.negate() );
//adenom.add( Qa );
}
}
return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom);
}
/**
* Univariate GenPolynomial algebraic partial fraction decomposition,
* via absolute factorization to linear factors.
* @param A univariate GenPolynomial, deg(A) < deg(P).
* @param P univariate squarefree GenPolynomial, gcd(A,P) == 1.
* @return partial fraction container.
*/
@SuppressWarnings("unchecked")
public PartialFraction baseAlgebraicPartialFractionIrreducibleAbsolute(GenPolynomial A, GenPolynomial P) {
if (P == null || P.isZERO() ) {
throw new IllegalArgumentException(" P == null or P == 0");
}
//System.out.println("\nP_base_algeb_part = " + P);
GenPolynomialRing pfac = P.ring; // K[x]
if (pfac.nvar > 1) {
//System.out.println("facs_base_irred: univ");
throw new IllegalArgumentException("only for univariate polynomials");
}
if (!pfac.coFac.isField()) {
//System.out.println("facs_base_irred: field");
throw new IllegalArgumentException("only for field coefficients");
}
List cfactors = new ArrayList();
List> cdenom = new ArrayList>();
List> afactors = new ArrayList>();
List>> adenom = new ArrayList>>();
// P linear
if (P.degree(0) <= 1) {
cfactors.add(A.leadingBaseCoefficient());
cdenom.add(P);
return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom);
}
// non linear case
Factors afacs = factorsAbsoluteIrreducible(P);
//System.out.println("linear algebraic factors = " + afacs);
//System.out.println("afactors = " + afacs.afactors);
//System.out.println("arfactors = " + afacs.arfactors);
//System.out.println("arfactors pol = " + afacs.arfactors.get(0).poly);
//System.out.println("arfactors2 = " + afacs.arfactors.get(0).afactors);
List>> fact = afacs.getFactors();
//System.out.println("factors = " + fact);
GenPolynomial> Pa = afacs.apoly;
GenPolynomial> Aa = PolyUtil
. convertToRecAlgebraicCoefficients(1, Pa.ring, A);
GreatestCommonDivisorAbstract> aengine = GCDFactory.getProxy(afacs.afac);
//System.out.println("denom = " + Pa);
//System.out.println("numer = " + Aa);
List>> numers = aengine.basePartialFraction(Aa,fact);
//System.out.println("part frac = " + numers);
GenPolynomial> A0 = numers.remove(0);
if ( ! A0.isZERO() ) {
throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)");
}
int i = 0;
for ( GenPolynomial> fa : fact ) {
GenPolynomial> an = numers.get(i++);
if ( fa.degree(0) <= 1 ) {
afactors.add(an.leadingBaseCoefficient());
adenom.add( fa );
continue;
}
System.out.println("fa = " + fa);
Factors> faf = afacs.getFactor(fa);
System.out.println("faf = " + faf);
List>>> fafact = faf.getFactors();
GenPolynomial>> Aaa = PolyUtil
.> convertToRecAlgebraicCoefficients(1, faf.apoly.ring, an);
GreatestCommonDivisorAbstract>> aaengine = GCDFactory.getImplementation(faf.afac);
List>>> anumers = aaengine.basePartialFraction(Aaa,fafact);
System.out.println("algeb part frac = " + anumers);
GenPolynomial>> A0a = anumers.remove(0);
if ( ! A0a.isZERO() ) {
throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)");
}
int k = 0;
for ( GenPolynomial>> faa : fafact ) {
GenPolynomial>> ana = anumers.get(k++);
System.out.println("faa = " + faa);
System.out.println("ana = " + ana);
if ( faa.degree(0) > 1 ) {
throw new ArithmeticException(" faa not linear");
}
GenPolynomial> ana1 = (GenPolynomial>)(GenPolynomial)ana;
GenPolynomial> faa1 = (GenPolynomial>)(GenPolynomial)faa;
afactors.add(ana1.leadingBaseCoefficient());
adenom.add( faa1 );
}
}
return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom);
}
/**
* GenPolynomial absolute factorization of a polynomial.
* @param P GenPolynomial.
* @return factors map container: [p_1 -> e_1, ..., p_k -> e_k] with P =
* prod_{i=1,...,k} p_i**e_i. Note: K(alpha) not yet
* minimal.
*/
public FactorsMap factorsAbsolute(GenPolynomial P) {
if (P == null) {
throw new IllegalArgumentException(this.getClass().getName() + " P == null");
}
SortedMap, Long> factors = new TreeMap, Long>();
if (P.isZERO()) {
return new FactorsMap(P, factors);
}
//System.out.println("\nP_mult = " + P);
GenPolynomialRing pfac = P.ring; // K[x]
if (pfac.nvar <= 1) {
return baseFactorsAbsolute(P);
}
if (!pfac.coFac.isField()) {
throw new IllegalArgumentException("only for field coefficients");
}
if (P.degree() <= 1) {
factors.put(P, 1L);
return new FactorsMap(P, factors);
}
// factor over K (=C)
SortedMap, Long> facs = factors(P);
if (debug && !isFactorization(P, facs)) {
throw new ArithmeticException("isFactorization = false");
}
if (logger.isInfoEnabled()) {
logger.info("all K factors = " + facs); // Q[X]
//System.out.println("\nall K factors = " + facs); // Q[X]
}
SortedMap, Long> afactors = new TreeMap, Long>();
// factor over K(alpha)
for ( Map.Entry, Long> me : facs.entrySet()) {
GenPolynomial p = me.getKey();
Long e = me.getValue(); //facs.get(p);
if (p.degree() <= 1) {
factors.put(p, e);
} else {
Factors afacs = factorsAbsoluteIrreducible(p);
if (afacs.afac == null) { // absolute irreducible
factors.put(p, e);
} else {
afactors.put(afacs, e);
}
}
}
//System.out.println("K(alpha) factors multi = " + factors);
return new FactorsMap(P, factors, afactors);
}
/**
* GenPolynomial absolute factorization of a squarefree polynomial.
* @param P squarefree and primitive GenPolynomial.
* @return factors list container: [p_1,...,p_k] with P = prod_{i=1, ..., k}
* p_i. Note: K(alpha) not yet minimal.
*/
// @Override
public FactorsList factorsAbsoluteSquarefree(GenPolynomial P) {
if (P == null) {
throw new IllegalArgumentException(this.getClass().getName() + " P == null");
}
List> factors = new ArrayList>();
if (P.isZERO()) {
return new FactorsList(P, factors);
}
//System.out.println("\nP = " + P);
GenPolynomialRing pfac = P.ring; // K[x]
if (pfac.nvar <= 1) {
return baseFactorsAbsoluteSquarefree(P);
}
if (!pfac.coFac.isField()) {
throw new IllegalArgumentException("only for field coefficients");
}
if (P.degree() <= 1) {
factors.add(P);
return new FactorsList(P, factors);
}
// factor over K (=C)
List> facs = factorsSquarefree(P);
if (debug && !isFactorization(P, facs)) {
throw new ArithmeticException("isFactorization = false");
}
if (logger.isInfoEnabled()) {
logger.info("all K factors = " + facs); // Q[X]
//System.out.println("\nall K factors = " + facs); // Q[X]
}
List> afactors = new ArrayList>();
// factor over K(alpha)
for (GenPolynomial p : facs) {
if (p.degree() <= 1) {
factors.add(p);
} else {
Factors afacs = factorsAbsoluteIrreducible(p);
if (debug) {
logger.info("K(alpha) factors = " + afacs); // K(alpha)[X]
}
if (afacs.afac == null) { // absolute irreducible
factors.add(p);
} else {
afactors.add(afacs);
}
}
}
//System.out.println("K(alpha) factors = " + factors);
return new FactorsList(P, factors, afactors);
}
/**
* GenPolynomial absolute factorization of a irreducible polynomial.
* @param P irreducible! GenPolynomial.
* @return factors container: [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i
* in K(alpha)[x] for suitable alpha and p_i irreducible over L[x],
* where K \subset K(alpha) \subset L is an algebraically closed
* field over K. Note: K(alpha) not yet minimal.
*/
public Factors factorsAbsoluteIrreducible(GenPolynomial P) {
if (P == null) {
throw new IllegalArgumentException(this.getClass().getName() + " P == null");
}
if (P.isZERO()) {
return new Factors(P);
}
GenPolynomialRing pfac = P.ring; // K[x]
if (pfac.nvar <= 1) {
return baseFactorsAbsoluteIrreducible(P);
}
if (!pfac.coFac.isField()) {
throw new IllegalArgumentException("only for field coefficients");
}
//List> factors = new ArrayList>();
if (P.degree() <= 1) {
return new Factors(P);
}
// find field extension K(alpha)
GenPolynomial up = P;
RingFactory cf = pfac.coFac;
long cr = cf.characteristic().longValue(); // char might be larger
if (cr == 0L) {
cr = Long.MAX_VALUE;
}
long rp = 0L;
for (int i = 0; i < (pfac.nvar - 1); i++) {
rp = 0L;
GenPolynomialRing nfac = pfac.contract(1);
String[] vn = new String[] { pfac.getVars()[pfac.nvar - 1] };
GenPolynomialRing> rfac = new GenPolynomialRing>(nfac, 1,
pfac.tord, vn);
GenPolynomial> upr = PolyUtil. recursive(rfac, up);
//System.out.println("upr = " + upr);
GenPolynomial ep;
do {
if (rp >= cr) {
throw new ArithmeticException("elements of prime field exhausted: " + cr);
}
C r = cf.fromInteger(rp); //cf.random(rp);
//System.out.println("r = " + r);
ep = PolyUtil. evaluateMainRecursive(nfac, upr, r);
//System.out.println("ep = " + ep);
rp++;
} while (!isSquarefree(ep) /*todo: || ep.degree() <= 1*/); // max deg
up = ep;
pfac = nfac;
}
up = up.monic();
if (debug) {
logger.info("P(" + rp + ") = " + up);
//System.out.println("up = " + up);
}
if (debug && !isSquarefree(up)) {
throw new ArithmeticException("not irreducible up = " + up);
}
if (up.degree(0) <= 1) {
return new Factors(P);
}
// find irreducible factor of up
List> UF = baseFactorsSquarefree(up);
//System.out.println("UF = " + UF);
FactorsList aUF = baseFactorsAbsoluteSquarefree(up);
//System.out.println("aUF = " + aUF);
AlgebraicNumberRing arfac = aUF.findExtensionField();
//System.out.println("arfac = " + arfac);
long e = up.degree(0);
// search factor polynomial with smallest degree
for (int i = 0; i < UF.size(); i++) {
GenPolynomial upi = UF.get(i);
long d = upi.degree(0);
if (1 <= d && d <= e) {
up = upi;
e = up.degree(0);
}
}
if (up.degree(0) <= 1) {
return new Factors(P);
}
if (debug) {
logger.info("field extension by " + up);
}
List>> afactors = new ArrayList>>();
// setup field extension K(alpha)
//String[] vars = new String[] { "z_" + Math.abs(up.hashCode() % 1000) };
String[] vars = pfac.newVars( "z_" );
pfac = pfac.copy();
//String[] ovars =
pfac.setVars(vars); // side effects!
//GenPolynomial aup = pfac.copy(up); // hack to exchange the variables
//AlgebraicNumberRing afac = new AlgebraicNumberRing(aup,true); // since irreducible
AlgebraicNumberRing afac = arfac;
int depth = afac.depth();
//System.out.println("afac = " + afac);
GenPolynomialRing> pafac = new GenPolynomialRing>(afac,
P.ring.nvar, P.ring.tord, P.ring.getVars());
//System.out.println("pafac = " + pafac);
// convert to K(alpha)
GenPolynomial> Pa = PolyUtil
. convertToRecAlgebraicCoefficients(depth, pafac, P);
//System.out.println("Pa = " + Pa);
// factor over K(alpha)
FactorAbstract> engine = FactorFactory. getImplementation(afac);
afactors = engine.factorsSquarefree(Pa);
if (debug) {
logger.info("K(alpha) factors multi = " + afactors);
//System.out.println("K(alpha) factors = " + afactors);
}
if (afactors.size() <= 1) {
return new Factors(P);
}
// normalize first factor to monic
GenPolynomial> p1 = afactors.get(0);
AlgebraicNumber p1c = p1.leadingBaseCoefficient();
if (!p1c.isONE()) {
GenPolynomial> p2 = afactors.get(1);
afactors.remove(p1);
afactors.remove(p2);
p1 = p1.divide(p1c);
p2 = p2.multiply(p1c);
afactors.add(p1);
afactors.add(p2);
}
// recursion for splitting field
// find minimal field extension K(beta) \subset K(alpha)
return new Factors(P, afac, Pa, afactors);
}
/**
* GenPolynomial is absolute factorization.
* @param facs factors container.
* @return true if P = prod_{i=1,...,r} p_i, else false.
*/
public boolean isAbsoluteFactorization(Factors facs) {
if (facs == null) {
throw new IllegalArgumentException("facs may not be null");
}
if (facs.afac == null) {
return true;
}
GenPolynomial> fa = facs.apoly;
GenPolynomialRing> pafac = fa.ring;
GenPolynomial> t = pafac.getONE();
for (GenPolynomial