001/* 002 * $Id$ 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.logging.log4j.Logger; 015import org.apache.logging.log4j.LogManager; 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>> 040 extends SquarefreeFieldCharP<AlgebraicNumber<C>> { 041 042 043 private static final Logger logger = LogManager.getLogger(SquarefreeInfiniteAlgebraicFieldCharP.class); 044 045 046 //private static final boolean debug = logger.isDebugEnabled(); 047 048 049 /** 050 * Squarefree engine for infinite ring of characteristic p base 051 * coefficients. 052 */ 053 protected final SquarefreeAbstract<C> aengine; 054 055 056 /** 057 * Constructor. 058 */ 059 public SquarefreeInfiniteAlgebraicFieldCharP(RingFactory<AlgebraicNumber<C>> fac) { 060 super(fac); 061 // isFinite() predicate now present 062 if (fac.isFinite()) { 063 throw new IllegalArgumentException("fac must be in-finite"); 064 } 065 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) fac; 066 GenPolynomialRing<C> rfac = afac.ring; 067 //System.out.println("rfac = " + rfac); 068 //System.out.println("rfac = " + rfac.coFac); 069 aengine = SquarefreeFactory.<C> getImplementation(rfac); 070 //System.out.println("aengine = " + aengine); 071 } 072 073 074 /* --------- algebraic number char-th roots --------------------- */ 075 076 /** 077 * Squarefree factors of a AlgebraicNumber. 078 * @param P AlgebraicNumber. 079 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1, ..., k} 080 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 081 */ 082 @Override 083 public SortedMap<AlgebraicNumber<C>, Long> squarefreeFactors(AlgebraicNumber<C> P) { 084 if (P == null) { 085 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 086 } 087 SortedMap<AlgebraicNumber<C>, Long> factors = new TreeMap<AlgebraicNumber<C>, Long>(); 088 if (P.isZERO()) { 089 return factors; 090 } 091 if (P.isONE()) { 092 factors.put(P, 1L); 093 return factors; 094 } 095 GenPolynomial<C> an = P.val; 096 AlgebraicNumberRing<C> pfac = P.ring; 097 if (!an.isONE()) { 098 //System.out.println("an = " + an); 099 //System.out.println("aengine = " + aengine); 100 SortedMap<GenPolynomial<C>, Long> nfac = aengine.squarefreeFactors(an); 101 //System.out.println("nfac = " + nfac); 102 for (Map.Entry<GenPolynomial<C>, Long> me : nfac.entrySet()) { 103 GenPolynomial<C> nfp = me.getKey(); 104 AlgebraicNumber<C> nf = new AlgebraicNumber<C>(pfac, nfp); 105 factors.put(nf, me.getValue()); //nfac.get(nfp)); 106 } 107 } 108 if (factors.size() == 0) { 109 factors.put(P, 1L); 110 } 111 return factors; 112 } 113 114 115 /** 116 * Characteristics root of a AlgebraicNumber. 117 * @param P AlgebraicNumber. 118 * @return [p -> k] if exists k with e=charactristic(P)*k and P = p**e, 119 * else null. 120 */ 121 @SuppressWarnings("unchecked") 122 public SortedMap<AlgebraicNumber<C>, Long> rootCharacteristic(AlgebraicNumber<C> P) { 123 if (P == null) { 124 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 125 } 126 java.math.BigInteger c = P.ring.characteristic(); 127 if (c.signum() == 0) { 128 return null; 129 } 130 SortedMap<AlgebraicNumber<C>, Long> root = new TreeMap<AlgebraicNumber<C>, Long>(); 131 if (P.isZERO()) { 132 return root; 133 } 134 if (P.isONE()) { 135 root.put(P, 1L); 136 return root; 137 } 138 // generate system of equations 139 AlgebraicNumberRing<C> afac = P.ring; 140 long deg = afac.modul.degree(0); 141 int d = (int) deg; 142 String[] vn = GenPolynomialRing.newVars("c", d); 143 GenPolynomialRing<AlgebraicNumber<C>> pfac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, d, vn); 144 List<GenPolynomial<AlgebraicNumber<C>>> uv = (List<GenPolynomial<AlgebraicNumber<C>>>) pfac 145 .univariateList(); 146 GenPolynomial<AlgebraicNumber<C>> cp = pfac.getZERO(); 147 GenPolynomialRing<C> apfac = afac.ring; 148 long i = 0; 149 for (GenPolynomial<AlgebraicNumber<C>> pa : uv) { 150 GenPolynomial<C> ca = apfac.univariate(0, i++); 151 GenPolynomial<AlgebraicNumber<C>> pb = pa.multiply(new AlgebraicNumber<C>(afac, ca)); 152 cp = cp.sum(pb); 153 } 154 GenPolynomial<AlgebraicNumber<C>> cpp = Power.<GenPolynomial<AlgebraicNumber<C>>> positivePower(cp, 155 c); 156 if (logger.isInfoEnabled()) { 157 logger.info("cp = " + cp); 158 logger.info("cp^p = " + cpp); 159 logger.info("P = " + P); 160 } 161 GenPolynomialRing<C> ppfac = new GenPolynomialRing<C>(apfac.coFac, pfac); 162 List<GenPolynomial<C>> gl = new ArrayList<GenPolynomial<C>>(); 163 if (deg == c.longValueExact() && afac.modul.length() == 2) { 164 logger.info("deg(" + deg + ") == char_p(" + c.longValueExact() + ")"); 165 for (Monomial<AlgebraicNumber<C>> m : cpp) { 166 ExpVector f = m.e; 167 AlgebraicNumber<C> a = m.c; 168 //System.out.println("a = " + a + " : " + a.toScriptFactory()); 169 GenPolynomial<C> ap = a.val; 170 for (Monomial<C> ma : ap) { 171 ExpVector e = ma.e; 172 C cc = ma.c; 173 C pc = P.val.coefficient(e); 174 C cc1 = ((RingFactory<C>) pc.factory()).getONE(); 175 C pc1 = ((RingFactory<C>) pc.factory()).getZERO(); 176 //System.out.println("cc = " + cc + ", e = " + e); 177 //System.out.println("pc = " + pc + " : " + cc.toScriptFactory()); 178 if (cc instanceof AlgebraicNumber && pc instanceof AlgebraicNumber) { 179 throw new UnsupportedOperationException( 180 "case multiple algebraic extensions not implemented"); 181 } else if (cc instanceof Quotient && pc instanceof Quotient) { 182 Quotient<C> ccp = (Quotient<C>) (Object) cc; 183 Quotient<C> pcp = (Quotient<C>) (Object) pc; 184 if (pcp.isConstant()) { 185 //logger.error("finite field not allowed here " + afac.toScript()); 186 throw new ArithmeticException("finite field not allowed here " + afac.toScript()); 187 } 188 //C dc = cc.divide(pc); 189 Quotient<C> dcp = ccp.divide(pcp); 190 if (dcp.isConstant()) { // not possible: dc.isConstant() 191 //System.out.println("dcp = " + dcp + " : " + cc.toScriptFactory()); // + ", dc = " + dc); 192 //if ( dcp.num.isConstant() ) 193 cc1 = cc; 194 pc1 = pc; 195 } 196 GenPolynomial<C> r = new GenPolynomial<C>(ppfac, cc1, f); 197 r = r.subtract(pc1); 198 //System.out.println("r = " + r); 199 gl.add(r); 200 } 201 } 202 } 203 } else { 204 for (Monomial<AlgebraicNumber<C>> m : cpp) { 205 ExpVector f = m.e; 206 AlgebraicNumber<C> a = m.c; 207 //System.out.println("m = " + m); 208 GenPolynomial<C> ap = a.val; 209 for (Monomial<C> ma : ap) { 210 ExpVector e = ma.e; 211 C cc = ma.c; 212 C pc = P.val.coefficient(e); 213 GenPolynomial<C> r = new GenPolynomial<C>(ppfac, cc, f); 214 r = r.subtract(pc); 215 //System.out.println("r = " + r); 216 gl.add(r); 217 } 218 } 219 } 220 if (logger.isInfoEnabled()) { 221 logger.info("equations = " + gl); 222 } 223 // solve system of equations and construct result 224 Reduction<C> red = new ReductionSeq<C>(); 225 gl = red.irreducibleSet(gl); 226 GroebnerBaseAbstract<C> bb = new GroebnerBaseSeq<C>(); //GBFactory.<C>getImplementation(); 227 int z = bb.commonZeroTest(gl); 228 if (z < 0) { // no solution 229 return null; 230 } 231 if (logger.isInfoEnabled()) { 232 logger.info("solution = " + gl); 233 } 234 GenPolynomial<C> car = apfac.getZERO(); 235 for (GenPolynomial<C> pl : gl) { 236 if (pl.length() <= 1) { 237 continue; 238 } 239 if (pl.length() > 2) { 240 throw new IllegalArgumentException("dim > 0 not implemented " + pl); 241 } 242 //System.out.println("pl = " + pl); 243 ExpVector e = pl.leadingExpVector(); 244 int[] v = e.dependencyOnVariables(); 245 if (v == null || v.length == 0) { 246 continue; 247 } 248 int vi = v[0]; 249 //System.out.println("vi = " + vi); 250 GenPolynomial<C> ca = apfac.univariate(0, deg - 1 - vi); 251 //System.out.println("ca = " + ca); 252 C tc = pl.trailingBaseCoefficient(); 253 tc = tc.negate(); 254 if (e.maxDeg() == c.longValueExact()) { // p-th root of tc ... 255 //SortedMap<C, Long> br = aengine.rootCharacteristic(tc); 256 SortedMap<C, Long> br = aengine.squarefreeFactors(tc); 257 //System.out.println("br = " + br); 258 if (br != null && br.size() > 0) { 259 C cc = apfac.coFac.getONE(); 260 for (Map.Entry<C, Long> me : br.entrySet()) { 261 C bc = me.getKey(); 262 long ll = me.getValue(); 263 if (ll % c.longValueExact() == 0L) { 264 long fl = ll / c.longValueExact(); 265 cc = cc.multiply(bc.power(fl)); 266 } else { // fail ? 267 cc = cc.multiply(bc); 268 } 269 } 270 //System.out.println("cc = " + cc); 271 tc = cc; 272 } 273 } 274 ca = ca.multiply(tc); 275 car = car.sum(ca); 276 } 277 AlgebraicNumber<C> rr = new AlgebraicNumber<C>(afac, car); 278 if (logger.isInfoEnabled()) { 279 logger.info("solution AN = " + rr); 280 //System.out.println("rr = " + rr); 281 } 282 root.put(rr, 1L); 283 return root; 284 } 285 286 287 /** 288 * GenPolynomial char-th root main variable. 289 * @param P univariate GenPolynomial with AlgebraicNumber coefficients. 290 * @return char-th_rootOf(P), or null, if P is no char-th root. 291 */ 292 public GenPolynomial<AlgebraicNumber<C>> rootCharacteristic(GenPolynomial<AlgebraicNumber<C>> P) { 293 if (P == null || P.isZERO()) { 294 return P; 295 } 296 GenPolynomialRing<AlgebraicNumber<C>> pfac = P.ring; 297 if (pfac.nvar > 1) { 298 // go to recursion 299 GenPolynomialRing<GenPolynomial<AlgebraicNumber<C>>> rfac = pfac.recursive(1); 300 GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> Pr = PolyUtil 301 .<AlgebraicNumber<C>> recursive(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( 313 P.getClass().getName() + " only for ModInteger polynomials " + rf); 314 } 315 long mp = rf.characteristic().longValueExact(); 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(); 335 if (gl > 1) { 336 rp = rp.power(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().longValueExact(); 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(); 390 //System.out.println("gl = " + gl); 391 AlgebraicNumber<C> re = rp; 392 if (gl > 1) { 393 re = rp.power(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( 424 P.getClass().getName() + " 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().longValueExact(); 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}