001/* 002 * $Id: WordGroebnerBaseAbstract.java 5280 2015-07-30 16:18:15Z kredel $ 003 */ 004 005package edu.jas.gb; 006 007 008import java.util.ArrayList; 009import java.util.Collections; 010import java.util.HashSet; 011import java.util.List; 012import java.util.Set; 013import java.util.SortedMap; 014import java.util.TreeMap; 015 016import org.apache.log4j.Logger; 017 018import edu.jas.poly.GenWordPolynomial; 019import edu.jas.poly.GenWordPolynomialRing; 020import edu.jas.poly.Word; 021import edu.jas.structure.RingElem; 022 023 024/** 025 * Non-commutative Groebner Bases abstract class. Implements common Groebner 026 * bases and GB test methods. 027 * @param <C> coefficient type 028 * @author Heinz Kredel 029 */ 030 031public abstract class WordGroebnerBaseAbstract<C extends RingElem<C>> implements WordGroebnerBase<C> { 032 033 034 private static final Logger logger = Logger.getLogger(WordGroebnerBaseAbstract.class); 035 036 037 private final boolean debug = logger.isDebugEnabled(); 038 039 040 /** 041 * Reduction engine. 042 */ 043 public final WordReduction<C> red; 044 045 046 /** 047 * Strategy for pair selection. 048 */ 049 public final WordPairList<C> strategy; 050 051 052 /** 053 * Constructor. 054 */ 055 public WordGroebnerBaseAbstract() { 056 this(new WordReductionSeq<C>()); 057 } 058 059 060 /** 061 * Constructor. 062 * @param red Word Reduction engine 063 */ 064 public WordGroebnerBaseAbstract(WordReduction<C> red) { 065 this(red, new OrderedWordPairlist<C>()); 066 } 067 068 069 /** 070 * Constructor. 071 * @param red Word Reduction engine 072 * @param pl Word pair selection strategy 073 */ 074 public WordGroebnerBaseAbstract(WordReduction<C> red, WordPairList<C> pl) { 075 this.red = red; 076 this.strategy = pl; 077 } 078 079 080 /** 081 * Get the String representation with GB engines. 082 * @see java.lang.Object#toString() 083 */ 084 @Override 085 public String toString() { 086 return this.getClass().getSimpleName(); 087 } 088 089 090 /** 091 * Normalize polynomial list. 092 * @param A list of polynomials. 093 * @return list of polynomials with zeros removed and ones/units reduced. 094 */ 095 public List<GenWordPolynomial<C>> normalizeZerosOnes(List<GenWordPolynomial<C>> A) { 096 if (A == null) { 097 return A; 098 } 099 List<GenWordPolynomial<C>> N = new ArrayList<GenWordPolynomial<C>>(A.size()); 100 if (A.isEmpty()) { 101 return N; 102 } 103 for (GenWordPolynomial<C> p : A) { 104 if (p == null || p.isZERO()) { 105 continue; 106 } 107 if (p.isUnit()) { 108 N.clear(); 109 N.add(p.ring.getONE()); 110 return N; 111 } 112 N.add(p.abs()); 113 } 114 //N.trimToSize(); 115 return N; 116 } 117 118 119 /** 120 * Common zero test, test if univariate leading words exist for all 121 * variables. 122 * @param F polynomial list. 123 * @return -1, 0 or 1 if "dimension"(ideal(F)) &eq; -1, 0 or ≥ 1. 124 */ 125 public int commonZeroTest(List<GenWordPolynomial<C>> F) { 126 if (F == null || F.isEmpty()) { 127 return 1; 128 } 129 GenWordPolynomialRing<C> pfac = F.get(0).ring; 130 if (pfac.alphabet.length() <= 0) { 131 return -1; 132 } 133 Set<String> v = new HashSet<String>(); // for non reduced GBs 134 for (GenWordPolynomial<C> p : F) { 135 if (p.isZERO()) { 136 continue; 137 } 138 if (p.isConstant()) { // for non-monic lists 139 return -1; 140 } 141 Word e = p.leadingWord(); 142 if (e == null) { 143 continue; 144 } 145 SortedMap<String, Integer> u = e.dependencyOnVariables(); 146 if (u == null) { 147 continue; 148 } 149 if (u.size() == 1) { 150 v.add(u.firstKey()); 151 } 152 } 153 if (pfac.alphabet.length() == v.size()) { 154 return 0; 155 } 156 return 1; 157 } 158 159 160 /** 161 * Univariate head term degrees. 162 * @param A list of polynomials. 163 * @return a list of the degrees of univariate head terms. 164 */ 165 public List<Long> univariateDegrees(List<GenWordPolynomial<C>> A) { 166 List<Long> ud = new ArrayList<Long>(); 167 if (A == null || A.size() == 0) { 168 return ud; 169 } 170 GenWordPolynomialRing<C> pfac = A.get(0).ring; 171 if (pfac.alphabet.length() <= 0) { 172 return ud; 173 } 174 SortedMap<String, Long> v = new TreeMap<String, Long>(); // for non reduced GBs 175 for (GenWordPolynomial<C> p : A) { 176 Word e = p.leadingWord(); 177 if (e == null) { 178 continue; 179 } 180 SortedMap<String, Integer> u = e.dependencyOnVariables(); 181 if (u == null) { 182 continue; 183 } 184 if (u.size() == 1) { 185 Long d = v.get(u.firstKey()); 186 if (d == null) { // record only once 187 v.put(u.firstKey(), Long.valueOf(u.get(u.firstKey()))); 188 } 189 } 190 } 191 ud.addAll(v.values()); 192 //Collections.reverse(ud); 193 return ud; 194 } 195 196 197 /** 198 * Word Groebner base test. 199 * @param F Word polynomial list. 200 * @return true, if F is a Groebner base, else false. 201 */ 202 public boolean isGB(List<GenWordPolynomial<C>> F) { 203 if (F == null || F.size() <= 1) { 204 return true; 205 } 206 for (int i = 0; i < F.size(); i++) { 207 GenWordPolynomial<C> pi = F.get(i); 208 for (int j = i + 1; j < F.size(); j++) { 209 GenWordPolynomial<C> pj = F.get(j); 210 List<GenWordPolynomial<C>> S = red.SPolynomials(pi, pj); 211 for (GenWordPolynomial<C> s : S) { 212 //System.out.println("s-pol("+i+","+j+"): " + s.leadingWord()); 213 GenWordPolynomial<C> h = red.normalform(F, s); 214 if (!h.isZERO()) { 215 logger.info("no GB: pi = " + pi + ", pj = " + pj); 216 logger.info("s = " + s + ", h = " + h); 217 return false; 218 } 219 } 220 S = red.SPolynomials(pj, pi); 221 for (GenWordPolynomial<C> s : S) { 222 //System.out.println("s-pol("+j+","+i+"): " + s.leadingWord()); 223 GenWordPolynomial<C> h = red.normalform(F, s); 224 if (!h.isZERO()) { 225 logger.info("no GB: pj = " + pj + ", pi = " + pi); 226 logger.info("s = " + s + ", h = " + h); 227 return false; 228 } 229 } 230 } 231 } 232 return true; 233 } 234 235 236 /** 237 * Groebner base using pairlist class. 238 * @param F polynomial list. 239 * @return GB(F) a Groebner base of F. 240 */ 241 public abstract List<GenWordPolynomial<C>> GB(List<GenWordPolynomial<C>> F); 242 243 244 /** 245 * Minimal ordered Groebner basis. 246 * @param Gp a Groebner base. 247 * @return a reduced Groebner base of Gp. 248 */ 249 public List<GenWordPolynomial<C>> minimalGB(List<GenWordPolynomial<C>> Gp) { 250 if (Gp == null || Gp.size() <= 1) { 251 return Gp; 252 } 253 // remove zero polynomials 254 List<GenWordPolynomial<C>> G = new ArrayList<GenWordPolynomial<C>>(Gp.size()); 255 for (GenWordPolynomial<C> a : Gp) { 256 if (a != null && !a.isZERO()) { // always true in GB() 257 // already positive a = a.abs(); 258 G.add(a); 259 } 260 } 261 if (G.size() <= 1) { 262 return G; 263 } 264 // remove top reducible polynomials 265 GenWordPolynomial<C> a; 266 List<GenWordPolynomial<C>> F; 267 F = new ArrayList<GenWordPolynomial<C>>(G.size()); 268 while (G.size() > 0) { 269 a = G.remove(0); 270 if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { 271 // drop polynomial 272 if (debug) { 273 System.out.println("dropped " + a); 274 List<GenWordPolynomial<C>> ff; 275 ff = new ArrayList<GenWordPolynomial<C>>(G); 276 ff.addAll(F); 277 a = red.normalform(ff, a); 278 if (!a.isZERO()) { 279 System.out.println("error, nf(a) " + a); 280 } 281 } 282 } else { 283 F.add(a); 284 } 285 } 286 G = F; 287 if (G.size() <= 1) { 288 return G; 289 } 290 // reduce remaining polynomials 291 Collections.reverse(G); // important for lex GB 292 int len = G.size(); 293 if (debug) { 294 System.out.println("#G " + len); 295 for (GenWordPolynomial<C> aa : G) { 296 System.out.println("aa = " + aa.length() + ", lt = " + aa.getMap().keySet()); 297 } 298 } 299 int i = 0; 300 while (i < len) { 301 a = G.remove(0); 302 if (debug) { 303 System.out.println("doing " + a.length() + ", lt = " + a.leadingWord()); 304 } 305 a = red.normalform(G, a); 306 G.add(a); // adds as last 307 i++; 308 } 309 return G; 310 } 311 312 313 /** 314 * Test for minimal ordered Groebner basis. 315 * @param Gp an ideal base. 316 * @return true, if Gp is a reduced minimal Groebner base. 317 */ 318 public boolean isMinimalGB(List<GenWordPolynomial<C>> Gp) { 319 if (Gp == null || Gp.size() == 0) { 320 return true; 321 } 322 // test for zero polynomials 323 for (GenWordPolynomial<C> a : Gp) { 324 if (a == null || a.isZERO()) { 325 if (debug) { 326 logger.debug("zero polynomial " + a); 327 } 328 return false; 329 } 330 } 331 // test for top reducible polynomials 332 List<GenWordPolynomial<C>> G = new ArrayList<GenWordPolynomial<C>>(Gp); 333 List<GenWordPolynomial<C>> F = new ArrayList<GenWordPolynomial<C>>(G.size()); 334 while (G.size() > 0) { 335 GenWordPolynomial<C> a = G.remove(0); 336 if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { 337 if (debug) { 338 logger.debug("top reducible polynomial " + a); 339 } 340 return false; 341 } 342 F.add(a); 343 } 344 G = F; 345 if (G.size() <= 1) { 346 return true; 347 } 348 // test reducibility of polynomials 349 int len = G.size(); 350 int i = 0; 351 while (i < len) { 352 GenWordPolynomial<C> a = G.remove(0); 353 if (!red.isNormalform(G, a)) { 354 if (debug) { 355 logger.debug("reducible polynomial " + a); 356 } 357 return false; 358 } 359 G.add(a); // re-adds as last 360 i++; 361 } 362 return true; 363 } 364 365 366 /** 367 * Cleanup and terminate ThreadPool. 368 */ 369 public void terminate() { 370 logger.info("terminate not implemented"); 371 } 372 373 374 /** 375 * Cancel ThreadPool. 376 */ 377 public int cancel() { 378 logger.info("cancel not implemented"); 379 return 0; 380 } 381 382}