001/* 002 * $Id: SolvableGroebnerBaseAbstract.java 4184 2012-09-10 19:33:52Z kredel $ 003 */ 004 005package edu.jas.gb; 006 007import java.util.ArrayList; 008import java.util.List; 009import java.util.ListIterator; 010 011import org.apache.log4j.Logger; 012 013import edu.jas.poly.ExpVector; 014import edu.jas.poly.GenPolynomial; 015import edu.jas.poly.GenSolvablePolynomial; 016import edu.jas.poly.GenSolvablePolynomialRing; 017import edu.jas.poly.PolynomialList; 018 019import edu.jas.structure.RingElem; 020 021import edu.jas.vector.BasicLinAlg; 022 023 024/** 025 * Solvable Groebner Bases abstract class. 026 * Implements common left, right and twosided Groebner bases 027 * and left, right and twosided GB tests. 028 * @param <C> coefficient type 029 * @author Heinz Kredel. 030 */ 031 032public abstract class SolvableGroebnerBaseAbstract<C extends RingElem<C>> 033 implements SolvableGroebnerBase<C> { 034 035 private static final Logger logger = Logger.getLogger(SolvableGroebnerBaseAbstract.class); 036 private final boolean debug = logger.isDebugEnabled(); 037 038 039 /** 040 * Solvable reduction engine. 041 */ 042 protected SolvableReduction<C> sred; 043 044 045 /** 046 * Reduction engine. 047 */ 048 protected final Reduction<C> red; 049 050 051 /** 052 * Strategy for pair selection. 053 */ 054 public final PairList<C> strategy; 055 056 057 /** 058 * Linear algebra engine. 059 */ 060 protected final BasicLinAlg<GenPolynomial<C>> blas; 061 062 063 /** 064 * Constructor. 065 */ 066 public SolvableGroebnerBaseAbstract() { 067 this( new SolvableReductionSeq<C>() ); 068 } 069 070 071 /** 072 * Constructor. 073 * @param sred Solvable reduction engine 074 */ 075 public SolvableGroebnerBaseAbstract(SolvableReduction<C> sred) { 076 this(sred,new OrderedPairlist<C>()); 077 } 078 079 080 /** 081 * Constructor. 082 * @param sred Solvable reduction engine 083 * @param pl pair selection strategy 084 */ 085 public SolvableGroebnerBaseAbstract(SolvableReduction<C> sred, PairList<C> pl) { 086 this.red = new ReductionSeq<C>(); 087 this.sred = sred; 088 this.strategy = pl; 089 blas = new BasicLinAlg<GenPolynomial<C>>(); 090 } 091 092 093 /** 094 * Left Groebner base test. 095 * @param F solvable polynomial list. 096 * @return true, if F is a left Groebner base, else false. 097 */ 098 public boolean isLeftGB(List<GenSolvablePolynomial<C>> F) { 099 return isLeftGB(0,F); 100 } 101 102 103 /** 104 * Left Groebner base test. 105 * @param modv number of module variables. 106 * @param F solvable polynomial list. 107 * @return true, if F is a left Groebner base, else false. 108 */ 109 public boolean isLeftGB(int modv, 110 List<GenSolvablePolynomial<C>> F) { 111 GenSolvablePolynomial<C> pi, pj, s, h; 112 for ( int i = 0; i < F.size(); i++ ) { 113 pi = F.get(i); 114 for ( int j = i+1; j < F.size(); j++ ) { 115 pj = F.get(j); 116 if ( ! red.moduleCriterion( modv, pi, pj ) ) { 117 continue; 118 } 119 // if ( ! red.criterion4( pi, pj ) ) { continue; } 120 s = sred.leftSPolynomial( pi, pj ); 121 if ( s.isZERO() ) { 122 continue; 123 } 124 h = sred.leftNormalform( F, s ); 125 if ( ! h.isZERO() ) { 126 return false; 127 } 128 } 129 } 130 return true; 131 } 132 133 134 /** 135 * Twosided Groebner base test. 136 * @param Fp solvable polynomial list. 137 * @return true, if Fp is a two-sided Groebner base, else false. 138 */ 139 public boolean isTwosidedGB(List<GenSolvablePolynomial<C>> Fp) { 140 return isTwosidedGB(0,Fp); 141 } 142 143 144 /** 145 * Twosided Groebner base test. 146 * @param modv number of module variables. 147 * @param Fp solvable polynomial list. 148 * @return true, if Fp is a two-sided Groebner base, else false. 149 */ 150 public boolean isTwosidedGB(int modv, 151 List<GenSolvablePolynomial<C>> Fp) { 152 if ( Fp == null || Fp.size() == 0 ) { // 0 not 1 153 return true; 154 } 155 GenSolvablePolynomialRing<C> fac = Fp.get(0).ring; // assert != null 156 //List<GenSolvablePolynomial<C>> X = generateUnivar( modv, Fp ); 157 List<GenSolvablePolynomial<C>> X = fac.univariateList( modv ); 158 List<GenSolvablePolynomial<C>> F 159 = new ArrayList<GenSolvablePolynomial<C>>( Fp.size() * (1+X.size()) ); 160 F.addAll( Fp ); 161 GenSolvablePolynomial<C> p, x, pi, pj, s, h; 162 for ( int i = 0; i < Fp.size(); i++ ) { 163 p = Fp.get(i); 164 for ( int j = 0; j < X.size(); j++ ) { 165 x = X.get(j); 166 p = p.multiply( x ); 167 p = sred.leftNormalform(F, p); 168 if (!p.isZERO()) { 169 F.add(p); 170 } 171 } 172 } 173 //System.out.println("F to check = " + F); 174 for ( int i = 0; i < F.size(); i++ ) { 175 pi = F.get(i); 176 for ( int j = i+1; j < F.size(); j++ ) { 177 pj = F.get(j); 178 if ( ! red.moduleCriterion( modv, pi, pj ) ) { 179 continue; 180 } 181 // if ( ! red.criterion4( pi, pj ) ) { continue; } 182 s = sred.leftSPolynomial( pi, pj ); 183 if ( s.isZERO() ) { 184 continue; 185 } 186 h = sred.leftNormalform( F, s ); 187 if ( ! h.isZERO() ) { 188 logger.info("is not TwosidedGB: " + h); 189 return false; 190 } 191 } 192 } 193 return true; 194 } 195 196 197 /** 198 * Right Groebner base test. 199 * @param F solvable polynomial list. 200 * @return true, if F is a right Groebner base, else false. 201 */ 202 public boolean isRightGB(List<GenSolvablePolynomial<C>> F) { 203 return isRightGB(0,F); 204 } 205 206 207 /** 208 * Right Groebner base test. 209 * @param modv number of module variables. 210 * @param F solvable polynomial list. 211 * @return true, if F is a right Groebner base, else false. 212 */ 213 public boolean isRightGB(int modv, List<GenSolvablePolynomial<C>> F) { 214 GenSolvablePolynomial<C> pi, pj, s, h; 215 for ( int i = 0; i < F.size(); i++ ) { 216 pi = F.get(i); 217 //System.out.println("pi right = " + pi); 218 for ( int j = i+1; j < F.size(); j++ ) { 219 pj = F.get(j); 220 //System.out.println("pj right = " + pj); 221 if ( ! red.moduleCriterion( modv, pi, pj ) ) { 222 continue; 223 } 224 // if ( ! red.criterion4( pi, pj ) ) { continue; } 225 s = sred.rightSPolynomial( pi, pj ); 226 if ( s.isZERO() ) { 227 continue; 228 } 229 //System.out.println("s right = " + s); 230 h = sred.rightNormalform( F, s ); 231 if ( ! h.isZERO() ) { 232 logger.info("isRightGB non zero h = " + h + " :: " + h.ring); 233 logger.info("p"+i+" = " + pi + ", p"+j+" = " + pj ); 234 return false; 235 } else { 236 //logger.info("isRightGB zero h = " + h); 237 } 238 } 239 } 240 return true; 241 } 242 243 244 /** 245 * Left Groebner base using pairlist class. 246 * @param F solvable polynomial list. 247 * @return leftGB(F) a left Groebner base of F. 248 */ 249 public List<GenSolvablePolynomial<C>> 250 leftGB(List<GenSolvablePolynomial<C>> F) { 251 return leftGB(0,F); 252 } 253 254 255 /** 256 * Solvable Extended Groebner base using critical pair class. 257 * @param F solvable polynomial list. 258 * @return a container for an extended left Groebner base of F. 259 */ 260 public SolvableExtendedGB<C> 261 extLeftGB( List<GenSolvablePolynomial<C>> F ) { 262 return extLeftGB(0,F); 263 } 264 265 266 /** 267 * Left minimal ordered groebner basis. 268 * @param Gp a left Groebner base. 269 * @return leftGBmi(F) a minimal left Groebner base of Gp. 270 */ 271 public List<GenSolvablePolynomial<C>> 272 leftMinimalGB(List<GenSolvablePolynomial<C>> Gp) { 273 ArrayList<GenSolvablePolynomial<C>> G 274 = new ArrayList<GenSolvablePolynomial<C>>(); 275 ListIterator<GenSolvablePolynomial<C>> it = Gp.listIterator(); 276 for ( GenSolvablePolynomial<C> a: Gp ) { 277 // a = (SolvablePolynomial) it.next(); 278 if ( a.length() != 0 ) { // always true 279 // already monic a = a.monic(); 280 G.add( a ); 281 } 282 } 283 if ( G.size() <= 1 ) { 284 return G; 285 } 286 287 ExpVector e; 288 ExpVector f; 289 GenSolvablePolynomial<C> a, p; 290 ArrayList<GenSolvablePolynomial<C>> F 291 = new ArrayList<GenSolvablePolynomial<C>>(); 292 boolean mt; 293 294 while ( G.size() > 0 ) { 295 a = G.remove(0); 296 e = a.leadingExpVector(); 297 298 it = G.listIterator(); 299 mt = false; 300 while ( it.hasNext() && ! mt ) { 301 p = it.next(); 302 f = p.leadingExpVector(); 303 mt = e.multipleOf( f ); 304 } 305 it = F.listIterator(); 306 while ( it.hasNext() && ! mt ) { 307 p = it.next(); 308 f = p.leadingExpVector(); 309 mt = e.multipleOf( f ); 310 } 311 if ( ! mt ) { 312 F.add( a ); 313 } else { 314 // System.out.println("dropped " + a.length()); 315 } 316 } 317 G = F; 318 if ( G.size() <= 1 ) { 319 return G; 320 } 321 322 F = new ArrayList<GenSolvablePolynomial<C>>(); 323 while ( G.size() > 0 ) { 324 a = G.remove(0); 325 // System.out.println("doing " + a.length()); 326 a = sred.leftNormalform( G, a ); 327 a = sred.leftNormalform( F, a ); 328 F.add( a ); 329 } 330 return F; 331 } 332 333 334 /** 335 * Twosided Groebner base using pairlist class. 336 * @param Fp solvable polynomial list. 337 * @return tsGB(Fp) a twosided Groebner base of Fp. 338 */ 339 public List<GenSolvablePolynomial<C>> 340 twosidedGB(List<GenSolvablePolynomial<C>> Fp) { 341 return twosidedGB(0,Fp); 342 } 343 344 345 /** 346 * Right Groebner base using opposite ring left GB. 347 * @param F solvable polynomial list. 348 * @return rightGB(F) a right Groebner base of F. 349 */ 350 public List<GenSolvablePolynomial<C>> 351 rightGB(List<GenSolvablePolynomial<C>> F) { 352 return rightGB(0,F); 353 } 354 355 356 /** 357 * Right Groebner base using opposite ring left GB. 358 * @param modv number of module variables. 359 * @param F solvable polynomial list. 360 * @return rightGB(F) a right Groebner base of F. 361 */ 362 @SuppressWarnings("unchecked") 363 public List<GenSolvablePolynomial<C>> 364 rightGB(int modv, 365 List<GenSolvablePolynomial<C>> F) { 366 GenSolvablePolynomialRing<C> ring = null; 367 for ( GenSolvablePolynomial<C> p : F ) { 368 if ( p != null ) { 369 ring = p.ring; 370 break; 371 } 372 } 373 if ( ring == null ) { 374 return F; 375 } 376 GenSolvablePolynomialRing<C> rring = ring.reverse(true); //true 377 //System.out.println("reversed ring = " + rring); 378 //ring = rring.reverse(true); // true 379 GenSolvablePolynomial<C> q; 380 List<GenSolvablePolynomial<C>> rF; 381 rF = new ArrayList<GenSolvablePolynomial<C>>( F.size() ); 382 for ( GenSolvablePolynomial<C> p : F ) { 383 if ( p != null ) { 384 q = (GenSolvablePolynomial<C>)p.reverse(rring); 385 rF.add( q ); 386 } 387 } 388 if ( true || debug ) { 389 PolynomialList<C> pl = new PolynomialList<C>(rring,rF); 390 logger.info("reversed problem = " + pl); 391 } 392 //System.out.println("reversed problem = " + rF); 393 List<GenSolvablePolynomial<C>> rG = leftGB( modv, rF ); 394 if ( true || debug ) { 395 //PolynomialList<C> pl = new PolynomialList<C>(rring,rG); 396 //logger.info("reversed GB = " + pl); 397 long t = System.currentTimeMillis(); 398 boolean isit = isLeftGB( rG ); 399 t = System.currentTimeMillis() - t; 400 logger.info("is left GB = " + isit + ", in " + t + " milliseconds"); 401 } 402 //System.out.println("reversed left GB = " + rG); 403 ring = rring.reverse(true); // true 404 List<GenSolvablePolynomial<C>> G = new ArrayList<GenSolvablePolynomial<C>>(rG.size()); 405 for ( GenSolvablePolynomial<C> p : rG ) { 406 if ( p != null ) { 407 q = (GenSolvablePolynomial<C>)p.reverse(ring); 408 G.add( q ); 409 } 410 } 411 if ( true || debug ) { 412 //PolynomialList<C> pl = new PolynomialList<C>(ring,G); 413 //logger.info("GB = " + pl); 414 long t = System.currentTimeMillis(); 415 boolean isit = isRightGB( G ); 416 t = System.currentTimeMillis() - t; 417 logger.info("is right GB = " + isit + ", in " + t + " milliseconds"); 418 } 419 return G; 420 } 421 422 423 /** 424 * Test if left reduction matrix. 425 * @param exgb an SolvableExtendedGB container. 426 * @return true, if exgb contains a left reduction matrix, else false. 427 */ 428 public boolean 429 isLeftReductionMatrix(SolvableExtendedGB<C> exgb) { 430 if ( exgb == null ) { 431 return true; 432 } 433 return isLeftReductionMatrix(exgb.F,exgb.G,exgb.F2G,exgb.G2F); 434 } 435 436 437 /** 438 * Test if left reduction matrix. 439 * @param F a solvable polynomial list. 440 * @param G a left Groebner base. 441 * @param Mf a possible left reduction matrix. 442 * @param Mg a possible left reduction matrix. 443 * @return true, if Mg and Mf are left reduction matrices, else false. 444 */ 445 public boolean 446 isLeftReductionMatrix(List<GenSolvablePolynomial<C>> F, 447 List<GenSolvablePolynomial<C>> G, 448 List<List<GenSolvablePolynomial<C>>> Mf, 449 List<List<GenSolvablePolynomial<C>>> Mg) { 450 // no more check G and Mg: G * Mg[i] == 0 451 // check F and Mg: F * Mg[i] == G[i] 452 int k = 0; 453 for ( List<GenSolvablePolynomial<C>> row : Mg ) { 454 boolean t = sred.isLeftReductionNF( row, F, G.get( k ), null ); 455 if ( ! t ) { 456 System.out.println("row = " + row); 457 System.out.println("F = " + F); 458 System.out.println("Gk = " + G.get(k)); 459 logger.info("F isLeftReductionMatrix s, k = " + F.size() + ", " + k); 460 return false; 461 } 462 k++; 463 } 464 // check G and Mf: G * Mf[i] == F[i] 465 k = 0; 466 for ( List<GenSolvablePolynomial<C>> row : Mf ) { 467 boolean t = sred.isLeftReductionNF( row, G, F.get( k ), null ); 468 if ( ! t ) { 469 logger.error("G isLeftReductionMatrix s, k = " + G.size() + ", " + k); 470 return false; 471 } 472 k++; 473 } 474 return true; 475 } 476 477}