001/*
002 * $Id: PolyGBUtil.java 4049 2012-07-25 17:10:49Z kredel $
003 */
004
005package edu.jas.gbufd;
006
007
008import java.util.ArrayList;
009import java.util.List;
010
011import org.apache.log4j.Logger;
012
013import edu.jas.gb.GroebnerBaseAbstract;
014import edu.jas.poly.ExpVector;
015import edu.jas.poly.GenPolynomial;
016import edu.jas.poly.GenPolynomialRing;
017import edu.jas.poly.PolyUtil;
018import edu.jas.structure.GcdRingElem;
019import edu.jas.structure.RingElem;
020
021
022/**
023 * Package gbufd utilities.
024 * @author Heinz Kredel
025 */
026
027public class PolyGBUtil {
028
029
030    private static final Logger logger = Logger.getLogger(PolyGBUtil.class);
031
032
033    private static boolean debug = logger.isDebugEnabled();
034
035
036    /**
037     * Test for resultant.
038     * @param A generic polynomial.
039     * @param B generic polynomial.
040     * @param r generic polynomial.
041     * @return true if res(A,B) isContained in ideal(A,B), else false.
042     */
043    public static <C extends GcdRingElem<C>> 
044      boolean isResultant(GenPolynomial<C> A, GenPolynomial<C> B, GenPolynomial<C> r) {
045        if (r == null || r.isZERO()) {
046            return true;
047        }
048        GroebnerBaseAbstract<C> bb = GBFactory.<C> getImplementation(r.ring.coFac);
049        List<GenPolynomial<C>> F = new ArrayList<GenPolynomial<C>>(2);
050        F.add(A);
051        F.add(B);
052        List<GenPolynomial<C>> G = bb.GB(F);
053        //System.out.println("G = " + G);
054        GenPolynomial<C> n = bb.red.normalform(G, r);
055        //System.out.println("n = " + n);
056        return n.isZERO();
057    }
058
059
060    /**
061     * Top pseudo reduction wrt the main variables.
062     * @param P generic polynomial.
063     * @param A list of generic polynomials sorted according to appearing main variables.
064     * @return top pseudo remainder of P wrt. A for the appearing variables.
065     */
066    public static <C extends RingElem<C>> 
067      GenPolynomial<C> topPseudoRemainder(List<GenPolynomial<C>> A, GenPolynomial<C> P) {
068        if (A == null || A.isEmpty()) {
069            return P.monic();
070        }
071        if (P.isZERO()) {
072            return P;
073        }
074        //System.out.println("remainder, P = " + P);
075        GenPolynomialRing<C> pfac = A.get(0).ring;
076        if (pfac.nvar <= 1) { // recursion base 
077            GenPolynomial<C> R = PolyUtil.<C> baseSparsePseudoRemainder(P, A.get(0));
078            return R.monic();
079        }
080        // select polynomials according to the main variable
081        GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1);
082        GenPolynomial<C> Q = A.get(0); // wrong, must eventually search polynomial
083        GenPolynomial<GenPolynomial<C>> qr = PolyUtil.<C> recursive(rfac, Q);
084        GenPolynomial<GenPolynomial<C>> pr = PolyUtil.<C> recursive(rfac, P);
085        GenPolynomial<GenPolynomial<C>> rr;
086        if (qr.isONE()) {
087            return P.ring.getZERO();
088        }
089        if (qr.degree(0) > 0) {
090            rr = PolyUtil.<C> recursiveSparsePseudoRemainder(pr, qr);
091            //System.out.println("remainder, pr = " + pr);
092            //System.out.println("remainder, qr = " + qr);
093            //System.out.println("remainder, rr = " + rr);
094        } else {
095            rr = pr;
096        }
097        if (rr.degree(0) > 0) {
098            GenPolynomial<C> R = PolyUtil.<C> distribute(pfac, rr);
099            return R.monic();
100            // not further reduced wrt. other variables = top-reduction only
101        }
102        List<GenPolynomial<C>> zeroDeg = zeroDegrees(A);
103        GenPolynomial<C> R = topPseudoRemainder(zeroDeg, rr.leadingBaseCoefficient());
104        R = R.extend(pfac, 0, 0L);
105        return R.monic();
106    }
107
108
109    /**
110     * Top coefficient pseudo remainder of the leading coefficient of P wrt A in the main variables.
111     * @param P generic polynomial in n+1 variables.
112     * @param A list of generic polynomials in n variables sorted according to appearing main variables.
113     * @return pseudo remainder of the leading coefficient of P wrt A.
114     */
115    public static <C extends RingElem<C>> 
116      GenPolynomial<C> topCoefficientPseudoRemainder(List<GenPolynomial<C>> A, GenPolynomial<C> P) {
117        if (A == null || A.isEmpty()) {
118            return P.monic();
119        }
120        if (P.isZERO()) {
121            return P;
122        }
123        GenPolynomialRing<C> pfac = P.ring;
124        GenPolynomialRing<C> pfac1 = A.get(0).ring;
125        if (pfac1.nvar <= 1) { // recursion base 
126            GenPolynomial<C> a = A.get(0);
127            GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(pfac.nvar - 1);
128            GenPolynomial<GenPolynomial<C>> pr = PolyUtil.<C> recursive(rfac, P);
129            // ldcf(P,x_m) = q a + r 
130            GenPolynomial<GenPolynomial<C>> rr = PolyGBUtil.<C> coefficientPseudoRemainderBase(pr, a);
131            GenPolynomial<C> R = PolyUtil.<C> distribute(pfac, rr);
132            return R.monic();
133        }
134        // select polynomials according to the main variable
135        GenPolynomialRing<GenPolynomial<C>> rfac1 = pfac1.recursive(1);
136        int nv = pfac.nvar - pfac1.nvar;
137        GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1 + nv);
138        GenPolynomialRing<GenPolynomial<GenPolynomial<C>>> rfac2 = rfac.recursive(nv);
139        if (debug) {
140            logger.info("rfac =" + rfac);
141        }
142        GenPolynomial<GenPolynomial<C>> pr = PolyUtil.<C> recursive(rfac, P);
143        GenPolynomial<GenPolynomial<GenPolynomial<C>>> pr2 = PolyUtil.<GenPolynomial<C>> recursive(rfac2, pr);
144        //System.out.println("recursion, pr2 = " + pr2);
145        GenPolynomial<C> Q = A.get(0);
146        GenPolynomial<GenPolynomial<C>> qr = PolyUtil.<C> recursive(rfac1, Q);
147        GenPolynomial<GenPolynomial<GenPolynomial<C>>> rr;
148        if (qr.isONE()) {
149            return P.ring.getZERO();
150        }
151        if (qr.degree(0) > 0) {
152            // pseudo remainder:  ldcf(P,x_m) = a q + r 
153            rr = PolyGBUtil.<C> coefficientPseudoRemainder(pr2, qr);
154            //System.out.println("recursion, qr  = " + qr);
155            //System.out.println("recursion, pr  = " + pr2);
156            //System.out.println("recursion, rr  = " + rr);
157        } else {
158            rr = pr2;
159        }
160        // reduction wrt. the other variables
161        List<GenPolynomial<C>> zeroDeg = zeroDegrees(A);
162        GenPolynomial<GenPolynomial<C>> Rr = PolyUtil.<GenPolynomial<C>> distribute(rfac, rr);
163        GenPolynomial<C> R = PolyUtil.<C> distribute(pfac, Rr);
164        R = topCoefficientPseudoRemainder(zeroDeg, R);
165        return R.monic();
166    }
167
168
169    /**
170     * Polynomial leading coefficient pseudo remainder.
171     * @param P generic polynomial in n+1 variables.
172     * @param A generic polynomial in n variables.
173     * @return pseudo remainder of the leading coefficient of P wrt A, with
174     *         ldcf(A)<sup>m'</sup> P = quotient * A + remainder.
175     */
176    public static <C extends RingElem<C>> 
177      GenPolynomial<GenPolynomial<GenPolynomial<C>>> coefficientPseudoRemainder(
178                    GenPolynomial<GenPolynomial<GenPolynomial<C>>> P, GenPolynomial<GenPolynomial<C>> A) {
179        if (A == null || A.isZERO()) { // findbugs
180            throw new ArithmeticException(P + " division by zero " + A);
181        }
182        if (A.isONE()) {
183            return P.ring.getZERO();
184        }
185        if (P.isZERO() || P.isONE()) {
186            return P;
187        }
188        GenPolynomialRing<GenPolynomial<GenPolynomial<C>>> pfac = P.ring;
189        GenPolynomialRing<GenPolynomial<C>> afac = A.ring; // == pfac.coFac
190        GenPolynomial<GenPolynomial<GenPolynomial<C>>> r = P;
191        GenPolynomial<GenPolynomial<C>> h;
192        GenPolynomial<GenPolynomial<GenPolynomial<C>>> hr;
193        GenPolynomial<GenPolynomial<C>> ldcf = P.leadingBaseCoefficient();
194        long m = ldcf.degree(0);
195        long n = A.degree(0);
196        GenPolynomial<C> c = A.leadingBaseCoefficient();
197        GenPolynomial<GenPolynomial<C>> cc = afac.getZERO().sum(c);
198        //System.out.println("cc = " + cc);
199        ExpVector e = A.leadingExpVector();
200        for (long i = m; i >= n; i--) {
201            if (r.isZERO()) {
202                return r;
203            }
204            GenPolynomial<GenPolynomial<C>> p = r.leadingBaseCoefficient();
205            ExpVector g = r.leadingExpVector();
206            long k = p.degree(0);
207            if (i == k) {
208                GenPolynomial<C> pl = p.leadingBaseCoefficient();
209                ExpVector f = p.leadingExpVector();
210                f = f.subtract(e);
211                r = r.multiply(cc); // coeff cc
212                h = A.multiply(pl, f); // coeff ac
213                hr = new GenPolynomial<GenPolynomial<GenPolynomial<C>>>(pfac, h, g);
214                r = r.subtract(hr);
215            } else {
216                r = r.multiply(cc);
217            }
218            //System.out.println("r = " + r);
219        }
220        if (r.degree(0) < P.degree(0)) { // recursion for degree
221            r = coefficientPseudoRemainder(r, A);
222        }
223        return r;
224    }
225
226
227    /**
228     * Polynomial leading coefficient pseudo remainder, base case.
229     * @param P generic polynomial in 1+1 variables.
230     * @param A generic polynomial in 1 variable.
231     * @return pseudo remainder of the leading coefficient of P wrt. A, with
232     *         ldcf(A)<sup>m'</sup> P = quotient * A + remainder.
233     */
234    public static <C extends RingElem<C>> 
235      GenPolynomial<GenPolynomial<C>> coefficientPseudoRemainderBase(
236                    GenPolynomial<GenPolynomial<C>> P, GenPolynomial<C> A) {
237        if (A == null || A.isZERO()) { // findbugs
238            throw new ArithmeticException(P + " division by zero " + A);
239        }
240        if (A.isONE()) {
241            return P.ring.getZERO();
242        }
243        if (P.isZERO() || P.isONE()) {
244            return P;
245        }
246        GenPolynomialRing<GenPolynomial<C>> pfac = P.ring;
247        GenPolynomialRing<C> afac = A.ring; // == pfac.coFac
248        GenPolynomial<GenPolynomial<C>> r = P;
249        GenPolynomial<C> h;
250        GenPolynomial<GenPolynomial<C>> hr;
251        GenPolynomial<C> ldcf = P.leadingBaseCoefficient();
252        long m = ldcf.degree(0);
253        long n = A.degree(0);
254        C c = A.leadingBaseCoefficient();
255        GenPolynomial<C> cc = afac.getZERO().sum(c);
256        //System.out.println("cc = " + cc);
257        ExpVector e = A.leadingExpVector();
258        for (long i = m; i >= n; i--) {
259            if (r.isZERO()) {
260                return r;
261            }
262            GenPolynomial<C> p = r.leadingBaseCoefficient();
263            ExpVector g = r.leadingExpVector();
264            long k = p.degree(0);
265            if (i == k) {
266                C pl = p.leadingBaseCoefficient();
267                ExpVector f = p.leadingExpVector();
268                f = f.subtract(e);
269                r = r.multiply(cc); // coeff cc
270                h = A.multiply(pl, f); // coeff ac
271                hr = new GenPolynomial<GenPolynomial<C>>(pfac, h, g);
272                r = r.subtract(hr);
273            } else {
274                r = r.multiply(cc);
275            }
276            //System.out.println("r = " + r);
277        }
278        if (r.degree(0) < P.degree(0)) { // recursion for degree
279            r = coefficientPseudoRemainderBase(r, A);
280        }
281        return r;
282    }
283
284
285    /**
286     * Extract polynomials with degree zero in the main variable.
287     * @param A list of generic polynomials in n variables.
288     * @return Z = [a_i] with deg(a_i,x_n) = 0 and in n-1 variables.
289     */
290    public static <C extends RingElem<C>> List<GenPolynomial<C>> zeroDegrees(List<GenPolynomial<C>> A) {
291        if (A == null || A.isEmpty()) {
292            return A;
293        }
294        GenPolynomialRing<C> pfac = A.get(0).ring;
295        GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1);
296        List<GenPolynomial<C>> zeroDeg = new ArrayList<GenPolynomial<C>>(A.size());
297        for (int i = 0; i < A.size(); i++) {
298            GenPolynomial<C> q = A.get(i);
299            GenPolynomial<GenPolynomial<C>> fr = PolyUtil.<C> recursive(rfac, q);
300            if (fr.degree(0) == 0) {
301                zeroDeg.add(fr.leadingBaseCoefficient());
302            }
303        }
304        return zeroDeg;
305    }
306
307}