001/* 002 * $Id: RelationTable.java 5311 2015-10-25 22:28:29Z kredel $ 003 */ 004 005package edu.jas.poly; 006 007 008import java.io.Serializable; 009import java.util.ArrayList; 010import java.util.HashMap; 011import java.util.Iterator; 012import java.util.LinkedList; 013import java.util.List; 014import java.util.ListIterator; 015import java.util.Map; 016 017import org.apache.log4j.Logger; 018 019import edu.jas.kern.PrettyPrint; 020import edu.jas.structure.RingElem; 021 022 023/** 024 * RelationTable for solvable polynomials. This class maintains the 025 * non-commutative multiplication relations of solvable polynomial rings. The 026 * table entries are initialized with relations of the form x<sub>j</sub> * 027 * x<sub>i</sub> = p<sub>ij</sub>. During multiplication the relations are 028 * updated by relations of the form x<sub>j</sub><sup>k</sup> * 029 * x<sub>i</sub><sup>l</sup> = p<sub>ijkl</sub>. If no relation for 030 * x<sub>j</sub> * x<sub>i</sub> is found in the table, this multiplication is 031 * assumed to be commutative x<sub>i</sub> x<sub>j</sub>. Can also be used for 032 * relations between coefficients and main variables. 033 * @author Heinz Kredel 034 */ 035 036public class RelationTable<C extends RingElem<C>> implements Serializable { 037 038 039 /** 040 * The data structure for the relations. 041 */ 042 public final Map<List<Integer>, List> table; 043 044 045 /** 046 * The factory for the solvable polynomial ring. 047 */ 048 public final GenSolvablePolynomialRing<C> ring; 049 050 051 /** 052 * Usage indicator: table or coeffTable. 053 */ 054 public final boolean coeffTable; 055 056 057 private static final Logger logger = Logger.getLogger(RelationTable.class); 058 059 060 private final boolean debug = logger.isDebugEnabled(); 061 062 063 /** 064 * Constructor for RelationTable requires ring factory. Note: This 065 * constructor is called within the constructor of the ring factory, so 066 * methods of this class can only be used after the other constructor has 067 * terminated. 068 * @param r solvable polynomial ring factory. 069 */ 070 public RelationTable(GenSolvablePolynomialRing<C> r) { 071 this(r, false); 072 } 073 074 075 /** 076 * Constructor for RelationTable requires ring factory. Note: This 077 * constructor is called within the constructor of the ring factory, so 078 * methods of this class can only be used after the other constructor has 079 * terminated. 080 * @param r solvable polynomial ring factory. 081 * @param coeffTable indicator for coeffTable. 082 */ 083 public RelationTable(GenSolvablePolynomialRing<C> r, boolean coeffTable) { 084 table = new HashMap<List<Integer>, List>(); 085 ring = r; 086 if (ring == null) { 087 throw new IllegalArgumentException("RelationTable no ring"); 088 } 089 this.coeffTable = coeffTable; 090 } 091 092 093 /** 094 * RelationTable equals. Tests same keySets and base relations. 095 * @see java.lang.Object#equals(java.lang.Object) 096 */ 097 @Override 098 @SuppressWarnings("unchecked") 099 public boolean equals(Object p) { 100 if (p == null) { 101 return false; 102 } 103 if (!(p instanceof RelationTable)) { 104 logger.info("no RelationTable"); 105 return false; 106 } 107 RelationTable<C> tab = (RelationTable<C>) p; 108 // not possible because of infinite recursion: 109 //if (!ring.equals(tab.ring)) { 110 // logger.info("not same Ring " + ring.toScript() + ", " + tab.ring.toScript()); 111 // return false; 112 //} 113 if (!table.keySet().equals(tab.table.keySet())) { 114 logger.info("keySet != : a = " + table.keySet() + ", b = " + tab.table.keySet()); 115 return false; 116 } 117 for (Map.Entry<List<Integer>,List> me : table.entrySet()) { 118 List<Integer> k = me.getKey(); 119 List a = me.getValue(); 120 List b = tab.table.get(k); 121 // check contents, but only base relations 122 Map<ExpVectorPair, GenPolynomial<C>> t1ex = fromListDeg2(a); 123 Map<ExpVectorPair, GenPolynomial<C>> t2ex = fromListDeg2(b); 124 if (!equalMaps(t1ex, t2ex)) { 125 //System.out.println("a != b, a = " + t1ex + ", b = " + t2ex); 126 return false; 127 } 128 } 129 return true; 130 } 131 132 133 /** 134 * Convert mixed list to map for base relations. 135 * @param a mixed list 136 * @returns a map constructed from the list with deg(key) == 2. 137 */ 138 @SuppressWarnings("unchecked") 139 Map<ExpVectorPair, GenPolynomial<C>> fromListDeg2(List a) { 140 Map<ExpVectorPair, GenPolynomial<C>> tex = new HashMap<ExpVectorPair, GenPolynomial<C>>(); 141 Iterator ait = a.iterator(); 142 while (ait.hasNext()) { 143 ExpVectorPair ae = (ExpVectorPair) ait.next(); 144 if (!ait.hasNext()) { 145 break; 146 } 147 GenPolynomial<C> p = (GenPolynomial<C>) ait.next(); 148 if (ae.totalDeg() == 2) { // only base relations 149 //System.out.println("ae => p: " + ae + " => " + p); 150 tex.put(ae, p); 151 } 152 } 153 return tex; 154 } 155 156 157 /** 158 * Hash code for base relations. 159 * @param a mixed list 160 * @returns hashCode(a) 161 */ 162 @SuppressWarnings("unchecked") 163 int fromListDeg2HashCode(List a) { 164 int h = 0; 165 Iterator ait = a.iterator(); 166 while (ait.hasNext()) { 167 ExpVectorPair ae = (ExpVectorPair) ait.next(); 168 h = 31 * h + ae.hashCode(); 169 if (!ait.hasNext()) { 170 break; 171 } 172 GenPolynomial<C> p = (GenPolynomial<C>) ait.next(); 173 if (ae.totalDeg() == 2) { // only base relations 174 //System.out.println("ae => p: " + ae + " => " + p); 175 h = 31 * h + p.val.hashCode(); // avoid hash of ring 176 } 177 } 178 return h; 179 } 180 181 182 /** 183 * Equals for special maps. 184 * @param m1 first map 185 * @param m2 second map 186 * @returns true if both maps are equal 187 */ 188 @SuppressWarnings("unchecked") 189 boolean equalMaps(Map<ExpVectorPair, GenPolynomial<C>> m1, Map<ExpVectorPair, GenPolynomial<C>> m2) { 190 if (!m1.keySet().equals(m2.keySet())) { 191 return false; 192 } 193 for (Map.Entry<ExpVectorPair, GenPolynomial<C>> me : m1.entrySet()) { 194 GenPolynomial<C> p1 = me.getValue(); 195 ExpVectorPair ep = me.getKey(); 196 GenPolynomial<C> p2 = m2.get(ep); 197 if (p1.compareTo(p2) != 0) { // not working: !p1.equals(p2)) { // TODO 198 logger.info("ep = " + ep + ", p1 = " + p1 + ", p2 = " + p2); 199 //logger.info("p1.compareTo(p2) = " + p1.compareTo(p2)); 200 //logger.info("p1.equals(p2) = " + p1.equals(p2)); 201 return false; 202 } 203 } 204 return true; 205 } 206 207 208 /** 209 * Hash code for this relation table. 210 * @see java.lang.Object#hashCode() 211 */ 212 @Override 213 public int hashCode() { 214 //int h = ring.hashCode(); // infinite recursion 215 int h = 0; //table.hashCode(); 216 h = table.keySet().hashCode(); 217 for (Map.Entry<List<Integer>,List> me : table.entrySet()) { 218 //List<Integer> k = me.getKey(); 219 List a = me.getValue(); 220 int t1 = fromListDeg2HashCode(a); 221 h = 31 * h + t1; 222 } 223 return h; 224 } 225 226 227 /** 228 * Test if the table is empty. 229 * @return true if the table is empty, else false. 230 */ 231 public boolean isEmpty() { 232 return table.isEmpty(); 233 } 234 235 236 /** 237 * Get the String representation. 238 * @see java.lang.Object#toString() 239 */ 240 @Override 241 public String toString() { 242 List v; 243 StringBuffer s = new StringBuffer("RelationTable["); 244 boolean first = true; 245 for (Map.Entry<List<Integer>,List> me : table.entrySet()) { 246 List<Integer> k = me.getKey(); 247 if (first) { 248 first = false; 249 } else { 250 s.append(", "); 251 } 252 s.append(k.toString()); 253 v = me.getValue(); 254 s.append("="); 255 s.append(v.toString()); 256 } 257 s.append("]"); 258 return s.toString(); 259 } 260 261 262 /** 263 * Get the String representation. 264 * @param vars names for the variables. 265 * @see java.lang.Object#toString() 266 */ 267 @SuppressWarnings({ "unchecked", "cast" }) 268 public String toString(String[] vars) { 269 if (vars == null) { 270 return toString(); 271 } 272 StringBuffer s = new StringBuffer(""); 273 String[] cvars = null; 274 if (coeffTable) { 275 if (ring.coFac instanceof GenPolynomialRing) { 276 cvars = ((GenPolynomialRing<C>) (Object) ring.coFac).getVars(); 277 } else if (ring.coFac instanceof GenWordPolynomialRing) { 278 cvars = ((GenWordPolynomialRing<C>) (Object) ring.coFac).getVars(); 279 } 280 s.append("Coefficient "); 281 } 282 s.append("RelationTable\n("); 283 List v; 284 if (PrettyPrint.isTrue()) { 285 boolean first = true; 286 for (Map.Entry<List<Integer>,List> me : table.entrySet()) { 287 List<Integer> k = me.getKey(); 288 if (first) { 289 first = false; 290 s.append("\n"); 291 } else { 292 s.append(",\n"); 293 } 294 v = me.getValue(); 295 for (Iterator jt = v.iterator(); jt.hasNext();) { 296 ExpVectorPair ep = (ExpVectorPair) jt.next(); 297 GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) jt.next(); 298 if (ep.totalDeg() != 2) { // only base relations 299 continue; 300 } 301 s.append("( " + ep.getFirst().toString(vars) + " ), "); 302 if (cvars == null) { 303 s.append("( " + ep.getSecond().toString(vars) + " ), "); 304 } else { 305 s.append("( " + ep.getSecond().toString(cvars) + " ), "); 306 } 307 s.append("( " + p.toString(vars) + " )"); 308 if (jt.hasNext()) { 309 s.append(",\n"); 310 } 311 } 312 } 313 } else { 314 boolean first = true; 315 for (Map.Entry<List<Integer>,List> me : table.entrySet()) { 316 List<Integer> k = me.getKey(); 317 if (first) { 318 first = false; 319 } else { 320 s.append(",\n"); 321 } 322 v = me.getValue(); 323 for (Iterator jt = v.iterator(); jt.hasNext();) { 324 ExpVectorPair ep = (ExpVectorPair) jt.next(); 325 s.append("( " + ep.getFirst().toString(vars) + " ), "); 326 if (cvars == null) { 327 s.append("( " + ep.getSecond().toString(vars) + " ), "); 328 } else { 329 s.append("( " + ep.getSecond().toString(cvars) + " ), "); 330 } 331 GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) jt.next(); 332 //s.append("( " + p.toString(vars) + " )"); 333 s.append(" " + p.toString(vars)); 334 if (jt.hasNext()) { 335 s.append(",\n"); 336 } 337 } 338 } 339 } 340 s.append("\n)\n"); 341 return s.toString(); 342 } 343 344 345 /** 346 * Get a scripting compatible string representation. 347 * @return script compatible representation for this relation table. 348 */ 349 @SuppressWarnings({ "unchecked", "cast" }) 350 public String toScript() { 351 // Python case 352 String[] vars = ring.vars; 353 String[] cvars = null; 354 if (coeffTable) { 355 if (ring.coFac instanceof GenPolynomialRing) { 356 cvars = ((GenPolynomialRing<C>) (Object) ring.coFac).getVars(); 357 } else if (ring.coFac instanceof GenWordPolynomialRing) { 358 cvars = ((GenWordPolynomialRing<C>) (Object) ring.coFac).getVars(); 359 } 360 } 361 List v; 362 StringBuffer s = new StringBuffer("["); 363 boolean first = true; 364 for (Map.Entry<List<Integer>,List> me : table.entrySet()) { 365 List<Integer> k = me.getKey(); 366 if (first) { 367 first = false; 368 s.append(""); 369 } else { 370 s.append(", "); 371 } 372 v = me.getValue(); 373 for (Iterator jt = v.iterator(); jt.hasNext();) { 374 ExpVectorPair ep = (ExpVectorPair) jt.next(); 375 GenPolynomial<C> p = (GenPolynomial<C>) jt.next(); 376 if (ep.totalDeg() > 2) { // only base relations 377 continue; 378 } 379 s.append("" + ep.getFirst().toScript(vars) + ", "); 380 if (coeffTable) { 381 String eps = ep.getSecond().toScript(cvars); 382 if (eps.isEmpty()) { // if from a deeper down ring 383 eps = p.leadingBaseCoefficient().abs().toScript(); 384 } 385 s.append("" + eps + ", "); 386 } else { 387 s.append("" + ep.getSecond().toScript(vars) + ", "); 388 } 389 //s.append("( " + p.toScript() + " )"); 390 s.append(" " + p.toScript()); 391 if (jt.hasNext()) { 392 s.append(", "); 393 } 394 } 395 } 396 s.append("]"); 397 return s.toString(); 398 } 399 400 401 /** 402 * Update or initialize RelationTable with new relation. relation is e * f = 403 * p. 404 * @param e first term. 405 * @param f second term. 406 * @param p solvable product polynomial. 407 */ 408 @SuppressWarnings({ "unchecked", "cast" }) 409 public synchronized void update(ExpVector e, ExpVector f, GenSolvablePolynomial<C> p) { 410 if (p == null || e == null || f == null) { 411 throw new IllegalArgumentException("RelationTable update e|f|p == null"); 412 } 413 GenSolvablePolynomialRing<C> sring = p.ring; 414 if (debug) { 415 logger.info("new relation = " + sring.toScript(e) + " .*. " + sring.toScript(f) + " = " 416 + p.toScript()); 417 } 418 // test equal HTs for left and right side 419 if (!coeffTable) { // old case 420 if (e.totalDeg() == 1 && f.totalDeg() == 1) { // higher or mixed degrees TODO 421 int[] de = e.dependencyOnVariables(); 422 int[] df = f.dependencyOnVariables(); 423 logger.debug("update e ? f " + de[0] + " " + df[0]); 424 //int t = ring.tord.getDescendComparator().compare(e,f); 425 //System.out.println("update compare(e,f) = " + t); 426 if (de[0] == df[0]) { // error 427 throw new IllegalArgumentException("RelationTable update e==f"); 428 } 429 if (de[0] > df[0]) { // invalid update 430 logger.error("update e < f: " + sring.toScript(e) + " < " + sring.toScript(f)); 431 //if (debug && false) { 432 // throw new IllegalArgumentException("update e < f"); 433 //} 434 ExpVector tmp = e; 435 e = f; 436 f = tmp; 437 Map.Entry<ExpVector, C> m = p.leadingMonomial(); 438 ExpVector ef = e.sum(f); 439 if (!ef.equals(m.getKey())) { 440 throw new IllegalArgumentException("update e*f != lt(p): " + sring.toScript(ef) 441 + ", lt = " + sring.toScript(m.getKey())); 442 } 443 GenPolynomial<C> r = p.reductum(); //subtract(m.getValue(), m.getKey()); 444 r = r.negate(); 445 //p = (GenSolvablePolynomial<C>) r.sum(m.getValue(), m.getKey()); 446 p = (GenSolvablePolynomial<C>) r; 447 p.doPutToMap(m.getKey(), m.getValue()); 448 } 449 } 450 ExpVector ef = e.sum(f); 451 ExpVector lp = p.leadingExpVector(); 452 if (!ef.equals(lp)) { // check for suitable term order 453 logger.error("relation term order = " + ring.tord); 454 throw new IllegalArgumentException("update e*f != lt(p): " + sring.toScript(ef) + " != " 455 + sring.toScript(lp)); 456 } 457 } else { // is coeffTable 458 ExpVector lp = p.leadingExpVector(); 459 if (!e.equals(lp)) { // check for suitable term order 460 logger.error("relation term order = " + ring.tord); 461 throw new IllegalArgumentException("Coefficient RelationTable update e != lt(p): " 462 + sring.toScript(e) + " != " + sring.toScript(lp)); 463 } 464 if (p.leadingBaseCoefficient() instanceof GenPolynomial) { 465 lp = ((GenPolynomial<C>) (Object) p.leadingBaseCoefficient()).leadingExpVector(); 466 if (!f.equals(lp)) { // check for suitable term order 467 logger.error("relation term order = " + ring.tord); 468 logger.error("Coefficient RelationTable update f != lt(lfcd(p)): " + sring.toScript(e) 469 + ", f = " + f + ", p = " + p.toScript()); 470 throw new IllegalArgumentException("Coefficient RelationTable update f != lt(lfcd(p)): " 471 + e + ", f = " + f + ", p = " + p); 472 } 473 } else if (p.leadingBaseCoefficient() instanceof GenWordPolynomial) { 474 lp = ((GenWordPolynomial<C>) (Object) p.leadingBaseCoefficient()).leadingWord() 475 .leadingExpVector(); 476 if (!f.equals(lp)) { // check for suitable term order and word structure 477 logger.error("relation term order = " + ring.tord); 478 logger.error("Coefficient RelationTable update f != lt(lfcd(p)): " + sring.toScript(e) 479 + ", f = " + f + ", p = " + p.toScript()); 480 throw new IllegalArgumentException("Coefficient RelationTable update f != lt(lfcd(p)): " 481 + e + ", f = " + f + ", p = " + p); 482 } 483 } 484 } 485 List<Integer> key = makeKey(e, f); 486 ExpVectorPair evp = new ExpVectorPair(e, f); 487 if (key.size() != 2) { 488 logger.warn("key = " + key + ", evp = " + evp); 489 } 490 List part = table.get(key); 491 if (part == null) { // initialization only 492 part = new LinkedList(); 493 part.add(evp); 494 part.add(p); 495 table.put(key, part); 496 return; 497 } 498 @SuppressWarnings("unused") 499 Object skip; 500 int index = -1; 501 synchronized (part) { // with lookup() 502 for (ListIterator it = part.listIterator(); it.hasNext();) { 503 ExpVectorPair look = (ExpVectorPair) it.next(); 504 skip = it.next(); // skip poly 505 if (look.isMultiple(evp)) { 506 index = it.nextIndex(); 507 // last index of or first index of: break 508 } 509 } 510 if (index < 0) { 511 index = 0; 512 } 513 part.add(index, evp); 514 part.add(index + 1, p); 515 } 516 // table.put( key, part ); // required?? 517 } 518 519 520 /** 521 * Update or initialize RelationTable with new relation. relation is e * f = 522 * p. 523 * @param E first term polynomial. 524 * @param F second term polynomial. 525 * @param p solvable product polynomial. 526 */ 527 @SuppressWarnings({ "unchecked", "cast" }) 528 public void update(GenPolynomial<C> E, GenPolynomial<C> F, GenSolvablePolynomial<C> p) { 529 if (E.isZERO() || F.isZERO()) { 530 throw new IllegalArgumentException("polynomials may not be zero: " + E + ", " + F); 531 } 532 C ce = E.leadingBaseCoefficient(); 533 C cf = F.leadingBaseCoefficient(); 534 if (!ce.isONE()) { 535 throw new IllegalArgumentException("lbcf of polynomials must be one: " + ce + ", " + cf 536 + ", p = " + p); 537 } 538 ExpVector e = E.leadingExpVector(); 539 ExpVector f = F.leadingExpVector(); 540 if (coeffTable && f.isZERO()) { 541 if (cf instanceof GenPolynomial) { 542 f = ((GenPolynomial<C>) (Object) cf).leadingExpVector(); 543 } else if (cf instanceof GenWordPolynomial) { 544 f = ((GenWordPolynomial<C>) (Object) cf).leadingWord().leadingExpVector(); 545 } 546 } 547 //logger.info("update: " + e + " .*. " + f + " = " + p); 548 update(e, f, p); 549 } 550 551 552 /** 553 * Update or initialize RelationTable with new relation. relation is e * f = 554 * p. 555 * @param E first term polynomial. 556 * @param F second term polynomial. 557 * @param p product polynomial. 558 */ 559 public void update(GenPolynomial<C> E, GenPolynomial<C> F, GenPolynomial<C> p) { 560 if (p.isZERO()) { 561 throw new IllegalArgumentException("polynomial may not be zero: " + p); 562 } 563 if (p.isONE()) { 564 throw new IllegalArgumentException("product of polynomials may not be one: " + p); 565 } 566 GenSolvablePolynomial<C> sp = new GenSolvablePolynomial<C>(ring, p.val); 567 update(E, F, sp); 568 } 569 570 571 /** 572 * Update or initialize RelationTable with new relation. relation is e * f = 573 * p. 574 * @param e first term. 575 * @param f second term. 576 * @param p solvable product polynomial. 577 */ 578 public void update(ExpVector e, ExpVector f, GenPolynomial<C> p) { 579 if (p.isZERO()) { 580 throw new IllegalArgumentException("polynomial may not be zero: " + p); 581 } 582 if (p.isONE()) { 583 throw new IllegalArgumentException("product of polynomials may not be one: " + p); 584 } 585 GenSolvablePolynomial<C> sp = new GenSolvablePolynomial<C>(ring, p.val); 586 update(e, f, sp); 587 } 588 589 590 /** 591 * Lookup RelationTable for existing relation. Find p with e * f = p. If no 592 * relation for e * f is contained in the table then return the symmetric 593 * product p = 1 e f. 594 * @param e first term. 595 * @param f second term. 596 * @return t table relation container, contains e' and f' with e f = e' 597 * lt(p) f'. 598 */ 599 @SuppressWarnings({ "unchecked", "cast" }) 600 public TableRelation<C> lookup(ExpVector e, ExpVector f) { 601 List<Integer> key = makeKey(e, f); 602 List part = table.get(key); 603 if (part == null) { // symmetric product 604 GenSolvablePolynomial<C> p = null; 605 C c = null; 606 if (!coeffTable) { 607 ExpVector ef = e.sum(f); 608 //p = new GenSolvablePolynomial<C>(ring, ring.getONECoefficient(), ef); 609 p = ring.valueOf(ef); 610 } else { 611 if (ring.coFac instanceof GenPolynomialRing) { 612 GenPolynomialRing<C> cofac = (GenPolynomialRing<C>) (Object) ring.coFac; 613 //System.out.println("f = " + f + ", e = " + e); 614 GenPolynomial<C> pc = cofac.valueOf(f); 615 c = (C) (Object) pc; 616 } else if (ring.coFac instanceof GenWordPolynomialRing) { 617 GenWordPolynomialRing<C> cofac = (GenWordPolynomialRing<C>) (Object) ring.coFac; 618 //System.out.println("f = " + f + ", e = " + e); 619 GenWordPolynomial<C> pc = cofac.valueOf(f); 620 c = (C) (Object) pc; 621 } 622 p = new GenSolvablePolynomial<C>(ring, c, e); 623 //System.out.println("pc = " + pc + ", p = " + p); 624 } 625 return new TableRelation<C>(null, null, p); 626 } 627 // no distinction between coefficient f or polynomial f 628 ExpVectorPair evp = new ExpVectorPair(e, f); 629 ExpVector ep = null; 630 ExpVector fp = null; 631 ExpVectorPair look = null; 632 GenSolvablePolynomial<C> p = null; 633 synchronized (part) { // with update() 634 for (Iterator it = part.iterator(); it.hasNext();) { 635 look = (ExpVectorPair) it.next(); 636 p = (GenSolvablePolynomial<C>) it.next(); 637 if (evp.isMultiple(look)) { 638 ep = e.subtract(look.getFirst()); 639 fp = f.subtract(look.getSecond()); 640 if (ep.isZERO()) { 641 ep = null; 642 } 643 if (fp.isZERO()) { 644 fp = null; 645 } 646 if (debug) { 647 if (p != null && p.ring.vars != null) { 648 logger.info("found relation = " + e.toString(p.ring.vars) + " .*. " 649 + f.toString(p.ring.vars) + " = " + p); 650 } else { 651 logger.info("found relation = " + e + " .*. " + f + " = " + p); 652 } 653 } 654 return new TableRelation<C>(ep, fp, p); 655 } 656 } 657 } 658 // unreacheable code! 659 throw new RuntimeException("no entry found in relation table for " + evp); 660 } 661 662 663 /** 664 * Construct a key for (e,f). 665 * @param e first term. 666 * @param f second term. 667 * @return k key for (e,f). 668 */ 669 protected List<Integer> makeKey(ExpVector e, ExpVector f) { 670 int[] de = e.dependencyOnVariables(); 671 int[] df = f.dependencyOnVariables(); 672 List<Integer> key = new ArrayList<Integer>(de.length + df.length); 673 for (int i = 0; i < de.length; i++) { 674 key.add(Integer.valueOf(de[i])); 675 } 676 for (int i = 0; i < df.length; i++) { 677 key.add(Integer.valueOf(df[i])); 678 } 679 return key; 680 } 681 682 683 /** 684 * Size of the table. 685 * @return n number of non-commutative relations. 686 */ 687 public int size() { 688 int s = 0; 689 if (table == null || table.isEmpty()) { 690 return s; 691 } 692 for (Iterator<List> it = table.values().iterator(); it.hasNext();) { 693 List list = it.next(); 694 s += list.size() / 2; 695 } 696 return s; 697 } 698 699 700 /** 701 * Extend variables. Used e.g. in module embedding. Extend all ExpVectors 702 * and polynomials of the given relation table by i elements and put the 703 * relations into this table, i.e. this should be empty. 704 * @param tab a relation table to be extended and inserted into this. 705 */ 706 @SuppressWarnings("unchecked") 707 public void extend(RelationTable<C> tab) { 708 if (tab.table.isEmpty()) { 709 return; 710 } 711 // assert this.size() == 0 712 int i = ring.nvar - tab.ring.nvar; 713 int j = 0; 714 long k = 0l; 715 List val; 716 for (List<Integer> key : tab.table.keySet()) { 717 val = tab.table.get(key); 718 for (Iterator jt = val.iterator(); jt.hasNext();) { 719 ExpVectorPair ep = (ExpVectorPair) jt.next(); 720 ExpVector e = ep.getFirst(); 721 ExpVector f = ep.getSecond(); 722 GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) jt.next(); 723 ExpVector ex = e.extend(i, j, k); 724 ExpVector fx; 725 if (coeffTable) { 726 fx = f; 727 } else { 728 fx = f.extend(i, j, k); 729 } 730 GenSolvablePolynomial<C> px = (GenSolvablePolynomial<C>) p.extend(ring, j, k); 731 this.update(ex, fx, px); 732 } 733 } 734 return; 735 } 736 737 738 /** 739 * Contract variables. Used e.g. in module embedding. Contract all 740 * ExpVectors and polynomials of the given relation table by i elements and 741 * put the relations into this table, i.e. this should be empty. 742 * @param tab a relation table to be contracted and inserted into this. 743 */ 744 @SuppressWarnings("unchecked") 745 public void contract(RelationTable<C> tab) { 746 if (tab.table.isEmpty()) { 747 return; 748 } 749 // assert this.size() == 0 750 int i = tab.ring.nvar - ring.nvar; 751 List val; 752 for (List<Integer> key : tab.table.keySet()) { 753 val = tab.table.get(key); 754 //System.out.println("key = " + key + ", val = " + val); 755 for (Iterator jt = val.iterator(); jt.hasNext();) { 756 ExpVectorPair ep = (ExpVectorPair) jt.next(); 757 ExpVector e = ep.getFirst(); 758 ExpVector f = ep.getSecond(); 759 GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) jt.next(); 760 ExpVector ec = e.contract(i, e.length() - i); 761 ExpVector fc; 762 if (coeffTable) { 763 fc = f; 764 } else { 765 fc = f.contract(i, f.length() - i); 766 } 767 //System.out.println("ec = " + ec + ", fc = " + fc); 768 if (ec.isZERO()) { 769 continue; 770 } 771 Map<ExpVector, GenPolynomial<C>> mc = p.contract(ring); 772 if (mc.size() != 1) { 773 continue; 774 } 775 GenPolynomial<C> pc = mc.values().iterator().next(); 776 this.update(ec, fc, pc); 777 } 778 } 779 return; 780 } 781 782 783 /** 784 * Recursive representation. Split all ExpVectors and polynomials of the 785 * given relation table to lower elements and upper elements and put the 786 * relations into this table or this as coefficient table, i.e. this should 787 * be empty. 788 * @param tab a relation table to be contracted and inserted into this. 789 */ 790 @SuppressWarnings({ "unchecked", "cast" }) 791 public void recursive(RelationTable tab) { //<C> 792 if (tab.table.isEmpty()) { 793 return; 794 } 795 //System.out.println("rel ring = " + ring.toScript()); 796 // assert this.size() == 0 797 GenPolynomialRing<C> cring = (GenPolynomialRing<C>) (Object) ring.coFac; 798 //System.out.println("cring = " + cring.toScript()); 799 GenSolvablePolynomial<C> pc; 800 int i = ring.nvar; // tab.ring.nvar - 801 for (Object okey : tab.table.keySet()) { 802 List<Integer> key = (List<Integer>) okey; 803 List val = (List) tab.table.get(key); 804 //System.out.println("key = " + key + ", val = " + val); 805 for (Iterator jt = val.iterator(); jt.hasNext();) { 806 ExpVectorPair ep = (ExpVectorPair) jt.next(); 807 ExpVector e = ep.getFirst(); 808 ExpVector f = ep.getSecond(); 809 GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) jt.next(); 810 ExpVector ec = e.contract(0, i); 811 ExpVector fc; 812 if (coeffTable) { 813 fc = f; 814 } else { 815 fc = f.contract(0, i); 816 } 817 //System.out.println("ec = " + ec + ", fc = " + fc); 818 if (ec.isZERO()) { 819 continue; 820 } 821 Map<ExpVector, GenPolynomial<C>> mc = p.contract(cring); 822 //System.out.println("mc = " + mc + ", p = " + p); 823 //System.out.println("mc.ring = " + mc.values().iterator().next().ring.toScript()); 824 if (mc.size() == 1) { // < 1 only for p == 0 825 pc = (GenSolvablePolynomial<C>) mc.values().iterator().next(); 826 this.update(ec, fc, pc); 827 } else { // construct recursive polynomial 828 GenSolvablePolynomial<C> qr = ring.getZERO(); 829 for (Map.Entry<ExpVector, GenPolynomial<C>> mce : mc.entrySet()) { 830 ExpVector g = mce.getKey(); 831 GenPolynomial<C> q = mce.getValue(); 832 C cq = (C) (Object) q; 833 GenSolvablePolynomial<C> qp = new GenSolvablePolynomial<C>(ring, cq, g); 834 qr = (GenSolvablePolynomial<C>) qr.sum(qp); 835 } 836 if (coeffTable) { 837 fc = ((GenPolynomial<C>) (Object) qr.leadingBaseCoefficient()).leadingExpVector(); 838 } 839 if (fc.isZERO()) { 840 continue; 841 } 842 //System.out.println("ec = " + ec + ", fc = " + fc + ", qr = " + qr); 843 if (coeffTable) { 844 logger.info("coeffTable: adding " + qr); 845 } else { 846 logger.info("no coeffTable: adding " + qr); 847 } 848 this.update(ec, fc, qr); 849 } 850 } 851 } 852 return; 853 } 854 855 856 /** 857 * Reverse variables and relations. Used e.g. in opposite rings. Reverse all 858 * ExpVectors and polynomials of the given relation table and put the 859 * modified relations into this table, i.e. this should be empty. 860 * @param tab a relation table to be reverted and inserted into this. 861 */ 862 @SuppressWarnings("unchecked") 863 public void reverse(RelationTable<C> tab) { 864 if (tab.table.isEmpty()) { 865 return; 866 } 867 // assert this.size() == 0 868 if (!table.isEmpty()) { 869 logger.error("reverse table not empty"); 870 } 871 int k = -1; 872 if (ring.tord.getEvord2() != 0 && ring.partial) { 873 k = ring.tord.getSplit(); 874 } 875 logger.debug("k split = " + k); 876 //System.out.println("k split = " + k ); 877 //System.out.println("reversed ring = " + ring.toScript() ); 878 for (List<Integer> key : tab.table.keySet()) { 879 List val = tab.table.get(key); 880 for (Iterator jt = val.iterator(); jt.hasNext();) { 881 ExpVectorPair ep = (ExpVectorPair) jt.next(); 882 ExpVector e = ep.getFirst(); 883 ExpVector f = ep.getSecond(); 884 GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) jt.next(); 885 //logger.info("e pre reverse = " + e ); 886 //logger.info("f pre reverse = " + f ); 887 //logger.info("p pre reverse = " + p ); 888 //if (e.degree() > 1 || f.degree() > 1) { // not required 889 // continue; // revert only base relations 890 //} 891 ExpVector ex; 892 ExpVector fx; 893 GenSolvablePolynomial<C> px; 894 boolean change = true; // if relevant vars reversed 895 if (k >= 0) { 896 ex = e.reverse(k); 897 if (coeffTable) { 898 fx = f; 899 } else { 900 fx = f.reverse(k); 901 } 902 //int[] ed = ex.dependencyOnVariables(); // = e 903 //if (ed.length == 0 || ed[0] >= k) { // k >= 0 904 // change = false; todo 905 //} 906 //int[] fd = fx.dependencyOnVariables(); // = f 907 //if (fd.length == 0 || fd[0] >= k) { // k >= 0 908 // change = false; todo 909 //} 910 } else { 911 ex = e.reverse(); 912 if (coeffTable) { 913 fx = f; 914 } else { 915 fx = f.reverse(); 916 } 917 } 918 px = (GenSolvablePolynomial<C>) p.reverse(ring); 919 //System.out.println("update, p, px: " + p.toScript() + " reverse:" + px.toScript() ); 920 if (!change) { 921 this.update(e, f, px); // same order 922 } else { 923 if (coeffTable) { 924 this.update(ex, fx, px); // same order 925 } else { 926 this.update(fx, ex, px); // opposite order 927 } 928 } 929 } 930 } 931 return; 932 } 933 934 935 /** 936 * Convert relation table to list of polynomial triples. 937 * @return rel = (e1,f1,p1, ...) where ei * fi = pi are solvable relations. 938 */ 939 @SuppressWarnings({ "unchecked", "cast" }) 940 public List<GenSolvablePolynomial<C>> relationList() { 941 List<GenSolvablePolynomial<C>> rels = new ArrayList<GenSolvablePolynomial<C>>(); 942 //C one = ring.getONECoefficient(); 943 for (Map.Entry<List<Integer>,List> me : table.entrySet()) { 944 List<Integer> k = me.getKey(); 945 List v = me.getValue(); 946 for (Iterator jt = v.iterator(); jt.hasNext();) { 947 ExpVectorPair ep = (ExpVectorPair) jt.next(); 948 ExpVector e = ep.getFirst(); 949 GenSolvablePolynomial<C> pe = ring.valueOf(e); 950 ExpVector f = ep.getSecond(); 951 GenSolvablePolynomial<C> pf = null; 952 if (coeffTable) { // todo 953 C cf = null; 954 if (ring.coFac instanceof GenPolynomialRing) { 955 GenPolynomial<C> cpf; 956 cpf = ((GenPolynomialRing<C>) (Object) ring.coFac).valueOf(f); 957 cf = (C) (Object) cpf; // down cast 958 } else if (ring.coFac instanceof GenWordPolynomialRing) { 959 GenWordPolynomial<C> cpf; 960 cpf = ((GenWordPolynomialRing<C>) (Object) ring.coFac).valueOf(f); 961 cf = (C) (Object) cpf; // down cast 962 } 963 //pf = new GenSolvablePolynomial<C>(ring, cf); 964 pf = ring.valueOf(cf); 965 } else { 966 pf = ring.valueOf(f); 967 } 968 GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) jt.next(); 969 rels.add(pe); 970 rels.add(pf); 971 rels.add(p); 972 } 973 } 974 return rels; 975 } 976 977 978 /** 979 * Add list of polynomial triples as relations. 980 * @param rel = (e1,f1,p1, ...) where ei * fi = pi are solvable relations. 981 * <b>Note:</b> Only because of type erasure, aequivalent to 982 * addRelations(). 983 */ 984 //@SuppressWarnings("unchecked") 985 public void addSolvRelations(List<GenSolvablePolynomial<C>> rel) { 986 PolynomialList<C> Prel = new PolynomialList<C>(ring, rel); 987 addRelations(Prel.getList()); 988 } 989 990 991 /** 992 * Add list of polynomial triples as relations. 993 * @param rel = (e1,f1,p1, ...) where ei * fi = pi are solvable relations. 994 */ 995 @SuppressWarnings({ "unchecked", "cast" }) 996 public void addRelations(List<GenPolynomial<C>> rel) { 997 if (rel == null || rel.isEmpty()) { 998 return; 999 } 1000 Iterator<GenPolynomial<C>> relit = rel.iterator(); 1001 while (relit.hasNext()) { 1002 GenPolynomial<C> E = relit.next(); 1003 ExpVector e = E.leadingExpVector(); 1004 ExpVector f = null; 1005 if (!relit.hasNext()) { 1006 throw new IllegalArgumentException("F and poly part missing"); 1007 } 1008 GenPolynomial<C> F = relit.next(); 1009 if (!relit.hasNext()) { 1010 throw new IllegalArgumentException("poly part missing"); 1011 } 1012 GenPolynomial<C> P = relit.next(); 1013 if (coeffTable && F.isConstant()) { // todo 1014 if (ring.coFac instanceof GenPolynomialRing) { 1015 f = ((GenPolynomial<C>) (Object) F.leadingBaseCoefficient()).leadingExpVector(); 1016 } else if (ring.coFac instanceof GenWordPolynomialRing) { 1017 f = ((GenWordPolynomial<C>) (Object) F.leadingBaseCoefficient()).leadingWord() 1018 .leadingExpVector(); 1019 } 1020 } else { 1021 f = F.leadingExpVector(); 1022 } 1023 update(e, f, P); 1024 } 1025 return; 1026 } 1027 1028}