/*
* $Id$
*/
package edu.jas.gbufd;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import edu.jas.gb.GroebnerBaseAbstract;
import edu.jas.gb.SolvableGroebnerBaseAbstract;
import edu.jas.gb.SolvableGroebnerBaseSeq;
import edu.jas.gb.SolvableReductionAbstract;
import edu.jas.gb.SolvableReductionSeq;
import edu.jas.poly.ExpVector;
import edu.jas.poly.GenPolynomial;
import edu.jas.poly.GenPolynomialRing;
import edu.jas.poly.GenSolvablePolynomial;
import edu.jas.poly.GenSolvablePolynomialRing;
import edu.jas.poly.PolyUtil;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.RingElem;
/**
* Package gbufd utilities.
* @author Heinz Kredel
*/
public class PolyGBUtil {
private static final Logger logger = Logger.getLogger(PolyGBUtil.class);
private static boolean debug = logger.isDebugEnabled();
/**
* Test for resultant.
* @param A generic polynomial.
* @param B generic polynomial.
* @param r generic polynomial.
* @return true if res(A,B) isContained in ideal(A,B), else false.
*/
public static > boolean isResultant(GenPolynomial A, GenPolynomial B,
GenPolynomial r) {
if (r == null || r.isZERO()) {
return true;
}
GroebnerBaseAbstract bb = GBFactory. getImplementation(r.ring.coFac);
List> F = new ArrayList>(2);
F.add(A);
F.add(B);
List> G = bb.GB(F);
//System.out.println("G = " + G);
GenPolynomial n = bb.red.normalform(G, r);
//System.out.println("n = " + n);
return n.isZERO();
}
/**
* Top pseudo reduction wrt the main variables.
* @param P generic polynomial.
* @param A list of generic polynomials sorted according to appearing main
* variables.
* @return top pseudo remainder of P wrt. A for the appearing variables.
*/
public static > GenPolynomial topPseudoRemainder(List> A,
GenPolynomial P) {
if (A == null || A.isEmpty()) {
return P.monic();
}
if (P.isZERO()) {
return P;
}
//System.out.println("remainder, P = " + P);
GenPolynomialRing pfac = A.get(0).ring;
if (pfac.nvar <= 1) { // recursion base
GenPolynomial R = PolyUtil. baseSparsePseudoRemainder(P, A.get(0));
return R.monic();
}
// select polynomials according to the main variable
GenPolynomialRing> rfac = pfac.recursive(1);
GenPolynomial Q = A.get(0); // wrong, must eventually search polynomial
GenPolynomial> qr = PolyUtil. recursive(rfac, Q);
GenPolynomial> pr = PolyUtil. recursive(rfac, P);
GenPolynomial> rr;
if (qr.isONE()) {
return P.ring.getZERO();
}
if (qr.degree(0) > 0) {
rr = PolyUtil. recursiveSparsePseudoRemainder(pr, qr);
//System.out.println("remainder, pr = " + pr);
//System.out.println("remainder, qr = " + qr);
//System.out.println("remainder, rr = " + rr);
} else {
rr = pr;
}
if (rr.degree(0) > 0) {
GenPolynomial R = PolyUtil. distribute(pfac, rr);
return R.monic();
// not further reduced wrt. other variables = top-reduction only
}
List> zeroDeg = zeroDegrees(A);
GenPolynomial R = topPseudoRemainder(zeroDeg, rr.leadingBaseCoefficient());
R = R.extend(pfac, 0, 0L);
return R.monic();
}
/**
* Top coefficient pseudo remainder of the leading coefficient of P wrt A in
* the main variables.
* @param P generic polynomial in n+1 variables.
* @param A list of generic polynomials in n variables sorted according to
* appearing main variables.
* @return pseudo remainder of the leading coefficient of P wrt A.
*/
public static > GenPolynomial topCoefficientPseudoRemainder(
List> A, GenPolynomial P) {
if (A == null || A.isEmpty()) {
return P.monic();
}
if (P.isZERO()) {
return P;
}
GenPolynomialRing pfac = P.ring;
GenPolynomialRing pfac1 = A.get(0).ring;
if (pfac1.nvar <= 1) { // recursion base
GenPolynomial a = A.get(0);
GenPolynomialRing> rfac = pfac.recursive(pfac.nvar - 1);
GenPolynomial> pr = PolyUtil. recursive(rfac, P);
// ldcf(P,x_m) = q a + r
GenPolynomial> rr = PolyGBUtil. coefficientPseudoRemainderBase(pr, a);
GenPolynomial R = PolyUtil. distribute(pfac, rr);
return R.monic();
}
// select polynomials according to the main variable
GenPolynomialRing> rfac1 = pfac1.recursive(1);
int nv = pfac.nvar - pfac1.nvar;
GenPolynomialRing> rfac = pfac.recursive(1 + nv);
GenPolynomialRing>> rfac2 = rfac.recursive(nv);
if (debug) {
logger.info("rfac =" + rfac);
}
GenPolynomial> pr = PolyUtil. recursive(rfac, P);
GenPolynomial>> pr2 = PolyUtil.> recursive(rfac2, pr);
//System.out.println("recursion, pr2 = " + pr2);
GenPolynomial Q = A.get(0);
GenPolynomial> qr = PolyUtil. recursive(rfac1, Q);
GenPolynomial>> rr;
if (qr.isONE()) {
return P.ring.getZERO();
}
if (qr.degree(0) > 0) {
// pseudo remainder: ldcf(P,x_m) = a q + r
rr = PolyGBUtil. coefficientPseudoRemainder(pr2, qr);
//System.out.println("recursion, qr = " + qr);
//System.out.println("recursion, pr = " + pr2);
//System.out.println("recursion, rr = " + rr);
} else {
rr = pr2;
}
// reduction wrt. the other variables
List> zeroDeg = zeroDegrees(A);
GenPolynomial> Rr = PolyUtil.> distribute(rfac, rr);
GenPolynomial R = PolyUtil. distribute(pfac, Rr);
R = topCoefficientPseudoRemainder(zeroDeg, R);
return R.monic();
}
/**
* Polynomial leading coefficient pseudo remainder.
* @param P generic polynomial in n+1 variables.
* @param A generic polynomial in n variables.
* @return pseudo remainder of the leading coefficient of P wrt A, with
* ldcf(A)m' P = quotient * A + remainder.
*/
public static > GenPolynomial>> coefficientPseudoRemainder(
GenPolynomial>> P, GenPolynomial> A) {
if (A == null || A.isZERO()) { // findbugs
throw new ArithmeticException(P + " division by zero " + A);
}
if (A.isONE()) {
return P.ring.getZERO();
}
if (P.isZERO() || P.isONE()) {
return P;
}
GenPolynomialRing>> pfac = P.ring;
GenPolynomialRing> afac = A.ring; // == pfac.coFac
GenPolynomial>> r = P;
GenPolynomial> h;
GenPolynomial>> hr;
GenPolynomial> ldcf = P.leadingBaseCoefficient();
long m = ldcf.degree(0);
long n = A.degree(0);
GenPolynomial c = A.leadingBaseCoefficient();
GenPolynomial> cc = afac.getZERO().sum(c);
//System.out.println("cc = " + cc);
ExpVector e = A.leadingExpVector();
for (long i = m; i >= n; i--) {
if (r.isZERO()) {
return r;
}
GenPolynomial> p = r.leadingBaseCoefficient();
ExpVector g = r.leadingExpVector();
long k = p.degree(0);
if (i == k) {
GenPolynomial pl = p.leadingBaseCoefficient();
ExpVector f = p.leadingExpVector();
f = f.subtract(e);
r = r.multiply(cc); // coeff cc
h = A.multiply(pl, f); // coeff ac
hr = new GenPolynomial>>(pfac, h, g);
r = r.subtract(hr);
} else {
r = r.multiply(cc);
}
//System.out.println("r = " + r);
}
if (r.degree(0) < P.degree(0)) { // recursion for degree
r = coefficientPseudoRemainder(r, A);
}
return r;
}
/**
* Polynomial leading coefficient pseudo remainder, base case.
* @param P generic polynomial in 1+1 variables.
* @param A generic polynomial in 1 variable.
* @return pseudo remainder of the leading coefficient of P wrt. A, with
* ldcf(A)m' P = quotient * A + remainder.
*/
public static > GenPolynomial> coefficientPseudoRemainderBase(
GenPolynomial> P, GenPolynomial A) {
if (A == null || A.isZERO()) { // findbugs
throw new ArithmeticException(P + " division by zero " + A);
}
if (A.isONE()) {
return P.ring.getZERO();
}
if (P.isZERO() || P.isONE()) {
return P;
}
GenPolynomialRing> pfac = P.ring;
GenPolynomialRing afac = A.ring; // == pfac.coFac
GenPolynomial> r = P;
GenPolynomial h;
GenPolynomial> hr;
GenPolynomial ldcf = P.leadingBaseCoefficient();
long m = ldcf.degree(0);
long n = A.degree(0);
C c = A.leadingBaseCoefficient();
GenPolynomial cc = afac.getZERO().sum(c);
//System.out.println("cc = " + cc);
ExpVector e = A.leadingExpVector();
for (long i = m; i >= n; i--) {
if (r.isZERO()) {
return r;
}
GenPolynomial p = r.leadingBaseCoefficient();
ExpVector g = r.leadingExpVector();
long k = p.degree(0);
if (i == k) {
C pl = p.leadingBaseCoefficient();
ExpVector f = p.leadingExpVector();
f = f.subtract(e);
r = r.multiply(cc); // coeff cc
h = A.multiply(pl, f); // coeff ac
hr = new GenPolynomial>(pfac, h, g);
r = r.subtract(hr);
} else {
r = r.multiply(cc);
}
//System.out.println("r = " + r);
}
if (r.degree(0) < P.degree(0)) { // recursion for degree
r = coefficientPseudoRemainderBase(r, A);
}
return r;
}
/**
* Extract polynomials with degree zero in the main variable.
* @param A list of generic polynomials in n variables.
* @return Z = [a_i] with deg(a_i,x_n) = 0 and in n-1 variables.
*/
public static > List> zeroDegrees(List> A) {
if (A == null || A.isEmpty()) {
return A;
}
GenPolynomialRing pfac = A.get(0).ring;
GenPolynomialRing> rfac = pfac.recursive(1);
List> zeroDeg = new ArrayList>(A.size());
for (int i = 0; i < A.size(); i++) {
GenPolynomial q = A.get(i);
GenPolynomial> fr = PolyUtil. recursive(rfac, q);
if (fr.degree(0) == 0) {
zeroDeg.add(fr.leadingBaseCoefficient());
}
}
return zeroDeg;
}
/**
* Intersection. Generators for the intersection of ideals.
* @param pfac polynomial ring
* @param A list of polynomials
* @param B list of polynomials
* @return generators for (A \cap B)
*/
public static > List> intersect(GenPolynomialRing pfac,
List> A, List> B) {
if (A == null || A.isEmpty()) { // (0)
return B;
}
if (B == null || B.isEmpty()) { // (0)
return A;
}
int s = A.size() + B.size();
List> c = new ArrayList>(s);
GenPolynomialRing tfac = pfac.extend(1);
// term order is also adjusted
for (GenPolynomial p : A) {
p = p.extend(tfac, 0, 1L); // t*p
c.add(p);
}
for (GenPolynomial p : B) {
GenPolynomial q = p.extend(tfac, 0, 1L);
GenPolynomial r = p.extend(tfac, 0, 0L);
p = r.subtract(q); // (1-t)*p
c.add(p);
}
GroebnerBaseAbstract bb = GBFactory. getImplementation(tfac.coFac);
logger.warn("intersect computing GB");
List> G = bb.GB(c);
if (debug) {
logger.debug("intersect GB = " + G);
}
List> I = PolyUtil. intersect(pfac, G);
return I;
}
/**
* Intersection. Generators for the intersection of ideals.
* @param pfac solvable polynomial ring
* @param A list of polynomials
* @param B list of polynomials
* @return generators for (A \cap B)
*/
public static > List> intersect(
GenSolvablePolynomialRing pfac, List> A,
List> B) {
if (A == null || A.isEmpty()) { // (0)
return B;
}
if (B == null || B.isEmpty()) { // (0)
return A;
}
int s = A.size() + B.size();
List> c = new ArrayList>(s);
GenSolvablePolynomialRing tfac = pfac.extend(1);
// term order is also adjusted
for (GenSolvablePolynomial p : A) {
p = (GenSolvablePolynomial) p.extend(tfac, 0, 1L); // t*p
c.add(p);
}
for (GenSolvablePolynomial p : B) {
GenSolvablePolynomial q = (GenSolvablePolynomial) p.extend(tfac, 0, 1L);
GenSolvablePolynomial r = (GenSolvablePolynomial) p.extend(tfac, 0, 0L);
p = (GenSolvablePolynomial) r.subtract(q); // (1-t)*p
c.add(p);
}
SolvableGroebnerBaseAbstract sbb = new SolvableGroebnerBaseSeq();
//GBFactory. getImplementation(tfac.coFac);
logger.warn("intersect computing GB");
List> g = sbb.leftGB(c);
if (debug) {
logger.debug("intersect GB = " + g);
}
List> I = PolyUtil. intersect(pfac, g);
return I;
}
/**
* Least common multiple via ideal intersection.
* @param r solvable polynomial ring.
* @param n first solvable polynomial.
* @param d second solvable polynomial.
* @return lcm(n,d)
*/
public static > GenSolvablePolynomial syzLcm(GenSolvablePolynomialRing r,
GenSolvablePolynomial n, GenSolvablePolynomial d) {
if (n.isZERO()) {
return n;
}
if (d.isZERO()) {
return d;
}
if (n.isONE()) {
return d;
}
if (d.isONE()) {
return n;
}
List> A = new ArrayList>(1);
A.add(n);
List> B = new ArrayList>(1);
B.add(d);
List> c = PolyGBUtil. intersect(r, A, B);
//if (c.size() != 1) {
// SolvableSyzygyAbstract sz = new SolvableSyzygyAbstract();
// GenSolvablePolynomial[] oc = sz.leftOreCond(n,d);
// GenSolvablePolynomial nc = oc[0].multiply(n);
// System.out.println("nc = " + nc);
// return nc;
//}
GenSolvablePolynomial lcm = null;
for (GenSolvablePolynomial p : c) {
if (p == null || p.isZERO()) {
continue;
}
//System.out.println("p = " + p);
if (lcm == null) {
lcm = p;
continue;
}
if (lcm.compareTo(p) > 0) {
lcm = p;
}
}
if (lcm == null) {
throw new RuntimeException("this cannot happen: lcm == null: " + c);
}
return lcm;
}
/**
* Greatest common divisor via least common multiple.
* @param r solvable polynomial ring.
* @param n first solvable polynomial.
* @param d second solvable polynomial.
* @return gcd(n,d)
*/
public static > GenSolvablePolynomial syzGcd(GenSolvablePolynomialRing r,
GenSolvablePolynomial n, GenSolvablePolynomial d) {
if (n.isZERO()) {
return d;
}
if (d.isZERO()) {
return n;
}
if (n.isONE()) {
return n;
}
if (d.isONE()) {
return d;
}
if (n.totalDegree() > 3 || d.totalDegree() > 3) { // how avoid too long running GBs ?
//if (n.totalDegree() + d.totalDegree() > 6) { // how avoid too long running GBs ?
// && n.length() < 10 && d.length() < 10
logger.warn("skipping GB computation: degs = " + n.totalDegree() + ", " + d.totalDegree());
return r.getONE();
}
List> A = new ArrayList>(2);
A.add(n);
A.add(d);
SolvableGroebnerBaseAbstract sbb = new SolvableGroebnerBaseSeq();
logger.warn("syzGcd computing GB: " + A);
List> G = sbb.rightGB(A); //leftGB, not: sbb.twosidedGB(A);
if ( logger.isInfoEnabled() ) {
logger.info("G = " + G);
}
if (G.size() == 1) {
return G.get(0);
}
logger.warn("gcd not determined, set to 1: " + G); // + ", A = " + A);
return r.getONE();
}
/**
* Solvable quotient and remainder via reduction.
* @param n first solvable polynomial.
* @param d second solvable polynomial.
* @return [ n/d, n - (n/d)*d ]
*/
public static > GenSolvablePolynomial[] quotientRemainder(
GenSolvablePolynomial n, GenSolvablePolynomial d) {
GenSolvablePolynomial[] res = (GenSolvablePolynomial[]) new GenSolvablePolynomial[2];
if (d.isZERO()) {
throw new RuntimeException("division by zero: " + n + "/" + d);
}
if (n.isZERO()) {
res[0] = n;
res[1] = n;
return res;
}
GenSolvablePolynomialRing r = n.ring;
if (d.isONE()) {
res[0] = n;
res[1] = r.getZERO();
return res;
}
// divide
List> Q = new ArrayList>(1);
Q.add(r.getZERO());
List> D = new ArrayList>(1);
D.add(d);
SolvableReductionAbstract sred = new SolvableReductionSeq();
res[1] = sred.rightNormalform(Q, D, n); // left
res[0] = Q.get(0);
return res;
}
/**
* Greatest common divisor and cofactors via least common multiple and
* reduction.
* @param r solvable polynomial ring.
* @param n first solvable polynomial.
* @param d second solvable polynomial.
* @return [ g=gcd(n,d), n/g, d/g ]
*/
public static > GenSolvablePolynomial[] syzGcdCofactors(
GenSolvablePolynomialRing r, GenSolvablePolynomial n, GenSolvablePolynomial d) {
GenSolvablePolynomial[] res = (GenSolvablePolynomial[]) new GenSolvablePolynomial[3];
res[0] = PolyGBUtil. syzGcd(r, n, d);
res[1] = n;
res[2] = d;
if ( res[0].isONE() ) {
return res;
}
GenSolvablePolynomial[] nqr = PolyGBUtil. quotientRemainder(n, res[0]);
if ( !nqr[1].isZERO() ) {
res[0] = r.getONE();
return res;
}
GenSolvablePolynomial[] dqr = PolyGBUtil. quotientRemainder(d, res[0]);
if ( !dqr[1].isZERO() ) {
res[0] = r.getONE();
return res;
}
res[1] = nqr[0];
res[2] = dqr[0];
return res;
}
/**
* Least common multiple. Just for fun, is not efficient.
* @param r polynomial ring.
* @param n first polynomial.
* @param d second polynomial.
* @return lcm(n,d)
*/
public static > GenPolynomial syzLcm(GenPolynomialRing r,
GenPolynomial n, GenPolynomial d) {
List> A = new ArrayList>(1);
A.add(n);
List> B = new ArrayList>(1);
B.add(d);
List> c = PolyGBUtil. intersect(r, A, B);
if (c.size() != 1) {
logger.warn("lcm not uniqe: " + c);
//throw new RuntimeException("lcm not uniqe: " + c);
}
GenPolynomial lcm = c.get(0);
return lcm;
}
/**
* Greatest common divisor. Just for fun, is not efficient.
* @param r polynomial ring.
* @param n first polynomial.
* @param d second polynomial.
* @return gcd(n,d)
*/
public static > GenPolynomial syzGcd(GenPolynomialRing r,
GenPolynomial n, GenPolynomial d) {
if (n.isZERO()) {
return d;
}
if (d.isZERO()) {
return n;
}
if (n.isONE()) {
return n;
}
if (d.isONE()) {
return d;
}
GenPolynomial p = n.multiply(d);
GenPolynomial lcm = syzLcm(r, n, d);
GenPolynomial gcd = PolyUtil. basePseudoDivide(p, lcm);
return gcd;
}
}
Ads help maintain this website.