001/* 002 * $Id: FactorAlgebraic.java 5871 2018-07-20 15:58:45Z kredel $ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.List; 010 011import org.apache.logging.log4j.Logger; 012import org.apache.logging.log4j.LogManager; 013 014import edu.jas.poly.AlgebraicNumber; 015import edu.jas.poly.AlgebraicNumberRing; 016import edu.jas.poly.GenPolynomial; 017import edu.jas.poly.GenPolynomialRing; 018import edu.jas.poly.PolyUtil; 019import edu.jas.poly.TermOrder; 020import edu.jas.structure.GcdRingElem; 021 022 023/** 024 * Algebraic number coefficients factorization algorithms. This class implements 025 * factorization methods for polynomials over algebraic numbers over rational 026 * numbers or over (prime) modular integers. 027 * @author Heinz Kredel 028 * @param <C> coefficient type 029 */ 030 031public class FactorAlgebraic<C extends GcdRingElem<C>> extends FactorAbsolute<AlgebraicNumber<C>> { 032 033 034 private static final Logger logger = LogManager.getLogger(FactorAlgebraic.class); 035 036 037 private static final boolean debug = logger.isDebugEnabled(); 038 039 040 /** 041 * Factorization engine for base coefficients. 042 */ 043 public final FactorAbstract<C> factorCoeff; 044 045 046 /** 047 * No argument constructor. <b>Note:</b> can't use this constructor. 048 */ 049 protected FactorAlgebraic() { 050 throw new IllegalArgumentException("don't use this constructor"); 051 } 052 053 054 /** 055 * Constructor. 056 * @param fac algebraic number factory. 057 */ 058 public FactorAlgebraic(AlgebraicNumberRing<C> fac) { 059 this(fac, FactorFactory.<C> getImplementation(fac.ring.coFac) ); 060 } 061 062 063 /** 064 * Constructor. 065 * @param fac algebraic number factory. 066 * @param factorCoeff factorization engine for polynomials over base coefficients. 067 */ 068 public FactorAlgebraic(AlgebraicNumberRing<C> fac, FactorAbstract<C> factorCoeff) { 069 super(fac); 070 this.factorCoeff = factorCoeff; 071 } 072 073 074 /** 075 * GenPolynomial base factorization of a squarefree polynomial. 076 * @param P squarefree GenPolynomial<AlgebraicNumber<C>>. 077 * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. 078 */ 079 @Override 080 public List<GenPolynomial<AlgebraicNumber<C>>> baseFactorsSquarefree(GenPolynomial<AlgebraicNumber<C>> P) { 081 if (P == null) { 082 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 083 } 084 List<GenPolynomial<AlgebraicNumber<C>>> factors = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>(); 085 if (P.isZERO()) { 086 return factors; 087 } 088 if (P.isONE()) { 089 factors.add(P); 090 return factors; 091 } 092 GenPolynomialRing<AlgebraicNumber<C>> pfac = P.ring; // Q(alpha)[x] 093 if (pfac.nvar > 1) { 094 throw new IllegalArgumentException("only for univariate polynomials"); 095 } 096 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac; 097 AlgebraicNumber<C> ldcf = P.leadingBaseCoefficient(); 098 if (!ldcf.isONE()) { 099 P = P.monic(); 100 factors.add(pfac.getONE().multiply(ldcf)); 101 } 102 //System.out.println("\nP = " + P); 103 if (debug) { 104 Squarefree<AlgebraicNumber<C>> sqengine = SquarefreeFactory.<AlgebraicNumber<C>> getImplementation(afac); 105 if ( !sqengine.isSquarefree(P) ) { 106 throw new RuntimeException("P not squarefree: " + sqengine.squarefreeFactors(P)); 107 } 108 GenPolynomial<C> modu = afac.modul; 109 if ( !factorCoeff.isIrreducible(modu) ) { 110 throw new RuntimeException("modul not irreducible: " + factorCoeff.factors(modu)); 111 } 112 System.out.println("P squarefree and modul irreducible"); 113 //GreatestCommonDivisor<AlgebraicNumber<C>> aengine //= GCDFactory.<AlgebraicNumber<C>> getProxy(afac); 114 // = new GreatestCommonDivisorSimple<AlgebraicNumber<C>>( /*cfac.coFac*/ ); 115 } 116 117 // search squarefree norm 118 long k = 0L; 119 long ks = k; 120 GenPolynomial<C> res = null; 121 boolean sqf = false; 122 //int[] klist = new int[]{ 0, 1, 2, 3, -1, -2, -3 , 5, -5, 7, -7, 101, -101, 1001, -1001 }; 123 //int[] klist = new int[]{ 0, 1, 2, 3, -1, -2, -3 , 5, -5, 7, -7, 23, -23, 167, -167 }; 124 //int[] klist = new int[] { 0, -1, -2, 1, 2, -3, 3 }; 125 int[] klist = new int[] { 0, -1, -2, 1, 2 }; 126 int ki = 0; 127 while (!sqf) { 128 // k = 0,1,2,-1,-2 129 if (ki >= klist.length) { 130 break; 131 } 132 k = klist[ki]; 133 ki++; 134 // compute norm with x -> ( y - k x ) 135 ks = k; 136 res = PolyUfdUtil.<C> norm(P, ks); 137 //System.out.println("res = " + res); 138 if (res.isZERO() || res.isConstant()) { 139 continue; 140 } 141 sqf = factorCoeff.isSquarefree(res); 142 //System.out.println("sqf("+ks+") = " + res.degree()); 143 //System.out.println("resfact = " + factorCoeff.baseFactors(res) + "\n"); 144 } 145 // if Res is now squarefree, else must take radical factorization 146 List<GenPolynomial<C>> nfacs; 147 if (!sqf) { 148 //System.out.println("\nres = " + res); 149 System.out.println("sqf(" + ks + ") = " + res.degree()); 150 //res = factorCoeff.squarefreePart(res); // better use obtained factors 151 //res = factorCoeff.baseFactors(res).lastKey(); 152 } 153 //res = res.monic(); 154 if (logger.isInfoEnabled()) { 155 logger.info("res = " + res); 156 //System.out.println("\nres = " + res); 157 } 158 nfacs = factorCoeff.baseFactorsRadical(res); 159 if (logger.isInfoEnabled()) { 160 logger.info("res facs = " + nfacs); // Q[X] 161 //System.out.println("\nnfacs = " + nfacs); // Q[X] 162 } 163 if (nfacs.size() == 1) { 164 factors.add(P); 165 return factors; 166 } 167 168 // compute gcds of factors with polynomial in Q(alpha)[X] 169 GenPolynomial<AlgebraicNumber<C>> Pp = P; 170 //System.out.println("Pp = " + Pp); 171 GenPolynomial<AlgebraicNumber<C>> Ni; 172 for (GenPolynomial<C> nfi : nfacs) { 173 //System.out.println("nfi = " + nfi); 174 Ni = PolyUfdUtil.<C> substituteConvertToAlgebraicCoefficients(pfac, nfi, ks); 175 if (logger.isInfoEnabled()) { 176 logger.info("Ni = " + Ni); 177 //System.out.println("Pp = " + Pp); 178 //System.out.println("Ni = " + Ni); 179 } 180 // compute gcds of factors with polynomial 181 GenPolynomial<AlgebraicNumber<C>> pni = engine.gcd(Ni, Pp); 182 if (!pni.leadingBaseCoefficient().isONE()) { 183 //System.out.println("gcd(Ni,Pp) not monic " + pni); 184 pni = pni.monic(); 185 } 186 if (logger.isInfoEnabled()) { 187 logger.info("gcd(Ni,Pp) = " + pni); 188 //System.out.println("gcd(Ni,Pp) = " + pni); 189 } 190 if (!pni.isONE()) { 191 factors.add(pni); 192 Pp = Pp.divide(pni); 193 // } else { 194 // GenPolynomial<AlgebraicNumber<C>> qni = Pp.divide(Ni); 195 // GenPolynomial<AlgebraicNumber<C>> rni = Pp.remainder(Ni); 196 // System.out.println("div qni = " + qni); 197 // System.out.println("div rni = " + rni); 198 // continue; 199 // //throw new RuntimeException("gcd(Ni,Pp) == 1"); 200 } 201 } 202 if (!Pp.isZERO() && !Pp.isONE()) { // irreducible rest 203 factors.add(Pp); 204 } 205 //System.out.println("afactors = " + factors); 206 return factors; 207 } 208 209}