001/*
002 * $Id: ReductionAbstract.java 5601 2016-09-25 19:17:08Z kredel $
003 */
004
005package edu.jas.gb;
006
007
008import java.util.ArrayList;
009import java.util.LinkedList;
010import java.util.List;
011import java.util.Map;
012
013import org.apache.log4j.Logger;
014
015import edu.jas.poly.ExpVector;
016import edu.jas.poly.GenPolynomial;
017import edu.jas.poly.Monomial;
018import edu.jas.structure.RingElem;
019
020
021/**
022 * Polynomial Reduction abstract class. Implements common S-Polynomial,
023 * normalform, criterion 4 module criterion and irreducible set.
024 * @param <C> coefficient type
025 * @author Heinz Kredel
026 */
027
028public abstract class ReductionAbstract<C extends RingElem<C>> implements Reduction<C> {
029
030
031    private static final Logger logger = Logger.getLogger(ReductionAbstract.class);
032
033
034    private static final boolean debug = logger.isDebugEnabled();
035
036
037    /**
038     * Constructor.
039     */
040    public ReductionAbstract() {
041    }
042
043
044    /**
045     * S-Polynomial.
046     * @param A polynomial.
047     * @param B polynomial.
048     * @return spol(A,B) the S-polynomial of A and B.
049     */
050    public GenPolynomial<C> SPolynomial(GenPolynomial<C> A, GenPolynomial<C> B) {
051        if (B == null || B.isZERO()) {
052            if (A == null) {
053                return B;
054            }
055            return A.ring.getZERO();
056        }
057        if (A == null || A.isZERO()) {
058            return B.ring.getZERO();
059        }
060        if (debug) {
061            if (!A.ring.equals(B.ring)) {
062                logger.error("rings not equal " + A.ring + ", " + B.ring);
063            }
064        }
065        Map.Entry<ExpVector, C> ma = A.leadingMonomial();
066        Map.Entry<ExpVector, C> mb = B.leadingMonomial();
067
068        ExpVector e = ma.getKey();
069        ExpVector f = mb.getKey();
070
071        ExpVector g = e.lcm(f);
072        ExpVector e1 = g.subtract(e);
073        ExpVector f1 = g.subtract(f);
074
075        C a = ma.getValue();
076        C b = mb.getValue();
077
078        //GenPolynomial<C> App = A.multiply(b, e1);
079        //GenPolynomial<C> Bpp = B.multiply(a, f1);
080        //GenPolynomial<C> Cp = App.subtract(Bpp);
081        GenPolynomial<C> Cp = A.scaleSubtractMultiple(b, e1, a, f1, B);
082        return Cp;
083    }
084
085
086    /**
087     * S-Polynomial with recording.
088     * @param S recording matrix, is modified. <b>Note</b> the negative
089     *            S-polynomial is recorded as required by all applications.
090     * @param i index of Ap in basis list.
091     * @param A a polynomial.
092     * @param j index of Bp in basis list.
093     * @param B a polynomial.
094     * @return Spol(A, B), the S-Polynomial for A and B.
095     */
096    public GenPolynomial<C> SPolynomial(List<GenPolynomial<C>> S, int i, GenPolynomial<C> A, int j,
097                    GenPolynomial<C> B) {
098        if (debug) {
099            if (B == null || B.isZERO()) {
100                throw new ArithmeticException("Spol B is zero");
101            }
102            if (A == null || A.isZERO()) {
103                throw new ArithmeticException("Spol A is zero");
104            }
105            if (!A.ring.equals(B.ring)) {
106                logger.error("rings not equal " + A.ring + ", " + B.ring);
107            }
108        }
109        Map.Entry<ExpVector, C> ma = A.leadingMonomial();
110        Map.Entry<ExpVector, C> mb = B.leadingMonomial();
111
112        ExpVector e = ma.getKey();
113        ExpVector f = mb.getKey();
114
115        ExpVector g = e.lcm(f);
116        ExpVector e1 = g.subtract(e);
117        ExpVector f1 = g.subtract(f);
118
119        C a = ma.getValue();
120        C b = mb.getValue();
121
122        //GenPolynomial<C> App = A.multiply(b, e1);
123        //GenPolynomial<C> Bpp = B.multiply(a, f1);
124        //GenPolynomial<C> Cp = App.subtract(Bpp);
125        GenPolynomial<C> Cp = A.scaleSubtractMultiple(b, e1, a, f1, B);
126
127        GenPolynomial<C> zero = A.ring.getZERO();
128        GenPolynomial<C> As = zero.sum(b.negate(), e1);
129        GenPolynomial<C> Bs = zero.sum(a /*correct .negate()*/, f1);
130        S.set(i, As);
131        S.set(j, Bs);
132        return Cp;
133    }
134
135
136    /**
137     * Module criterium.
138     * @param modv number of module variables.
139     * @param A polynomial.
140     * @param B polynomial.
141     * @return true if the module S-polynomial(i,j) is required.
142     */
143    public boolean moduleCriterion(int modv, GenPolynomial<C> A, GenPolynomial<C> B) {
144        if (modv == 0) {
145            return true;
146        }
147        ExpVector ei = A.leadingExpVector();
148        ExpVector ej = B.leadingExpVector();
149        return moduleCriterion(modv, ei, ej);
150    }
151
152
153    /**
154     * Module criterium.
155     * @param modv number of module variables.
156     * @param ei ExpVector.
157     * @param ej ExpVector.
158     * @return true if the module S-polynomial(i,j) is required.
159     */
160    public boolean moduleCriterion(int modv, ExpVector ei, ExpVector ej) {
161        if (modv == 0) {
162            return true;
163        }
164        if (ei.invLexCompareTo(ej, 0, modv) != 0) {
165            return false; // skip pair
166        }
167        return true;
168    }
169
170
171    /**
172     * GB criterium 4. Use only for commutative polynomial rings.
173     * @param A polynomial.
174     * @param B polynomial.
175     * @param e = lcm(ht(A),ht(B))
176     * @return true if the S-polynomial(i,j) is required, else false.
177     */
178    public boolean criterion4(GenPolynomial<C> A, GenPolynomial<C> B, ExpVector e) {
179        if (logger.isInfoEnabled()) {
180            if (!A.ring.equals(B.ring)) {
181                logger.error("rings not equal " + A.ring + ", " + B.ring);
182            }
183            if (!A.ring.isCommutative()) { //B instanceof GenSolvablePolynomial ) {
184                logger.error("GBCriterion4 not applicabable to non-commutative polynomials");
185                return true;
186            }
187        }
188        ExpVector ei = A.leadingExpVector();
189        ExpVector ej = B.leadingExpVector();
190        return criterion4(ei, ej, e);
191    }
192
193
194    /**
195     * GB criterium 4. Use only for commutative polynomial rings.
196     * @param ei exponent vector.
197     * @param ej exponent vector.
198     * @param e = lcm(ei,ej)
199     * @return true if the S-polynomial(i,j) is required, else false.
200     */
201    public boolean criterion4(ExpVector ei, ExpVector ej, ExpVector e) {
202        ExpVector g = ei.sum(ej);
203        ExpVector h = g.subtract(e);
204        int s = h.signum();
205        return s != 0;
206    }
207
208
209    /**
210     * GB criterium 4.
211     * @param A polynomial.
212     * @param B polynomial.
213     * @return true if the S-polynomial(i,j) is required, else false.
214     */
215    public boolean criterion4(GenPolynomial<C> A, GenPolynomial<C> B) {
216        if (logger.isInfoEnabled()) {
217            if (!A.ring.isCommutative() || !B.ring.isCommutative()) { // A instanceof GenSolvablePolynomial
218                logger.error("GBCriterion4 not applicabable to non-commutative polynomials");
219                return true;
220            }
221        }
222        ExpVector ei = A.leadingExpVector();
223        ExpVector ej = B.leadingExpVector();
224        ExpVector e = ei.lcm(ej);
225        return criterion4(ei, ej, e);
226    }
227
228
229    /**
230     * Normalform with respect to marked head terms.
231     * @param Mp leading monomial list.
232     * @param Pp polynomial list.
233     * @param Ap polynomial.
234     * @return nf(Ap) with respect to Mp+Pp.
235     */
236    public GenPolynomial<C> normalformMarked(List<Monomial<C>> Mp, List<GenPolynomial<C>> Pp,
237                    GenPolynomial<C> Ap) {
238        throw new UnsupportedOperationException("not implemented: " + Mp + " " + Pp + " " + Ap);
239    }
240
241
242    /**
243     * Normalform Set.
244     * @param Ap polynomial list.
245     * @param Pp polynomial list.
246     * @return list of nf(a) with respect to Pp for all a in Ap.
247     */
248    public List<GenPolynomial<C>> normalform(List<GenPolynomial<C>> Pp, List<GenPolynomial<C>> Ap) {
249        if (Pp == null || Pp.isEmpty()) {
250            return Ap;
251        }
252        if (Ap == null || Ap.isEmpty()) {
253            return Ap;
254        }
255        ArrayList<GenPolynomial<C>> red = new ArrayList<GenPolynomial<C>>();
256        for (GenPolynomial<C> A : Ap) {
257            A = normalform(Pp, A);
258            red.add(A);
259        }
260        return red;
261    }
262
263
264    /**
265     * Is top reducible.
266     * @param A polynomial.
267     * @param P polynomial list.
268     * @return true if A is top reducible with respect to P.
269     */
270    public boolean isTopReducible(List<GenPolynomial<C>> P, GenPolynomial<C> A) {
271        if (P == null || P.isEmpty()) {
272            return false;
273        }
274        if (A == null || A.isZERO()) {
275            return false;
276        }
277        boolean mt = false;
278        ExpVector e = A.leadingExpVector();
279        for (GenPolynomial<C> p : P) {
280            mt = e.multipleOf(p.leadingExpVector());
281            if (mt) {
282                return true;
283            }
284        }
285        return false;
286    }
287
288
289    /**
290     * Is reducible.
291     * @param Ap polynomial.
292     * @param Pp polynomial list.
293     * @return true if Ap is reducible with respect to Pp.
294     */
295    public boolean isReducible(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) {
296        return !isNormalform(Pp, Ap);
297    }
298
299
300    /**
301     * Is in Normalform.
302     * @param Ap polynomial.
303     * @param Pp polynomial list.
304     * @return true if Ap is in normalform with respect to Pp.
305     */
306    @SuppressWarnings("unchecked")
307    public boolean isNormalform(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) {
308        if (Pp == null || Pp.isEmpty()) {
309            return true;
310        }
311        if (Ap == null || Ap.isZERO()) {
312            return true;
313        }
314        int l;
315        GenPolynomial<C>[] P;
316        synchronized (Pp) {
317            l = Pp.size();
318            P = new GenPolynomial[l];
319            //P = Pp.toArray();
320            for (int i = 0; i < Pp.size(); i++) {
321                P[i] = Pp.get(i);
322            }
323        }
324        ExpVector[] htl = new ExpVector[l];
325        GenPolynomial<C>[] p = new GenPolynomial[l];
326        Map.Entry<ExpVector, C> m;
327        int i;
328        int j = 0;
329        for (i = 0; i < l; i++) {
330            p[i] = P[i];
331            m = p[i].leadingMonomial();
332            if (m != null) {
333                p[j] = p[i];
334                htl[j] = m.getKey();
335                j++;
336            }
337        }
338        l = j;
339        boolean mt = false;
340        for (ExpVector e : Ap.getMap().keySet()) {
341            for (i = 0; i < l; i++) {
342                mt = e.multipleOf(htl[i]);
343                if (mt) {
344                    return false;
345                }
346            }
347        }
348        return true;
349    }
350
351
352    /**
353     * Is in Normalform.
354     * @param Pp polynomial list.
355     * @return true if each Ap in Pp is in normalform with respect to Pp\{Ap}.
356     */
357    public boolean isNormalform(List<GenPolynomial<C>> Pp) {
358        if (Pp == null || Pp.isEmpty()) {
359            return true;
360        }
361        GenPolynomial<C> Ap;
362        List<GenPolynomial<C>> P = new LinkedList<GenPolynomial<C>>(Pp);
363        int s = P.size();
364        for (int i = 0; i < s; i++) {
365            Ap = P.remove(i);
366            if (!isNormalform(P, Ap)) {
367                return false;
368            }
369            P.add(Ap);
370        }
371        return true;
372    }
373
374
375    /**
376     * Irreducible set.
377     * @param Pp polynomial list.
378     * @return a list P of monic polynomials which are in normalform wrt. P and
379     *         with ideal(Pp) = ideal(P).
380     */
381    public List<GenPolynomial<C>> irreducibleSet(List<GenPolynomial<C>> Pp) {
382        ArrayList<GenPolynomial<C>> P = new ArrayList<GenPolynomial<C>>();
383        for (GenPolynomial<C> a : Pp) {
384            if (a.length() != 0) {
385                a = a.monic();
386                if (a.isONE()) {
387                    P.clear();
388                    P.add(a);
389                    return P;
390                }
391                P.add(a);
392            }
393        }
394        int l = P.size();
395        if (l <= 1)
396            return P;
397
398        int irr = 0;
399        ExpVector e;
400        ExpVector f;
401        GenPolynomial<C> a;
402        logger.debug("irr = ");
403        while (irr != l) {
404            //it = P.listIterator(); 
405            //a = P.get(0); //it.next();
406            a = P.remove(0);
407            e = a.leadingExpVector();
408            a = normalform(P, a);
409            logger.debug(String.valueOf(irr));
410            if (a.length() == 0) {
411                l--;
412                if (l <= 1) {
413                    return P;
414                }
415            } else {
416                f = a.leadingExpVector();
417                if (f.signum() == 0) {
418                    P = new ArrayList<GenPolynomial<C>>();
419                    P.add(a.monic());
420                    return P;
421                }
422                if (e.equals(f)) {
423                    irr++;
424                } else {
425                    irr = 0;
426                    a = a.monic();
427                }
428                P.add(a);
429            }
430        }
431        //System.out.println();
432        return P;
433    }
434
435
436    /**
437     * Is reduction of normal form.
438     * @param row recording matrix.
439     * @param Pp a polynomial list for reduction.
440     * @param Ap a polynomial.
441     * @param Np nf(Pp,Ap), a normal form of Ap wrt. Pp.
442     * @return true, if Np + sum( row[i]*Pp[i] ) == Ap, else false.
443     */
444
445    public boolean isReductionNF(List<GenPolynomial<C>> row, List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap,
446                    GenPolynomial<C> Np) {
447        if (row == null && Pp == null) {
448            if (Ap == null) {
449                return Np == null;
450            }
451            return Ap.equals(Np);
452        }
453        if (row == null || Pp == null) {
454            return false;
455        }
456        if (row.size() != Pp.size()) {
457            return false;
458        }
459        GenPolynomial<C> t = Np;
460        //System.out.println("t0 = " + t );
461        GenPolynomial<C> r;
462        GenPolynomial<C> p;
463        for (int m = 0; m < Pp.size(); m++) {
464            r = row.get(m);
465            p = Pp.get(m);
466            if (r != null && p != null) {
467                if (t == null) {
468                    t = r.multiply(p);
469                } else {
470                    t = t.sum(r.multiply(p));
471                }
472            }
473            //System.out.println("r = " + r );
474            //System.out.println("p = " + p );
475        }
476        //System.out.println("t+ = " + t );
477        if (t == null) {
478            if (Ap == null) {
479                return true;
480            }
481            return Ap.isZERO();
482        }
483        r = t.subtract(Ap);
484        boolean z = r.isZERO();
485        if (!z) {
486            logger.info("t = " + t);
487            logger.info("a = " + Ap);
488            logger.info("t-a = " + r);
489        }
490        return z;
491    }
492}