001/*
002 * $Id$
003 */
004
005package edu.jas.gbufd;
006
007
008import java.util.ArrayList;
009import java.util.Collections;
010import java.util.List;
011
012import org.apache.logging.log4j.Logger;
013import org.apache.logging.log4j.LogManager; 
014
015import edu.jas.poly.GenPolynomial;
016import edu.jas.poly.GenPolynomialRing;
017import edu.jas.poly.OrderedPolynomialList;
018import edu.jas.poly.PolyUtil;
019import edu.jas.structure.GcdRingElem;
020import edu.jas.ufd.GCDFactory;
021import edu.jas.ufd.GreatestCommonDivisorAbstract;
022
023
024/**
025 * Characteristic Set class according to the simple algorithm, where the
026 * leading coefficients are <strong>not</strong> rereduced. Implements methods
027 * for Characteristic Sets and tests.
028 * @param <C> coefficient type
029 * @author Heinz Kredel
030 */
031public class CharacteristicSetSimple<C extends GcdRingElem<C>> implements CharacteristicSet<C> {
032
033
034    private static final Logger logger = LogManager.getLogger(CharacteristicSetSimple.class);
035
036
037    private static final boolean debug = logger.isDebugEnabled();
038
039
040    /**
041     * Characteristic set. According to the simple algorithm. The leading
042     * coefficients are <strong>not</strong> rereduced.
043     * @param A list of generic polynomials.
044     * @return charSetWu(A).
045     */
046    public List<GenPolynomial<C>> characteristicSet(List<GenPolynomial<C>> A) {
047        List<GenPolynomial<C>> S = new ArrayList<GenPolynomial<C>>();
048        if (A == null || A.isEmpty()) {
049            return S;
050        }
051        GenPolynomialRing<C> pfac = A.get(0).ring;
052        if (pfac.nvar <= 1) { // take gcd
053            GreatestCommonDivisorAbstract<C> ufd = GCDFactory.<C> getImplementation(pfac.coFac);
054            GenPolynomial<C> g = ufd.gcd(A).monic();
055            logger.info("charSet base gcd = {}", g);
056            S.add(g);
057            return S;
058        }
059        // sort polynomials according to the main variable
060        GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1);
061        List<GenPolynomial<GenPolynomial<C>>> positiveDeg = new ArrayList<GenPolynomial<GenPolynomial<C>>>();
062        List<GenPolynomial<C>> zeroDeg = new ArrayList<GenPolynomial<C>>();
063        for (GenPolynomial<C> f : A) {
064            if (f.isZERO()) {
065                continue;
066            }
067            f = f.monic();
068            if (f.isONE()) {
069                S.add(f);
070                return S;
071            }
072            GenPolynomial<GenPolynomial<C>> fr = PolyUtil.<C> recursive(rfac, f);
073            if (fr.degree(0) == 0) {
074                zeroDeg.add(fr.leadingBaseCoefficient());
075            } else {
076                positiveDeg.add(fr);
077            }
078        }
079        if (positiveDeg.isEmpty() && zeroDeg.isEmpty()) {
080            return S;
081        }
082        // do pseudo division wrt. the main variable
083        OrderedPolynomialList<GenPolynomial<C>> opl = new OrderedPolynomialList<GenPolynomial<C>>(rfac,
084                        positiveDeg);
085        List<GenPolynomial<GenPolynomial<C>>> pd = new ArrayList<GenPolynomial<GenPolynomial<C>>>(opl.list);
086        Collections.reverse(pd); // change OrderedPolynomialList to avoid
087        if (debug) {
088            logger.info("positive degrees: {}", pd);
089        }
090        //System.out.println("positive degrees: " + pd);
091        //System.out.println("zero     degrees: " + zeroDeg);
092        while (pd.size() > 1) {
093            GenPolynomial<GenPolynomial<C>> fr = pd.remove(0);
094            GenPolynomial<GenPolynomial<C>> qr = pd.get(0); // = get(1)
095            logger.info("pseudo remainder by deg = {} in variable {}", qr.degree(), rfac.getVars()[0]);
096            GenPolynomial<GenPolynomial<C>> rr = PolyUtil.<C> recursiveSparsePseudoRemainder(fr, qr);
097            if (rr.isZERO()) {
098                logger.warn("variety is reducible");
099                // replace qr by gcd(qr,fr) ?
100                continue;
101            }
102            if (rr.degree(0) == 0) {
103                zeroDeg.add(rr.leadingBaseCoefficient().monic());
104            } else {
105                pd.add(rr);
106                pd = OrderedPolynomialList.sort(rfac, pd);
107                Collections.reverse(pd); // avoid
108            }
109        }
110        // recursion for degree zero polynomials
111        List<GenPolynomial<C>> Sp = characteristicSet(zeroDeg); // recursion
112        for (GenPolynomial<C> f : Sp) {
113            GenPolynomial<C> fp = f.extend(pfac, 0, 0L);
114            S.add(fp);
115        }
116        //logger.info("charSet recursion, Sp = {}", Sp);
117        if (pd.isEmpty()) {
118            return S;
119        }
120        GenPolynomial<GenPolynomial<C>> rr = pd.get(0);
121        GenPolynomial<C> sr = PolyUtil.<C> distribute(pfac, rr);
122        sr = sr.monic();
123        // no rereduction of leading coefficient wrt. characteristic set.
124        S.add(0, sr);
125        return S;
126    }
127
128
129    /**
130     * Characteristic set test.
131     * @param A list of generic polynomials.
132     * @return true, if A is (at least a simple) characteristic set, else false.
133     */
134    public boolean isCharacteristicSet(List<GenPolynomial<C>> A) {
135        if (A == null || A.isEmpty()) {
136            return true; // ?
137        }
138        GenPolynomialRing<C> pfac = A.get(0).ring;
139        if (pfac.nvar <= 1) {
140            return A.size() <= 1;
141        }
142        if (pfac.nvar < A.size()) {
143            return false;
144        }
145        // select polynomials according to the main variable
146        GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1);
147        List<GenPolynomial<C>> zeroDeg = new ArrayList<GenPolynomial<C>>();
148        int positiveDeg = 0;
149        for (GenPolynomial<C> f : A) {
150            if (f.isZERO()) {
151                return false;
152            }
153            //f = f.monic();
154            GenPolynomial<GenPolynomial<C>> fr = PolyUtil.<C> recursive(rfac, f);
155            if (fr.degree(0) == 0) {
156                zeroDeg.add(fr.leadingBaseCoefficient());
157            } else {
158                positiveDeg++;
159                if (positiveDeg > 1) {
160                    return false;
161                }
162            }
163        }
164        return isCharacteristicSet(zeroDeg);
165    }
166
167
168    /**
169     * Characteristic set reduction. Pseudo remainder wrt. the main variable.
170     * @param P generic polynomial.
171     * @param A list of generic polynomials as characteristic set.
172     * @return characteristicSetRemainder(A,P)
173     */
174    public GenPolynomial<C> characteristicSetReduction(List<GenPolynomial<C>> A, GenPolynomial<C> P) {
175        if (A == null || A.isEmpty()) {
176            return P.monic();
177        }
178        if (P.isZERO()) {
179            return P;
180        }
181        GenPolynomial<C> R = PolyGBUtil.<C> topPseudoRemainder(A, P);
182        R = R.monic();
183        //System.out.println("remainder, R = " + R);
184        return R;
185    }
186
187}