001/* 002 * $Id: SyzygyAbstract.java 4125 2012-08-19 19:05:22Z kredel $ 003 */ 004 005package edu.jas.gbmod; 006 007 008import java.io.Serializable; 009import java.util.ArrayList; 010import java.util.Iterator; 011import java.util.List; 012import java.util.Map; 013 014import org.apache.log4j.Logger; 015 016import edu.jas.gb.ExtendedGB; 017import edu.jas.gb.GroebnerBase; 018import edu.jas.gb.Reduction; 019import edu.jas.gb.ReductionSeq; 020import edu.jas.gbufd.GBFactory; 021import edu.jas.poly.ExpVector; 022import edu.jas.poly.GenPolynomial; 023import edu.jas.poly.GenPolynomialRing; 024import edu.jas.poly.ModuleList; 025import edu.jas.poly.PolynomialList; 026import edu.jas.structure.GcdRingElem; 027import edu.jas.structure.RingElem; 028import edu.jas.vector.BasicLinAlg; 029import edu.jas.vector.GenVector; 030import edu.jas.vector.GenVectorModul; 031 032 033/** 034 * SyzygyAbstract class. Implements Syzygy computations and tests. 035 * @param <C> coefficient type 036 * @author Heinz Kredel 037 */ 038 039public class SyzygyAbstract<C extends GcdRingElem<C>> implements Syzygy<C> { 040 041 042 private static final Logger logger = Logger.getLogger(SyzygyAbstract.class); 043 044 045 private final boolean debug = logger.isDebugEnabled(); 046 047 048 /** 049 * Reduction engine. 050 */ 051 protected Reduction<C> red; 052 053 054 /** 055 * Linear algebra engine. 056 */ 057 protected BasicLinAlg<GenPolynomial<C>> blas; 058 059 060 /** 061 * Constructor. 062 */ 063 public SyzygyAbstract() { 064 red = new ReductionSeq<C>(); 065 blas = new BasicLinAlg<GenPolynomial<C>>(); 066 //gb = new GroebnerBaseSeqPairSeq<C>(); 067 //gb = new GroebnerBaseSeq<C>(); 068 //gb = GBFactory. getImplementation(); 069 } 070 071 072 /** 073 * Syzygy module from Groebner base. F must be a Groebner base. 074 * @param F a Groebner base. 075 * @return syz(F), a basis for the module of syzygies for F. 076 */ 077 public List<List<GenPolynomial<C>>> zeroRelations(List<GenPolynomial<C>> F) { 078 return zeroRelations(0, F); 079 } 080 081 082 /** 083 * Syzygy module from Groebner base. F must be a Groebner base. 084 * @param modv number of module variables. 085 * @param F a Groebner base. 086 * @return syz(F), a basis for the module of syzygies for F. 087 */ 088 public List<List<GenPolynomial<C>>> zeroRelations(int modv, List<GenPolynomial<C>> F) { 089 List<List<GenPolynomial<C>>> Z = new ArrayList<List<GenPolynomial<C>>>(); 090 if (F == null) { 091 return Z; 092 } 093 GenVectorModul<GenPolynomial<C>> mfac = null; 094 int i = 0; 095 while (mfac == null && i < F.size()) { 096 GenPolynomial<C> p = F.get(i); 097 if (p != null) { 098 mfac = new GenVectorModul<GenPolynomial<C>>(p.ring, F.size()); 099 } 100 } 101 if (mfac == null) { 102 return Z; 103 } 104 GenVector<GenPolynomial<C>> v = mfac.fromList(F); 105 //System.out.println("F = " + F + " v = " + v); 106 return zeroRelations(modv, v); 107 } 108 109 110 /** 111 * Syzygy module from Groebner base. v must be a Groebner base. 112 * @param modv number of module variables. 113 * @param v a Groebner base. 114 * @return syz(v), a basis for the module of syzygies for v. 115 */ 116 public List<List<GenPolynomial<C>>> zeroRelations(int modv, GenVector<GenPolynomial<C>> v) { 117 118 List<List<GenPolynomial<C>>> Z = new ArrayList<List<GenPolynomial<C>>>(); 119 120 GenVectorModul<GenPolynomial<C>> mfac = v.modul; 121 List<GenPolynomial<C>> F = v.val; 122 GenVector<GenPolynomial<C>> S = mfac.getZERO(); 123 GenPolynomial<C> pi, pj, s, h; 124 //zero = mfac.coFac.getZERO(); 125 for (int i = 0; i < F.size(); i++) { 126 pi = F.get(i); 127 for (int j = i + 1; j < F.size(); j++) { 128 pj = F.get(j); 129 //logger.info("p"+i+", p"+j+" = " + pi + ", " +pj); 130 131 if (!red.moduleCriterion(modv, pi, pj)) { 132 continue; 133 } 134 // if ( ! red.criterion4( pi, pj ) ) { continue; } 135 List<GenPolynomial<C>> row = S.copy().val; 136 137 s = red.SPolynomial(row, i, pi, j, pj); 138 if (s.isZERO()) { 139 Z.add(row); 140 continue; 141 } 142 143 h = red.normalform(row, F, s); 144 if (!h.isZERO()) { 145 throw new RuntimeException("Syzygy no GB"); 146 } 147 if (debug) { 148 logger.info("row = " + row.size()); 149 } 150 Z.add(row); 151 } 152 } 153 return Z; 154 } 155 156 157 /** 158 * Syzygy module from module Groebner base. M must be a module Groebner 159 * base. 160 * @param M a module Groebner base. 161 * @return syz(M), a basis for the module of syzygies for M. 162 */ 163 public ModuleList<C> zeroRelations(ModuleList<C> M) { 164 ModuleList<C> N = M; 165 if (M == null || M.list == null) { 166 return N; 167 } 168 if (M.rows == 0 || M.cols == 0) { 169 return N; 170 } 171 GenPolynomial<C> zero = M.ring.getZERO(); 172 //System.out.println("zero = " + zero); 173 174 //ModuleList<C> Np = null; 175 PolynomialList<C> F = M.getPolynomialList(); 176 int modv = M.cols; // > 0 177 //System.out.println("modv = " + modv); 178 List<List<GenPolynomial<C>>> G = zeroRelations(modv, F.list); 179 //if (G == null) { 180 // return N; 181 //} 182 List<List<GenPolynomial<C>>> Z = new ArrayList<List<GenPolynomial<C>>>(); 183 for (int i = 0; i < G.size(); i++) { 184 //F = new PolynomialList(F.ring,(List)G.get(i)); 185 List<GenPolynomial<C>> Gi = G.get(i); 186 List<GenPolynomial<C>> Zi = new ArrayList<GenPolynomial<C>>(); 187 // System.out.println("\nG("+i+") = " + G.get(i)); 188 for (int j = 0; j < Gi.size(); j++) { 189 //System.out.println("\nG("+i+","+j+") = " + Gi.get(j)); 190 GenPolynomial<C> p = Gi.get(j); 191 if (p != null) { 192 Map<ExpVector, GenPolynomial<C>> r = p.contract(M.ring); 193 int s = 0; 194 for (GenPolynomial<C> vi : r.values()) { 195 Zi.add(vi); 196 s++; 197 } 198 if (s == 0) { 199 Zi.add(zero); 200 } else if (s > 1) { // will not happen 201 System.out.println("p = " + p); 202 System.out.println("map(" + i + "," + j + ") = " + r + ", size = " + r.size()); 203 throw new RuntimeException("Map.size() > 1 = " + r.size()); 204 } 205 } 206 } 207 //System.out.println("\nZ("+i+") = " + Zi); 208 Z.add(Zi); 209 } 210 N = new ModuleList<C>(M.ring, Z); 211 //System.out.println("\n\nN = " + N); 212 return N; 213 } 214 215 216 /** 217 * Test if sysygy. 218 * @param Z list of sysygies. 219 * @param F a polynomial list. 220 * @return true, if Z is a list of syzygies for F, else false. 221 */ 222 223 public boolean isZeroRelation(List<List<GenPolynomial<C>>> Z, List<GenPolynomial<C>> F) { 224 for (List<GenPolynomial<C>> row : Z) { 225 GenPolynomial<C> p = blas.scalarProduct(row, F); 226 if (p == null) { 227 continue; 228 } 229 if (!p.isZERO()) { 230 logger.info("is not ZeroRelation = " + p.toString(p.ring.getVars())); 231 logger.info("row = " + row); 232 //logger.info("F = " + F); 233 return false; 234 } 235 } 236 return true; 237 } 238 239 240 /** 241 * Test if sysygy of modules. 242 * @param Z list of sysygies. 243 * @param F a module list. 244 * @return true, if Z is a list of syzygies for F, else false. 245 */ 246 247 public boolean isZeroRelation(ModuleList<C> Z, ModuleList<C> F) { 248 if (Z == null || Z.list == null) { 249 return true; 250 } 251 for (List<GenPolynomial<C>> row : Z.list) { 252 List<GenPolynomial<C>> zr = blas.leftScalarProduct(row, F.list); 253 if (!blas.isZero(zr)) { 254 logger.info("is not ZeroRelation (" + zr.size() + ") = " + zr); 255 return false; 256 } 257 } 258 return true; 259 } 260 261 262 /** 263 * Resolution of a module. Only with direct GBs. 264 * @param M a module list of a Groebner basis. 265 * @return a resolution of M. 266 */ 267 public List<ResPart<C>> resolution(ModuleList<C> M) { 268 List<ResPart<C>> R = new ArrayList<ResPart<C>>(); 269 ModuleList<C> MM = M; 270 ModuleList<C> GM; 271 ModuleList<C> Z; 272 ModGroebnerBase<C> mbb = new ModGroebnerBaseAbstract<C>(M.ring.coFac); 273 while (true) { 274 GM = mbb.GB(MM); 275 Z = zeroRelations(GM); 276 R.add(new ResPart<C>(MM, GM, Z)); 277 if (Z == null || Z.list == null || Z.list.size() == 0) { 278 break; 279 } 280 MM = Z; 281 } 282 return R; 283 } 284 285 286 /** 287 * Resolution of a polynomial list. Only with direct GBs. 288 * @param F a polynomial list of a Groebner basis. 289 * @return a resolution of F. 290 */ 291 public List // <ResPart<C>|ResPolPart<C>> 292 resolution(PolynomialList<C> F) { 293 List<List<GenPolynomial<C>>> Z; 294 ModuleList<C> Zm; 295 List<GenPolynomial<C>> G; 296 PolynomialList<C> Gl; 297 298 GroebnerBase<C> gb = GBFactory.getImplementation(F.ring.coFac); 299 G = gb.GB(F.list); 300 Z = zeroRelations(G); 301 Gl = new PolynomialList<C>(F.ring, G); 302 Zm = new ModuleList<C>(F.ring, Z); 303 304 List R = resolution(Zm); //// <ResPart<C>|ResPolPart<C>> 305 R.add(0, new ResPolPart<C>(F, Gl, Zm)); 306 return R; 307 } 308 309 310 /** 311 * Resolution of a polynomial list. 312 * @param F a polynomial list of an arbitrary basis. 313 * @return a resolution of F. 314 */ 315 public List // <ResPart<C>|ResPolPart<C>> 316 resolutionArbitrary(PolynomialList<C> F) { 317 List<List<GenPolynomial<C>>> Z; 318 ModuleList<C> Zm; 319 //List<GenPolynomial<C>> G; 320 PolynomialList<C> Gl = null; 321 322 //G = (new GroebnerBaseSeq<C>()).GB( F.list ); 323 Z = zeroRelationsArbitrary(F.list); 324 //Gl = new PolynomialList<C>(F.ring, F.list); 325 Zm = new ModuleList<C>(F.ring, Z); 326 327 List R = resolutionArbitrary(Zm); //// <ResPart<C>|ResPolPart<C>> 328 R.add(0, new ResPolPart<C>(F, Gl, Zm)); 329 return R; 330 } 331 332 333 /** 334 * Resolution of a module. 335 * @param M a module list of an arbitrary basis. 336 * @return a resolution of M. 337 */ 338 public List<ResPart<C>> resolutionArbitrary(ModuleList<C> M) { 339 List<ResPart<C>> R = new ArrayList<ResPart<C>>(); 340 ModuleList<C> MM = M; 341 ModuleList<C> GM = null; 342 ModuleList<C> Z; 343 //ModGroebnerBase<C> mbb = new ModGroebnerBaseAbstract<C>(M.ring.coFac); 344 while (true) { 345 //GM = mbb.GB(MM); 346 Z = zeroRelationsArbitrary(MM); 347 R.add(new ResPart<C>(MM, GM, Z)); 348 if (Z == null || Z.list == null || Z.list.size() == 0) { 349 break; 350 } 351 MM = Z; 352 } 353 return R; 354 } 355 356 357 /** 358 * Syzygy module from arbitrary base. 359 * @param F a polynomial list. 360 * @return syz(F), a basis for the module of syzygies for F. 361 */ 362 public List<List<GenPolynomial<C>>> zeroRelationsArbitrary(List<GenPolynomial<C>> F) { 363 return zeroRelationsArbitrary(0, F); 364 } 365 366 367 /** 368 * Syzygy module from arbitrary base. 369 * @param modv number of module variables. 370 * @param F a polynomial list. 371 * @return syz(F), a basis for the module of syzygies for F. 372 */ 373 public List<List<GenPolynomial<C>>> zeroRelationsArbitrary(int modv, List<GenPolynomial<C>> F) { 374 if (F == null) { 375 return new ArrayList<List<GenPolynomial<C>>>(); 376 //return zeroRelations(modv, F); 377 } 378 if (F.size() <= 1) { 379 return zeroRelations(modv, F); 380 } 381 GroebnerBase<C> gb = GBFactory.getImplementation(F.get(0).ring.coFac); 382 final int lenf = F.size(); 383 ExtendedGB<C> exgb = gb.extGB(F); 384 if (debug) { 385 logger.debug("exgb = " + exgb); 386 if (!gb.isReductionMatrix(exgb)) { 387 logger.error("is reduction matrix ? false"); 388 } 389 } 390 List<GenPolynomial<C>> G = exgb.G; 391 List<List<GenPolynomial<C>>> G2F = exgb.G2F; 392 List<List<GenPolynomial<C>>> F2G = exgb.F2G; 393 394 List<List<GenPolynomial<C>>> sg = zeroRelations(modv, G); 395 GenPolynomialRing<C> ring = G.get(0).ring; 396 ModuleList<C> S = new ModuleList<C>(ring, sg); 397 if (debug) { 398 logger.debug("syz = " + S); 399 if (!isZeroRelation(sg, G)) { 400 logger.error("is syzygy ? false"); 401 } 402 } 403 List<List<GenPolynomial<C>>> sf; 404 sf = new ArrayList<List<GenPolynomial<C>>>(sg.size()); 405 //List<GenPolynomial<C>> row; 406 for (List<GenPolynomial<C>> r : sg) { 407 Iterator<GenPolynomial<C>> it = r.iterator(); 408 Iterator<List<GenPolynomial<C>>> jt = G2F.iterator(); 409 410 List<GenPolynomial<C>> rf; 411 rf = new ArrayList<GenPolynomial<C>>(lenf); 412 for (int m = 0; m < lenf; m++) { 413 rf.add(ring.getZERO()); 414 } 415 while (it.hasNext() && jt.hasNext()) { 416 GenPolynomial<C> si = it.next(); 417 List<GenPolynomial<C>> ai = jt.next(); 418 //System.out.println("si = " + si); 419 //System.out.println("ai = " + ai); 420 if (si == null || ai == null) { 421 continue; 422 } 423 List<GenPolynomial<C>> pi = blas.scalarProduct(si, ai); 424 //System.out.println("pi = " + pi); 425 rf = blas.vectorAdd(rf, pi); 426 } 427 if (it.hasNext() || jt.hasNext()) { 428 logger.error("zeroRelationsArbitrary wrong sizes"); 429 } 430 //System.out.println("\nrf = " + rf + "\n"); 431 sf.add(rf); 432 } 433 List<List<GenPolynomial<C>>> M; 434 M = new ArrayList<List<GenPolynomial<C>>>(lenf); 435 for (List<GenPolynomial<C>> r : F2G) { 436 Iterator<GenPolynomial<C>> it = r.iterator(); 437 Iterator<List<GenPolynomial<C>>> jt = G2F.iterator(); 438 439 List<GenPolynomial<C>> rf; 440 rf = new ArrayList<GenPolynomial<C>>(lenf); 441 for (int m = 0; m < lenf; m++) { 442 rf.add(ring.getZERO()); 443 } 444 while (it.hasNext() && jt.hasNext()) { 445 GenPolynomial<C> si = it.next(); 446 List<GenPolynomial<C>> ai = jt.next(); 447 //System.out.println("si = " + si); 448 //System.out.println("ai = " + ai); 449 if (si == null || ai == null) { 450 continue; 451 } 452 List<GenPolynomial<C>> pi = blas.scalarProduct(ai, si); 453 //System.out.println("pi = " + pi); 454 rf = blas.vectorAdd(rf, pi); 455 } 456 if (it.hasNext() || jt.hasNext()) { 457 logger.error("zeroRelationsArbitrary wrong sizes"); 458 } 459 //System.out.println("\nMg Mf = " + rf + "\n"); 460 M.add(rf); 461 } 462 //ModuleList<C> ML = new ModuleList<C>( ring, M ); 463 //System.out.println("syz ML = " + ML); 464 // debug only: 465 /* not true in general 466 List<GenPolynomial<C>> F2 = new ArrayList<GenPolynomial<C>>( F.size() ); 467 for ( List<GenPolynomial<C>> rr: M ) { 468 GenPolynomial<C> rrg = blas.scalarProduct( F, rr ); 469 F2.add( rrg ); 470 } 471 PolynomialList<C> pF = new PolynomialList<C>( ring, F ); 472 PolynomialList<C> pF2 = new PolynomialList<C>( ring, F2 ); 473 if ( ! pF.equals( pF2 ) ) { 474 logger.error("is FAB = F ? false"); 475 } 476 */ 477 int sflen = sf.size(); 478 List<List<GenPolynomial<C>>> M2; 479 M2 = new ArrayList<List<GenPolynomial<C>>>(lenf); 480 int i = 0; 481 for (List<GenPolynomial<C>> ri : M) { 482 List<GenPolynomial<C>> r2i; 483 r2i = new ArrayList<GenPolynomial<C>>(ri.size()); 484 int j = 0; 485 for (GenPolynomial<C> rij : ri) { 486 GenPolynomial<C> p = null; 487 if (i == j) { 488 p = ring.getONE().subtract(rij); 489 } else { 490 if (rij != null) { 491 p = rij.negate(); 492 } 493 } 494 r2i.add(p); 495 j++; 496 } 497 M2.add(r2i); 498 if (!blas.isZero(r2i)) { 499 sf.add(r2i); 500 } 501 i++; 502 } 503 if (debug) { 504 ModuleList<C> M2L = new ModuleList<C>(ring, M2); 505 logger.debug("syz M2L = " + M2L); 506 ModuleList<C> SF = new ModuleList<C>(ring, sf); 507 logger.debug("syz sf = " + SF); 508 logger.debug("#syz " + sflen + ", " + sf.size()); 509 if (!isZeroRelation(sf, F)) { 510 logger.error("is syz sf ? false"); 511 } 512 } 513 return sf; 514 } 515 516 517 /** 518 * Syzygy module from arbitrary module base. 519 * @param M an arbitrary module base. 520 * @return syz(M), a basis for the module of syzygies for M. 521 */ 522 public ModuleList<C> zeroRelationsArbitrary(ModuleList<C> M) { 523 ModuleList<C> N = M; 524 if (M == null || M.list == null) { 525 return N; 526 } 527 if (M.rows == 0 || M.cols == 0) { 528 return N; 529 } 530 GenPolynomial<C> zero = M.ring.getZERO(); 531 //System.out.println("zero = " + zero); 532 533 //ModuleList<C> Np = null; 534 PolynomialList<C> F = M.getPolynomialList(); 535 int modv = M.cols; // > 0 536 //System.out.println("modv = " + modv); 537 List<List<GenPolynomial<C>>> G = zeroRelationsArbitrary(modv, F.list); 538 //if (G == null) { 539 // return N; 540 //} 541 List<List<GenPolynomial<C>>> Z = new ArrayList<List<GenPolynomial<C>>>(); 542 for (int i = 0; i < G.size(); i++) { 543 //F = new PolynomialList(F.ring,(List)G.get(i)); 544 List<GenPolynomial<C>> Gi = G.get(i); 545 List<GenPolynomial<C>> Zi = new ArrayList<GenPolynomial<C>>(); 546 // System.out.println("\nG("+i+") = " + G.get(i)); 547 for (int j = 0; j < Gi.size(); j++) { 548 //System.out.println("\nG("+i+","+j+") = " + Gi.get(j)); 549 GenPolynomial<C> p = Gi.get(j); 550 if (p != null) { 551 Map<ExpVector, GenPolynomial<C>> r = p.contract(M.ring); 552 int s = 0; 553 for (GenPolynomial<C> vi : r.values()) { 554 Zi.add(vi); 555 s++; 556 } 557 if (s == 0) { 558 Zi.add(zero); 559 } else if (s > 1) { // will not happen 560 System.out.println("p = " + p); 561 System.out.println("map(" + i + "," + j + ") = " + r + ", size = " + r.size()); 562 throw new RuntimeException("Map.size() > 1 = " + r.size()); 563 } 564 } 565 } 566 //System.out.println("\nZ("+i+") = " + Zi); 567 Z.add(Zi); 568 } 569 N = new ModuleList<C>(M.ring, Z); 570 //System.out.println("\n\nN = " + N); 571 return N; 572 } 573 574} 575 576 577/** 578 * Container for module resolution components. 579 * @param <C> coefficient type 580 */ 581class ResPart<C extends RingElem<C>> implements Serializable { 582 583 584 public final ModuleList<C> module; 585 586 587 public final ModuleList<C> GB; 588 589 590 public final ModuleList<C> syzygy; 591 592 593 /** 594 * ResPart. 595 * @param m a module list. 596 * @param g a module list GB. 597 * @param z a syzygy module list. 598 */ 599 public ResPart(ModuleList<C> m, ModuleList<C> g, ModuleList<C> z) { 600 module = m; 601 GB = g; 602 syzygy = z; 603 } 604 605 606 /** 607 * toString. 608 */ 609 @Override 610 public String toString() { 611 StringBuffer s = new StringBuffer("ResPart(\n"); 612 s.append("module = " + module); 613 s.append("\n GB = " + GB); 614 s.append("\n syzygy = " + syzygy); 615 s.append(")"); 616 return s.toString(); 617 } 618} 619 620 621/** 622 * Container for polynomial resolution components. 623 */ 624class ResPolPart<C extends RingElem<C>> implements Serializable { 625 626 627 public final PolynomialList<C> ideal; 628 629 630 public final PolynomialList<C> GB; 631 632 633 public final ModuleList<C> syzygy; 634 635 636 /** 637 * ResPolPart. 638 * @param m a polynomial list. 639 * @param g a polynomial list GB. 640 * @param z a syzygy module list. 641 */ 642 public ResPolPart(PolynomialList<C> m, PolynomialList<C> g, ModuleList<C> z) { 643 ideal = m; 644 GB = g; 645 syzygy = z; 646 } 647 648 649 /** 650 * toString. 651 */ 652 @Override 653 public String toString() { 654 StringBuffer s = new StringBuffer("ResPolPart(\n"); 655 s.append("ideal = " + ideal); 656 s.append("\n GB = " + GB); 657 s.append("\n syzygy = " + syzygy); 658 s.append(")"); 659 return s.toString(); 660 } 661 662}