001/* 002 * $Id: SquarefreeInfiniteAlgebraicFieldCharP.java 3290 2010-08-26 09:18:48Z 003 * kredel $ 004 */ 005 006package edu.jas.ufd; 007 008 009import java.util.ArrayList; 010import java.util.List; 011import java.util.Map; 012import java.util.SortedMap; 013import java.util.TreeMap; 014 015import org.apache.log4j.Logger; 016 017import edu.jas.gb.GroebnerBaseAbstract; 018import edu.jas.gb.GroebnerBaseSeq; 019import edu.jas.gb.Reduction; 020import edu.jas.gb.ReductionSeq; 021import edu.jas.poly.AlgebraicNumber; 022import edu.jas.poly.AlgebraicNumberRing; 023import edu.jas.poly.ExpVector; 024import edu.jas.poly.GenPolynomial; 025import edu.jas.poly.GenPolynomialRing; 026import edu.jas.poly.Monomial; 027import edu.jas.poly.PolyUtil; 028import edu.jas.structure.GcdRingElem; 029import edu.jas.structure.Power; 030import edu.jas.structure.RingFactory; 031 032 033/** 034 * Squarefree decomposition for algebraic extensions of infinite coefficient 035 * fields of characteristic p > 0. 036 * @author Heinz Kredel 037 */ 038 039public class SquarefreeInfiniteAlgebraicFieldCharP<C extends GcdRingElem<C>> extends 040 SquarefreeFieldCharP<AlgebraicNumber<C>> { 041 042 043 private static final Logger logger = Logger.getLogger(SquarefreeInfiniteAlgebraicFieldCharP.class); 044 045 046 //private final boolean debug = logger.isDebugEnabled(); 047 048 049 /** 050 * Squarefree engine for infinite ring of characteristic p base coefficients. 051 */ 052 protected final SquarefreeAbstract<C> aengine; 053 054 055 /** 056 * Constructor. 057 */ 058 public SquarefreeInfiniteAlgebraicFieldCharP(RingFactory<AlgebraicNumber<C>> fac) { 059 super(fac); 060 // isFinite() predicate now present 061 if (fac.isFinite()) { 062 throw new IllegalArgumentException("fac must be in-finite"); 063 } 064 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) fac; 065 GenPolynomialRing<C> rfac = afac.ring; 066 //System.out.println("rfac = " + rfac); 067 //System.out.println("rfac = " + rfac.coFac); 068 aengine = SquarefreeFactory.<C> getImplementation(rfac); 069 //System.out.println("aengine = " + aengine); 070 } 071 072 073 /* --------- algebraic number char-th roots --------------------- */ 074 075 /** 076 * Squarefree factors of a AlgebraicNumber. 077 * @param P AlgebraicNumber. 078 * @return [p_1 -> e_1,...,p_k - > e_k] with P = prod_{i=1, ..., k} 079 * p_i**e_k. 080 */ 081 @Override 082 public SortedMap<AlgebraicNumber<C>, Long> squarefreeFactors(AlgebraicNumber<C> P) { 083 if (P == null) { 084 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 085 } 086 SortedMap<AlgebraicNumber<C>, Long> factors = new TreeMap<AlgebraicNumber<C>, Long>(); 087 if (P.isZERO()) { 088 return factors; 089 } 090 if (P.isONE()) { 091 factors.put(P, 1L); 092 return factors; 093 } 094 GenPolynomial<C> an = P.val; 095 AlgebraicNumberRing<C> pfac = P.ring; 096 if (!an.isONE()) { 097 //System.out.println("an = " + an); 098 //System.out.println("aengine = " + aengine); 099 SortedMap<GenPolynomial<C>, Long> nfac = aengine.squarefreeFactors(an); 100 //System.out.println("nfac = " + nfac); 101 for (Map.Entry<GenPolynomial<C>, Long> me : nfac.entrySet()) { 102 GenPolynomial<C> nfp = me.getKey(); 103 AlgebraicNumber<C> nf = new AlgebraicNumber<C>(pfac, nfp); 104 factors.put(nf, me.getValue()); //nfac.get(nfp)); 105 } 106 } 107 if (factors.size() == 0) { 108 factors.put(P, 1L); 109 } 110 return factors; 111 } 112 113 114 /** 115 * Characteristics root of a AlgebraicNumber. 116 * @param P AlgebraicNumber. 117 * @return [p -> k] if exists k with e=charactristic(P)*k and P = p**e, 118 * else null. 119 */ 120 public SortedMap<AlgebraicNumber<C>, Long> rootCharacteristic(AlgebraicNumber<C> P) { 121 if (P == null) { 122 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 123 } 124 java.math.BigInteger c = P.ring.characteristic(); 125 if (c.signum() == 0) { 126 return null; 127 } 128 SortedMap<AlgebraicNumber<C>, Long> root = new TreeMap<AlgebraicNumber<C>, Long>(); 129 if (P.isZERO()) { 130 return root; 131 } 132 if (P.isONE()) { 133 root.put(P, 1L); 134 return root; 135 } 136 // generate system of equations 137 AlgebraicNumberRing<C> afac = P.ring; 138 long deg = afac.modul.degree(0); 139 int d = (int) deg; 140 String[] vn = GenPolynomialRing.newVars("c", d); 141 GenPolynomialRing<AlgebraicNumber<C>> pfac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, d, vn); 142 List<GenPolynomial<AlgebraicNumber<C>>> uv = (List<GenPolynomial<AlgebraicNumber<C>>>) pfac 143 .univariateList(); 144 GenPolynomial<AlgebraicNumber<C>> cp = pfac.getZERO(); 145 GenPolynomialRing<C> apfac = afac.ring; 146 long i = 0; 147 for (GenPolynomial<AlgebraicNumber<C>> pa : uv) { 148 GenPolynomial<C> ca = apfac.univariate(0, i++); 149 GenPolynomial<AlgebraicNumber<C>> pb = pa.multiply(new AlgebraicNumber<C>(afac, ca)); 150 cp = cp.sum(pb); 151 } 152 GenPolynomial<AlgebraicNumber<C>> cpp = Power 153 .<GenPolynomial<AlgebraicNumber<C>>> positivePower(cp, c); 154 if (logger.isInfoEnabled()) { 155 logger.info("cp = " + cp); 156 logger.info("cp^p = " + cpp); 157 logger.info("P = " + P); 158 } 159 GenPolynomialRing<C> ppfac = new GenPolynomialRing<C>(apfac.coFac, pfac); 160 List<GenPolynomial<C>> gl = new ArrayList<GenPolynomial<C>>(); 161 if (deg == c.longValue() && afac.modul.length() == 2) { 162 logger.info("deg(" + deg + ") == char_p(" + c.longValue() + ")"); 163 for (Monomial<AlgebraicNumber<C>> m : cpp) { 164 ExpVector f = m.e; 165 AlgebraicNumber<C> a = m.c; 166 //System.out.println("a = " + a + " : " + a.toScriptFactory()); 167 GenPolynomial<C> ap = a.val; 168 for (Monomial<C> ma : ap) { 169 ExpVector e = ma.e; 170 C cc = ma.c; 171 C pc = P.val.coefficient(e); 172 C cc1 = ((RingFactory<C>) pc.factory()).getONE(); 173 C pc1 = ((RingFactory<C>) pc.factory()).getZERO(); 174 //System.out.println("cc = " + cc + ", e = " + e); 175 //System.out.println("pc = " + pc + " : " + cc.toScriptFactory()); 176 if (cc instanceof AlgebraicNumber && pc instanceof AlgebraicNumber) { 177 throw new UnsupportedOperationException( 178 "case multiple algebraic extensions not implemented"); 179 } else if (cc instanceof Quotient && pc instanceof Quotient) { 180 Quotient<C> ccp = (Quotient<C>) (Object) cc; 181 Quotient<C> pcp = (Quotient<C>) (Object) pc; 182 if (pcp.isConstant()) { 183 //logger.error("finite field not allowed here " + afac.toScript()); 184 throw new ArithmeticException("finite field not allowed here " + afac.toScript()); 185 } 186 //C dc = cc.divide(pc); 187 Quotient<C> dcp = ccp.divide(pcp); 188 if (dcp.isConstant()) { // not possible: dc.isConstant() 189 //System.out.println("dcp = " + dcp + " : " + cc.toScriptFactory()); // + ", dc = " + dc); 190 //if ( dcp.num.isConstant() ) 191 cc1 = cc; 192 pc1 = pc; 193 } 194 GenPolynomial<C> r = new GenPolynomial<C>(ppfac, cc1, f); 195 r = r.subtract(pc1); 196 //System.out.println("r = " + r); 197 gl.add(r); 198 } 199 } 200 } 201 } else { 202 for (Monomial<AlgebraicNumber<C>> m : cpp) { 203 ExpVector f = m.e; 204 AlgebraicNumber<C> a = m.c; 205 //System.out.println("m = " + m); 206 GenPolynomial<C> ap = a.val; 207 for (Monomial<C> ma : ap) { 208 ExpVector e = ma.e; 209 C cc = ma.c; 210 C pc = P.val.coefficient(e); 211 GenPolynomial<C> r = new GenPolynomial<C>(ppfac, cc, f); 212 r = r.subtract(pc); 213 //System.out.println("r = " + r); 214 gl.add(r); 215 } 216 } 217 } 218 if (logger.isInfoEnabled()) { 219 logger.info("equations = " + gl); 220 } 221 // solve system of equations and construct result 222 Reduction<C> red = new ReductionSeq<C>(); 223 gl = red.irreducibleSet(gl); 224 GroebnerBaseAbstract<C> bb = new GroebnerBaseSeq<C>(); //GBFactory.<C>getImplementation(); 225 int z = bb.commonZeroTest(gl); 226 if (z < 0) { // no solution 227 return null; 228 } 229 if (logger.isInfoEnabled()) { 230 logger.info("solution = " + gl); 231 } 232 GenPolynomial<C> car = apfac.getZERO(); 233 for (GenPolynomial<C> pl : gl) { 234 if (pl.length() <= 1) { 235 continue; 236 } 237 if (pl.length() > 2) { 238 throw new IllegalArgumentException("dim > 0 not implemented " + pl); 239 } 240 //System.out.println("pl = " + pl); 241 ExpVector e = pl.leadingExpVector(); 242 int[] v = e.dependencyOnVariables(); 243 if (v == null || v.length == 0) { 244 continue; 245 } 246 int vi = v[0]; 247 //System.out.println("vi = " + vi); 248 GenPolynomial<C> ca = apfac.univariate(0, deg - 1 - vi); 249 //System.out.println("ca = " + ca); 250 C tc = pl.trailingBaseCoefficient(); 251 tc = tc.negate(); 252 if (e.maxDeg() == c.longValue()) { // p-th root of tc ... 253 //SortedMap<C, Long> br = aengine.rootCharacteristic(tc); 254 SortedMap<C, Long> br = aengine.squarefreeFactors(tc); 255 //System.out.println("br = " + br); 256 if (br != null && br.size() > 0) { 257 C cc = apfac.coFac.getONE(); 258 for (Map.Entry<C, Long> me : br.entrySet()) { 259 C bc = me.getKey(); 260 long ll = me.getValue(); //br.get(bc); 261 if (ll % c.longValue() == 0L) { 262 long fl = ll / c.longValue(); 263 cc = cc.multiply(Power.<C> positivePower(bc, fl)); 264 } else { // fail ? 265 cc = cc.multiply(bc); 266 } 267 } 268 //System.out.println("cc = " + cc); 269 tc = cc; 270 } 271 } 272 ca = ca.multiply(tc); 273 car = car.sum(ca); 274 } 275 AlgebraicNumber<C> rr = new AlgebraicNumber<C>(afac, car); 276 if (logger.isInfoEnabled()) { 277 logger.info("solution AN = " + rr); 278 //System.out.println("rr = " + rr); 279 } 280 root.put(rr, 1L); 281 return root; 282 } 283 284 285 /** 286 * GenPolynomial char-th root main variable. 287 * @param P univariate GenPolynomial with AlgebraicNumber coefficients. 288 * @return char-th_rootOf(P), or null, if P is no char-th root. 289 */ 290 public GenPolynomial<AlgebraicNumber<C>> rootCharacteristic(GenPolynomial<AlgebraicNumber<C>> P) { 291 if (P == null || P.isZERO()) { 292 return P; 293 } 294 GenPolynomialRing<AlgebraicNumber<C>> pfac = P.ring; 295 if (pfac.nvar > 1) { 296 // go to recursion 297 GenPolynomialRing<AlgebraicNumber<C>> cfac = pfac.contract(1); 298 GenPolynomialRing<GenPolynomial<AlgebraicNumber<C>>> rfac = new GenPolynomialRing<GenPolynomial<AlgebraicNumber<C>>>( 299 cfac, 1); 300 GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> Pr = PolyUtil.<AlgebraicNumber<C>> recursive( 301 rfac, P); 302 GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> Prc = recursiveUnivariateRootCharacteristic(Pr); 303 if (Prc == null) { 304 return null; 305 } 306 GenPolynomial<AlgebraicNumber<C>> D = PolyUtil.<AlgebraicNumber<C>> distribute(pfac, Prc); 307 return D; 308 } 309 RingFactory<AlgebraicNumber<C>> rf = pfac.coFac; 310 if (rf.characteristic().signum() != 1) { 311 // basePthRoot not possible 312 throw new IllegalArgumentException(P.getClass().getName() + " only for ModInteger polynomials " 313 + rf); 314 } 315 long mp = rf.characteristic().longValue(); 316 GenPolynomial<AlgebraicNumber<C>> d = pfac.getZERO().copy(); 317 for (Monomial<AlgebraicNumber<C>> m : P) { 318 ExpVector f = m.e; 319 long fl = f.getVal(0); 320 if (fl % mp != 0) { 321 return null; 322 } 323 fl = fl / mp; 324 SortedMap<AlgebraicNumber<C>, Long> sm = rootCharacteristic(m.c); 325 if (sm == null) { 326 return null; 327 } 328 if (logger.isInfoEnabled()) { 329 logger.info("sm_alg,root = " + sm); 330 } 331 AlgebraicNumber<C> r = rf.getONE(); 332 for (Map.Entry<AlgebraicNumber<C>, Long> me : sm.entrySet()) { 333 AlgebraicNumber<C> rp = me.getKey(); 334 long gl = me.getValue(); //sm.get(rp); 335 if (gl > 1) { 336 rp = Power.<AlgebraicNumber<C>> positivePower(rp, gl); 337 } 338 r = r.multiply(rp); 339 } 340 ExpVector e = ExpVector.create(1, 0, fl); 341 d.doPutToMap(e, r); 342 } 343 logger.info("sm_alg,root,d = " + d); 344 return d; 345 } 346 347 348 /** 349 * GenPolynomial char-th root univariate polynomial. 350 * @param P GenPolynomial. 351 * @return char-th_rootOf(P). 352 */ 353 @Override 354 public GenPolynomial<AlgebraicNumber<C>> baseRootCharacteristic(GenPolynomial<AlgebraicNumber<C>> P) { 355 if (P == null || P.isZERO()) { 356 return P; 357 } 358 GenPolynomialRing<AlgebraicNumber<C>> pfac = P.ring; 359 if (pfac.nvar > 1) { 360 // basePthRoot not possible by return type 361 throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); 362 } 363 RingFactory<AlgebraicNumber<C>> rf = pfac.coFac; 364 if (rf.characteristic().signum() != 1) { 365 // basePthRoot not possible 366 throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); 367 } 368 long mp = rf.characteristic().longValue(); 369 GenPolynomial<AlgebraicNumber<C>> d = pfac.getZERO().copy(); 370 for (Monomial<AlgebraicNumber<C>> m : P) { 371 //System.out.println("m = " + m); 372 ExpVector f = m.e; 373 long fl = f.getVal(0); 374 if (fl % mp != 0) { 375 return null; 376 } 377 fl = fl / mp; 378 SortedMap<AlgebraicNumber<C>, Long> sm = rootCharacteristic(m.c); 379 if (sm == null) { 380 return null; 381 } 382 if (logger.isInfoEnabled()) { 383 logger.info("sm_alg,base,root = " + sm); 384 } 385 AlgebraicNumber<C> r = rf.getONE(); 386 for (Map.Entry<AlgebraicNumber<C>, Long> me : sm.entrySet()) { 387 AlgebraicNumber<C> rp = me.getKey(); 388 //System.out.println("rp = " + rp); 389 long gl = me.getValue(); //sm.get(rp); 390 //System.out.println("gl = " + gl); 391 AlgebraicNumber<C> re = rp; 392 if (gl > 1) { 393 re = Power.<AlgebraicNumber<C>> positivePower(rp, gl); 394 } 395 //System.out.println("re = " + re); 396 r = r.multiply(re); 397 } 398 ExpVector e = ExpVector.create(1, 0, fl); 399 d.doPutToMap(e, r); 400 } 401 if (logger.isInfoEnabled()) { 402 logger.info("sm_alg,base,d = " + d); 403 } 404 return d; 405 } 406 407 408 /** 409 * GenPolynomial char-th root univariate polynomial with polynomial 410 * coefficients. 411 * @param P recursive univariate GenPolynomial. 412 * @return char-th_rootOf(P), or null if P is no char-th root. 413 */ 414 @Override 415 public GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> recursiveUnivariateRootCharacteristic( 416 GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> P) { 417 if (P == null || P.isZERO()) { 418 return P; 419 } 420 GenPolynomialRing<GenPolynomial<AlgebraicNumber<C>>> pfac = P.ring; 421 if (pfac.nvar > 1) { 422 // basePthRoot not possible by return type 423 throw new IllegalArgumentException(P.getClass().getName() 424 + " only for univariate recursive polynomials"); 425 } 426 RingFactory<GenPolynomial<AlgebraicNumber<C>>> rf = pfac.coFac; 427 if (rf.characteristic().signum() != 1) { 428 // basePthRoot not possible 429 throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); 430 } 431 long mp = rf.characteristic().longValue(); 432 GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> d = pfac.getZERO().copy(); 433 for (Monomial<GenPolynomial<AlgebraicNumber<C>>> m : P) { 434 ExpVector f = m.e; 435 long fl = f.getVal(0); 436 if (fl % mp != 0) { 437 return null; 438 } 439 fl = fl / mp; 440 GenPolynomial<AlgebraicNumber<C>> r = rootCharacteristic(m.c); 441 if (r == null) { 442 return null; 443 } 444 ExpVector e = ExpVector.create(1, 0, fl); 445 d.doPutToMap(e, r); 446 } 447 return d; 448 } 449 450}