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