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