001/* 002 * $Id: HenselMultUtil.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.arith.BigInteger; 015import edu.jas.arith.ModIntegerRing; 016import edu.jas.arith.ModLongRing; 017import edu.jas.arith.Modular; 018import edu.jas.arith.ModularRingFactory; 019import edu.jas.poly.GenPolynomial; 020import edu.jas.poly.GenPolynomialRing; 021import edu.jas.poly.PolyUtil; 022import edu.jas.ps.PolynomialTaylorFunction; 023import edu.jas.ps.TaylorFunction; 024import edu.jas.ps.UnivPowerSeries; 025import edu.jas.ps.UnivPowerSeriesRing; 026import edu.jas.structure.GcdRingElem; 027import edu.jas.structure.RingFactory; 028 029 030/** 031 * Hensel multivariate lifting utilities. 032 * @author Heinz Kredel 033 */ 034 035public class HenselMultUtil { 036 037 038 private static final Logger logger = LogManager.getLogger(HenselMultUtil.class); 039 040 041 private static final boolean debug = logger.isInfoEnabled(); 042 043 044 /** 045 * Modular diophantine equation solution and lifting algorithm. Let p = 046 * A_i.ring.coFac.modul() and assume ggt(A,B) == 1 mod p. 047 * @param A modular GenPolynomial, mod p^k 048 * @param B modular GenPolynomial, mod p^k 049 * @param C modular GenPolynomial, mod p^k 050 * @param V list of substitution values, mod p^k 051 * @param d desired approximation exponent (x_i-v_i)^d. 052 * @param k desired approximation exponent p^k. 053 * @return [s, t] with s A' + t B' = C mod p^k, with A' = B, B' = A. 054 */ 055 public static <MOD extends GcdRingElem<MOD> & Modular> List<GenPolynomial<MOD>> liftDiophant( 056 GenPolynomial<MOD> A, GenPolynomial<MOD> B, GenPolynomial<MOD> C, List<MOD> V, long d, 057 long k) throws NoLiftingException { 058 GenPolynomialRing<MOD> pkfac = C.ring; 059 if (pkfac.nvar == 1) { // V, d ignored 060 return HenselUtil.<MOD> liftDiophant(A, B, C, k); 061 } 062 if (!pkfac.equals(A.ring)) { 063 throw new IllegalArgumentException("A.ring != pkfac: " + A.ring + " != " + pkfac); 064 } 065 066 // evaluate at v_n: 067 List<MOD> Vp = new ArrayList<MOD>(V); 068 MOD v = Vp.remove(Vp.size() - 1); 069 //GenPolynomial<MOD> zero = pkfac.getZERO(); 070 // (x_n - v) 071 GenPolynomial<MOD> mon = pkfac.getONE(); 072 GenPolynomial<MOD> xv = pkfac.univariate(0, 1); 073 xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); 074 //System.out.println("xv = " + xv); 075 // A(v), B(v), C(v) 076 ModularRingFactory<MOD> cf = (ModularRingFactory<MOD>) pkfac.coFac; 077 MOD vp = cf.fromInteger(v.getSymmetricInteger().getVal()); 078 //System.out.println("v = " + v + ", vp = " + vp); 079 GenPolynomialRing<MOD> ckfac = pkfac.contract(1); 080 GenPolynomial<MOD> Ap = PolyUtil.<MOD> evaluateMain(ckfac, A, vp); 081 GenPolynomial<MOD> Bp = PolyUtil.<MOD> evaluateMain(ckfac, B, vp); 082 GenPolynomial<MOD> Cp = PolyUtil.<MOD> evaluateMain(ckfac, C, vp); 083 //System.out.println("Ap = " + Ap); 084 //System.out.println("Bp = " + Bp); 085 //System.out.println("Cp = " + Cp); 086 087 // recursion: 088 List<GenPolynomial<MOD>> su = HenselMultUtil.<MOD> liftDiophant(Ap, Bp, Cp, Vp, d, k); 089 //System.out.println("su@p^" + k + " = " + su); 090 //System.out.println("coFac = " + su.get(0).ring.coFac.toScript()); 091 if (pkfac.nvar == 2 && !HenselUtil.<MOD> isDiophantLift(Bp, Ap, su.get(0), su.get(1), Cp)) { 092 //System.out.println("isDiophantLift: false"); 093 throw new NoLiftingException("isDiophantLift: false"); 094 } 095 if (!ckfac.equals(su.get(0).ring)) { 096 throw new IllegalArgumentException("qfac != ckfac: " + su.get(0).ring + " != " + ckfac); 097 } 098 GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(new BigInteger(), pkfac); 099 //GenPolynomialRing<BigInteger> cifac = new GenPolynomialRing<BigInteger>(new BigInteger(), ckfac); 100 //System.out.println("ifac = " + ifac.toScript()); 101 String[] mn = new String[] { pkfac.getVars()[pkfac.nvar - 1] }; 102 GenPolynomialRing<GenPolynomial<MOD>> qrfac = new GenPolynomialRing<GenPolynomial<MOD>>(ckfac, 1, mn); 103 //System.out.println("qrfac = " + qrfac); 104 105 List<GenPolynomial<MOD>> sup = new ArrayList<GenPolynomial<MOD>>(su.size()); 106 List<GenPolynomial<BigInteger>> supi = new ArrayList<GenPolynomial<BigInteger>>(su.size()); 107 for (GenPolynomial<MOD> s : su) { 108 GenPolynomial<MOD> sp = s.extend(pkfac, 0, 0L); 109 sup.add(sp); 110 GenPolynomial<BigInteger> spi = PolyUtil.integerFromModularCoefficients(ifac, sp); 111 supi.add(spi); 112 } 113 //System.out.println("sup = " + sup); 114 //System.out.println("supi = " + supi); 115 GenPolynomial<BigInteger> Ai = PolyUtil.integerFromModularCoefficients(ifac, A); 116 GenPolynomial<BigInteger> Bi = PolyUtil.integerFromModularCoefficients(ifac, B); 117 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(ifac, C); 118 //System.out.println("Ai = " + Ai); 119 //System.out.println("Bi = " + Bi); 120 //System.out.println("Ci = " + Ci); 121 //GenPolynomial<MOD> aq = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, Ai); 122 //GenPolynomial<MOD> bq = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, Bi); 123 //System.out.println("aq = " + aq); 124 //System.out.println("bq = " + bq); 125 126 // compute error: 127 GenPolynomial<BigInteger> E = Ci; // - sum_i s_i b_i 128 E = E.subtract(Bi.multiply(supi.get(0))); 129 E = E.subtract(Ai.multiply(supi.get(1))); 130 //System.out.println("E = " + E); 131 if (E.isZERO()) { 132 logger.info("liftDiophant leaving on zero E"); 133 return sup; 134 } 135 GenPolynomial<MOD> Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 136 //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); 137 logger.info("Ep(0," + pkfac.nvar + ") = " + Ep); 138 if (Ep.isZERO()) { 139 logger.info("liftDiophant leaving on zero Ep mod p^k"); 140 return sup; 141 } 142 for (int e = 1; e <= d; e++) { 143 //System.out.println("\ne = " + e + " -------------------------------------- " + pkfac.nvar); 144 GenPolynomial<GenPolynomial<MOD>> Epr = PolyUtil.<MOD> recursive(qrfac, Ep); 145 //System.out.println("Epr = " + Epr); 146 UnivPowerSeriesRing<GenPolynomial<MOD>> psfac = new UnivPowerSeriesRing<GenPolynomial<MOD>>( 147 qrfac); 148 //System.out.println("psfac = " + psfac); 149 TaylorFunction<GenPolynomial<MOD>> F = new PolynomialTaylorFunction<GenPolynomial<MOD>>(Epr); 150 //System.out.println("F = " + F); 151 //List<GenPolynomial<MOD>> Vs = new ArrayList<GenPolynomial<MOD>>(1); 152 GenPolynomial<MOD> vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); 153 //Vs.add(vq); 154 //System.out.println("Vs = " + Vs); 155 UnivPowerSeries<GenPolynomial<MOD>> Epst = psfac.seriesOfTaylor(F, vq); 156 //System.out.println("Epst = " + Epst); 157 GenPolynomial<MOD> cm = Epst.coefficient(e); 158 //System.out.println("cm = " + cm + ", cm.ring = " + cm.ring.toScript()); 159 160 // recursion: 161 List<GenPolynomial<MOD>> S = HenselMultUtil.<MOD> liftDiophant(Ap, Bp, cm, Vp, d, k); 162 //System.out.println("S = " + S); 163 if (!ckfac.coFac.equals(S.get(0).ring.coFac)) { 164 throw new IllegalArgumentException( 165 "ckfac != pkfac: " + ckfac.coFac + " != " + S.get(0).ring.coFac); 166 } 167 if (pkfac.nvar == 2 && !HenselUtil.<MOD> isDiophantLift(Ap, Bp, S.get(1), S.get(0), cm)) { 168 //System.out.println("isDiophantLift: false"); 169 throw new NoLiftingException("isDiophantLift: false"); 170 } 171 mon = mon.multiply(xv); // Power.<GenPolynomial<MOD>> power(pkfac,xv,e); 172 //System.out.println("mon = " + mon); 173 //List<GenPolynomial<MOD>> Sp = new ArrayList<GenPolynomial<MOD>>(S.size()); 174 int i = 0; 175 supi = new ArrayList<GenPolynomial<BigInteger>>(su.size()); 176 for (GenPolynomial<MOD> dd : S) { 177 //System.out.println("dd = " + dd); 178 GenPolynomial<MOD> de = dd.extend(pkfac, 0, 0L); 179 GenPolynomial<MOD> dm = de.multiply(mon); 180 //Sp.add(dm); 181 de = sup.get(i).sum(dm); 182 //System.out.println("dd = " + dd); 183 sup.set(i++, de); 184 GenPolynomial<BigInteger> spi = PolyUtil.integerFromModularCoefficients(ifac, dm); 185 supi.add(spi); 186 } 187 //System.out.println("Sp = " + Sp); 188 //System.out.println("sup = " + sup); 189 //System.out.println("supi = " + supi); 190 // compute new error 191 //E = E; // - sum_i s_i b_i 192 E = E.subtract(Bi.multiply(supi.get(0))); 193 E = E.subtract(Ai.multiply(supi.get(1))); 194 //System.out.println("E = " + E); 195 if (E.isZERO()) { 196 logger.info("liftDiophant leaving on zero E"); 197 return sup; 198 } 199 Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 200 //System.out.println("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); 201 logger.info("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); 202 if (Ep.isZERO()) { 203 logger.info("liftDiophant leaving on zero Ep mod p^k"); 204 return sup; 205 } 206 } 207 //System.out.println("*** done: " + pkfac.nvar); 208 return sup; 209 } 210 211 212 /** 213 * Modular diophantine equation solution and lifting algorithm. Let p = 214 * A_i.ring.coFac.modul() and assume ggt(a,b) == 1 mod p, for a, b in A. 215 * @param A list of modular GenPolynomials, mod p^k 216 * @param C modular GenPolynomial, mod p^k 217 * @param V list of substitution values, mod p^k 218 * @param d desired approximation exponent (x_i-v_i)^d. 219 * @param k desired approximation exponent p^k. 220 * @return [s_1,..., s_n] with sum_i s_i A_i' = C mod p^k, with Ai' = 221 * prod_{j!=i} A_j. 222 */ 223 public static <MOD extends GcdRingElem<MOD> & Modular> List<GenPolynomial<MOD>> liftDiophant( 224 List<GenPolynomial<MOD>> A, GenPolynomial<MOD> C, List<MOD> V, long d, long k) 225 throws NoLiftingException { 226 GenPolynomialRing<MOD> pkfac = C.ring; 227 if (pkfac.nvar == 1) { // V, d ignored 228 return HenselUtil.<MOD> liftDiophant(A, C, k); 229 } 230 if (!pkfac.equals(A.get(0).ring)) { 231 throw new IllegalArgumentException("A.ring != pkfac: " + A.get(0).ring + " != " + pkfac); 232 } 233 // co-products 234 GenPolynomial<MOD> As = pkfac.getONE(); 235 for (GenPolynomial<MOD> a : A) { 236 As = As.multiply(a); 237 } 238 List<GenPolynomial<MOD>> Bp = new ArrayList<GenPolynomial<MOD>>(A.size()); 239 for (GenPolynomial<MOD> a : A) { 240 GenPolynomial<MOD> b = PolyUtil.<MOD> basePseudoDivide(As, a); 241 Bp.add(b); 242 } 243 244 // evaluate at v_n: 245 List<MOD> Vp = new ArrayList<MOD>(V); 246 MOD v = Vp.remove(Vp.size() - 1); 247 // (x_n - v) 248 GenPolynomial<MOD> mon = pkfac.getONE(); 249 GenPolynomial<MOD> xv = pkfac.univariate(0, 1); 250 xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); 251 //System.out.println("xv = " + xv); 252 // A(v), B(v), C(v) 253 ModularRingFactory<MOD> cf = (ModularRingFactory<MOD>) pkfac.coFac; 254 MOD vp = cf.fromInteger(v.getSymmetricInteger().getVal()); 255 //System.out.println("v = " + v + ", vp = " + vp); 256 GenPolynomialRing<MOD> ckfac = pkfac.contract(1); 257 List<GenPolynomial<MOD>> Ap = new ArrayList<GenPolynomial<MOD>>(A.size()); 258 for (GenPolynomial<MOD> a : A) { 259 GenPolynomial<MOD> ap = PolyUtil.<MOD> evaluateMain(ckfac, a, vp); 260 Ap.add(ap); 261 } 262 GenPolynomial<MOD> Cp = PolyUtil.<MOD> evaluateMain(ckfac, C, vp); 263 //System.out.println("Ap = " + Ap); 264 //System.out.println("Cp = " + Cp); 265 266 // recursion: 267 List<GenPolynomial<MOD>> su = HenselMultUtil.<MOD> liftDiophant(Ap, Cp, Vp, d, k); 268 //System.out.println("su@p^" + k + " = " + su); 269 //System.out.println("coFac = " + su.get(0).ring.coFac.toScript()); 270 if (pkfac.nvar == 2 && !HenselUtil.<MOD> isDiophantLift(Ap, su, Cp)) { 271 //System.out.println("isDiophantLift: false"); 272 throw new NoLiftingException("isDiophantLift: false"); 273 } 274 if (!ckfac.equals(su.get(0).ring)) { 275 throw new IllegalArgumentException("qfac != ckfac: " + su.get(0).ring + " != " + ckfac); 276 } 277 GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(new BigInteger(), pkfac); 278 //GenPolynomialRing<BigInteger> cifac = new GenPolynomialRing<BigInteger>(new BigInteger(), ckfac); 279 //System.out.println("ifac = " + ifac.toScript()); 280 String[] mn = new String[] { pkfac.getVars()[pkfac.nvar - 1] }; 281 GenPolynomialRing<GenPolynomial<MOD>> qrfac = new GenPolynomialRing<GenPolynomial<MOD>>(ckfac, 1, mn); 282 //System.out.println("qrfac = " + qrfac); 283 284 List<GenPolynomial<MOD>> sup = new ArrayList<GenPolynomial<MOD>>(su.size()); 285 List<GenPolynomial<BigInteger>> supi = new ArrayList<GenPolynomial<BigInteger>>(su.size()); 286 for (GenPolynomial<MOD> s : su) { 287 GenPolynomial<MOD> sp = s.extend(pkfac, 0, 0L); 288 sup.add(sp); 289 GenPolynomial<BigInteger> spi = PolyUtil.integerFromModularCoefficients(ifac, sp); 290 supi.add(spi); 291 } 292 //System.out.println("sup = " + sup); 293 //System.out.println("supi = " + supi); 294 //List<GenPolynomial<BigInteger>> Ai = new ArrayList<GenPolynomial<BigInteger>>(A.size()); 295 //for (GenPolynomial<MOD> a : A) { 296 // GenPolynomial<BigInteger> ai = PolyUtil.integerFromModularCoefficients(ifac, a); 297 // Ai.add(ai); 298 //} 299 List<GenPolynomial<BigInteger>> Bi = new ArrayList<GenPolynomial<BigInteger>>(A.size()); 300 for (GenPolynomial<MOD> b : Bp) { 301 GenPolynomial<BigInteger> bi = PolyUtil.integerFromModularCoefficients(ifac, b); 302 Bi.add(bi); 303 } 304 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(ifac, C); 305 //System.out.println("Ai = " + Ai); 306 //System.out.println("Ci = " + Ci); 307 308 //List<GenPolynomial<MOD>> Aq = new ArrayList<GenPolynomial<MOD>>(A.size()); 309 //for (GenPolynomial<BigInteger> ai : Ai) { 310 // GenPolynomial<MOD> aq = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, ai); 311 // Aq.add(aq); 312 //} 313 //System.out.println("Aq = " + Aq); 314 315 // compute error: 316 GenPolynomial<BigInteger> E = Ci; // - sum_i s_i b_i 317 int i = 0; 318 for (GenPolynomial<BigInteger> bi : Bi) { 319 E = E.subtract(bi.multiply(supi.get(i++))); 320 } 321 //System.out.println("E = " + E); 322 if (E.isZERO()) { 323 logger.info("liftDiophant leaving on zero E"); 324 return sup; 325 } 326 GenPolynomial<MOD> Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 327 //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); 328 logger.info("Ep(0," + pkfac.nvar + ") = " + Ep); 329 if (Ep.isZERO()) { 330 logger.info("liftDiophant leaving on zero Ep mod p^k"); 331 return sup; 332 } 333 for (int e = 1; e <= d; e++) { 334 //System.out.println("\ne = " + e + " -------------------------------------- " + pkfac.nvar); 335 GenPolynomial<GenPolynomial<MOD>> Epr = PolyUtil.<MOD> recursive(qrfac, Ep); 336 //System.out.println("Epr = " + Epr); 337 UnivPowerSeriesRing<GenPolynomial<MOD>> psfac = new UnivPowerSeriesRing<GenPolynomial<MOD>>( 338 qrfac); 339 //System.out.println("psfac = " + psfac); 340 TaylorFunction<GenPolynomial<MOD>> F = new PolynomialTaylorFunction<GenPolynomial<MOD>>(Epr); 341 //System.out.println("F = " + F); 342 //List<GenPolynomial<MOD>> Vs = new ArrayList<GenPolynomial<MOD>>(1); 343 GenPolynomial<MOD> vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); 344 //Vs.add(vq); 345 //System.out.println("Vs = " + Vs); 346 UnivPowerSeries<GenPolynomial<MOD>> Epst = psfac.seriesOfTaylor(F, vq); 347 //System.out.println("Epst = " + Epst); 348 GenPolynomial<MOD> cm = Epst.coefficient(e); 349 //System.out.println("cm = " + cm + ", cm.ring = " + cm.ring.toScript()); 350 if (cm.isZERO()) { 351 continue; 352 } 353 // recursion: 354 List<GenPolynomial<MOD>> S = HenselMultUtil.<MOD> liftDiophant(Ap, cm, Vp, d, k); 355 //System.out.println("S = " + S); 356 if (!ckfac.coFac.equals(S.get(0).ring.coFac)) { 357 throw new IllegalArgumentException( 358 "ckfac != pkfac: " + ckfac.coFac + " != " + S.get(0).ring.coFac); 359 } 360 if (pkfac.nvar == 2 && !HenselUtil.<MOD> isDiophantLift(Ap, S, cm)) { 361 //System.out.println("isDiophantLift: false"); 362 throw new NoLiftingException("isDiophantLift: false"); 363 } 364 mon = mon.multiply(xv); // Power.<GenPolynomial<MOD>> power(pkfac,xv,e); 365 //System.out.println("mon = " + mon); 366 //List<GenPolynomial<MOD>> Sp = new ArrayList<GenPolynomial<MOD>>(S.size()); 367 i = 0; 368 supi = new ArrayList<GenPolynomial<BigInteger>>(su.size()); 369 for (GenPolynomial<MOD> dd : S) { 370 //System.out.println("dd = " + dd); 371 GenPolynomial<MOD> de = dd.extend(pkfac, 0, 0L); 372 GenPolynomial<MOD> dm = de.multiply(mon); 373 //Sp.add(dm); 374 de = sup.get(i).sum(dm); 375 //System.out.println("dd = " + dd); 376 sup.set(i++, de); 377 GenPolynomial<BigInteger> spi = PolyUtil.integerFromModularCoefficients(ifac, dm); 378 supi.add(spi); 379 } 380 //System.out.println("Sp = " + Sp); 381 //System.out.println("sup = " + sup); 382 //System.out.println("supi = " + supi); 383 // compute new error 384 //E = E; // - sum_i s_i b_i 385 i = 0; 386 for (GenPolynomial<BigInteger> bi : Bi) { 387 E = E.subtract(bi.multiply(supi.get(i++))); 388 } 389 //System.out.println("E = " + E); 390 if (E.isZERO()) { 391 logger.info("liftDiophant leaving on zero E"); 392 return sup; 393 } 394 Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 395 //System.out.println("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); 396 logger.info("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); 397 if (Ep.isZERO()) { 398 logger.info("liftDiophant leaving on zero Ep mod p^k"); 399 return sup; 400 } 401 } 402 //System.out.println("*** done: " + pkfac.nvar); 403 return sup; 404 } 405 406 407 /** 408 * Modular Hensel lifting algorithm on coefficients test. Let p = 409 * f_i.ring.coFac.modul() and assume C == prod_{0,...,n-1} f_i mod p with 410 * gcd(f_i,f_j) == 1 mod p for i != j 411 * @param C integer polynomial 412 * @param Cp GenPolynomial mod p^k 413 * @param F = [f_0,...,f_{n-1}] list of monic modular polynomials. 414 * @param L = [g_0,...,g_{n-1}] list of lifted modular polynomials. 415 * @return true if C = prod_{0,...,n-1} g_i mod p^k, else false. 416 */ 417 @SuppressWarnings("unused") 418 public static <MOD extends GcdRingElem<MOD> & Modular> boolean isHenselLift(GenPolynomial<BigInteger> C, 419 GenPolynomial<MOD> Cp, List<GenPolynomial<MOD>> F, List<GenPolynomial<MOD>> L) { 420 boolean t = true; 421 GenPolynomialRing<MOD> qfac = L.get(0).ring; 422 GenPolynomial<MOD> q = qfac.getONE(); 423 for (GenPolynomial<MOD> fi : L) { 424 q = q.multiply(fi); 425 } 426 t = Cp.equals(q); 427 if (!t) { 428 System.out.println("Cp = " + Cp); 429 System.out.println("q = " + q); 430 System.out.println("Cp != q: " + Cp.subtract(q)); 431 return t; 432 } 433 GenPolynomialRing<BigInteger> dfac = C.ring; 434 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(dfac, q); 435 t = C.equals(Ci); 436 if (!t) { 437 System.out.println("C = " + C); 438 System.out.println("Ci = " + Ci); 439 System.out.println("C != Ci: " + C.subtract(Ci)); 440 return t; 441 } 442 // test L mod id(V) == F 443 return t; 444 } 445 446 447 /** 448 * Modular Hensel lifting algorithm, monic case. Let p = 449 * A_i.ring.coFac.modul() and assume ggt(a,b) == 1 mod p, for a, b in A. 450 * @param C monic GenPolynomial with integer coefficients 451 * @param Cp GenPolynomial mod p^k 452 * @param F list of modular GenPolynomials, mod (I_v, p^k ) 453 * @param V list of integer substitution values 454 * @param k desired approximation exponent p^k. 455 * @return [g'_1,..., g'_n] with prod_i g'_i = Cp mod p^k. 456 */ 457 public static <MOD extends GcdRingElem<MOD> & Modular> List<GenPolynomial<MOD>> liftHenselMonic( 458 GenPolynomial<BigInteger> C, GenPolynomial<MOD> Cp, List<GenPolynomial<MOD>> F, 459 List<BigInteger> V, long k) throws NoLiftingException { 460 GenPolynomialRing<MOD> pkfac = Cp.ring; 461 //if (pkfac.nvar == 1) { // V ignored 462 // return HenselUtil.<MOD> liftHenselMonic(C,F,k); 463 //} 464 long d = C.degree(); 465 //System.out.println("d = " + d); 466 // prepare stack of polynomial rings and polynomials 467 List<GenPolynomialRing<MOD>> Pfac = new ArrayList<GenPolynomialRing<MOD>>(); 468 List<GenPolynomial<MOD>> Ap = new ArrayList<GenPolynomial<MOD>>(); 469 List<MOD> Vb = new ArrayList<MOD>(); 470 MOD v = pkfac.coFac.fromInteger(V.get(0).getVal()); 471 Pfac.add(pkfac); 472 Ap.add(Cp); 473 Vb.add(v); 474 GenPolynomialRing<MOD> pf = pkfac; 475 GenPolynomial<MOD> ap = Cp; 476 for (int j = pkfac.nvar; j > 2; j--) { 477 pf = pf.contract(1); 478 Pfac.add(0, pf); 479 //MOD vp = pkfac.coFac.fromInteger(V.get(j - 2).getSymmetricInteger().getVal()); 480 MOD vp = pkfac.coFac.fromInteger(V.get(j - 2).getVal()); 481 //System.out.println("vp = " + vp); 482 Vb.add(1, vp); 483 ap = PolyUtil.<MOD> evaluateMain(pf, ap, vp); 484 Ap.add(0, ap); 485 } 486 //System.out.println("Pfac = " + Pfac); 487 if (debug) { 488 logger.debug("Pfac = " + Pfac); 489 } 490 //System.out.println("Ap = " + Ap); 491 //System.out.println("V = " + V); 492 //System.out.println("Vb = " + Vb); 493 // setup bi-variate base case 494 GenPolynomialRing<MOD> pk1fac = F.get(0).ring; 495 if (!pkfac.coFac.equals(pk1fac.coFac)) { 496 throw new IllegalArgumentException("F.ring != pkfac: " + pk1fac + " != " + pkfac); 497 } 498 // TODO: adjust leading coefficients 499 pkfac = Pfac.get(0); 500 //Cp = Ap.get(0); 501 //System.out.println("pkfac = " + pkfac.toScript()); 502 //System.out.println("pk1fac = " + pk1fac.toScript()); 503 GenPolynomialRing<BigInteger> i1fac = new GenPolynomialRing<BigInteger>(new BigInteger(), pk1fac); 504 //System.out.println("i1fac = " + i1fac.toScript()); 505 List<GenPolynomial<BigInteger>> Bi = new ArrayList<GenPolynomial<BigInteger>>(F.size()); 506 for (GenPolynomial<MOD> b : F) { 507 GenPolynomial<BigInteger> bi = PolyUtil.integerFromModularCoefficients(i1fac, b); 508 Bi.add(bi); 509 } 510 //System.out.println("Bi = " + Bi); 511 // evaluate Cp at v_n: 512 //ModularRingFactory<MOD> cf = (ModularRingFactory<MOD>) pkfac.coFac; 513 //MOD vp = cf.fromInteger(v.getSymmetricInteger().getVal()); 514 //System.out.println("v = " + v + ", vp = " + vp); 515 GenPolynomialRing<MOD> ckfac; // = pkfac.contract(1); 516 //GenPolynomial<MOD> Cs = PolyUtil.<MOD> evaluateMain(ckfac, Cp, vp); 517 //System.out.println("Cp = " + Cp); 518 //System.out.println("Cs = " + Cs); 519 520 List<GenPolynomial<MOD>> U = new ArrayList<GenPolynomial<MOD>>(F.size()); 521 for (GenPolynomial<MOD> b : F) { 522 GenPolynomial<MOD> bi = b.extend(pkfac, 0, 0L); 523 U.add(bi); 524 } 525 //System.out.println("U = " + U); 526 List<GenPolynomial<MOD>> U1 = F; 527 //System.out.println("U1 = " + U1); 528 529 GenPolynomial<BigInteger> E = C.ring.getZERO(); 530 List<MOD> Vh = new ArrayList<MOD>(); 531 532 while (Pfac.size() > 0) { // loop through stack of polynomial rings 533 pkfac = Pfac.remove(0); 534 Cp = Ap.remove(0); 535 v = Vb.remove(0); 536 //Vh.add(0,v); 537 //System.out.println("\npkfac = " + pkfac.toScript() + " ================================== " + Vh); 538 539 // (x_n - v) 540 GenPolynomial<MOD> mon = pkfac.getONE(); 541 GenPolynomial<MOD> xv = pkfac.univariate(0, 1); 542 xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); 543 //System.out.println("xv = " + xv); 544 545 long deg = Cp.degree(pkfac.nvar - 1); 546 //System.out.println("deg = " + deg); 547 548 GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(new BigInteger(), pkfac); 549 //System.out.println("ifac = " + ifac.toScript()); 550 List<GenPolynomial<BigInteger>> Bip = new ArrayList<GenPolynomial<BigInteger>>(F.size()); 551 for (GenPolynomial<BigInteger> b : Bi) { 552 GenPolynomial<BigInteger> bi = b.extend(ifac, 0, 0L); 553 Bip.add(bi); 554 } 555 Bi = Bip; 556 //System.out.println("Bi = " + Bi); 557 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(ifac, Cp); 558 //System.out.println("Ci = " + Ci); 559 560 // compute error: 561 E = ifac.getONE(); 562 for (GenPolynomial<BigInteger> bi : Bi) { 563 E = E.multiply(bi); 564 } 565 E = Ci.subtract(E); 566 //System.out.println("E = " + E); 567 GenPolynomial<MOD> Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 568 //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); 569 logger.info("Ep(0," + deg + "," + pkfac.nvar + ") = " + Ep); 570 571 String[] mn = new String[] { pkfac.getVars()[pkfac.nvar - 1] }; 572 ckfac = pkfac.contract(1); 573 GenPolynomialRing<GenPolynomial<MOD>> pkrfac = new GenPolynomialRing<GenPolynomial<MOD>>(ckfac, 1, 574 mn); 575 //System.out.println("pkrfac = " + pkrfac.toScript()); 576 577 for (int e = 1; e <= deg && !Ep.isZERO(); e++) { 578 //System.out.println("\ne = " + e + " -------------------------------------- " + pkfac.nvar); 579 GenPolynomial<GenPolynomial<MOD>> Epr = PolyUtil.<MOD> recursive(pkrfac, Ep); 580 //System.out.println("Epr = " + Epr); 581 UnivPowerSeriesRing<GenPolynomial<MOD>> psfac = new UnivPowerSeriesRing<GenPolynomial<MOD>>( 582 pkrfac); 583 //System.out.println("psfac = " + psfac); 584 TaylorFunction<GenPolynomial<MOD>> T = new PolynomialTaylorFunction<GenPolynomial<MOD>>(Epr); 585 //System.out.println("T = " + T); 586 //List<GenPolynomial<MOD>> Vs = new ArrayList<GenPolynomial<MOD>>(1); 587 GenPolynomial<MOD> vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); 588 //Vs.add(vq); 589 //System.out.println("Vs = " + Vs + ", Vh = " + Vh); 590 UnivPowerSeries<GenPolynomial<MOD>> Epst = psfac.seriesOfTaylor(T, vq); 591 //System.out.println("Epst = " + Epst); 592 logger.info("Epst(" + e + "," + deg + ", " + pkfac.nvar + ") = " + Epst); 593 GenPolynomial<MOD> cm = Epst.coefficient(e); 594 //System.out.println("cm = " + cm); 595 if (cm.isZERO()) { 596 continue; 597 } 598 List<GenPolynomial<MOD>> Ud = HenselMultUtil.<MOD> liftDiophant(U1, cm, Vh, d, k); 599 //System.out.println("Ud = " + Ud); 600 601 mon = mon.multiply(xv); 602 //System.out.println("mon = " + mon); 603 //List<GenPolynomial<MOD>> Sd = new ArrayList<GenPolynomial<MOD>>(Ud.size()); 604 int i = 0; 605 List<GenPolynomial<BigInteger>> Si = new ArrayList<GenPolynomial<BigInteger>>(Ud.size()); 606 for (GenPolynomial<MOD> dd : Ud) { 607 //System.out.println("dd = " + dd); 608 GenPolynomial<MOD> de = dd.extend(pkfac, 0, 0L); 609 GenPolynomial<MOD> dm = de.multiply(mon); 610 //Sd.add(dm); 611 de = U.get(i).sum(dm); 612 //System.out.println("de = " + de); 613 U.set(i++, de); 614 GenPolynomial<BigInteger> si = PolyUtil.integerFromModularCoefficients(ifac, de); 615 Si.add(si); 616 } 617 //System.out.println("Sd = " + Sd); 618 //System.out.println("U = " + U); 619 //System.out.println("Si = " + Si); 620 621 // compute new error: 622 E = ifac.getONE(); 623 for (GenPolynomial<BigInteger> bi : Si) { 624 E = E.multiply(bi); 625 } 626 E = Ci.subtract(E); 627 //System.out.println("E = " + E); 628 Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 629 //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); 630 logger.info("Ep(" + e + "," + deg + "," + pkfac.nvar + ") = " + Ep); 631 } 632 Vh.add(v); 633 U1 = U; 634 if (Pfac.size() > 0) { 635 List<GenPolynomial<MOD>> U2 = new ArrayList<GenPolynomial<MOD>>(U.size()); 636 pkfac = Pfac.get(0); 637 for (GenPolynomial<MOD> b : U) { 638 GenPolynomial<MOD> bi = b.extend(pkfac, 0, 0L); 639 U2.add(bi); 640 } 641 U = U2; 642 //System.out.println("U = " + U); 643 } 644 } 645 if (E.isZERO()) { 646 logger.info("liftHensel leaving with zero E"); 647 } 648 return U; 649 } 650 651 652 /** 653 * Modular Hensel lifting algorithm. Let p = A_i.ring.coFac.modul() and 654 * assume ggt(a,b) == 1 mod p, for a, b in A. 655 * @param C GenPolynomial with integer coefficients 656 * @param Cp GenPolynomial C mod p^k 657 * @param F list of modular GenPolynomials, mod (I_v, p^k ) 658 * @param V list of integral substitution values 659 * @param k desired approximation exponent p^k. 660 * @param G list of leading coefficients of the factors of C. 661 * @return [g'_1,..., g'_n] with prod_i g'_i = Cp mod p^k. 662 */ 663 public static <MOD extends GcdRingElem<MOD> & Modular> List<GenPolynomial<MOD>> liftHensel( 664 GenPolynomial<BigInteger> C, GenPolynomial<MOD> Cp, List<GenPolynomial<MOD>> F, 665 List<BigInteger> V, long k, List<GenPolynomial<BigInteger>> G) throws NoLiftingException { 666 GenPolynomialRing<MOD> pkfac = Cp.ring; 667 long d = C.degree(); 668 //System.out.println("C = " + C); 669 //System.out.println("Cp = " + Cp); 670 //System.out.println("G = " + G); 671 672 //GenPolynomial<BigInteger> cd = G.get(0); // 1 673 //System.out.println("cd = " + cd + ", ring = " + C.ring); 674 //if ( cd.equals(C.ring.univariate(0)) ) { 675 // System.out.println("cd == G[1]"); 676 //} 677 // G mod p^k, in all variables 678 GenPolynomialRing<MOD> pkfac1 = new GenPolynomialRing<MOD>(pkfac.coFac, G.get(0).ring); 679 List<GenPolynomial<MOD>> Lp = new ArrayList<GenPolynomial<MOD>>(G.size()); 680 for (GenPolynomial<BigInteger> cd1 : G) { 681 GenPolynomial<MOD> cdq = PolyUtil.<MOD> fromIntegerCoefficients(pkfac1, cd1); 682 cdq = cdq.extendLower(pkfac, 0, 0L); // reintroduce lower variable 683 Lp.add(cdq); 684 } 685 logger.info("G modulo p^k: " + Lp); // + ", ring = " + pkfac1); 686 687 // prepare stack of polynomial rings, polynomials and evaluated leading coefficients 688 List<GenPolynomialRing<MOD>> Pfac = new ArrayList<GenPolynomialRing<MOD>>(); 689 List<GenPolynomial<MOD>> Ap = new ArrayList<GenPolynomial<MOD>>(); 690 List<List<GenPolynomial<MOD>>> Gp = new ArrayList<List<GenPolynomial<MOD>>>(); 691 List<MOD> Vb = new ArrayList<MOD>(); 692 //MOD v = V.get(0); // fromInteger 693 Pfac.add(pkfac); 694 Ap.add(Cp); 695 Gp.add(Lp); 696 GenPolynomialRing<MOD> pf = pkfac; 697 //GenPolynomialRing<MOD> pf1 = pkfac1; 698 GenPolynomial<MOD> ap = Cp; 699 List<GenPolynomial<MOD>> Lpp = Lp; 700 for (int j = pkfac.nvar; j > 2; j--) { 701 pf = pf.contract(1); 702 Pfac.add(0, pf); 703 //MOD vp = pkfac.coFac.fromInteger(V.get(pkfac.nvar - j).getSymmetricInteger().getVal()); 704 MOD vp = pkfac.coFac.fromInteger(V.get(pkfac.nvar - j).getVal()); 705 //System.out.println("vp = " + vp); 706 Vb.add(vp); 707 ap = PolyUtil.<MOD> evaluateMain(pf, ap, vp); 708 Ap.add(0, ap); 709 List<GenPolynomial<MOD>> Lps = new ArrayList<GenPolynomial<MOD>>(Lpp.size()); 710 for (GenPolynomial<MOD> qp : Lpp) { 711 GenPolynomial<MOD> qpe = PolyUtil.<MOD> evaluateMain(pf, qp, vp); 712 Lps.add(qpe); 713 } 714 //System.out.println("Lps = " + Lps); 715 Lpp = Lps; 716 Gp.add(0, Lpp); 717 } 718 Vb.add(pkfac.coFac.fromInteger(V.get(pkfac.nvar - 2).getVal())); 719 //System.out.println("Pfac = " + Pfac); 720 if (debug) { 721 logger.debug("Pfac = " + Pfac); 722 } 723 //System.out.println("Ap = " + Ap); 724 //System.out.println("Gp = " + Gp); 725 //System.out.println("Gp[0] = " + Gp.get(0) + ", Gp[0].ring = " + Gp.get(0).get(0).ring); 726 //System.out.println("V = " + V); 727 //System.out.println("Vb = " + Vb + ", V == Vb: " + V.equals(Vb)); 728 729 // check bi-variate base case 730 GenPolynomialRing<MOD> pk1fac = F.get(0).ring; 731 if (!pkfac.coFac.equals(pk1fac.coFac)) { 732 throw new IllegalArgumentException("F.ring != pkfac: " + pk1fac + " != " + pkfac); 733 } 734 735 // init recursion 736 List<GenPolynomial<MOD>> U = F; 737 //logger.info("to lift U = " + U); // + ", U1.ring = " + U1.get(0).ring); 738 GenPolynomial<BigInteger> E = C.ring.getZERO(); 739 List<MOD> Vh = new ArrayList<MOD>(); 740 List<GenPolynomial<BigInteger>> Si; // = new ArrayList<GenPolynomial<BigInteger>>(F.size()); 741 MOD v = null; 742 743 while (Pfac.size() > 0) { // loop through stack of polynomial rings 744 pkfac = Pfac.remove(0); 745 Cp = Ap.remove(0); 746 Lpp = Gp.remove(0); 747 v = Vb.remove(Vb.size() - 1); // last in stack 748 //System.out.println("\npkfac = " + pkfac.toScript() + " ================================== " + v); 749 logger.info("stack loop: pkfac = " + pkfac.toScript() + " v = " + v); 750 751 List<GenPolynomial<MOD>> U1 = U; 752 logger.info("to lift U1 = " + U1); // + ", U1.ring = " + U1.get(0).ring); 753 U = new ArrayList<GenPolynomial<MOD>>(U1.size()); 754 755 // update U, replace leading coefficient if required 756 int j = 0; 757 for (GenPolynomial<MOD> b : U1) { 758 //System.out.println("b = " + b + ", b.ring = " + b.ring); 759 GenPolynomial<MOD> bi = b.extend(pkfac, 0, 0L); 760 GenPolynomial<MOD> li = Lpp.get(j); 761 if (!li.isONE()) { 762 //System.out.println("li = " + li + ", li.ring = " + li.ring); 763 //System.out.println("bi = " + bi); 764 GenPolynomialRing<GenPolynomial<MOD>> pkrfac = pkfac.recursive(pkfac.nvar - 1); 765 //System.out.println("pkrfac = " + pkrfac); 766 GenPolynomial<GenPolynomial<MOD>> br = PolyUtil.<MOD> recursive(pkrfac, bi); 767 //System.out.println("br = " + br); 768 GenPolynomial<GenPolynomial<MOD>> bs = PolyUtil.<MOD> switchVariables(br); 769 //System.out.println("bs = " + bs + ", bs.ring = " + bs.ring); 770 771 GenPolynomial<GenPolynomial<MOD>> lr = PolyUtil.<MOD> recursive(pkrfac, li); 772 //System.out.println("lr = " + lr); 773 GenPolynomial<GenPolynomial<MOD>> ls = PolyUtil.<MOD> switchVariables(lr); 774 //System.out.println("ls = " + ls + ", ls.ring = " + ls.ring); 775 if (!ls.isConstant() && !ls.isZERO()) { 776 throw new RuntimeException("ls not constant " + ls + ", li = " + li); 777 } 778 bs.doPutToMap(bs.leadingExpVector(), ls.leadingBaseCoefficient()); 779 //System.out.println("bs = " + bs + ", bs.ring = " + bs.ring); 780 br = PolyUtil.<MOD> switchVariables(bs); 781 //System.out.println("br = " + br); 782 bi = PolyUtil.<MOD> distribute(pkfac, br); 783 //System.out.println("bi = " + bi); 784 } 785 U.add(bi); 786 j++; 787 } 788 logger.info("U with leading coefficient replaced = " + U); // + ", U.ring = " + U.get(0).ring); 789 790 // (x_n - v) 791 GenPolynomial<MOD> mon = pkfac.getONE(); 792 GenPolynomial<MOD> xv = pkfac.univariate(0, 1); 793 xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); 794 //System.out.println("xv = " + xv); 795 796 long deg = Cp.degree(pkfac.nvar - 1); 797 //System.out.println("deg = " + deg + ", degv = " + Cp.degreeVector()); 798 799 // convert to integer polynomials 800 GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(new BigInteger(), pkfac); 801 //System.out.println("ifac = " + ifac.toScript()); 802 List<GenPolynomial<BigInteger>> Bi = PolyUtil.integerFromModularCoefficients(ifac, U); 803 //System.out.println("Bi = " + Bi); 804 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(ifac, Cp); 805 //System.out.println("Ci = " + Ci); 806 807 // compute error: 808 E = ifac.getONE(); 809 for (GenPolynomial<BigInteger> bi : Bi) { 810 E = E.multiply(bi); 811 } 812 //System.out.println("E = " + E); 813 E = Ci.subtract(E); 814 //System.out.println("E = " + E); 815 GenPolynomial<MOD> Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 816 logger.info("Ep(0," + deg + "," + pkfac.nvar + ") = " + Ep); 817 818 GenPolynomialRing<GenPolynomial<MOD>> pkrfac = pkfac.recursive(1); 819 GenPolynomialRing<MOD> ckfac = (GenPolynomialRing<MOD>) pkrfac.coFac; 820 //System.out.println("pkrfac = " + pkrfac.toScript()); 821 822 for (int e = 1; e <= deg && !Ep.isZERO(); e++) { 823 //System.out.println("\ne = " + e + " -------------------------------------- " + deg); 824 logger.info("approximation loop: e = " + e + " of deg = " + deg); 825 GenPolynomial<GenPolynomial<MOD>> Epr = PolyUtil.<MOD> recursive(pkrfac, Ep); 826 //System.out.println("Epr = " + Epr); 827 UnivPowerSeriesRing<GenPolynomial<MOD>> psfac = new UnivPowerSeriesRing<GenPolynomial<MOD>>( 828 pkrfac); 829 //System.out.println("psfac = " + psfac); 830 TaylorFunction<GenPolynomial<MOD>> T = new PolynomialTaylorFunction<GenPolynomial<MOD>>(Epr); 831 //System.out.println("T = " + T); 832 GenPolynomial<MOD> vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); 833 //System.out.println("vq = " + vq + ", Vh = " + Vh); 834 UnivPowerSeries<GenPolynomial<MOD>> Epst = psfac.seriesOfTaylor(T, vq); 835 //System.out.println("Epst = " + Epst); 836 logger.info("Epst(" + e + "," + deg + "," + pkfac.nvar + ") = " + Epst); 837 GenPolynomial<MOD> cm = Epst.coefficient(e); 838 if (cm.isZERO()) { 839 //System.out.println("cm = " + cm); 840 continue; 841 } 842 List<GenPolynomial<MOD>> Ud = HenselMultUtil.<MOD> liftDiophant(U1, cm, Vh, d, k); 843 //System.out.println("Ud = " + Ud); 844 845 mon = mon.multiply(xv); 846 //System.out.println("mon = " + mon); 847 //List<GenPolynomial<MOD>> Sd = new ArrayList<GenPolynomial<MOD>>(Ud.size()); 848 int i = 0; 849 Si = new ArrayList<GenPolynomial<BigInteger>>(Ud.size()); 850 for (GenPolynomial<MOD> dd : Ud) { 851 //System.out.println("dd = " + dd); 852 GenPolynomial<MOD> de = dd.extend(pkfac, 0, 0L); 853 GenPolynomial<MOD> dm = de.multiply(mon); 854 //Sd.add(dm); 855 de = U.get(i).sum(dm); 856 //System.out.println("de = " + de); 857 U.set(i++, de); 858 GenPolynomial<BigInteger> si = PolyUtil.integerFromModularCoefficients(ifac, de); 859 Si.add(si); 860 } 861 //System.out.println("Sd = " + Sd); 862 //System.out.println("U = " + U + ", U.ring = " + U.get(0).ring); 863 //System.out.println("Si = " + Si); 864 865 // compute new error: 866 E = ifac.getONE(); 867 for (GenPolynomial<BigInteger> bi : Si) { 868 E = E.multiply(bi); 869 } 870 E = Ci.subtract(E); 871 //System.out.println("E = " + E); 872 Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 873 //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); 874 logger.info("Ep(" + e + "," + deg + "," + pkfac.nvar + ") = " + Ep); 875 } 876 Vh.add(v); 877 GenPolynomial<MOD> Uf = U.get(0).ring.getONE(); 878 for (GenPolynomial<MOD> Upp : U) { 879 Uf = Uf.multiply(Upp); 880 } 881 if (false && !Cp.leadingExpVector().equals(Uf.leadingExpVector())) { // not meanigfull test 882 System.out.println("\nU = " + U); 883 System.out.println("Cp = " + Cp); 884 System.out.println("Uf = " + Uf); 885 //System.out.println("Cp.ring = " + Cp.ring.toScript() + ", Uf.ring = " + Uf.ring.toScript() + "\n"); 886 System.out.println(""); 887 //throw new NoLiftingException("no factorization, Cp != Uf"); 888 } 889 } 890 if (E.isZERO()) { 891 logger.info("liftHensel leaving with zero E, Ep"); 892 } 893 if (false && debug) { 894 // remove normalization required ?? 895 GreatestCommonDivisorAbstract<BigInteger> ufd = GCDFactory.getImplementation(new BigInteger()); 896 List<GenPolynomial<BigInteger>> Fii = new ArrayList<GenPolynomial<BigInteger>>(U.size()); 897 for (GenPolynomial<BigInteger> bi : Si) { 898 GenPolynomial<BigInteger> ci = ufd.content(bi); //ufd.primitivePart(bi); // ?? 899 if (!ci.isONE()) { 900 System.out.println("bi = " + bi + ", cont(bi) = " + ci); 901 } 902 //Fii.add(ci); 903 } 904 //Si = Fii; 905 //System.out.println("Si = " + Si); 906 } 907 logger.info("multivariate lift: U = " + U + ", of " + F); 908 return U; 909 } 910 911 912 /** 913 * Modular Hensel full lifting algorithm. Let p = A_i.ring.coFac.modul() and 914 * assume ggt(a,b) == 1 mod p, for a, b in A. 915 * @param C GenPolynomial with integer coefficients 916 * @param F list of modular GenPolynomials, mod (I_v, p ) 917 * @param V list of integer substitution values 918 * @param k desired approximation exponent p^k. 919 * @param G = [g_1,...,g_n] list of factors of leading coefficients. 920 * @return [c_1,..., c_n] with prod_i c_i = C mod p^k. 921 */ 922 @SuppressWarnings("unchecked") 923 public static <MOD extends GcdRingElem<MOD> & Modular> List<GenPolynomial<MOD>> liftHenselFull( 924 GenPolynomial<BigInteger> C, List<GenPolynomial<MOD>> F, List<BigInteger> V, long k, 925 List<GenPolynomial<BigInteger>> G) throws NoLiftingException { 926 if (F == null || F.size() == 0) { 927 return new ArrayList<GenPolynomial<MOD>>(); 928 } 929 GenPolynomialRing<MOD> pkfac = F.get(0).ring; 930 //long d = C.degree(); 931 // setup q = p^k 932 RingFactory<MOD> cfac = pkfac.coFac; 933 ModularRingFactory<MOD> pcfac = (ModularRingFactory<MOD>) cfac; 934 //System.out.println("pcfac = " + pcfac); 935 BigInteger p = pcfac.getIntegerModul(); 936 BigInteger q = p.power(k); 937 ModularRingFactory<MOD> mcfac; 938 if (ModLongRing.MAX_LONG.compareTo(q.getVal()) > 0) { 939 mcfac = (ModularRingFactory) new ModLongRing(q.getVal()); 940 } else { 941 mcfac = (ModularRingFactory) new ModIntegerRing(q.getVal()); 942 } 943 //System.out.println("mcfac = " + mcfac); 944 945 // convert C from Z[...] to Z_q[...] 946 GenPolynomialRing<MOD> qcfac = new GenPolynomialRing<MOD>(mcfac, C.ring); 947 GenPolynomial<MOD> Cq = PolyUtil.<MOD> fromIntegerCoefficients(qcfac, C); 948 //System.out.println("C = " + C); 949 //System.out.println("Cq = " + Cq); 950 951 // convert g_i from Z[...] to Z_q[...] 952 GenPolynomialRing<MOD> gcfac = new GenPolynomialRing<MOD>(mcfac, G.get(0).ring); 953 List<GenPolynomial<MOD>> GQ = new ArrayList<GenPolynomial<MOD>>(); 954 boolean allOnes = true; 955 for (GenPolynomial<BigInteger> g : G) { 956 if (!g.isONE()) { 957 allOnes = false; 958 } 959 GenPolynomial<MOD> gq = PolyUtil.<MOD> fromIntegerCoefficients(gcfac, g); 960 GQ.add(gq); 961 } 962 //System.out.println("G = " + G); 963 //System.out.println("GQ = " + GQ); 964 965 // evaluate C to Z_q[x] 966 GenPolynomialRing<MOD> pf = qcfac; 967 GenPolynomial<MOD> ap = Cq; 968 for (int j = C.ring.nvar; j > 1; j--) { 969 pf = pf.contract(1); 970 //MOD vp = mcfac.fromInteger(V.get(C.ring.nvar - j).getSymmetricInteger().getVal()); 971 MOD vp = mcfac.fromInteger(V.get(C.ring.nvar - j).getVal()); 972 //System.out.println("vp = " + vp); 973 ap = PolyUtil.<MOD> evaluateMain(pf, ap, vp); 974 //System.out.println("ap = " + ap); 975 } 976 GenPolynomial<MOD> Cq1 = ap; 977 //System.out.println("Cq1 = " + Cq1); 978 if (Cq1.isZERO()) { 979 throw new NoLiftingException("C mod (I, p^k) == 0: " + C); 980 } 981 GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(new BigInteger(), pf); 982 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(ifac, Cq1); 983 //System.out.println("Ci = " + Ci); 984 GreatestCommonDivisorAbstract<BigInteger> ufd = GCDFactory.getImplementation(new BigInteger()); 985 Ci = Ci.abs(); 986 BigInteger cCi = ufd.baseContent(Ci); 987 Ci = Ci.divide(cCi); 988 //System.out.println("cCi = " + cCi); 989 //System.out.println("Ci = " + Ci); 990 ////System.out.println("F.fac = " + F.get(0).ring); 991 992 // evaluate G to Z_q 993 //List<GenPolynomial<MOD>> GP = new ArrayList<GenPolynomial<MOD>>(); 994 for (GenPolynomial<MOD> gq : GQ) { 995 GenPolynomialRing<MOD> gf = gcfac; 996 GenPolynomial<MOD> gp = gq; 997 for (int j = gcfac.nvar; j > 1; j--) { 998 gf = gf.contract(1); 999 //MOD vp = mcfac.fromInteger(V.get(gcfac.nvar - j).getSymmetricInteger().getVal()); 1000 MOD vp = mcfac.fromInteger(V.get(gcfac.nvar - j).getVal()); 1001 //System.out.println("vp = " + vp); 1002 gp = PolyUtil.<MOD> evaluateMain(gf, gp, vp); 1003 //System.out.println("gp = " + gp); 1004 } 1005 //GP.add(gp); 1006 } 1007 //System.out.println("GP = " + GP); // + ", GP.ring = " + GP.get(0).ring); 1008 1009 // leading coefficient for recursion base, for Cq1 and list GP 1010 BigInteger gi0 = Ci.leadingBaseCoefficient(); // gq0.getSymmetricInteger(); 1011 //System.out.println("gi0 = " + gi0); 1012 1013 // lift F to Z_{p^k}[x] 1014 //System.out.println("Ci = " + Ci + ", F = " + F + ", k = " + k + ", p = " + F.get(0).ring + ", gi0 = " + gi0); 1015 List<GenPolynomial<MOD>> U1 = null; 1016 if (gi0.isONE()) { 1017 U1 = HenselUtil.<MOD> liftHenselMonic(Ci, F, k); 1018 } else { 1019 U1 = HenselUtil.<MOD> liftHensel(Ci, F, k, gi0); // gi0 TODO ?? 1020 } 1021 logger.info("univariate lift: Ci = " + Ci + ", F = " + F + ", U1 = " + U1); 1022 //System.out.println("U1.fac = " + U1.get(0).ring); 1023 1024 // adjust leading coefficients of U1 with F 1025 List<GenPolynomial<BigInteger>> U1i = PolyUtil.<MOD> integerFromModularCoefficients(Ci.ring, U1); 1026 //System.out.println("U1i = " + U1i); 1027 boolean t = HenselUtil.isHenselLift(Ci, q, p, U1i); 1028 //System.out.println("isLift(U1) = " + t); 1029 if (!t) { 1030 //System.out.println("NoLiftingException, Ci = " + Ci + ", U1i = " + U1i); 1031 throw new NoLiftingException("Ci = " + Ci + ", U1i = " + U1i); 1032 } 1033 MOD cC = mcfac.fromInteger(cCi.getVal()); 1034 List<GenPolynomial<MOD>> U1f = PolyUtil.<MOD> fromIntegerCoefficients(F.get(0).ring, U1i); 1035 //System.out.println("U1f = " + U1f); 1036 List<GenPolynomial<MOD>> U1s = new ArrayList<GenPolynomial<MOD>>(U1.size()); 1037 int j = 0; 1038 int s = 0; 1039 for (GenPolynomial<MOD> u : U1) { 1040 GenPolynomial<MOD> uf = U1f.get(j); 1041 GenPolynomial<MOD> f = F.get(j); 1042 GenPolynomial<BigInteger> ui = U1i.get(j); 1043 GenPolynomial<BigInteger> gi = G.get(j); 1044 if (ui.signum() != gi.signum()) { 1045 //System.out.println("ui = " + ui + ", gi = " + gi); 1046 u = u.negate(); 1047 uf = uf.negate(); 1048 s++; 1049 } 1050 j++; 1051 if (uf.isConstant()) { 1052 //System.out.println("u = " + u); 1053 u = u.monic(); 1054 //System.out.println("u = " + u); 1055 u = u.multiply(cC); 1056 cC = cC.divide(cC); 1057 //System.out.println("u = " + u); 1058 } else { 1059 MOD x = f.leadingBaseCoefficient().divide(uf.leadingBaseCoefficient()); 1060 //System.out.println("x = " + x + ", xi = " + x.getSymmetricInteger()); 1061 if (!x.isONE()) { 1062 MOD xq = mcfac.fromInteger(x.getSymmetricInteger().getVal()); 1063 //System.out.println("xq = " + xq); 1064 u = u.multiply(xq); 1065 cC = cC.divide(xq); 1066 //System.out.println("cC = " + cC); 1067 } 1068 } 1069 U1s.add(u); 1070 } 1071 //if ( s % 2 != 0 || !cC.isONE()) { 1072 if (!cC.isONE()) { 1073 throw new NoLiftingException("s = " + s + ", Ci = " + Ci + ", U1i = " + U1i + ", cC = " + cC); 1074 } 1075 U1 = U1s; 1076 U1i = PolyUtil.<MOD> integerFromModularCoefficients(Ci.ring, U1); 1077 //System.out.println("U1i = " + U1i); 1078 U1f = PolyUtil.<MOD> fromIntegerCoefficients(F.get(0).ring, U1i); 1079 if (!F.equals(U1f)) { // evtl loop until reached 1080 System.out.println("F = " + F); 1081 System.out.println("U1f = " + U1f); 1082 throw new NoLiftingException("F = " + F + ", U1f = " + U1f); 1083 } 1084 logger.info("multivariate lift: U1 = " + U1); 1085 1086 // lift U to Z_{p^k}[x,...] 1087 //System.out.println("C = " + C + ", U1 = " + U1 + ", V = " + V + ", k = " + k + ", q = " + U1.get(0).ring + ", G = " + G); 1088 List<GenPolynomial<MOD>> U = null; 1089 if (allOnes) { 1090 U = HenselMultUtil.<MOD> liftHenselMonic(C, Cq, U1, V, k); 1091 } else { 1092 U = HenselMultUtil.<MOD> liftHensel(C, Cq, U1, V, k, G); 1093 } 1094 logger.info("multivariate lift: C = " + C + ", U1 = " + U1 + ", U = " + U); 1095 //System.out.println("U = " + U); 1096 //System.out.println("U.fac = " + U.get(0).ring); 1097 return U; 1098 } 1099 1100}