[Home] DMelt member access. Java source code: edu.jas.gbmod.SolvableSyzygyAbstract
/*
* $Id$
*/
package edu.jas.gbmod;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import edu.jas.gb.Reduction;
import edu.jas.gb.ReductionSeq;
import edu.jas.gb.SolvableExtendedGB;
import edu.jas.gb.SolvableGroebnerBase;
import edu.jas.gb.SolvableGroebnerBaseSeq;
import edu.jas.gb.SolvableReduction;
import edu.jas.gb.SolvableReductionSeq;
import edu.jas.poly.ExpVector;
import edu.jas.poly.GenPolynomial;
import edu.jas.poly.GenSolvablePolynomial;
import edu.jas.poly.GenSolvablePolynomialRing;
import edu.jas.poly.ModuleList;
import edu.jas.poly.PolynomialList;
import edu.jas.structure.RingElem;
import edu.jas.vector.BasicLinAlg;
/**
* Syzygy class for solvable polynomials. Implements Syzygy computations and
* tests.
* @param coefficient type
* @author Heinz Kredel
*/
public class SolvableSyzygyAbstract> implements SolvableSyzygy {
private static final Logger logger = Logger.getLogger(SolvableSyzygyAbstract.class);
private final boolean debug = logger.isDebugEnabled();
/**
* Solvable reduction engine.
*/
public final SolvableReduction sred;
/**
* Reduction engine.
*/
protected Reduction red;
/**
* Linear algebra engine.
*/
protected BasicLinAlg> blas;
/**
* Groebner basis engine.
*/
protected SolvableGroebnerBase sbb;
/**
* Module Groebner basis engine.
*/
protected ModSolvableGroebnerBase msbb;
/**
* Constructor.
*/
public SolvableSyzygyAbstract() {
red = new ReductionSeq();
sred = new SolvableReductionSeq();
blas = new BasicLinAlg>();
sbb = new SolvableGroebnerBaseSeq();
msbb = new ModSolvableGroebnerBaseAbstract();
}
/**
* Left syzygy for left Groebner base.
* @param F a Groebner base.
* @return leftSyz(F), a basis for the left module of syzygies for F.
*/
public List>> leftZeroRelations(List> F) {
return leftZeroRelations(0, F);
}
/**
* Left syzygy for left Groebner base.
* @param modv number of module variables.
* @param F a Groebner base.
* @return leftSyz(F), a basis for the left module of syzygies for F.
*/
public List>> leftZeroRelations(int modv, List> F) {
List>> Z = new ArrayList>>();
ArrayList> S = new ArrayList>(F.size());
for (int i = 0; i < F.size(); i++) {
S.add(null);
}
GenSolvablePolynomial pi, pj, s, h, zero;
zero = null;
for (int i = 0; i < F.size(); i++) {
pi = F.get(i);
if (pi != null && zero == null) {
zero = pi.ring.getZERO();
}
for (int j = i + 1; j < F.size(); j++) {
pj = F.get(j);
//logger.info("p"+i+", p"+j+" = " + pi + ", " +pj);
if (!red.moduleCriterion(modv, pi, pj)) {
continue;
}
// if ( ! red.criterion4( pi, pj ) ) continue;
List> row = new ArrayList>(S);
s = sred.leftSPolynomial(row, i, pi, j, pj);
//logger.info("row = " + row);
if (s.isZERO()) {
Z.add(row);
continue;
}
h = sred.leftNormalform(row, F, s);
if (!h.isZERO()) {
throw new ArithmeticException("Syzygy no leftGB");
}
if (logger.isDebugEnabled()) {
logger.info("row = " + row);
}
Z.add(row);
}
}
// set null to zero
for (List> vr : Z) {
for (int j = 0; j < vr.size(); j++) {
if (vr.get(j) == null) {
vr.set(j, zero);
}
}
}
return Z;
}
/**
* Left syzygy for left module Groebner base.
* @param M a Groebner base.
* @return leftSyz(M), a basis for the left module of syzygies for M.
*/
@SuppressWarnings("unchecked")
public ModuleList leftZeroRelations(ModuleList M) {
ModuleList N = null;
if (M == null || M.list == null) {
return N;
}
if (M.rows == 0 || M.cols == 0) {
return N;
}
GenSolvablePolynomial zero = (GenSolvablePolynomial) M.ring.getZERO();
//logger.info("zero = " + zero);
//ModuleList Np = null;
PolynomialList F = M.getPolynomialList();
int modv = M.cols; // > 0
logger.info("modv = " + modv);
List>> G = leftZeroRelations(modv, F.castToSolvableList());
//if (G == null) {
// return N;
//}
List>> Z = new ArrayList>>();
for (int i = 0; i < G.size(); i++) {
List> Gi = G.get(i);
List> Zi = new ArrayList>();
// System.out.println("\nG("+i+") = " + G.get(i));
for (int j = 0; j < Gi.size(); j++) {
//System.out.println("\nG("+i+","+j+") = " + Gi.get(j));
GenSolvablePolynomial p = Gi.get(j);
if (p != null) {
Map> r = p.contract(M.ring);
//System.out.println("map("+i+","+j+") = " + r + ", size = " + r.size() );
if (r.size() == 0) {
Zi.add(zero);
} else if (r.size() == 1) {
GenSolvablePolynomial vi = (GenSolvablePolynomial) (r.values().toArray())[0];
Zi.add(vi);
} else { // will not happen
throw new RuntimeException("Map.size() > 1 = " + r.size());
}
}
}
//System.out.println("\nZ("+i+") = " + Zi);
Z.add(Zi);
}
N = new ModuleList((GenSolvablePolynomialRing) M.ring, Z);
//System.out.println("\n\nN = " + N);
return N;
}
/**
* Test if left syzygy.
* @param Z list of sysygies.
* @param F a polynomial list.
* @return true, if Z is a list of left syzygies for F, else false.
*/
public boolean isLeftZeroRelation(List>> Z, List> F) {
List> Fp = PolynomialList. castToList(F);
for (List> row : Z) {
// p has wrong type:
GenPolynomial p = blas.scalarProduct(PolynomialList. castToList(row), Fp);
if (p == null) {
continue;
}
if (!p.isZERO()) {
logger.info("is not ZeroRelation = " + p);
return false;
}
}
return true;
}
/**
* Test if right syzygy.
* @param Z list of sysygies.
* @param F a polynomial list.
* @return true, if Z is a list of right syzygies for F, else false.
*/
public boolean isRightZeroRelation(List>> Z,
List> F) {
List> Fp = PolynomialList. castToList(F);
for (List> row : Z) {
List> yrow = PolynomialList. castToList(row);
// p has wrong type:
GenPolynomial p = blas.scalarProduct(Fp, yrow); // param order
if (p == null) {
continue;
}
if (!p.isZERO()) {
logger.info("is not ZeroRelation = " + p);
return false;
}
}
return true;
}
/**
* Test if left sysygy of modules
* @param Z list of sysygies.
* @param F a module list.
* @return true, if Z is a list of left syzygies for F, else false.
*/
public boolean isLeftZeroRelation(ModuleList Z, ModuleList F) {
if (Z == null || Z.list == null) {
return true;
}
for (List> row : Z.list) {
List> zr = blas.leftScalarProduct(row, F.list);
if (!blas.isZero(zr)) {
logger.info("is not ZeroRelation (" + zr.size() + ") = " + zr);
return false;
}
}
return true;
}
/**
* Test if right sysygy of modules
* @param Z list of sysygies.
* @param F a module list.
* @return true, if Z is a list of right syzygies for F, else false.
*/
public boolean isRightZeroRelation(ModuleList Z, ModuleList F) {
if (Z == null || Z.list == null) {
return true;
}
for (List> row : Z.list) {
List> zr = blas.rightScalarProduct(row, F.list);
//List> zr = blas.scalarProduct(row,F.list);
if (!blas.isZero(zr)) {
logger.info("is not ZeroRelation (" + zr.size() + ") = " + zr);
return false;
}
}
return true;
}
/**
* Resolution of a module. Only with direct GBs.
* @param M a module list of a Groebner basis.
* @return a resolution of M.
*/
public List> resolution(ModuleList M) {
List> R = new ArrayList>();
ModuleList MM = M;
ModuleList GM;
ModuleList Z;
while (true) {
GM = msbb.leftGB(MM);
Z = leftZeroRelations(GM);
R.add(new SolvResPart(MM, GM, Z));
if (Z == null || Z.list == null || Z.list.size() == 0) {
break;
}
MM = Z;
}
return R;
}
/**
* Resolution of a polynomial list. Only with direct GBs.
* @param F a polynomial list of a Groebner basis.
* @return a resolution of F.
*/
@SuppressWarnings("unchecked")
public List // |SolvResPolPart>
resolution(PolynomialList F) {
List>> Z;
ModuleList Zm;
List> G;
PolynomialList Gl;
G = sbb.leftGB(F.castToSolvableList());
Z = leftZeroRelations(G);
Gl = new PolynomialList((GenSolvablePolynomialRing) F.ring, G);
Zm = new ModuleList((GenSolvablePolynomialRing) F.ring, Z);
List R = resolution(Zm);
R.add(0, new SolvResPolPart(F, Gl, Zm));
return R;
}
/**
* Resolution of a module.
* @param M a module list of an arbitrary basis.
* @return a resolution of M.
*/
public List> resolutionArbitrary(ModuleList M) {
List> R = new ArrayList>();
ModuleList MM = M;
ModuleList GM = null;
ModuleList Z;
while (true) {
//GM = msbb.leftGB(MM);
Z = leftZeroRelationsArbitrary(MM);
R.add(new SolvResPart(MM, GM, Z));
if (Z == null || Z.list == null || Z.list.size() == 0) {
break;
}
MM = Z;
}
return R;
}
/**
* Resolution of a polynomial list.
* @param F a polynomial list of an arbitrary basis.
* @return a resolution of F.
*/
@SuppressWarnings("unchecked")
public List // |SolvResPolPart>
resolutionArbitrary(PolynomialList F) {
List>> Z;
ModuleList Zm;
PolynomialList Gl = null;
//List> G = sbb.leftGB( F.castToSolvableList() );
//Gl = new PolynomialList((GenSolvablePolynomialRing)F.ring, G);
Z = leftZeroRelationsArbitrary(F.castToSolvableList());
Zm = new ModuleList((GenSolvablePolynomialRing) F.ring, Z);
List R = resolutionArbitrary(Zm);
R.add(0, new SolvResPolPart(F, Gl, Zm));
return R;
}
/**
* Left syzygy module from arbitrary base.
* @param F a solvable polynomial list.
* @return syz(F), a basis for the module of left syzygies for F.
*/
public List>> leftZeroRelationsArbitrary(List> F) {
return leftZeroRelationsArbitrary(0, F);
}
/**
* Left syzygy module from arbitrary base.
* @param modv number of module variables.
* @param F a solvable polynomial list.
* @return syz(F), a basis for the module of left syzygies for F.
*/
@SuppressWarnings("unchecked")
public List>> leftZeroRelationsArbitrary(int modv,
List> F) {
if (F == null) {
return null; //leftZeroRelations( modv, F );
}
if (F.size() <= 1) {
return leftZeroRelations(modv, F);
}
final int lenf = F.size();
SolvableExtendedGB exgb = sbb.extLeftGB(F);
if (debug) {
logger.info("exgb = " + exgb);
}
if (!sbb.isLeftReductionMatrix(exgb)) {
logger.error("is reduction matrix ? false");
}
List> G = exgb.G;
List>> G2F = exgb.G2F;
List>> F2G = exgb.F2G;
List>> sg = leftZeroRelations(modv, G);
GenSolvablePolynomialRing ring = G.get(0).ring;
ModuleList S = new ModuleList(ring, sg);
if (debug) {
logger.info("syz = " + S);
}
if (!isLeftZeroRelation(sg, G)) {
logger.error("is syzygy ? false");
}
List>> sf;
sf = new ArrayList>>(sg.size());
//List> row;
for (List> r : sg) {
Iterator> it = r.iterator();
Iterator>> jt = G2F.iterator();
List> rf;
rf = new ArrayList>(lenf);
for (int m = 0; m < lenf; m++) {
rf.add(ring.getZERO());
}
while (it.hasNext() && jt.hasNext()) {
GenSolvablePolynomial si = it.next();
List> ai = jt.next();
//System.out.println("si = " + si);
//System.out.println("ai = " + ai);
if (si == null || ai == null) {
continue;
}
// pi has wrong type:
List> pi = blas.scalarProduct(si, PolynomialList. castToList(ai));
//System.out.println("pi = " + pi);
rf = PolynomialList. castToSolvableList(blas.vectorAdd(PolynomialList. castToList(rf),
pi));
}
if (it.hasNext() || jt.hasNext()) {
logger.error("leftZeroRelationsArbitrary wrong sizes");
}
//System.out.println("\nrf = " + rf + "\n");
sf.add(rf);
}
if (!isLeftZeroRelation(sf, F)) {
logger.error("is partial syz sf ? false");
}
List>> M;
M = new ArrayList>>(lenf);
for (List> r : F2G) {
Iterator> it = r.iterator();
Iterator>> jt = G2F.iterator();
List> rf;
rf = new ArrayList>(lenf);
for (int m = 0; m < lenf; m++) {
rf.add(ring.getZERO());
}
while (it.hasNext() && jt.hasNext()) {
GenSolvablePolynomial si = it.next();
List> ai = jt.next();
//System.out.println("si = " + si);
//System.out.println("ai = " + ai);
if (si == null || ai == null) {
continue;
}
//pi has wrong type, should be: List>
List> pi = blas.scalarProduct(si, PolynomialList. castToList(ai));
//System.out.println("pi = " + pi);
rf = PolynomialList. castToSolvableList(blas.vectorAdd(PolynomialList. castToList(rf),
pi));
}
if (it.hasNext() || jt.hasNext()) {
logger.error("zeroRelationsArbitrary wrong sizes");
}
//System.out.println("\nMg Mf = " + rf + "\n");
M.add(rf);
}
//ModuleList ML = new ModuleList( ring, M );
//System.out.println("syz ML = " + ML);
// debug only:
//List> F2 = new ArrayList>( F.size() );
/* not true in general
List> Fp = PolynomialList.castToList(F);
for ( List> rr: M ) {
GenSolvablePolynomial rrg = PolynomialList.castToSolvableList(blas.scalarProduct(Fp,PolynomialList.castToList(rr)));
F2.add( rrg );
}
PolynomialList pF = new PolynomialList( ring, F );
PolynomialList pF2 = new PolynomialList( ring, F2 );
if ( ! pF.equals( pF2 ) ) {
logger.error("is FAB = F ? false");
//System.out.println("pF = " + pF.list.size());
//System.out.println("pF2 = " + pF2.list.size());
}
*/
int sflen = sf.size();
List>> M2;
M2 = new ArrayList>>(lenf);
int i = 0;
for (List> ri : M) {
List> r2i;
r2i = new ArrayList>(ri.size());
int j = 0;
for (GenSolvablePolynomial rij : ri) {
GenSolvablePolynomial p = null;
if (i == j) {
p = (GenSolvablePolynomial) ring.getONE().subtract(rij);
} else {
if (rij != null) {
p = (GenSolvablePolynomial) rij.negate();
}
}
r2i.add(p);
j++;
}
M2.add(r2i);
if (!blas.isZero(PolynomialList. castToList(r2i))) {
sf.add(r2i);
}
i++;
}
ModuleList M2L = new ModuleList(ring, M2);
if (debug) {
logger.debug("syz M2L = " + M2L);
}
if (debug) {
ModuleList SF = new ModuleList(ring, sf);
logger.debug("syz sf = " + SF);
logger.debug("#syz " + sflen + ", " + sf.size());
}
if (!isLeftZeroRelation(sf, F)) {
logger.error("is syz sf ? false");
}
return sf;
}
/**
* Left syzygy for arbitrary left module base.
* @param M an arbitrary base.
* @return leftSyz(M), a basis for the left module of syzygies for M.
*/
@SuppressWarnings("unchecked")
public ModuleList leftZeroRelationsArbitrary(ModuleList M) {
ModuleList N = null;
if (M == null || M.list == null) {
return N;
}
if (M.rows == 0 || M.cols == 0) {
return N;
}
GenSolvablePolynomial zero = (GenSolvablePolynomial) M.ring.getZERO();
//logger.info("zero = " + zero);
//ModuleList Np = null;
PolynomialList F = M.getPolynomialList();
int modv = M.cols; // > 0
logger.info("modv = " + modv);
List>> G = leftZeroRelationsArbitrary(modv, F.castToSolvableList());
if (G == null) {
return N;
}
List>> Z = new ArrayList>>();
for (int i = 0; i < G.size(); i++) {
List> Gi = G.get(i);
List> Zi = new ArrayList>();
// System.out.println("\nG("+i+") = " + G.get(i));
for (int j = 0; j < Gi.size(); j++) {
//System.out.println("\nG("+i+","+j+") = " + Gi.get(j));
GenSolvablePolynomial p = Gi.get(j);
if (p != null) {
Map> r = p.contract(M.ring);
//System.out.println("map("+i+","+j+") = " + r + ", size = " + r.size() );
if (r.size() == 0) {
Zi.add(zero);
} else if (r.size() == 1) {
GenSolvablePolynomial vi = (GenSolvablePolynomial) (r.values().toArray())[0];
Zi.add(vi);
} else { // will not happen
throw new RuntimeException("Map.size() > 1 = " + r.size());
}
}
}
//System.out.println("\nZ("+i+") = " + Zi);
Z.add(Zi);
}
N = new ModuleList((GenSolvablePolynomialRing) M.ring, Z);
//System.out.println("\n\nN = " + N);
return N;
}
/**
* Right syzygy module from arbitrary base.
* @param F a solvable polynomial list.
* @return syz(F), a basis for the module of right syzygies for F.
*/
public List>> rightZeroRelationsArbitrary(List> F) {
return rightZeroRelationsArbitrary(0, F);
}
/**
* Right syzygy module from arbitrary base.
* @param modv number of module variables.
* @param F a solvable polynomial list.
* @return syz(F), a basis for the module of right syzygies for F.
*/
@SuppressWarnings("unchecked")
public List>> rightZeroRelationsArbitrary(int modv,
List> F) {
GenSolvablePolynomialRing ring = null;
for (GenSolvablePolynomial p : F) {
if (p != null) {
ring = p.ring;
break;
}
}
List>> Z;
if (ring == null) { // all null
Z = new ArrayList>>(1);
Z.add(F);
return Z;
}
GenSolvablePolynomialRing rring = ring.reverse(true);
GenSolvablePolynomial q;
List> rF;
rF = new ArrayList>(F.size());
for (GenSolvablePolynomial p : F) {
if (p != null) {
q = (GenSolvablePolynomial) p.reverse(rring);
rF.add(q);
}
}
if (debug) {
PolynomialList pl = new PolynomialList(rring, rF);
logger.info("reversed problem = " + pl.toScript());
//System.out.println("reversed problem = " + pl);
}
List>> rZ = leftZeroRelationsArbitrary(modv, rF);
if (debug) {
boolean isit = isLeftZeroRelation(rZ, rF);
logger.debug("isLeftZeroRelation = " + isit);
}
GenSolvablePolynomialRing oring = rring.reverse(true);
if (debug) {
logger.debug("ring == oring: " + ring.equals(oring));
}
ring = oring;
Z = new ArrayList>>(rZ.size());
for (List> z : rZ) {
if (z == null) {
continue;
}
List> s;
s = new ArrayList>(z.size());
for (GenSolvablePolynomial p : z) {
if (p != null) {
q = (GenSolvablePolynomial) p.reverse(ring);
s.add(q);
}
}
Z.add(s);
}
return Z;
}
/**
* Test left Ore condition.
* @param a solvable polynomial
* @param b solvable polynomial
* @param oc = [p,q] two solvable polynomials
* @return true if p*a = q*b, else false
*/
public boolean isLeftOreCond(GenSolvablePolynomial a, GenSolvablePolynomial b,
GenSolvablePolynomial[] oc) {
GenSolvablePolynomial c = oc[0].multiply(a);
GenSolvablePolynomial d = oc[1].multiply(b);
return c.equals(d);
}
/**
* Test right Ore condition.
* @param a solvable polynomial
* @param b solvable polynomial
* @param oc = [p,q] two solvable polynomials
* @return true if a*p = b*q, else false
*/
public boolean isRightOreCond(GenSolvablePolynomial a, GenSolvablePolynomial b,
GenSolvablePolynomial[] oc) {
GenSolvablePolynomial c = a.multiply(oc[0]);
GenSolvablePolynomial d = b.multiply(oc[1]);
return c.equals(d);
}
/**
* Left Ore condition.
* Generators for the left Ore condition of two solvable polynomials.
* @param a solvable polynomial
* @param b solvable polynomial
* @return [p,q] with p*a = q*b
*/
public GenSolvablePolynomial[] leftOreCond(GenSolvablePolynomial a, GenSolvablePolynomial b) {
if (a == null || a.isZERO() || b == null || b.isZERO()) {
throw new IllegalArgumentException("a and b must be non zero");
}
GenSolvablePolynomialRing pfac = a.ring;
GenSolvablePolynomial[] oc = (GenSolvablePolynomial[]) new GenSolvablePolynomial[2];
if ( a.equals(b) ) {
oc[0] = pfac.getONE();
oc[1] = pfac.getONE();
return oc;
}
if ( a.isConstant() ) {
if (pfac.coFac.isCommutative()) { // ??
oc[0] = b;
oc[1] = a;
return oc;
}
oc[1] = pfac.getONE();
C c = a.leadingBaseCoefficient().inverse();
oc[0] = b.multiply(c);
return oc;
}
if ( b.isConstant() ) {
if (pfac.coFac.isCommutative()) { // ??
oc[0] = b;
oc[1] = a;
return oc;
}
oc[0] = pfac.getONE();
C c = b.leadingBaseCoefficient().inverse();
oc[1] = a.multiply(c);
return oc;
}
logger.info("computing left Ore condition: " + a + ", " + b);
List> F = new ArrayList>(2);
F.add(a); F.add(b);
List>> Gz = leftZeroRelationsArbitrary(F);
if ( Gz.size() < 0 ) { // always false
//System.out.println("Gz = " + Gz);
ModuleList M = new ModuleList(pfac,Gz);
ModuleList GM = msbb.leftGB(M);
//System.out.println("GM = " + GM);
Gz = GM.castToSolvableList();
}
List> G1 = null;
GenSolvablePolynomial g1 = null;
for (List> Gi : Gz ) {
//System.out.println("Gi = " + Gi);
if ( Gi.get(0).isZERO() ) {
continue;
}
if ( G1 == null ) {
G1 = Gi;
}
if ( g1 == null ) {
g1 = G1.get(0);
} else if ( g1.compareTo(Gi.get(0)) > 0 ) { //g1.degree() > Gi.get(0).degree()
G1 = Gi;
g1 = G1.get(0);
}
}
oc[0] = g1; //G1.get(0);
oc[1] = (GenSolvablePolynomial) G1.get(1).negate();
//logger.info("Ore multiple: " + oc[0].multiply(a) + ", " + Arrays.toString(oc));
return oc;
}
/**
* Right Ore condition.
* Generators for the right Ore condition of two solvable polynomials.
* @param a solvable polynomial
* @param b solvable polynomial
* @return [p,q] with a*p = b*q
*/
public GenSolvablePolynomial[] rightOreCond(GenSolvablePolynomial a, GenSolvablePolynomial b) {
if (a == null || a.isZERO() || b == null || b.isZERO()) {
throw new IllegalArgumentException("a and b must be non zero");
}
GenSolvablePolynomialRing pfac = a.ring;
GenSolvablePolynomial[] oc = (GenSolvablePolynomial[]) new GenSolvablePolynomial[2];
if ( a.equals(b) ) {
oc[0] = pfac.getONE();
oc[1] = pfac.getONE();
return oc;
}
if ( a.isConstant() ) {
if (pfac.coFac.isCommutative()) { // ??
oc[0] = b;
oc[1] = a;
return oc;
}
oc[1] = pfac.getONE();
C c = a.leadingBaseCoefficient().inverse();
oc[0] = b.multiply(c);
return oc;
}
if ( b.isConstant() ) {
if (pfac.coFac.isCommutative()) { // ??
oc[0] = b;
oc[1] = a;
return oc;
}
oc[0] = pfac.getONE();
C c = b.leadingBaseCoefficient().inverse();
oc[1] = a.multiply(c);
return oc;
}
logger.info("computing right Ore condition: " + a + ", " + b);
List> F = new ArrayList