[Home] DMelt member access. Java source code: edu.jas.application.Ideal
/*
* $Id$
*/
package edu.jas.application;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import org.apache.log4j.Logger;
import edu.jas.gb.ExtendedGB;
import edu.jas.gb.GroebnerBaseAbstract;
import edu.jas.gb.Reduction;
import edu.jas.gbufd.GBFactory;
import edu.jas.gbufd.PolyGBUtil;
import edu.jas.gbufd.GroebnerBasePartial;
import edu.jas.gbmod.SyzygyAbstract;
import edu.jas.poly.AlgebraicNumber;
import edu.jas.poly.AlgebraicNumberRing;
import edu.jas.poly.ExpVector;
import edu.jas.poly.GenPolynomial;
import edu.jas.poly.GenPolynomialRing;
import edu.jas.poly.OptimizedPolynomialList;
import edu.jas.poly.PolyUtil;
import edu.jas.poly.PolynomialList;
import edu.jas.poly.TermOrder;
import edu.jas.poly.TermOrderOptimization;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.NotInvertibleException;
import edu.jas.structure.Power;
import edu.jas.structure.RingFactory;
import edu.jas.ufd.FactorAbstract;
import edu.jas.ufd.GCDFactory;
import edu.jas.ufd.GreatestCommonDivisor;
import edu.jas.ufd.PolyUfdUtil;
import edu.jas.ufd.Quotient;
import edu.jas.ufd.QuotientRing;
import edu.jas.ufd.SquarefreeAbstract;
import edu.jas.ufd.SquarefreeFactory;
/**
* Ideal implements some methods for ideal arithmetic, for example intersection,
* quotient and zero and positive dimensional ideal decomposition.
* @author Heinz Kredel
*/
public class Ideal> implements Comparable>, Serializable {
private static final Logger logger = Logger.getLogger(Ideal.class);
private final boolean debug = logger.isDebugEnabled();
/**
* The data structure is a PolynomialList.
*/
protected PolynomialList list;
/**
* Indicator if list is a Groebner Base.
*/
protected boolean isGB;
/**
* Indicator if test has been performed if this is a Groebner Base.
*/
protected boolean testGB;
/**
* Indicator if list has optimized term order.
*/
protected boolean isTopt;
/**
* Groebner base engine.
*/
protected final GroebnerBaseAbstract bb;
/**
* Reduction engine.
*/
protected final Reduction red;
/**
* Squarefree decomposition engine.
*/
protected final SquarefreeAbstract engine;
/**
* Constructor.
* @param ring polynomial ring
*/
public Ideal(GenPolynomialRing ring) {
this(ring, new ArrayList>());
}
/**
* Constructor.
* @param ring polynomial ring
* @param F list of polynomials
*/
public Ideal(GenPolynomialRing ring, List> F) {
this(new PolynomialList(ring, F));
}
/**
* Constructor.
* @param ring polynomial ring
* @param F list of polynomials
* @param gb true if F is known to be a Groebner Base, else false
*/
public Ideal(GenPolynomialRing ring, List> F, boolean gb) {
this(new PolynomialList(ring, F), gb);
}
/**
* Constructor.
* @param ring polynomial ring
* @param F list of polynomials
* @param gb true if F is known to be a Groebner Base, else false
* @param topt true if term order is optimized, else false
*/
public Ideal(GenPolynomialRing ring, List> F, boolean gb, boolean topt) {
this(new PolynomialList(ring, F), gb, topt);
}
/**
* Constructor.
* @param list polynomial list
*/
public Ideal(PolynomialList list) {
this(list, false);
}
/**
* Constructor.
* @param list polynomial list
* @param bb Groebner Base engine
* @param red Reduction engine
*/
public Ideal(PolynomialList list, GroebnerBaseAbstract bb, Reduction red) {
this(list, false, bb, red);
}
/**
* Constructor.
* @param list polynomial list
* @param gb true if list is known to be a Groebner Base, else false
*/
public Ideal(PolynomialList list, boolean gb) {
//this(list, gb, new GroebnerBaseSeqPairSeq(), new ReductionSeq());
this(list, gb, GBFactory.getImplementation(list.ring.coFac));
}
/**
* Constructor.
* @param list polynomial list
* @param gb true if list is known to be a Groebner Base, else false
* @param topt true if term order is optimized, else false
*/
public Ideal(PolynomialList list, boolean gb, boolean topt) {
//this(list, gb, topt, new GroebnerBaseSeqPairSeq(), new ReductionSeq());
this(list, gb, topt, GBFactory.getImplementation(list.ring.coFac));
}
/**
* Constructor.
* @param list polynomial list
* @param gb true if list is known to be a Groebner Base, else false
* @param bb Groebner Base engine
* @param red Reduction engine
*/
public Ideal(PolynomialList list, boolean gb, GroebnerBaseAbstract bb, Reduction red) {
this(list, gb, false, bb, red);
}
/**
* Constructor.
* @param list polynomial list
* @param gb true if list is known to be a Groebner Base, else false
* @param bb Groebner Base engine
*/
public Ideal(PolynomialList list, boolean gb, GroebnerBaseAbstract bb) {
this(list, gb, false, bb, bb.red);
}
/**
* Constructor.
* @param list polynomial list
* @param gb true if list is known to be a Groebner Base, else false
* @param topt true if term order is optimized, else false
* @param bb Groebner Base engine
*/
public Ideal(PolynomialList list, boolean gb, boolean topt, GroebnerBaseAbstract bb) {
this(list, gb, topt, bb, bb.red);
}
/**
* Constructor.
* @param list polynomial list
* @param gb true if list is known to be a Groebner Base, else false
* @param topt true if term order is optimized, else false
* @param bb Groebner Base engine
* @param red Reduction engine
*/
public Ideal(PolynomialList list, boolean gb, boolean topt, GroebnerBaseAbstract bb,
Reduction red) {
if (list == null || list.list == null) {
throw new IllegalArgumentException("list and list.list may not be null");
}
this.list = list;
this.isGB = gb;
this.isTopt = topt;
this.testGB = (gb ? true : false); // ??
this.bb = bb;
this.red = red;
this.engine = SquarefreeFactory. getImplementation(list.ring.coFac);
}
/**
* Clone this.
* @return a copy of this.
*/
public Ideal copy() {
return new Ideal(list.copy(), isGB, isTopt, bb, red);
}
/**
* Get the List of GenPolynomials.
* @return list.list
*/
public List> getList() {
return list.list;
}
/**
* Get the GenPolynomialRing.
* @return list.ring
*/
public GenPolynomialRing getRing() {
return list.ring;
}
/**
* Get the zero ideal.
* @return ideal(0)
*/
public Ideal getZERO() {
List> z = new ArrayList>(0);
PolynomialList pl = new PolynomialList(getRing(), z);
return new Ideal(pl, true, isTopt, bb, red);
}
/**
* Get the one ideal.
* @return ideal(1)
*/
public Ideal getONE() {
List> one = new ArrayList>(1);
one.add(list.ring.getONE());
PolynomialList pl = new PolynomialList(getRing(), one);
return new Ideal(pl, true, isTopt, bb, red);
}
/**
* String representation of the ideal.
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return list.toString();
}
/**
* Get a scripting compatible string representation.
* @return script compatible representation for this Element.
* @see edu.jas.structure.Element#toScript()
*/
public String toScript() {
// Python case
return list.toScript();
}
/**
* Comparison with any other object. Note: If both ideals are not Groebner
* Bases, then false may be returned even the ideals are equal.
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@SuppressWarnings("unchecked")
public boolean equals(Object b) {
if (!(b instanceof Ideal)) {
logger.warn("equals no Ideal");
return false;
}
Ideal B = null;
try {
B = (Ideal) b;
} catch (ClassCastException ignored) {
return false;
}
//if ( isGB && B.isGB ) {
// return list.equals( B.list ); requires also monic polys
//} else { // compute GBs ?
return this.contains(B) && B.contains(this);
//}
}
/**
* Ideal list comparison.
* @param L other Ideal.
* @return compareTo() of polynomial lists.
*/
public int compareTo(Ideal L) {
return list.compareTo(L.list);
}
/**
* Hash code for this ideal.
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int h;
h = list.hashCode();
if (isGB) {
h = h << 1;
}
if (testGB) {
h += 1;
}
return h;
}
/**
* Test if ZERO ideal.
* @return true, if this is the 0 ideal, else false
*/
public boolean isZERO() {
return list.isZERO();
}
/**
* Test if ONE is contained in the ideal. To test for a proper ideal use
* ! id.isONE().
* @return true, if this is the 1 ideal, else false
*/
public boolean isONE() {
return list.isONE();
}
/**
* Optimize the term order.
*/
public void doToptimize() {
if (isTopt) {
return;
}
list = TermOrderOptimization. optimizeTermOrder(list);
isTopt = true;
if (isGB) {
isGB = false;
doGB();
}
return;
}
/**
* Test if this is a Groebner base.
* @return true, if this is a Groebner base, else false
*/
public boolean isGB() {
if (testGB) {
return isGB;
}
logger.warn("isGB computing");
isGB = bb.isGB(getList());
testGB = true;
return isGB;
}
/**
* Do Groebner Base. compute the Groebner Base for this ideal.
*/
@SuppressWarnings("unchecked")
public void doGB() {
if (isGB && testGB) {
return;
}
//logger.warn("GB computing");
List> G = getList();
logger.info("GB computing = " + G);
G = bb.GB(G);
if (isTopt) {
List perm = ((OptimizedPolynomialList) list).perm;
list = new OptimizedPolynomialList(perm, getRing(), G);
} else {
list = new PolynomialList(getRing(), G);
}
isGB = true;
testGB = true;
return;
}
/**
* Groebner Base. Get a Groebner Base for this ideal.
* @return GB(this)
*/
public Ideal GB() {
if (isGB) {
return this;
}
doGB();
return this;
}
/**
* Ideal containment. Test if B is contained in this ideal. Note: this is
* eventually modified to become a Groebner Base.
* @param B ideal
* @return true, if B is contained in this, else false
*/
public boolean contains(Ideal B) {
if (B == null || B.isZERO()) {
return true;
}
return contains(B.getList());
}
/**
* Ideal containment. Test if b is contained in this ideal. Note: this is
* eventually modified to become a Groebner Base.
* @param b polynomial
* @return true, if b is contained in this, else false
*/
public boolean contains(GenPolynomial b) {
if (b == null || b.isZERO()) {
return true;
}
if (this.isONE()) {
return true;
}
if (this.isZERO()) {
return false;
}
if (!isGB) {
doGB();
}
GenPolynomial z;
z = red.normalform(getList(), b);
if (z == null || z.isZERO()) {
return true;
}
return false;
}
/**
* Ideal containment. Test if each b in B is contained in this ideal. Note:
* this is eventually modified to become a Groebner Base.
* @param B list of polynomials
* @return true, if each b in B is contained in this, else false
*/
public boolean contains(List> B) {
if (B == null || B.size() == 0) {
return true;
}
if (this.isONE()) {
return true;
}
if (!isGB) {
doGB();
}
for (GenPolynomial b : B) {
if (b == null) {
continue;
}
GenPolynomial z = red.normalform(getList(), b);
if (!z.isZERO()) {
//System.out.println("contains nf(b) != 0: " + b);
return false;
}
}
return true;
}
/**
* Summation. Generators for the sum of ideals. Note: if both ideals are
* Groebner bases, a Groebner base is returned.
* @param B ideal
* @return ideal(this+B)
*/
public Ideal sum(Ideal B) {
if (B == null || B.isZERO()) {
return this;
}
if (this.isZERO()) {
return B;
}
int s = getList().size() + B.getList().size();
List> c;
c = new ArrayList>(s);
c.addAll(getList());
c.addAll(B.getList());
Ideal I = new Ideal(getRing(), c, false);
if (isGB && B.isGB) {
I.doGB();
}
return I;
}
/**
* Summation. Generators for the sum of ideal and a polynomial. Note: if
* this ideal is a Groebner base, a Groebner base is returned.
* @param b polynomial
* @return ideal(this+{b})
*/
public Ideal sum(GenPolynomial b) {
if (b == null || b.isZERO()) {
return this;
}
int s = getList().size() + 1;
List> c;
c = new ArrayList>(s);
c.addAll(getList());
c.add(b);
Ideal I = new Ideal(getRing(), c, false);
if (isGB) {
I.doGB();
}
return I;
}
/**
* Summation. Generators for the sum of this ideal and a list of
* polynomials. Note: if this ideal is a Groebner base, a Groebner base is
* returned.
* @param L list of polynomials
* @return ideal(this+L)
*/
public Ideal sum(List> L) {
if (L == null || L.isEmpty()) {
return this;
}
int s = getList().size() + L.size();
List> c = new ArrayList>(s);
c.addAll(getList());
c.addAll(L);
Ideal I = new Ideal(getRing(), c, false);
if (isGB) {
I.doGB();
}
return I;
}
/**
* Product. Generators for the product of ideals. Note: if both ideals are
* Groebner bases, a Groebner base is returned.
* @param B ideal
* @return ideal(this*B)
*/
public Ideal product(Ideal B) {
if (B == null || B.isZERO()) {
return B;
}
if (this.isZERO()) {
return this;
}
int s = getList().size() * B.getList().size();
List> c;
c = new ArrayList>(s);
for (GenPolynomial p : getList()) {
for (GenPolynomial q : B.getList()) {
q = p.multiply(q);
c.add(q);
}
}
Ideal I = new Ideal(getRing(), c, false);
if (isGB && B.isGB) {
I.doGB();
}
return I;
}
/**
* Product. Generators for the product this ideal by a polynomial.
* Note: if this ideal is a
* Groebner base, a Groebner base is returned.
* @param b polynomial
* @return ideal(this*b)
*/
public Ideal product(GenPolynomial b) {
if (b == null || b.isZERO()) {
return getZERO();
}
if (this.isZERO()) {
return this;
}
List> c;
c = new ArrayList>(getList().size());
for (GenPolynomial p : getList()) {
GenPolynomial q = p.multiply(b);
c.add(q);
}
Ideal I = new Ideal(getRing(), c, false);
if (isGB) {
I.doGB();
}
return I;
}
/**
* Intersection. Generators for the intersection of ideals. Using an
* iterative algorithm.
* @param Bl list of ideals
* @return ideal(cap_i B_i), a Groebner base
*/
public Ideal intersect(List> Bl) {
if (Bl == null || Bl.size() == 0) {
return getZERO();
}
Ideal I = null;
for (Ideal B : Bl) {
if (I == null) {
I = B;
continue;
}
if (I.isONE()) {
return I;
}
I = I.intersect(B);
}
return I;
}
/**
* Intersection. Generators for the intersection of ideals.
* @param B ideal
* @return ideal(this \cap B), a Groebner base
*/
public Ideal intersect(Ideal B) {
if (B == null || B.isZERO()) { // (0)
return B;
}
if (this.isZERO()) {
return this;
}
List> c = PolyGBUtil. intersect(getRing(),getList(),B.getList());
Ideal I = new Ideal(getRing(), c, true);
return I;
}
/**
* Intersection. Generators for the intersection of a ideal with a
* polynomial ring. The polynomial ring of this ideal must be a
* contraction of R and the TermOrder must be an elimination
* order.
* @param R polynomial ring
* @return ideal(this \cap R)
*/
public Ideal intersect(GenPolynomialRing R) {
if (R == null) {
throw new IllegalArgumentException("R may not be null");
}
List> H = PolyUtil. intersect(R,getList());
return new Ideal(R, H, isGB, isTopt);
}
/**
* Eliminate. Generators for the intersection of a ideal with a polynomial
* ring. The polynomial rings must have variable names.
* @param R polynomial ring
* @return ideal(this \cap R)
*/
public Ideal eliminate(GenPolynomialRing R) {
if (R == null) {
throw new IllegalArgumentException("R may not be null");
}
if (list.ring.equals(R)) {
return this;
}
String[] ename = R.getVars();
Ideal I = eliminate(ename);
return I.intersect(R);
}
/**
* Eliminate. Preparation of generators for the intersection of a ideal with
* a polynomial ring.
* @param ename variables for the elimination ring.
* @return ideal(this) in K[ename,{vars \ ename}])
*/
public Ideal eliminate(String... ename) {
//System.out.println("ename = " + Arrays.toString(ename));
if (ename == null) {
throw new IllegalArgumentException("ename may not be null");
}
String[] aname = getRing().getVars();
//System.out.println("aname = " + Arrays.toString(aname));
if (aname == null) {
throw new IllegalArgumentException("aname may not be null");
}
GroebnerBasePartial bbp = new GroebnerBasePartial(bb, null);
String[] rname = GroebnerBasePartial.remainingVars(aname, ename);
//System.out.println("rname = " + Arrays.toString(rname));
PolynomialList Pl = null;
if (rname.length == 0) {
if (Arrays.equals(aname, ename)) {
return this;
}
Pl = bbp.partialGB(getList(), ename); // normal GB
} else {
Pl = bbp.elimPartialGB(getList(), rname, ename); // reversed!
}
//System.out.println("Pl = " + Pl);
if (debug) {
logger.debug("elimination GB = " + Pl);
}
Ideal I = new Ideal(Pl, true);
return I;
}
/**
* Quotient. Generators for the ideal quotient.
* @param h polynomial
* @return ideal(this : h), a Groebner base
*/
public Ideal quotient(GenPolynomial h) {
if (h == null) { // == (0)
return this;
}
if (h.isZERO()) {
return this;
}
if (this.isZERO()) {
return this;
}
List> H;
H = new ArrayList>(1);
H.add(h);
Ideal Hi = new Ideal(getRing(), H, true);
Ideal I = this.intersect(Hi);
List> Q;
Q = new ArrayList>(I.getList().size());
for (GenPolynomial q : I.getList()) {
q = q.divide(h); // remainder == 0
Q.add(q);
}
return new Ideal(getRing(), Q, true /*false?*/);
}
/**
* Quotient. Generators for the ideal quotient.
* @param H ideal
* @return ideal(this : H), a Groebner base
*/
public Ideal quotient(Ideal H) {
if (H == null) { // == (0)
return this;
}
if (H.isZERO()) {
return this;
}
if (this.isZERO()) {
return this;
}
Ideal Q = null;
for (GenPolynomial h : H.getList()) {
Ideal Hi = this.quotient(h);
if (Q == null) {
Q = Hi;
} else {
Q = Q.intersect(Hi);
}
}
return Q;
}
/**
* Infinite quotient. Generators for the infinite ideal quotient.
* @param h polynomial
* @return ideal(this : hs), a Groebner base
*/
public Ideal infiniteQuotientRab(GenPolynomial h) {
if (h == null || h.isZERO()) { // == (0)
return getONE();
}
if (h.isONE()) {
return this;
}
if (this.isZERO()) {
return this;
}
Ideal I = this.GB(); // should be already
List> a = I.getList();
List> c;
c = new ArrayList>(a.size() + 1);
GenPolynomialRing tfac = getRing().extend(1);
// term order is also adjusted
for (GenPolynomial p : a) {
p = p.extend(tfac, 0, 0L); // p
c.add(p);
}
GenPolynomial q = h.extend(tfac, 0, 1L);
GenPolynomial r = tfac.getONE(); // h.extend( tfac, 0, 0L );
GenPolynomial hs = q.subtract(r); // 1 - t*h // (1-t)*h
c.add(hs);
logger.warn("infiniteQuotientRab computing GB ");
List> g = bb.GB(c);
if (debug) {
logger.info("infiniteQuotientRab = " + tfac + ", c = " + c);
logger.info("infiniteQuotientRab GB = " + g);
}
Ideal E = new Ideal(tfac, g, true);
Ideal Is = E.intersect(getRing());
return Is;
}
/**
* Infinite quotient exponent.
* @param h polynomial
* @param Q quotient this : h^\infinity
* @return s with Q = this : hs
*/
public int infiniteQuotientExponent(GenPolynomial h, Ideal Q) {
int s = 0;
if (h == null) { // == 0
return s;
}
if (h.isZERO() || h.isONE()) {
return s;
}
if (this.isZERO() || this.isONE()) {
return s;
}
//see below: if (this.contains(Q)) {
// return s;
//}
GenPolynomial p = getRing().getONE();
for (GenPolynomial q : Q.getList()) {
if (this.contains(q)) {
continue;
}
//System.out.println("q = " + q + ", p = " + p + ", s = " + s);
GenPolynomial qp = q.multiply(p);
while (!this.contains(qp)) {
p = p.multiply(h);
s++;
qp = q.multiply(p);
}
}
return s;
}
/**
* Infinite quotient. Generators for the infinite ideal quotient.
* @param h polynomial
* @return ideal(this : hs), a Groebner base
*/
public Ideal infiniteQuotient(GenPolynomial h) {
if (h == null) { // == (0)
return this;
}
if (h.isZERO()) {
return this;
}
if (this.isZERO()) {
return this;
}
int s = 0;
Ideal I = this.GB(); // should be already
GenPolynomial hs = h;
Ideal Is = I;
boolean eq = false;
while (!eq) {
Is = I.quotient(hs);
Is = Is.GB(); // should be already
logger.info("infiniteQuotient s = " + s);
eq = Is.contains(I); // I.contains(Is) always
if (!eq) {
I = Is;
s++;
// hs = hs.multiply( h );
}
}
return Is;
}
/**
* Radical membership test.
* @param h polynomial
* @return true if h is contained in the radical of ideal(this), else false.
*/
public boolean isRadicalMember(GenPolynomial h) {
if (h == null) { // == (0)
return true;
}
if (h.isZERO()) {
return true;
}
if (this.isZERO()) {
return true;
}
Ideal x = infiniteQuotientRab(h);
if (debug) {
logger.debug("infiniteQuotientRab = " + x);
}
return x.isONE();
}
/**
* Infinite quotient. Generators for the infinite ideal quotient.
* @param h polynomial
* @return ideal(this : hs), a Groebner base
*/
public Ideal infiniteQuotientOld(GenPolynomial h) {
if (h == null) { // == (0)
return this;
}
if (h.isZERO()) {
return this;
}
if (this.isZERO()) {
return this;
}
int s = 0;
Ideal I = this.GB(); // should be already
GenPolynomial hs = h;
boolean eq = false;
while (!eq) {
Ideal Is = I.quotient(hs);
Is = Is.GB(); // should be already
logger.debug("infiniteQuotient s = " + s);
eq = Is.contains(I); // I.contains(Is) always
if (!eq) {
I = Is;
s++;
hs = hs.multiply(h);
}
}
return I;
}
/**
* Infinite Quotient. Generators for the ideal infinite quotient.
* @param H ideal
* @return ideal(this : Hs), a Groebner base
*/
public Ideal infiniteQuotient(Ideal H) {
if (H == null) { // == (0)
return this;
}
if (H.isZERO()) {
return this;
}
if (this.isZERO()) {
return this;
}
Ideal Q = null;
for (GenPolynomial h : H.getList()) {
Ideal Hi = this.infiniteQuotient(h);
if (Q == null) {
Q = Hi;
} else {
Q = Q.intersect(Hi);
}
}
return Q;
}
/**
* Infinite Quotient. Generators for the ideal infinite quotient.
* @param H ideal
* @return ideal(this : Hs), a Groebner base
*/
public Ideal infiniteQuotientRab(Ideal H) {
if (H == null) { // == (0)
return this;
}
if (H.isZERO()) {
return this;
}
if (this.isZERO()) {
return this;
}
Ideal Q = null;
for (GenPolynomial h : H.getList()) {
Ideal Hi = this.infiniteQuotientRab(h);
if (Q == null) {
Q = Hi;
} else {
Q = Q.intersect(Hi);
}
}
return Q;
}
/**
* Power. Generators for the power of this ideal. Note: if this ideal is a
* Groebner base, a Groebner base is returned.
* @param d integer
* @return ideal(this^d)
*/
public Ideal power(int d) {
if (d <= 0) {
return getONE();
}
if (this.isZERO() || this.isONE()) {
return this;
}
Ideal c = this;
for (int i = 1; i < d; i++) {
c = c.product(this);
}
return c;
}
/**
* Normalform for element.
* @param h polynomial
* @return normalform of h with respect to this
*/
public GenPolynomial normalform(GenPolynomial h) {
if (h == null) {
return h;
}
if (h.isZERO()) {
return h;
}
if (this.isZERO()) {
return h;
}
GenPolynomial r;
r = red.normalform(list.list, h);
return r;
}
/**
* Normalform for list of elements.
* @param L polynomial list
* @return list of normalforms of the elements of L with respect to this
*/
public List> normalform(List> L) {
if (L == null) {
return L;
}
if (L.size() == 0) {
return L;
}
if (this.isZERO()) {
return L;
}
List> M = new ArrayList>(L.size());
for (GenPolynomial h : L) {
GenPolynomial r = normalform(h);
if (r != null && !r.isZERO()) {
M.add(r);
}
}
return M;
}
/**
* Annihilator for element modulo this ideal.
* @param h polynomial
* @return annihilator of h with respect to this
*/
public Ideal annihilator(GenPolynomial h) {
if (h == null || h.isZERO()) {
return getZERO();
}
if (this.isZERO()) {
return this;
}
doGB();
List> F = new ArrayList>(1 + getList().size());
F.add(h);
F.addAll(getList());
//System.out.println("F = " + F);
SyzygyAbstract syz = new SyzygyAbstract();
List>> S = syz.zeroRelationsArbitrary(F);
//System.out.println("S = " + S);
List> gen = new ArrayList>(S.size());
for (List> rel : S) {
if (rel == null || rel.isEmpty()) {
continue;
}
GenPolynomial p = rel.get(0);
if (p == null || p.isZERO()) {
continue;
}
gen.add(p);
}
Ideal ann = new Ideal(getRing(),gen);
//System.out.println("ann = " + ann);
return ann;
}
/**
* Test for annihilator of element modulo this ideal.
* @param h polynomial
* @param A ideal
* @return true, if A is the annihilator of h with respect to this
*/
public boolean isAnnihilator(GenPolynomial h, Ideal A) {
Ideal B = A.product(h);
return contains(B);
}
/**
* Annihilator for ideal modulo this ideal.
* @param H ideal
* @return annihilator of H with respect to this
*/
public Ideal annihilator(Ideal H) {
if (H == null || H.isZERO()) {
return getZERO();
}
if (this.isZERO()) {
return this;
}
Ideal ann = null;
for (GenPolynomial h : H.getList()) {
Ideal Hi = this.annihilator(h);
if (ann == null) {
ann = Hi;
} else {
ann = ann.intersect(Hi);
}
}
return ann;
}
/**
* Test for annihilator of ideal modulo this ideal.
* @param H ideal
* @param A ideal
* @return true, if A is the annihilator of H with respect to this
*/
public boolean isAnnihilator(Ideal H, Ideal A) {
Ideal B = A.product(H);
return contains(B);
}
/**
* Inverse for element modulo this ideal.
* @param h polynomial
* @return inverse of h with respect to this, if defined
*/
public GenPolynomial inverse(GenPolynomial h) {
if (h == null || h.isZERO()) {
throw new NotInvertibleException("zero not invertible");
}
if (this.isZERO()) {
throw new NotInvertibleException("zero ideal");
}
if (h.isUnit()) {
return h.inverse();
}
doGB();
List> F = new ArrayList>(1 + list.list.size());
F.add(h);
F.addAll(list.list);
//System.out.println("F = " + F);
ExtendedGB x = bb.extGB(F);
List> G = x.G;
//System.out.println("G = " + G);
GenPolynomial one = null;
int i = -1;
for (GenPolynomial p : G) {
i++;
if (p == null) {
continue;
}
if (p.isUnit()) {
one = p;
break;
}
}
if (one == null) {
throw new NotInvertibleException(" h = " + h);
}
List> row = x.G2F.get(i); // != -1
GenPolynomial g = row.get(0);
if (g == null || g.isZERO()) {
throw new NotInvertibleException(" h = " + h);
}
// adjust g to get g*h == 1
GenPolynomial f = g.multiply(h);
GenPolynomial k = red.normalform(list.list, f);
if (!k.isONE()) {
C lbc = k.leadingBaseCoefficient();
lbc = lbc.inverse();
g = g.multiply(lbc);
}
if (debug) {
//logger.info("inv G = " + G);
//logger.info("inv G2F = " + x.G2F);
//logger.info("inv row "+i+" = " + row);
//logger.info("inv h = " + h);
//logger.info("inv g = " + g);
//logger.info("inv f = " + f);
f = g.multiply(h);
k = red.normalform(list.list, f);
logger.debug("inv k = " + k);
if (!k.isUnit()) {
throw new NotInvertibleException(" k = " + k);
}
}
return g;
}
/**
* Test if element is a unit modulo this ideal.
* @param h polynomial
* @return true if h is a unit with respect to this, else false
*/
public boolean isUnit(GenPolynomial h) {
if (h == null || h.isZERO()) {
return false;
}
if (this.isZERO()) {
return false;
}
List> F = new ArrayList>(1 + list.list.size());
F.add(h);
F.addAll(list.list);
List> G = bb.GB(F);
for (GenPolynomial p : G) {
if (p == null) {
continue;
}
if (p.isUnit()) {
return true;
}
}
return false;
}
/**
* Radical approximation. Squarefree generators for the ideal.
* @return squarefree(this), a Groebner base
*/
public Ideal squarefree() {
if (this.isZERO()) {
return this;
}
Ideal R = this;
Ideal Rp = null;
List> li, ri;
while (true) {
li = R.getList();
ri = new ArrayList>(li); //.size() );
for (GenPolynomial h : li) {
GenPolynomial r = engine.squarefreePart(h);
ri.add(r);
}
Rp = new Ideal(R.getRing(), ri, false);
Rp.doGB();
if (R.equals(Rp)) {
break;
}
R = Rp;
}
return R;
}
/**
* Ideal common zero test.
* @return -1, 0 or 1 if dimension(this) &eq; -1, 0 or ≥ 1.
*/
public int commonZeroTest() {
if (this.isZERO()) {
return 1;
}
if (!isGB) {
doGB();
}
if (this.isONE()) {
return -1;
}
return bb.commonZeroTest(getList());
}
/**
* Test if this ideal is maximal.
* @return true, if this is maximal and not one, else false.
*/
public boolean isMaximal() {
if (commonZeroTest() != 0) {
return false;
}
for (Long d : univariateDegrees()) {
if (d > 1L) {
// todo: test if irreducible
return false;
}
}
return true;
}
/**
* Univariate head term degrees.
* @return a list of the degrees of univariate head terms.
*/
public List univariateDegrees() {
List ud = new ArrayList();
if (this.isZERO()) {
return ud;
}
if (!isGB) {
doGB();
}
if (this.isONE()) {
return ud;
}
return bb.univariateDegrees(getList());
}
/**
* Ideal dimension.
* @return a dimension container (dim,maxIndep,list(maxIndep),vars).
*/
public Dimension dimension() {
int t = commonZeroTest();
Set S = new HashSet();
Set> M = new HashSet