001 /* 002 * $Id: GroebnerBasePartial.java 3423 2010-12-24 10:56:50Z kredel $ 003 */ 004 005 package edu.jas.gbufd; 006 007 008 import java.util.ArrayList; 009 import java.util.Collections; 010 import java.util.List; 011 012 import org.apache.log4j.Logger; 013 014 import edu.jas.gb.GroebnerBaseAbstract; 015 import edu.jas.gb.GroebnerBaseSeq; 016 import edu.jas.poly.GenPolynomial; 017 import edu.jas.poly.GenPolynomialRing; 018 import edu.jas.poly.OptimizedPolynomialList; 019 import edu.jas.poly.PolyUtil; 020 import edu.jas.poly.TermOrder; 021 import edu.jas.poly.TermOrderOptimization; 022 import edu.jas.structure.GcdRingElem; 023 import edu.jas.structure.RingFactory; 024 025 026 /** 027 * Partial Groebner Bases for subsets of variables. Let <code>pvars</code> be a 028 * subset of variables <code>vars</code> of the polynomial ring K[vars]. Methods 029 * compute Groebner bases with coefficients from K[vars \ pvars] in the 030 * polynomial ring K[vars \ pvars][pvars]. 031 * @param <C> coefficient type 032 * @author Heinz Kredel 033 */ 034 035 public class GroebnerBasePartial<C extends GcdRingElem<C>> extends GroebnerBaseAbstract<C> { 036 037 038 private static final Logger logger = Logger.getLogger(GroebnerBasePartial.class); 039 040 041 private final boolean debug = logger.isDebugEnabled(); 042 043 044 /** 045 * Backing Groebner base engine. 046 */ 047 protected GroebnerBaseAbstract<C> bb; 048 049 050 /** 051 * Backing recursive Groebner base engine. 052 */ 053 protected GroebnerBaseAbstract<GenPolynomial<C>> rbb; // can be null 054 055 056 /** 057 * Constructor. 058 */ 059 public GroebnerBasePartial() { 060 this(new GroebnerBaseSeq<C>(), null); 061 } 062 063 064 /** 065 * Constructor. 066 * @param rf coefficient ring factory. 067 */ 068 public GroebnerBasePartial(RingFactory<GenPolynomial<C>> rf) { 069 this(new GroebnerBaseSeq<C>(), new GroebnerBasePseudoRecSeq<C>(rf)); 070 } 071 072 073 /** 074 * Constructor. 075 * @param bb Groebner base engine 076 * @param rbb recursive Groebner base engine 077 */ 078 public GroebnerBasePartial(GroebnerBaseAbstract<C> bb, GroebnerBaseAbstract<GenPolynomial<C>> rbb) { 079 super(); 080 this.bb = bb; 081 this.rbb = rbb; 082 if (rbb == null) { 083 //logger.warn("no recursive GB given"); 084 } 085 } 086 087 088 /** 089 * Groebner base using pairlist class. 090 * @param modv module variable number. 091 * @param F polynomial list. 092 * @return GB(F) a Groebner base of F. 093 */ 094 public List<GenPolynomial<C>> GB(int modv, List<GenPolynomial<C>> F) { 095 return bb.GB(modv, F); 096 } 097 098 099 /** 100 * Groebner base test. 101 * @param F polynomial list. 102 * @return true, if F is a partial Groebner base, else false. 103 */ 104 public boolean isGBrec(List<GenPolynomial<GenPolynomial<C>>> F) { 105 return isGBrec(0, F); 106 } 107 108 109 /** 110 * Groebner base test. 111 * @param modv module variable number. 112 * @param F polynomial list. 113 * @return true, if F is a partial Groebner base, else false. 114 */ 115 public boolean isGBrec(int modv, List<GenPolynomial<GenPolynomial<C>>> F) { 116 if (F == null || F.isEmpty()) { 117 return true; 118 } 119 if (true) { 120 rbb = new GroebnerBasePseudoRecSeq<C>(F.get(0).ring.coFac); 121 } 122 return rbb.isGB(modv, F); 123 } 124 125 126 /** 127 * Partial permuation for specific variables. Computes a permutation perm 128 * for the variables vars, such that perm(vars) == pvars ... (vars \ pvars). 129 * Uses internal (reversed) variable sorting. 130 * @param vars names for all variables. 131 * @param pvars names for main variables, pvars subseteq vars. 132 * @return permutation for vars, such that perm(vars) == pvars ... (vars \ 133 * pvars). 134 */ 135 public static List<Integer> partialPermutation(String[] vars, String[] pvars) { 136 return partialPermutation(vars, pvars, null); 137 //no: return getPermutation(vars,pvars); 138 } 139 140 141 /** 142 * Permutation of variables for elimination. 143 * @param aname variables for the full polynomial ring. 144 * @param ename variables for the elimination ring, subseteq aname. 145 * @return perm({vars \ ename},ename) 146 */ 147 public static List<Integer> getPermutation(String[] aname, String[] ename) { 148 if (aname == null || ename == null) { 149 throw new IllegalArgumentException("aname or ename may not be null"); 150 } 151 List<Integer> perm = new ArrayList<Integer>(aname.length); 152 // add ename permutation 153 for (int i = 0; i < ename.length; i++) { 154 int j = indexOf(ename[i], aname); 155 if (j < 0) { 156 throw new IllegalArgumentException("ename not contained in aname"); 157 } 158 perm.add(j); 159 } 160 //System.out.println("perm_low = " + perm); 161 // add aname \ ename permutation 162 for (int i = 0; i < aname.length; i++) { 163 if (!perm.contains(i)) { 164 perm.add(i); 165 } 166 } 167 //System.out.println("perm_all = " + perm); 168 // reverse permutation indices 169 int n1 = aname.length - 1; 170 List<Integer> perm1 = new ArrayList<Integer>(aname.length); 171 for (Integer k : perm) { 172 perm1.add(n1 - k); 173 } 174 perm = perm1; 175 //System.out.println("perm_inv = " + perm1); 176 Collections.reverse(perm); 177 //System.out.println("perm_rev = " + perm); 178 return perm; 179 } 180 181 182 /** 183 * Index of s in A. 184 * @param s search string 185 * @param A string array 186 * @return i if s == A[i] for some i, else -1. 187 */ 188 public static int indexOf(String s, String[] A) { 189 for (int i = 0; i < A.length; i++) { 190 if (s.equals(A[i])) { 191 return i; 192 } 193 } 194 return -1; 195 } 196 197 198 /** 199 * Partial permuation for specific variables. Computes a permutation perm 200 * for the variables vars, such that perm(vars) == pvars ... (vars \ pvars). 201 * Uses internal (reversed) variable sorting. 202 * @param vars names for all variables. 203 * @param pvars names for main variables, pvars subseteq vars. 204 * @param rvars names for remaining variables, rvars eq { vars \ pvars }. 205 * @return permutation for vars, such that perm(vars) == (pvars, {vars \ 206 * pvars}). 207 */ 208 public static List<Integer> partialPermutation(String[] vars, String[] pvars, String[] rvars) { 209 if (vars == null || pvars == null) { 210 throw new IllegalArgumentException("no variable names found"); 211 } 212 List<String> variables = new ArrayList<String>(vars.length); 213 List<String> pvariables = new ArrayList<String>(pvars.length); 214 for (int i = 0; i < vars.length; i++) { 215 variables.add(vars[i]); 216 } 217 for (int i = 0; i < pvars.length; i++) { 218 pvariables.add(pvars[i]); 219 } 220 if (rvars == null) { 221 rvars = remainingVars(vars, pvars); 222 } 223 List<String> rvariables = new ArrayList<String>(rvars.length); 224 for (int i = 0; i < rvars.length; i++) { 225 rvariables.add(rvars[i]); 226 } 227 if (rvars.length + pvars.length == vars.length) { 228 //System.out.println("pvariables = " + pvariables); 229 return getPermutation(vars, rvars); 230 } else if (true) { 231 logger.info("not implemented for " + variables + " != " + pvariables + " cup " + rvariables); 232 throw new UnsupportedOperationException("not implemented"); 233 } 234 if (!variables.containsAll(pvariables) || !variables.containsAll(rvariables)) { 235 throw new IllegalArgumentException("partial variables not contained in all variables "); 236 } 237 Collections.reverse(variables); 238 Collections.reverse(pvariables); 239 Collections.reverse(rvariables); 240 System.out.println("variables = " + variables); 241 System.out.println("pvariables = " + pvariables); 242 System.out.println("rvariables = " + rvariables); 243 244 List<Integer> perm = new ArrayList<Integer>(); 245 List<Integer> pv = new ArrayList<Integer>(); 246 for (String s : variables) { 247 int j = pvariables.indexOf(s); 248 if (j >= 0) { 249 perm.add(j); 250 } 251 } 252 int i = pvariables.size(); 253 for (String s : variables) { 254 if (!pvariables.contains(s)) { 255 pv.add(i); 256 } 257 i++; 258 } 259 260 System.out.println("perm, 1 = " + perm); 261 //System.out.println("pv = " + pv); 262 // sort perm according to pvars 263 int ps = perm.size(); // == pvars.length 264 for (int k = 0; k < ps; k++) { 265 for (int j = k + 1; j < ps; j++) { 266 int kk = variables.indexOf(pvariables.get(k)); 267 int jj = variables.indexOf(pvariables.get(j)); 268 if (kk > jj) { // swap 269 int t = perm.get(k); 270 System.out.println("swap " + t + " with " + perm.get(j)); 271 perm.set(k, perm.get(j)); 272 perm.set(j, t); 273 } 274 } 275 } 276 //System.out.println("perm = " + perm); 277 // sort pv according to rvars 278 int rs = pv.size(); // == rvars.length 279 for (int k = 0; k < rs; k++) { 280 for (int j = k + 1; j < rs; j++) { 281 int kk = variables.indexOf(rvariables.get(k)); 282 int jj = variables.indexOf(rvariables.get(j)); 283 if (kk > jj) { // swap 284 int t = pv.get(k); 285 //System.out.println("swap " + t + " with " + perm.get(j)); 286 pv.set(k, pv.get(j)); 287 pv.set(j, t); 288 } 289 } 290 } 291 //System.out.println("pv = " + pv); 292 perm.addAll(pv); 293 System.out.println("perm, 2 = " + perm); 294 return perm; 295 } 296 297 298 /** 299 * Partial permuation for specific variables. Computes a permutation perm 300 * for the variables vars, such that perm(vars) == (evars, pvars, (vars \ { 301 * evars, pvars }). Uses internal (reversed) variable sorting. 302 * @param vars names for all variables. 303 * @param evars names for elimination variables, evars subseteq vars. 304 * @param pvars names for main variables, pvars subseteq vars. 305 * @param rvars names for remaining variables, rvars eq {vars \ { evars, 306 * pvars } }. 307 * @return permutation for vars, such that perm(vars) == (evars,pvars, {vars 308 * \ {evars,pvars}}. 309 */ 310 public static List<Integer> partialPermutation(String[] vars, String[] evars, String[] pvars, 311 String[] rvars) { 312 if (vars == null || evars == null || pvars == null) { 313 throw new IllegalArgumentException("not all variable names given"); 314 } 315 String[] uvars; 316 if (rvars != null) { 317 uvars = new String[pvars.length + rvars.length]; 318 for (int i = 0; i < pvars.length; i++) { 319 uvars[i] = pvars[i]; 320 } 321 for (int i = 0; i < rvars.length; i++) { 322 uvars[pvars.length + i] = rvars[i]; 323 } 324 } else { 325 uvars = pvars; 326 } 327 //System.out.println("uvars = " + Arrays.toString(uvars)); 328 List<Integer> perm = partialPermutation(vars, evars, uvars); 329 return perm; 330 } 331 332 333 /** 334 * Remaining variables vars \ pvars. Uses internal (reversed) variable 335 * sorting, original order is preserved. 336 * @param vars names for all variables. 337 * @param pvars names for main variables, pvars subseteq vars. 338 * @return remaining vars = (vars \ pvars). 339 */ 340 public static String[] remainingVars(String[] vars, String[] pvars) { 341 if (vars == null || pvars == null) { 342 throw new IllegalArgumentException("no variable names found"); 343 } 344 List<String> variables = new ArrayList<String>(vars.length); 345 List<String> pvariables = new ArrayList<String>(pvars.length); 346 for (int i = 0; i < vars.length; i++) { 347 variables.add(vars[i]); 348 } 349 for (int i = 0; i < pvars.length; i++) { 350 pvariables.add(pvars[i]); 351 } 352 if (!variables.containsAll(pvariables)) { 353 throw new IllegalArgumentException("partial variables not contained in all variables "); 354 } 355 // variables.setMinus(pvariables) 356 List<String> rvariables = new ArrayList<String>(variables); 357 for (String s : pvariables) { 358 rvariables.remove(s); 359 } 360 int cl = vars.length - pvars.length; 361 String[] rvars = new String[cl]; 362 int i = 0; 363 for (String s : rvariables) { 364 rvars[i++] = s; 365 } 366 return rvars; 367 } 368 369 370 /** 371 * Partial recursive Groebner base for specific variables. Computes Groebner 372 * base in K[vars \ pvars][pvars] with coefficients from K[vars \ pvars]. 373 * @param F polynomial list. 374 * @param pvars names for main variables of partial Groebner base 375 * computation. 376 * @return a container for a partial Groebner base of F wrt pvars. 377 */ 378 public OptimizedPolynomialList<GenPolynomial<C>> partialGBrec(List<GenPolynomial<C>> F, String[] pvars) { 379 if (F == null || F.isEmpty()) { 380 throw new IllegalArgumentException("empty F not allowed"); 381 } 382 GenPolynomialRing<C> fac = F.get(0).ring; 383 String[] vars = fac.getVars(); 384 if (vars == null || pvars == null) { 385 throw new IllegalArgumentException("not all variable names found"); 386 } 387 if (vars.length == pvars.length) { 388 throw new IllegalArgumentException("use non recursive partialGB algorithm"); 389 } 390 // compute permutation (in reverse sorting) 391 List<Integer> perm = partialPermutation(vars, pvars); 392 393 GenPolynomialRing<C> pfac = TermOrderOptimization.<C> permutation(perm, fac); 394 if (logger.isInfoEnabled()) { 395 logger.info("pfac = " + pfac); 396 } 397 List<GenPolynomial<C>> ppolys = TermOrderOptimization.<C> permutation(perm, pfac, F); 398 //System.out.println("ppolys = " + ppolys); 399 400 int cl = fac.nvar - pvars.length; // > 0 401 int pl = pvars.length; 402 String[] rvars = remainingVars(vars, pvars); 403 GenPolynomialRing<C> cfac = new GenPolynomialRing<C>(fac.coFac, cl, fac.tord, rvars); 404 //System.out.println("cfac = " + cfac); 405 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, pl, 406 fac.tord, pvars); 407 if (logger.isInfoEnabled()) { 408 logger.info("rfac = " + rfac); 409 } 410 //System.out.println("rfac = " + rfac); 411 412 List<GenPolynomial<GenPolynomial<C>>> Fr = PolyUtil.<C> recursive(rfac, ppolys); 413 //System.out.println("\nFr = " + Fr); 414 415 if (true) { 416 rbb = new GroebnerBasePseudoRecSeq<C>(cfac); 417 } 418 List<GenPolynomial<GenPolynomial<C>>> Gr = rbb.GB(Fr); 419 //System.out.println("\nGr = " + Gr); 420 //perm = perm.subList(0,pl); 421 OptimizedPolynomialList<GenPolynomial<C>> pgb = new OptimizedPolynomialList<GenPolynomial<C>>(perm, 422 rfac, Gr); 423 return pgb; 424 } 425 426 427 /** 428 * Partial Groebner base for specific variables. Computes Groebner base in 429 * K[vars \ pvars][pvars] with coefficients from K[vars \ pvars] but returns 430 * polynomials in K[vars \ pvars, pvars]. 431 * @param F polynomial list. 432 * @param pvars names for main variables of partial Groebner base 433 * computation. 434 * @return a container for a partial Groebner base of F wrt pvars. 435 */ 436 public OptimizedPolynomialList<C> partialGB(List<GenPolynomial<C>> F, String[] pvars) { 437 if (F == null || F.isEmpty()) { 438 throw new IllegalArgumentException("empty F not allowed"); 439 } 440 GenPolynomialRing<C> fac = F.get(0).ring; 441 String[] vars = fac.getVars(); 442 // compute permutation (in reverse sorting) 443 String[] xvars = remainingVars(vars, pvars); 444 //System.out.println("xvars = " + Arrays.toString(xvars)); 445 446 List<Integer> perm = partialPermutation(vars, pvars); 447 //System.out.println("pGB, perm = " + perm); 448 //System.out.println("pGB, perm,1 = " + getPermutation(vars, xvars)); 449 450 GenPolynomialRing<C> pfac = TermOrderOptimization.<C> permutation(perm, fac); 451 if (logger.isInfoEnabled()) { 452 logger.info("pfac = " + pfac); 453 } 454 List<GenPolynomial<C>> ppolys = TermOrderOptimization.<C> permutation(perm, pfac, F); 455 //System.out.println("ppolys = " + ppolys); 456 457 int cl = fac.nvar - pvars.length; 458 if (cl == 0) { // non recursive case 459 //GroebnerBaseSeq<C> bb = new GroebnerBaseSeq<C>(); 460 List<GenPolynomial<C>> G = bb.GB(ppolys); 461 OptimizedPolynomialList<C> pgb = new OptimizedPolynomialList<C>(perm, pfac, G); 462 return pgb; 463 } 464 // recursive case 465 int pl = pvars.length; 466 String[] rvars = remainingVars(vars, pvars); 467 GenPolynomialRing<C> cfac = new GenPolynomialRing<C>(fac.coFac, cl, fac.tord, rvars); 468 //System.out.println("cfac = " + cfac); 469 470 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, pl, 471 fac.tord, pvars); 472 if (logger.isInfoEnabled()) { 473 logger.info("rfac = " + rfac); 474 } 475 //System.out.println("rfac = " + rfac); 476 477 List<GenPolynomial<GenPolynomial<C>>> Fr = PolyUtil.<C> recursive(rfac, ppolys); 478 //System.out.println("\nFr = " + Fr); 479 480 if (true) { 481 rbb = new GroebnerBasePseudoRecSeq<C>(cfac); 482 } 483 List<GenPolynomial<GenPolynomial<C>>> Gr = rbb.GB(Fr); 484 //System.out.println("\nGr = " + Gr); 485 486 List<GenPolynomial<C>> G = PolyUtil.<C> distribute(pfac, Gr); 487 //System.out.println("\nG = " + G); 488 489 OptimizedPolynomialList<C> pgb = new OptimizedPolynomialList<C>(perm, pfac, G); 490 return pgb; 491 } 492 493 494 /** 495 * Partial Groebner base for specific variables. Computes Groebner base with 496 * coefficients from K[pvars] but returns polynomials in K[pvars, evars]. 497 * @param F polynomial list. 498 * @param evars names for upper main variables of partial Groebner base 499 * computation. 500 * @param pvars names for lower main variables of partial Groebner base 501 * computation. 502 * @return a container for a partial Groebner base of F wrt (pvars,evars). 503 */ 504 public OptimizedPolynomialList<C> elimPartialGB(List<GenPolynomial<C>> F, String[] evars, String[] pvars) { 505 if (F == null || F.isEmpty()) { 506 throw new IllegalArgumentException("empty F not allowed"); 507 } 508 GenPolynomialRing<C> fac = F.get(0).ring; 509 String[] vars = fac.getVars(); 510 // compute permutation (in reverse sorting) 511 //System.out.println("vars = " + Arrays.toString(vars)); 512 //System.out.println("evars = " + Arrays.toString(evars)); 513 //System.out.println("pvars = " + Arrays.toString(pvars)); 514 List<Integer> perm = partialPermutation(vars, evars, pvars); 515 //System.out.println("perm = " + perm); 516 517 GenPolynomialRing<C> pfac = TermOrderOptimization.<C> permutation(perm, fac); 518 if (logger.isInfoEnabled()) { 519 logger.info("pfac = " + pfac); 520 } 521 List<GenPolynomial<C>> ppolys = TermOrderOptimization.<C> permutation(perm, pfac, F); 522 //System.out.println("ppolys = " + ppolys); 523 524 int cl = fac.nvar - evars.length - pvars.length; 525 if (cl == 0) { // non recursive case 526 TermOrder to = pfac.tord; 527 int ev = to.getEvord(); 528 //ev = TermOrder.IGRLEX; 529 TermOrder split = new TermOrder(ev, ev, pfac.nvar, evars.length); 530 pfac = new GenPolynomialRing<C>(pfac.coFac, pfac.nvar, split, pfac.getVars()); 531 if (logger.isInfoEnabled()) { 532 //logger.info("split = " + split); 533 logger.info("pfac = " + pfac); 534 } 535 List<GenPolynomial<C>> Fs = new ArrayList<GenPolynomial<C>>(ppolys.size()); 536 for (GenPolynomial<C> p : ppolys) { 537 Fs.add(pfac.copy(p)); 538 } 539 List<GenPolynomial<C>> G = bb.GB(Fs); 540 OptimizedPolynomialList<C> pgb = new OptimizedPolynomialList<C>(perm, pfac, G); 541 if (logger.isInfoEnabled()) { 542 logger.info("pgb = " + pgb); 543 } 544 return pgb; 545 } else { 546 logger.info("not meaningful for elimination " + cl); 547 } 548 // recursive case 549 int pl = pvars.length + pvars.length; 550 String[] rvars = remainingVars(vars, evars); 551 rvars = remainingVars(rvars, pvars); 552 String[] uvars = new String[evars.length + pvars.length]; 553 for (int i = 0; i < pvars.length; i++) { 554 uvars[i] = pvars[i]; 555 } 556 for (int i = 0; i < evars.length; i++) { 557 uvars[pvars.length + i] = evars[i]; 558 } 559 560 GenPolynomialRing<C> cfac = new GenPolynomialRing<C>(fac.coFac, cl, fac.tord, rvars); 561 //System.out.println("cfac = " + cfac); 562 563 TermOrder to = pfac.tord; 564 int ev = to.getEvord(); 565 TermOrder split = new TermOrder(ev, ev, pl, evars.length); 566 567 GenPolynomialRing<C> sfac = new GenPolynomialRing<C>(pfac.coFac, pfac.nvar, split, pfac.getVars()); 568 569 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, pl, split, 570 uvars); 571 //System.out.println("rfac = " + rfac); 572 573 List<GenPolynomial<GenPolynomial<C>>> Fr = PolyUtil.<C> recursive(rfac, ppolys); 574 if (logger.isInfoEnabled()) { 575 logger.info("rfac = " + rfac); 576 logger.info("Fr = " + Fr); 577 } 578 579 if (true) { 580 rbb = new GroebnerBasePseudoRecSeq<C>(cfac); 581 } 582 List<GenPolynomial<GenPolynomial<C>>> Gr = rbb.GB(Fr); 583 //System.out.println("\nGr = " + Gr); 584 585 List<GenPolynomial<C>> G = PolyUtil.<C> distribute(pfac, Gr); 586 //System.out.println("\nG = " + G); 587 588 OptimizedPolynomialList<C> pgb = new OptimizedPolynomialList<C>(perm, pfac, G); 589 return pgb; 590 } 591 592 }