001/* 002 * $Id: GroebnerBaseSigSeqIter.java 5869 2018-07-20 15:53:10Z kredel $ 003 */ 004 005package edu.jas.gb; 006 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.Collections; 011 012import org.apache.logging.log4j.Logger; 013import org.apache.logging.log4j.LogManager; 014 015import edu.jas.poly.ExpVector; 016import edu.jas.poly.GenPolynomial; 017import edu.jas.poly.GenPolynomialRing; 018import edu.jas.poly.OrderedPolynomialList; 019import edu.jas.poly.PolyUtil; 020import edu.jas.structure.RingElem; 021 022 023/** 024 * Groebner Base signature based sequential iterative algorithm. Implements 025 * Groebner bases after the paper 026 * "Signature-based Algorithms to Compute Gröbner Bases" by Christian Eder and 027 * John Perry, ISSAC 2011. Compare the jython+JAS code in 028 * examples/basic_sigbased_gb.py. Originally the Python+Sage code is from 029 * http://www.math.usm.edu/perry/Research/basic_sigbased_gb.py 030 * 031 * @param <C> coefficient type 032 * @author Heinz Kredel 033 * 034 * @see edu.jas.application.GBAlgorithmBuilder 035 * @see edu.jas.gbufd.GBFactory 036 * @see edu.jas.gb.GroebnerBaseGGVSigSeqIter 037 * @see edu.jas.gb.GroebnerBaseArriSigSeqIter 038 * @see edu.jas.gb.GroebnerBaseF5zSigSeqIter 039 */ 040 041public class GroebnerBaseSigSeqIter<C extends RingElem<C>> extends GroebnerBaseAbstract<C> { 042 043 044 private static final Logger logger = LogManager.getLogger(GroebnerBaseSigSeqIter.class); 045 046 047 private static final boolean debug = logger.isDebugEnabled(); 048 049 050 final SigReductionSeq<C> sred; 051 052 053 /** 054 * Constructor. 055 */ 056 public GroebnerBaseSigSeqIter() { 057 this(new SigReductionSeq<C>()); 058 } 059 060 061 /** 062 * Constructor. 063 * @param red Reduction engine 064 */ 065 public GroebnerBaseSigSeqIter(SigReductionSeq<C> red) { 066 super(); 067 sred = red; 068 } 069 070 071 /** 072 * Groebner base signature iterative algorithm. 073 * @param modv module variable number. 074 * @param F polynomial list. 075 * @return GB(F) a Groebner base of F. 076 */ 077 public List<GenPolynomial<C>> GB(int modv, List<GenPolynomial<C>> F) { 078 List<GenPolynomial<C>> G = normalizeZerosOnes(F); 079 G = PolyUtil.<C> monic(G); 080 if (G.size() <= 1) { 081 return G; 082 } 083 // sort, no reverse 084 // G = OrderedPolynomialList.<C> sort(G); 085 G = OrderedPolynomialList.<C> sortDegree(G); 086 //no: Collections.reverse(G); 087 logger.info("G-sort = " + G); 088 List<GenPolynomial<C>> Gp = new ArrayList<GenPolynomial<C>>(); 089 for (GenPolynomial<C> p : G) { 090 if (logger.isInfoEnabled()) { 091 logger.info("p = " + p); 092 } 093 GenPolynomial<C> pp = red.normalform(Gp, p); 094 if (pp.isZERO()) { 095 continue; 096 } 097 Gp = GB(modv, Gp, p); 098 if (Gp.size() > 0) { 099 if (Gp.get(0).isONE()) { 100 return Gp; 101 } 102 } 103 } 104 return Gp; 105 } 106 107 108 /** 109 * Groebner base iterated. 110 * @param modv module variable number. 111 * @param G polynomial list of a Groebner base. 112 * @param f polynomial. 113 * @return GB(G,f) a Groebner base of G+(f). 114 */ 115 public List<GenPolynomial<C>> GB(int modv, List<GenPolynomial<C>> G, GenPolynomial<C> f) { 116 List<GenPolynomial<C>> F = new ArrayList<GenPolynomial<C>>(G); 117 GenPolynomial<C> g = f.monic(); 118 if (F.isEmpty()) { 119 F.add(g); 120 return F; // commutative 121 } 122 if (g.isZERO()) { 123 return F; 124 } 125 if (g.isONE()) { 126 F.clear(); 127 F.add(g); 128 return F; 129 } 130 GenPolynomialRing<C> ring = F.get(0).ring; 131 if (!ring.coFac.isField()) { 132 throw new IllegalArgumentException("coefficients not from a field"); 133 } 134 if (modv != 0) { 135 throw new UnsupportedOperationException("motv != 0 not implemented"); 136 } 137 // add signatures 138 List<SigPoly<C>> Gs = new ArrayList<SigPoly<C>>(); 139 for (GenPolynomial<C> p : F) { 140 Gs.add(new SigPoly<C>(ring.getZERO(), p)); 141 } 142 SigPoly<C> gs = new SigPoly<C>(ring.getONE(), g); 143 Gs.add(gs); 144 //logger.info("Gs = " + Gs); 145 // construct critical pair list 146 List<SigPair<C>> pairlist = new ArrayList<SigPair<C>>(); 147 for (SigPoly<C> p : Gs) { // F via continue 148 if (p.poly.equals(g)) { 149 continue; 150 } 151 pairlist.add(newPair(gs, p, Gs)); 152 } 153 //logger.info("start " + pairlist.size()); 154 logger.info("start " + Gs); 155 156 List<ExpVector> syz = initializeSyz(F, Gs); 157 List<SigPoly<C>> done = new ArrayList<SigPoly<C>>(); 158 159 SigPair<C> pair; 160 //SigPoly<C> pi, pj; 161 GenPolynomial<C> S, H, sigma; 162 while (!pairlist.isEmpty()) { 163 pairlist = pruneP(pairlist, syz); 164 if (pairlist.isEmpty()) { 165 continue; 166 } 167 List<SigPair<C>>[] spl = sred.minDegSubset(pairlist); 168 List<SigPair<C>> Sl = spl[0]; 169 long mdeg = sred.minimalSigDegree(Sl); 170 pairlist = spl[1]; 171 logger.info("treating " + Sl.size() + " signatures of degree " + mdeg); 172 //logger.info("Sl(" + mdeg + ") = " + Sl); 173 while (!Sl.isEmpty()) { 174 //logger.info("Sl_full = " + sred.sigmas(Sl)); 175 Sl = pruneS(Sl, syz, done, Gs); 176 if (Sl.isEmpty()) { 177 continue; 178 } 179 Sl = sred.sortSigma(Sl); 180 //logger.info("Sl_sort = " + Sl); 181 pair = Sl.remove(0); 182 if (pair == null) { 183 continue; 184 } 185 //logger.info("sigma = " + pair.sigma); 186 S = SPolynomial(pair); 187 SigPoly<C> Ss = new SigPoly<C>(pair.sigma, S); 188 if (S.isZERO()) { 189 updateSyz(syz, Ss); 190 done.add(Ss); 191 continue; 192 } 193 if (debug) { 194 logger.debug("ht(S) = " + S.leadingExpVector()); 195 } 196 197 SigPoly<C> Hs = sigNormalform(F, Gs, Ss); 198 H = Hs.poly; 199 sigma = Hs.sigma; 200 if (debug) { 201 logger.info("new polynomial = " + Hs); //.leadingExpVector() ); 202 } 203 if (H.isZERO()) { 204 updateSyz(syz, Hs); 205 done.add(Hs); 206 continue; 207 } 208 H = H.monic(); 209 if (debug) { 210 logger.info("ht(H) = " + H.leadingExpVector()); 211 } 212 213 if (H.isONE()) { 214 G.clear(); 215 G.add(H); 216 logger.info("end " + pairlist); 217 return G; // since no threads are activated 218 } 219 if (sred.isSigRedundant(Gs, Hs)) { 220 continue; 221 } 222 if (logger.isInfoEnabled()) { 223 //logger.info("sigma::h = " + sigma + " :: " + ring.toScript(H.leadingExpVector())); 224 logger.info("sigma::h = " + sigma + " :: " + H.leadingExpVector()); 225 } 226 if (H.length() > 0) { 227 for (SigPoly<C> p : Gs) { 228 if (p.poly.isZERO()) { 229 continue; 230 } 231 GenPolynomial<C> tau = p.sigma; 232 GenPolynomial<C>[] mult = SPolynomialFactors(Hs, p); 233 //System.out.print("sigma = " + sigma + ", tau = " + tau); 234 //System.out.println(", mult = " + Arrays.toString(mult)); 235 ExpVector se = sigma.leadingExpVector(); 236 ExpVector te = tau.leadingExpVector(); 237 if (mult[0].multiply(se).equals(mult[1].multiply(te))) { 238 //logger.info("skip by sigma"); 239 continue; 240 } 241 SigPair<C> pp; 242 //boolean xy = mult[0].multiply(se).compareTo(mult[1].multiply(te)) > 0; 243 if (mult[0].multiply(se).compareTo(mult[1].multiply(te)) > 0) { 244 pp = newPair(sigma.multiply(mult[0]), Hs, p, Gs); 245 } else { 246 pp = newPair(tau.multiply(mult[1]), p, Hs, Gs); 247 } 248 //System.out.println("new_pair " + pp.sigma + ", xy = " + xy + ", sigma = " + sigma + ", tau = " + tau + ", mult = " + Arrays.toString(mult) + ", m0*se = " + mult[0].multiply(se) + ", m1*te = " + mult[1].multiply(te) ); 249 if (pp.sigma.degree() == mdeg) { // mdeg is sigma.degree() 250 Sl.add(pp); // do not check contains 251 } else { 252 pairlist.add(pp); // do not check contains 253 } 254 } 255 Gs.add(Hs); 256 done.add(Hs); 257 } 258 } 259 } 260 logger.info("#sequential list before reduction = " + Gs.size()); 261 List<GenPolynomial<C>> Gp = sred.polys(Gs); 262 //logger.info("G_full = " + Gp); 263 G = minimalGB(Gp); 264 //G = red.irreducibleSet(Gp); 265 //G = OrderedPolynomialList.<C> sortDegree(G); 266 //logger.info("G_reduced = " + G); 267 logger.info("end " + pairlist); 268 return G; 269 } 270 271 272 /** 273 * S-Polynomial. 274 * @param A monic polynomial. 275 * @param B monic polynomial. 276 * @return spol(A,B) the S-polynomial of the A and B. 277 */ 278 GenPolynomial<C> SPolynomial(SigPoly<C> A, SigPoly<C> B) { 279 return sred.SPolynomial(A, B); 280 } 281 282 283 /** 284 * S-Polynomial. 285 * @param P pair. 286 * @return spol(A,B) the S-polynomial of the pair (A,B). 287 */ 288 GenPolynomial<C> SPolynomial(SigPair<C> P) { 289 return sred.SPolynomial(P.pi, P.pj); 290 } 291 292 293 /** 294 * S-Polynomial polynomial factors. 295 * @param A monic polynomial. 296 * @param B monic polynomial. 297 * @return polynomials [e,f] such that spol(A,B) = e*a - f*B. 298 */ 299 GenPolynomial<C>[] SPolynomialFactors(SigPoly<C> A, SigPoly<C> B) { 300 return sred.SPolynomialFactors(A, B); 301 } 302 303 304 /** 305 * Pair with signature. 306 * @param A polynomial with signature. 307 * @param B polynomial with signature. 308 * @param G polynomial ith signature list. 309 * @return signature pair according to algorithm. 310 */ 311 SigPair<C> newPair(SigPoly<C> A, SigPoly<C> B, List<SigPoly<C>> G) { 312 ExpVector e = A.poly.leadingExpVector().lcm(B.poly.leadingExpVector()) 313 .subtract(A.poly.leadingExpVector()); 314 return new SigPair<C>(e, A, B, G); 315 } 316 317 318 /** 319 * Pair with signature. 320 * @param s signature for pair. 321 * @param A polynomial with signature. 322 * @param B polynomial with signature. 323 * @param G polynomial ith signature list. 324 * @return signature pair according to algorithm. 325 */ 326 SigPair<C> newPair(GenPolynomial<C> s, SigPoly<C> A, SigPoly<C> B, List<SigPoly<C>> G) { 327 return new SigPair<C>(s, A, B, G); 328 } 329 330 331 /** 332 * Top normalform. 333 * @param A polynomial. 334 * @param F polynomial list. 335 * @param G polynomial list. 336 * @return nf(A) with respect to F and G. 337 */ 338 SigPoly<C> sigNormalform(List<GenPolynomial<C>> F, List<SigPoly<C>> G, SigPoly<C> A) { 339 return sred.sigNormalform(F, G, A); 340 } 341 342 343 /** 344 * Prune total pair list P. 345 * @param P pair list. 346 * @param syz list of exponent vectors representing syzygies. 347 * @return updated pair list. 348 */ 349 List<SigPair<C>> pruneP(List<SigPair<C>> P, List<ExpVector> syz) { 350 if (debug) { 351 logger.debug("unused " + syz); 352 } 353 return P; 354 } 355 356 357 /** 358 * Prune pair list of degree d. 359 * @param S pair list. 360 * @param syz list of exponent vectors representing syzygies. 361 * @param done list of treated polynomials. 362 * @param G polynomial with signature list. 363 * @return updated pair list. 364 */ 365 List<SigPair<C>> pruneS(List<SigPair<C>> S, List<ExpVector> syz, List<SigPoly<C>> done, 366 List<SigPoly<C>> G) { 367 if (debug) { 368 logger.debug("unused " + syz + " " + done + " " + G); 369 } 370 return S; 371 } 372 373 374 /** 375 * Initializes syzygy list. 376 * @param F polynomial list. 377 * @param G polynomial with signature list. 378 * @return list of exponent vectors representing syzygies. 379 */ 380 List<ExpVector> initializeSyz(List<GenPolynomial<C>> F, List<SigPoly<C>> G) { 381 if (debug) { 382 logger.debug("unused " + G + " " + F); 383 } 384 List<ExpVector> P = new ArrayList<ExpVector>(); 385 return P; 386 } 387 388 389 /** 390 * Update syzygy list. 391 * @param syz list of exponent vectors representing syzygies. 392 * @param r polynomial. <b>Note:</b> szy is modified to represent updated 393 * list of exponent vectors. 394 */ 395 void updateSyz(List<ExpVector> syz, SigPoly<C> r) { 396 if (debug) { 397 logger.debug("unused " + syz + " " + r); 398 } 399 return; 400 } 401 402}