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({}) == char_p({})", deg, 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 logger.info("equations = {}", gl); 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 logger.info("solution = {}", gl); 230 GenPolynomial<C> car = apfac.getZERO(); 231 for (GenPolynomial<C> pl : gl) { 232 if (pl.length() <= 1) { 233 continue; 234 } 235 if (pl.length() > 2) { 236 throw new IllegalArgumentException("dim > 0 not implemented " + pl); 237 } 238 //System.out.println("pl = " + pl); 239 ExpVector e = pl.leadingExpVector(); 240 int[] v = e.dependencyOnVariables(); 241 if (v == null || v.length == 0) { 242 continue; 243 } 244 int vi = v[0]; 245 //System.out.println("vi = " + vi); 246 GenPolynomial<C> ca = apfac.univariate(0, deg - 1 - vi); 247 //System.out.println("ca = " + ca); 248 C tc = pl.trailingBaseCoefficient(); 249 tc = tc.negate(); 250 if (e.maxDeg() == c.longValueExact()) { // p-th root of tc ... 251 //SortedMap<C, Long> br = aengine.rootCharacteristic(tc); 252 SortedMap<C, Long> br = aengine.squarefreeFactors(tc); 253 //System.out.println("br = " + br); 254 if (br != null && br.size() > 0) { 255 C cc = apfac.coFac.getONE(); 256 for (Map.Entry<C, Long> me : br.entrySet()) { 257 C bc = me.getKey(); 258 long ll = me.getValue(); 259 if (ll % c.longValueExact() == 0L) { 260 long fl = ll / c.longValueExact(); 261 cc = cc.multiply(bc.power(fl)); 262 } else { // fail ? 263 cc = cc.multiply(bc); 264 } 265 } 266 //System.out.println("cc = " + cc); 267 tc = cc; 268 } 269 } 270 ca = ca.multiply(tc); 271 car = car.sum(ca); 272 } 273 AlgebraicNumber<C> rr = new AlgebraicNumber<C>(afac, car); 274 if (logger.isInfoEnabled()) { 275 logger.info("solution AN = {}", rr); 276 //System.out.println("rr = " + rr); 277 } 278 root.put(rr, 1L); 279 return root; 280 } 281 282 283 /** 284 * GenPolynomial char-th root main variable. 285 * @param P univariate GenPolynomial with AlgebraicNumber coefficients. 286 * @return char-th_rootOf(P), or null, if P is no char-th root. 287 */ 288 public GenPolynomial<AlgebraicNumber<C>> rootCharacteristic(GenPolynomial<AlgebraicNumber<C>> P) { 289 if (P == null || P.isZERO()) { 290 return P; 291 } 292 GenPolynomialRing<AlgebraicNumber<C>> pfac = P.ring; 293 if (pfac.nvar > 1) { 294 // go to recursion 295 GenPolynomialRing<GenPolynomial<AlgebraicNumber<C>>> rfac = pfac.recursive(1); 296 GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> Pr = PolyUtil 297 .<AlgebraicNumber<C>> recursive(rfac, P); 298 GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> Prc = recursiveUnivariateRootCharacteristic(Pr); 299 if (Prc == null) { 300 return null; 301 } 302 GenPolynomial<AlgebraicNumber<C>> D = PolyUtil.<AlgebraicNumber<C>> distribute(pfac, Prc); 303 return D; 304 } 305 RingFactory<AlgebraicNumber<C>> rf = pfac.coFac; 306 if (rf.characteristic().signum() != 1) { 307 // basePthRoot not possible 308 throw new IllegalArgumentException( 309 P.getClass().getName() + " only for ModInteger polynomials " + rf); 310 } 311 long mp = rf.characteristic().longValueExact(); 312 GenPolynomial<AlgebraicNumber<C>> d = pfac.getZERO().copy(); 313 for (Monomial<AlgebraicNumber<C>> m : P) { 314 ExpVector f = m.e; 315 long fl = f.getVal(0); 316 if (fl % mp != 0) { 317 return null; 318 } 319 fl = fl / mp; 320 SortedMap<AlgebraicNumber<C>, Long> sm = rootCharacteristic(m.c); 321 if (sm == null) { 322 return null; 323 } 324 logger.info("sm_alg,root = {}", sm); 325 AlgebraicNumber<C> r = rf.getONE(); 326 for (Map.Entry<AlgebraicNumber<C>, Long> me : sm.entrySet()) { 327 AlgebraicNumber<C> rp = me.getKey(); 328 long gl = me.getValue(); 329 if (gl > 1) { 330 rp = rp.power(gl); 331 } 332 r = r.multiply(rp); 333 } 334 ExpVector e = ExpVector.create(1, 0, fl); 335 d.doPutToMap(e, r); 336 } 337 logger.info("sm_alg,root,d = {}", d); 338 return d; 339 } 340 341 342 /** 343 * GenPolynomial char-th root univariate polynomial. 344 * @param P GenPolynomial. 345 * @return char-th_rootOf(P). 346 */ 347 @Override 348 public GenPolynomial<AlgebraicNumber<C>> baseRootCharacteristic(GenPolynomial<AlgebraicNumber<C>> P) { 349 if (P == null || P.isZERO()) { 350 return P; 351 } 352 GenPolynomialRing<AlgebraicNumber<C>> pfac = P.ring; 353 if (pfac.nvar > 1) { 354 // basePthRoot not possible by return type 355 throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); 356 } 357 RingFactory<AlgebraicNumber<C>> rf = pfac.coFac; 358 if (rf.characteristic().signum() != 1) { 359 // basePthRoot not possible 360 throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); 361 } 362 long mp = rf.characteristic().longValueExact(); 363 GenPolynomial<AlgebraicNumber<C>> d = pfac.getZERO().copy(); 364 for (Monomial<AlgebraicNumber<C>> m : P) { 365 //System.out.println("m = " + m); 366 ExpVector f = m.e; 367 long fl = f.getVal(0); 368 if (fl % mp != 0) { 369 return null; 370 } 371 fl = fl / mp; 372 SortedMap<AlgebraicNumber<C>, Long> sm = rootCharacteristic(m.c); 373 if (sm == null) { 374 return null; 375 } 376 logger.info("sm_alg,base,root = {}", sm); 377 AlgebraicNumber<C> r = rf.getONE(); 378 for (Map.Entry<AlgebraicNumber<C>, Long> me : sm.entrySet()) { 379 AlgebraicNumber<C> rp = me.getKey(); 380 //System.out.println("rp = " + rp); 381 long gl = me.getValue(); 382 //System.out.println("gl = " + gl); 383 AlgebraicNumber<C> re = rp; 384 if (gl > 1) { 385 re = rp.power(gl); 386 } 387 //System.out.println("re = " + re); 388 r = r.multiply(re); 389 } 390 ExpVector e = ExpVector.create(1, 0, fl); 391 d.doPutToMap(e, r); 392 } 393 logger.info("sm_alg,base,d = {}", d); 394 return d; 395 } 396 397 398 /** 399 * GenPolynomial char-th root univariate polynomial with polynomial 400 * coefficients. 401 * @param P recursive univariate GenPolynomial. 402 * @return char-th_rootOf(P), or null if P is no char-th root. 403 */ 404 @Override 405 public GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> recursiveUnivariateRootCharacteristic( 406 GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> P) { 407 if (P == null || P.isZERO()) { 408 return P; 409 } 410 GenPolynomialRing<GenPolynomial<AlgebraicNumber<C>>> pfac = P.ring; 411 if (pfac.nvar > 1) { 412 // basePthRoot not possible by return type 413 throw new IllegalArgumentException( 414 P.getClass().getName() + " only for univariate recursive polynomials"); 415 } 416 RingFactory<GenPolynomial<AlgebraicNumber<C>>> rf = pfac.coFac; 417 if (rf.characteristic().signum() != 1) { 418 // basePthRoot not possible 419 throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); 420 } 421 long mp = rf.characteristic().longValueExact(); 422 GenPolynomial<GenPolynomial<AlgebraicNumber<C>>> d = pfac.getZERO().copy(); 423 for (Monomial<GenPolynomial<AlgebraicNumber<C>>> m : P) { 424 ExpVector f = m.e; 425 long fl = f.getVal(0); 426 if (fl % mp != 0) { 427 return null; 428 } 429 fl = fl / mp; 430 GenPolynomial<AlgebraicNumber<C>> r = rootCharacteristic(m.c); 431 if (r == null) { 432 return null; 433 } 434 ExpVector e = ExpVector.create(1, 0, fl); 435 d.doPutToMap(e, r); 436 } 437 return d; 438 } 439 440}