001/*
002 * $Id: CReductionSeq.java 4115 2012-08-19 13:18:59Z kredel $
003 */
004
005package edu.jas.application;
006
007
008import java.io.Serializable;
009import java.util.ArrayList;
010import java.util.Collections;
011import java.util.LinkedList;
012import java.util.List;
013import java.util.Map;
014
015import org.apache.log4j.Logger;
016
017import edu.jas.poly.ExpVector;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenPolynomialRing;
020import edu.jas.structure.GcdRingElem;
021import edu.jas.structure.RingFactory;
022import edu.jas.ufd.GCDFactory;
023import edu.jas.ufd.GreatestCommonDivisor;
024
025
026/**
027 * Polynomial parametric ring reduction sequential use algorithm. Implements
028 * normalform, condition construction and polynomial determination.
029 * @param <C> coefficient type
030 * @author Heinz Kredel
031 */
032public class CReductionSeq<C extends GcdRingElem<C>> implements Serializable
033/* extends ReductionAbstract<C> */
034/* implements CReduction<C> */{
035
036
037    private static final Logger logger = Logger.getLogger(CReductionSeq.class);
038
039
040    //private final boolean debug = logger.isDebugEnabled();
041
042
043    private final boolean info = logger.isInfoEnabled();
044
045
046    /**
047     * Greatest common divisor engine.
048     */
049    protected final GreatestCommonDivisor<C> engine;
050
051
052    /**
053     * Polynomial coefficient ring factory.
054     */
055    protected final RingFactory<C> cofac;
056
057
058    /**
059     * Flag if top-reduction only should be used.
060     */
061    protected boolean top = true; // false;
062
063
064    /**
065     * Constructor.
066     * @param rf coefficient factory.
067     */
068    public CReductionSeq(RingFactory<C> rf) {
069        cofac = rf;
070        // System.out.println("cofac = " + cofac);
071        engine = GCDFactory.<C> getImplementation(cofac);
072    }
073
074
075    /**
076     * S-Polynomial.
077     * @param Ap polynomial.
078     * @param Bp polynomial.
079     * @return spol(Ap,Bp) the S-polynomial of Ap and Bp.
080     */
081    public ColorPolynomial<C> SPolynomial(ColorPolynomial<C> Ap, ColorPolynomial<C> Bp) {
082        if (Bp == null || Bp.isZERO()) {
083            return Bp;
084        }
085        if (Ap == null || Ap.isZERO()) {
086            return Ap;
087        }
088
089        Map.Entry<ExpVector, GenPolynomial<C>> ma = Ap.red.leadingMonomial();
090        Map.Entry<ExpVector, GenPolynomial<C>> mb = Bp.red.leadingMonomial();
091
092        ExpVector e = ma.getKey();
093        ExpVector f = mb.getKey();
094
095        ExpVector g = e.lcm(f); // EVLCM(e,f);
096        ExpVector e1 = g.subtract(e); // EVDIF(g,e);
097        ExpVector f1 = g.subtract(f); // EVDIF(g,f);
098
099        GenPolynomial<C> a = ma.getValue();
100        GenPolynomial<C> b = mb.getValue();
101
102        GenPolynomial<C> c = engine.gcd(a, b);
103        if (!c.isONE()) {
104            // System.out.println("gcd =s " + c);
105            a = a.divide(c);
106            b = b.divide(c);
107        }
108
109        ColorPolynomial<C> App = Ap.multiply(b, e1);
110        ColorPolynomial<C> Bpp = Bp.multiply(a, f1);
111        ColorPolynomial<C> Cp = App.subtract(Bpp);
112        return Cp;
113    }
114
115
116    /**
117     * Is top reducible.
118     * @param A polynomial.
119     * @param P polynomial list.
120     * @return true if A is top reducible with respect to P.
121     */
122    public boolean isTopReducible(List<ColorPolynomial<C>> P, ColorPolynomial<C> A) {
123        if (P == null || P.isEmpty()) {
124            return false;
125        }
126        if (A == null || A.isZERO()) {
127            return false;
128        }
129        boolean mt = false;
130        ExpVector e = A.leadingExpVector();
131        for (ColorPolynomial<C> p : P) {
132            if (p == null) {
133                return false;
134            }
135            ExpVector f = p.leadingExpVector();
136            if (f == null) {
137                return false;
138            }
139            if (e == null) {
140                return false;
141            }
142            mt = e.multipleOf(f); // EVMT( e, p.leadingExpVector() );
143            if (mt) {
144                return true;
145            }
146        }
147        return false;
148    }
149
150
151    /**
152     * Is reducible.
153     * @param Ap polynomial.
154     * @param Pp polynomial list.
155     * @return true if Ap is reducible with respect to Pp.
156     */
157    public boolean isReducible(List<ColorPolynomial<C>> Pp, ColorPolynomial<C> Ap) {
158        return !isNormalform(Pp, Ap);
159    }
160
161
162    /**
163     * Is in Normalform.
164     * @param Ap polynomial.
165     * @param Pp polynomial list.
166     * @return true if Ap is in normalform with respect to Pp.
167     */
168    @SuppressWarnings("unchecked")
169    public boolean isNormalform(List<ColorPolynomial<C>> Pp, ColorPolynomial<C> Ap) {
170        if (Pp == null || Pp.isEmpty()) {
171            return true;
172        }
173        if (Ap == null || Ap.isZERO()) {
174            return true;
175        }
176        int l;
177        ColorPolynomial<C>[] P;
178        synchronized (Pp) {
179            l = Pp.size();
180            P = new ColorPolynomial[l];
181            // P = Pp.toArray();
182            for (int i = 0; i < Pp.size(); i++) {
183                P[i] = Pp.get(i);
184            }
185        }
186        ExpVector[] htl = new ExpVector[l];
187        ColorPolynomial<C>[] p = new ColorPolynomial[l];
188        Map.Entry<ExpVector, GenPolynomial<C>> m;
189        int i;
190        int j = 0;
191        for (i = 0; i < l; i++) {
192            p[i] = P[i];
193            m = p[i].red.leadingMonomial();
194            if (m != null) {
195                p[j] = p[i];
196                htl[j] = m.getKey();
197                j++;
198            }
199        }
200        l = j;
201        boolean mt = false;
202        for (ExpVector e : Ap.red.getMap().keySet()) {
203            for (i = 0; i < l; i++) {
204                mt = e.multipleOf(htl[i]); // EVMT( e, htl[i] );
205                if (mt) {
206                    System.out.println("not normalform " + Ap + ", P[i] = " + P[i]);
207                    return false;
208                }
209            }
210            if (top) {
211                return true;
212            }
213        }
214        for (ExpVector e : Ap.white.getMap().keySet()) {
215            for (i = 0; i < l; i++) {
216                mt = e.multipleOf(htl[i]); // EVMT( e, htl[i] );
217                if (mt) {
218                    System.out.println("not normalform " + Ap + ", P[i] = " + P[i]);
219                    return false;
220                }
221            }
222            if (top) {
223                return true;
224            }
225        }
226        return true;
227    }
228
229
230    /**
231     * Is in Normalform.
232     * @param Pp polynomial list.
233     * @return true if each Ap in Pp is in normalform with respect to Pp\{Ap}.
234     */
235    public boolean isNormalform(List<ColorPolynomial<C>> Pp) {
236        if (Pp == null || Pp.isEmpty()) {
237            return true;
238        }
239        ColorPolynomial<C> Ap;
240        List<ColorPolynomial<C>> P = new LinkedList<ColorPolynomial<C>>(Pp);
241        int s = P.size();
242        for (int i = 0; i < s; i++) {
243            Ap = P.remove(i);
244            if (!isNormalform(P, Ap)) {
245                return false;
246            }
247            P.add(Ap);
248        }
249        return true;
250    }
251
252
253    /**
254     * Normalform.
255     * @param Ap polynomial.
256     * @param Pp polynomial list.
257     * @param cond condition for these polynomials.
258     * @return nf(Ap) with respect to Pp.
259     */
260    @SuppressWarnings("unchecked")
261    public ColorPolynomial<C> normalform(Condition<C> cond, List<ColorPolynomial<C>> Pp, ColorPolynomial<C> Ap) {
262        if (Pp == null || Pp.isEmpty()) {
263            return Ap;
264        }
265        if (Ap == null || Ap.isZERO()) {
266            return Ap;
267        }
268        Map.Entry<ExpVector, GenPolynomial<C>> m;
269        int l;
270        ColorPolynomial<C>[] P;
271        synchronized (Pp) {
272            l = Pp.size();
273            P = new ColorPolynomial[l];
274            // P = Pp.toArray();
275            for (int i = 0; i < Pp.size(); i++) {
276                P[i] = Pp.get(i);
277            }
278        }
279        ExpVector[] htl = new ExpVector[l];
280        Object[] lbc = new Object[l]; // want C[]
281        ColorPolynomial<C>[] p = new ColorPolynomial[l];
282        int i;
283        int j = 0;
284        for (i = 0; i < l; i++) {
285            if (P[i] == null) {
286                continue;
287            }
288            p[i] = P[i];
289            m = p[i].red.leadingMonomial();
290            if (m != null) {
291                p[j] = p[i];
292                htl[j] = m.getKey();
293                lbc[j] = m.getValue();
294                j++;
295            }
296        }
297        l = j;
298        ExpVector e;
299        GenPolynomial<C> a;
300        boolean mt = false;
301        GenPolynomial<GenPolynomial<C>> zero = p[0].red.ring.getZERO();
302        ColorPolynomial<C> R = new ColorPolynomial<C>(zero, zero, zero);
303
304        // ColorPolynomial<C> T = null;
305        ColorPolynomial<C> Q = null;
306        ColorPolynomial<C> S = Ap;
307        while (S.length() > 0) {
308            m = S.leadingMonomial();
309            e = m.getKey();
310            a = m.getValue();
311            Condition.Color col = cond.color(a);
312            if (col == Condition.Color.GREEN) { // move to green terms
313                GenPolynomial<GenPolynomial<C>> g = S.green.sum(a, e);
314                GenPolynomial<GenPolynomial<C>> r = S.red;
315                GenPolynomial<GenPolynomial<C>> w = S.white;
316                if (S.red.isZERO()) {
317                    w = w.subtract(a, e);
318                } else { // only in minimalGB
319                    logger.info("green_red = " + zero.sum(a, e));
320                    r = r.subtract(a, e);
321                }
322                S = new ColorPolynomial<C>(g, r, w);
323                continue;
324            }
325            //if (col == Condition.Color.WHITE) { // refine condition
326                // System.out.println("white = " + zero.sum(a,e));
327                // return S; // return for new case distinction
328            //}
329            // System.out.println("NF, e = " + e);
330            for (i = 0; i < l; i++) {
331                mt = e.multipleOf(htl[i]); // EVMT( e, htl[i] );
332                if (mt)
333                    break;
334            }
335            if (!mt) {
336                // logger.debug("irred");
337                if (top) {
338                    return S;
339                }
340                R = R.sum(a, e);
341                S = S.subtract(a, e);
342                // System.out.println(" S = " + S);
343            } else {
344                e = e.subtract(htl[i]); // EVDIF( e, htl[i] );
345                // logger.info("red div = " + e);
346                GenPolynomial<C> c = (GenPolynomial<C>) lbc[i];
347                GenPolynomial<C> g = engine.gcd(a, c);
348                if (!g.isONE()) {
349                    // System.out.println("gcd = " + g);
350                    a = a.divide(g);
351                    c = c.divide(g);
352                }
353                S = S.multiply(c);
354                R = R.multiply(c);
355                Q = p[i].multiply(a, e);
356                S = S.subtract(Q);
357            }
358        }
359        return R;
360    }
361
362
363    /*
364     * -------- coloring and condition stuff ------------------------------
365     */
366
367    /**
368     * Case distinction conditions of parametric polynomial list. The returned
369     * condition determines the polynomial list.
370     * @param L list of parametric polynomials.
371     * @return list of conditions as case distinction.
372     */
373    public List<Condition<C>> caseDistinction(List<GenPolynomial<GenPolynomial<C>>> L) {
374        List<Condition<C>> cd = new ArrayList<Condition<C>>();
375        if (L == null || L.size() == 0) {
376            return cd;
377        }
378        for (GenPolynomial<GenPolynomial<C>> A : L) {
379            if (A != null && !A.isZERO()) {
380                cd = caseDistinction(cd, A);
381            }
382        }
383        // System.out.println("cd = " + cd);
384        return cd;
385    }
386
387
388    /**
389     * Case distinction conditions of parametric polynomial list.
390     * @param cd a list of conditions.
391     * @param A a parametric polynomial.
392     * @return list of conditions as case distinction extending the conditions
393     *         in cd.
394     */
395    public List<Condition<C>> caseDistinction(List<Condition<C>> cd, GenPolynomial<GenPolynomial<C>> A) {
396        if (A == null || A.isZERO()) {
397            return cd;
398        }
399        if (cd == null) {
400            cd = new ArrayList<Condition<C>>();
401        }
402        if (cd.size() == 0) { // construct empty condition
403            RingFactory<GenPolynomial<C>> crfac = A.ring.coFac;
404            GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) crfac;
405            Condition<C> sc = new Condition<C>(cfac);
406            cd.add(sc);
407        }
408        GenPolynomial<GenPolynomial<C>> Ap;
409        GenPolynomial<GenPolynomial<C>> Bp;
410
411        List<Condition<C>> C = new ArrayList<Condition<C>>( /* leer! */);
412        for (Condition<C> cond : cd) {
413            // System.out.println("caseDist: " + cond);
414            Condition<C> cz = cond;
415            Ap = A;
416            while (!Ap.isZERO()) {
417                GenPolynomial<C> c = Ap.leadingBaseCoefficient();
418                Bp = Ap.reductum();
419                //System.out.println("to color: " + c);
420                switch (cz.color(c)) {
421                case GREEN:
422                    // System.out.println("color green: " + c);
423                    Ap = Bp;
424                    continue;
425                case RED:
426                    // System.out.println("color red: " + c);
427                    C.add(cz);
428                    // wrong: return C;
429                    Ap = A.ring.getZERO();
430                    continue;
431                    // break;
432                case WHITE:
433                default:
434                    // System.out.println("color white: " + c);
435                    Condition<C> nc = cz.extendNonZero(c);
436                    if (nc != null) { // no contradiction
437                        if (!cz.equals(nc)) {
438                            C.add(nc);
439                        } else {
440                            cz = null;
441                            Ap = A.ring.getZERO();
442                            continue;
443                        }
444                    } else {
445                        System.out.println("this should not be printed " + c);
446                    }
447                    Condition<C> ez = cz.extendZero(c);
448                    if (ez != null) {
449                        cz = ez;
450                    } else { // contradiction
451                        cz = null;
452                        Ap = A.ring.getZERO();
453                        continue;
454                    }
455                    Ap = Bp;
456                }
457            }
458            // System.out.println("cond cz: " + cz);
459            if (cz == null || cz.isContradictory() || C.contains(cz)) {
460                // System.out.println("not added entry " + cz);
461            } else {
462                C.add(cz);
463            }
464        }
465        // System.out.println("C = " + C);
466        return C;
467    }
468
469
470    /**
471     * Case distinction conditions of parametric polynomial list.
472     * @param A a parametric polynomial.
473     * @param cond a condition.
474     * @return list of case distinction conditions.
475     */
476    public List<Condition<C>> caseDistinction(Condition<C> cond, GenPolynomial<GenPolynomial<C>> A) {
477        List<Condition<C>> cd = new ArrayList<Condition<C>>();
478        if (A == null || A.isZERO()) {
479            return cd;
480        }
481        cd.add(cond);
482        cd = caseDistinction(cd, A);
483        if (info) {
484            StringBuffer s = new StringBuffer("extending condition: " + cond + "\n");
485            s.append("case distinctions: [ \n");
486            for (Condition<C> c : cd) {
487                s.append(c.toString() + "\n");
488            }
489            s.append("]");
490            logger.info(s.toString());
491        }
492        return cd;
493    }
494
495
496    /**
497     * Determine polynomial list.
498     * @param H polynomial list.
499     * @return new determined list of colored systems.
500     */
501    public List<ColoredSystem<C>> determine(List<GenPolynomial<GenPolynomial<C>>> H) {
502        if (H == null || H.size() == 0) {
503            List<ColoredSystem<C>> CS = new ArrayList<ColoredSystem<C>>();
504            return CS;
505        }
506        //System.out.println("of determine     = " + H);
507        Collections.reverse(H);
508        List<Condition<C>> cd = caseDistinction(H);
509        //System.out.println("case Distinction = " + cd);
510        //System.out.println("of determine     = " + H);
511        return determine(cd, H);
512    }
513
514
515    /**
516     * Determine polynomial list.
517     * @param H polynomial list.
518     * @param cd case distiction, a condition list.
519     * @return new determined list of colored systems.
520     */
521    public List<ColoredSystem<C>> determine(List<Condition<C>> cd, List<GenPolynomial<GenPolynomial<C>>> H) {
522        List<ColoredSystem<C>> CS = new ArrayList<ColoredSystem<C>>();
523        if (H == null || H.size() == 0) {
524            return CS;
525        }
526        for (Condition<C> cond : cd) {
527            logger.info("determine wrt cond = " + cond);
528            if (cond.zero.isONE()) { // should not happen
529                System.out.println("ideal is one = " + cond.zero);
530                // continue; // can treat all coeffs as green
531            }
532            // if ( cond.isEmpty() ) { // do not use this code
533            // continue; // can skip condition (?)
534            // }
535            List<ColorPolynomial<C>> S = cond.determine(H);
536            ColoredSystem<C> cs = new ColoredSystem<C>(cond, S);
537            CS.add(cs);
538        }
539        return CS;
540    }
541
542}