001/* 002 * $Id$ 003 */ 004 005package edu.jas.gb; 006 007import java.util.ArrayList; 008import java.util.List; 009import java.util.ListIterator; 010 011import org.apache.logging.log4j.Logger; 012import org.apache.logging.log4j.LogManager; 013 014import edu.jas.structure.RingElem; 015import edu.jas.gb.OrderedPairlist; 016import edu.jas.poly.GenPolynomial; 017import edu.jas.poly.GenPolynomialRing; 018import edu.jas.poly.PolyUtil; 019import edu.jas.vector.BasicLinAlg; 020 021 022/** 023 * Groebner Base sequential algorithm. 024 * Implements Groebner bases and GB test. 025 * @param <C> coefficient type 026 * @author Heinz Kredel 027 * 028 * @see edu.jas.application.GBAlgorithmBuilder 029 * @see edu.jas.gbufd.GBFactory 030 */ 031 032public class GroebnerBaseSeq<C extends RingElem<C>> 033 extends GroebnerBaseAbstract<C> { 034 035 036 private static final Logger logger = LogManager.getLogger(GroebnerBaseSeq.class); 037 038 039 private static final boolean debug = logger.isDebugEnabled(); 040 041 042 /** 043 * Constructor. 044 */ 045 public GroebnerBaseSeq() { 046 super(); 047 } 048 049 050 /** 051 * Constructor. 052 * @param red Reduction engine 053 */ 054 public GroebnerBaseSeq(Reduction<C> red) { 055 super(red); 056 } 057 058 059 /** 060 * Constructor. 061 * @param pl pair selection strategy 062 */ 063 public GroebnerBaseSeq(PairList<C> pl) { 064 super(pl); 065 } 066 067 068 /** 069 * Constructor. 070 * @param red Reduction engine 071 * @param pl pair selection strategy 072 */ 073 public GroebnerBaseSeq(Reduction<C> red, PairList<C> pl) { 074 super(red,pl); 075 } 076 077 078 /** 079 * Groebner base using pairlist class. 080 * @param modv module variable number. 081 * @param F polynomial list. 082 * @return GB(F) a Groebner base of F. 083 */ 084 public List<GenPolynomial<C>> GB( int modv, List<GenPolynomial<C>> F ) { 085 List<GenPolynomial<C>> G = normalizeZerosOnes(F); 086 G = PolyUtil.<C> monic(G); 087 if ( G.size() <= 1 ) { 088 return G; 089 } 090 GenPolynomialRing<C> ring = G.get(0).ring; 091 if ( ! ring.coFac.isField() ) { 092 throw new IllegalArgumentException("coefficients not from a field"); 093 } 094 PairList<C> pairlist = strategy.create( modv, ring ); 095 pairlist.put(G); 096 logger.info("start {}", pairlist); 097 098 Pair<C> pair; 099 GenPolynomial<C> pi, pj, S, H; 100 while ( pairlist.hasNext() ) { 101 pair = pairlist.removeNext(); 102 //logger.debug("pair = {}", pair); 103 if ( pair == null ) { 104 continue; 105 } 106 pi = pair.pi; 107 pj = pair.pj; 108 if ( /*false &&*/ debug ) { 109 logger.debug("pi = {}", pi ); 110 logger.debug("pj = {}", pj ); 111 } 112 113 S = red.SPolynomial( pi, pj ); 114 if ( S.isZERO() ) { 115 pair.setZero(); 116 continue; 117 } 118 if ( debug ) { 119 logger.debug("ht(S) = {}", S.leadingExpVector() ); 120 } 121 122 H = red.normalform( G, S ); 123 if ( debug ) { 124 //logger.info("pair = {}", pair); 125 //logger.info("ht(S) = {}", S.monic()); //.leadingExpVector() ); 126 logger.info("ht(H) = {}", H.monic()); //.leadingExpVector() ); 127 } 128 if ( H.isZERO() ) { 129 pair.setZero(); 130 continue; 131 } 132 H = H.monic(); 133 if ( debug ) { 134 logger.info("ht(H) = {}", H.leadingExpVector() ); 135 } 136 137 H = H.monic(); 138 if ( H.isONE() ) { 139 G.clear(); G.add( H ); 140 pairlist.putOne(); 141 logger.info("end {}", pairlist); 142 return G; // since no threads are activated 143 } 144 if ( debug ) { 145 logger.info("H = {}", H ); 146 } 147 if ( H.length() > 0 ) { 148 //l++; 149 G.add( H ); 150 pairlist.put( H ); 151 } 152 } 153 logger.debug("#sequential list = {}", G.size()); 154 G = minimalGB(G); 155 logger.info("end {}", pairlist); 156 return G; 157 } 158 159 160 /** 161 * Extended Groebner base using critical pair class. 162 * @param modv module variable number. 163 * @param F polynomial list. 164 * @return a container for an extended Groebner base of F. 165 */ 166 @Override 167 public ExtendedGB<C> extGB(int modv, List<GenPolynomial<C>> F) { 168 if ( F == null || F.isEmpty() ) { 169 throw new IllegalArgumentException("null or empty F not allowed"); 170 } 171 List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>(); 172 List<List<GenPolynomial<C>>> F2G = new ArrayList<List<GenPolynomial<C>>>(); 173 List<List<GenPolynomial<C>>> G2F = new ArrayList<List<GenPolynomial<C>>>(); 174 PairList<C> pairlist = null; 175 boolean oneInGB = false; 176 int len = F.size(); 177 178 List<GenPolynomial<C>> row = null; 179 List<GenPolynomial<C>> rows = null; 180 List<GenPolynomial<C>> rowh = null; 181 GenPolynomialRing<C> ring = null; 182 GenPolynomial<C> H; 183 GenPolynomial<C> p; 184 185 int nzlen = 0; 186 for ( GenPolynomial<C> f : F ) { 187 if ( f.length() > 0 ) { 188 nzlen++; 189 } 190 if ( ring == null ) { 191 ring = f.ring; 192 } 193 } 194 GenPolynomial<C> mone = ring.getONE(); //.negate(); 195 int k = 0; 196 ListIterator<GenPolynomial<C>> it = F.listIterator(); 197 while ( it.hasNext() ) { 198 p = it.next(); 199 if ( p.length() > 0 ) { 200 row = blas.genVector(nzlen, null); 201 //C c = p.leadingBaseCoefficient(); 202 //c = c.inverse(); 203 //p = p.multiply( c ); 204 row.set( k, mone ); //.multiply(c) ); 205 k++; 206 if ( p.isUnit() ) { 207 G.clear(); G.add( p ); 208 G2F.clear(); G2F.add( row ); 209 oneInGB = true; 210 break; 211 } 212 G.add( p ); 213 G2F.add( row ); 214 if ( pairlist == null ) { 215 //pairlist = new OrderedPairlist<C>( modv, p.ring ); 216 pairlist = strategy.create( modv, p.ring ); 217 if ( ! p.ring.coFac.isField() ) { 218 throw new RuntimeException("coefficients not from a field"); 219 } 220 } 221 // putOne not required 222 pairlist.put( p ); 223 } else { 224 len--; 225 } 226 } 227 ExtendedGB<C> exgb; 228 if ( len <= 1 || oneInGB ) { 229 // adjust F2G 230 for ( GenPolynomial<C> f : F ) { 231 row = blas.genVector(G.size(), null); 232 H = red.normalform( row, G, f ); 233 if ( ! H.isZERO() ) { 234 logger.error("nonzero H = {}", H ); 235 } 236 F2G.add( row ); 237 } 238 exgb = new ExtendedGB<C>(F,G,F2G,G2F); 239 //System.out.println("exgb 1 = " + exgb); 240 return exgb; 241 } 242 243 Pair<C> pair; 244 int i, j; 245 GenPolynomial<C> pi; 246 GenPolynomial<C> pj; 247 GenPolynomial<C> S; 248 GenPolynomial<C> x; 249 GenPolynomial<C> y; 250 //GenPolynomial<C> z; 251 while ( pairlist.hasNext() && ! oneInGB ) { 252 pair = pairlist.removeNext(); 253 if ( pair == null ) { 254 continue; 255 } 256 i = pair.i; 257 j = pair.j; 258 pi = pair.pi; 259 pj = pair.pj; 260 if ( debug ) { 261 logger.info("i, pi = {}, {}", i, pi ); 262 logger.info("j, pj = {}, {}", j, pj ); 263 } 264 265 rows = blas.genVector(G.size(), null); 266 S = red.SPolynomial( rows, i, pi, j, pj ); 267 if ( debug ) { 268 logger.debug("is reduction S = " 269 + red.isReductionNF( rows, G, ring.getZERO(), S ) ); 270 } 271 if ( S.isZERO() ) { 272 // do not add to G2F 273 continue; 274 } 275 if ( debug ) { 276 logger.debug("ht(S) = {}", S.leadingExpVector() ); 277 } 278 279 rowh = blas.genVector(G.size(), null); 280 H = red.normalform( rowh, G, S ); 281 if ( debug ) { 282 logger.debug("is reduction H = " 283 + red.isReductionNF( rowh, G, S, H ) ); 284 } 285 if ( H.isZERO() ) { 286 // do not add to G2F 287 continue; 288 } 289 if ( debug ) { 290 logger.debug("ht(H) = {}", H.leadingExpVector() ); 291 } 292 293 row = blas.vectorCombineOld(rows,rowh); 294 // if ( debug ) { 295 // logger.debug("is reduction 0+sum(row,G) == H : " 296 // + red.isReductionNF( row, G, H, ring.getZERO() ) ); 297 // } 298 299 // H = H.monic(); 300 C c = H.leadingBaseCoefficient(); 301 c = c.inverse(); 302 H = H.multiply( c ); 303 row = blas.scalarProduct( mone.multiply(c), row ); 304 row.set( G.size(), mone ); 305 if ( H.isONE() ) { 306 // G.clear(); 307 G.add( H ); 308 G2F.add( row ); 309 oneInGB = true; 310 break; 311 } 312 if ( debug ) { 313 logger.debug("H = {}", H ); 314 } 315 G.add( H ); 316 pairlist.put( H ); 317 G2F.add( row ); 318 } 319 if ( debug ) { 320 exgb = new ExtendedGB<C>(F,G,F2G,G2F); 321 logger.info("exgb unnorm = {}", exgb); 322 } 323 G2F = normalizeMatrix( F.size(), G2F ); 324 if ( debug ) { 325 exgb = new ExtendedGB<C>(F,G,F2G,G2F); 326 logger.info("exgb nonmin = {}", exgb); 327 boolean t2 = isReductionMatrix( exgb ); 328 logger.info("exgb t2 = {}", t2); 329 } 330 exgb = minimalExtendedGB(F.size(),G,G2F); 331 G = exgb.G; 332 G2F = exgb.G2F; 333 logger.debug("#sequential list = {}", G.size()); 334 logger.info("{}", pairlist); 335 // setup matrices F and F2G 336 for ( GenPolynomial<C> f : F ) { 337 row = blas.genVector(G.size(), null); 338 H = red.normalform( row, G, f ); 339 if ( ! H.isZERO() ) { 340 logger.error("nonzero H = {}", H ); 341 } 342 F2G.add( row ); 343 } 344 exgb = new ExtendedGB<C>(F,G,F2G,G2F); 345 if ( debug ) { 346 logger.info("exgb nonmin = {}", exgb); 347 boolean t2 = isReductionMatrix( exgb ); 348 logger.info("exgb t2 = {}", t2); 349 } 350 return exgb; 351 } 352 353}