001    /*
002     * $Id: CReductionSeq.java 3426 2010-12-24 13:17:58Z kredel $
003     */
004    
005    package edu.jas.application;
006    
007    
008    import java.util.ArrayList;
009    import java.util.LinkedList;
010    import java.util.List;
011    import java.util.Map;
012    import java.util.Collections;
013    
014    import org.apache.log4j.Logger;
015    
016    import edu.jas.poly.ExpVector;
017    import edu.jas.poly.GenPolynomial;
018    import edu.jas.poly.GenPolynomialRing;
019    import edu.jas.structure.GcdRingElem;
020    import edu.jas.structure.RingFactory;
021    import edu.jas.ufd.GCDFactory;
022    import edu.jas.ufd.GreatestCommonDivisor;
023    
024    
025    /**
026     * Polynomial parametric ring reduction sequential use algorithm. Implements
027     * normalform, condition construction and polynomial determination.
028     * @param <C> coefficient type
029     * @author Heinz Kredel
030     */
031    public class CReductionSeq<C extends GcdRingElem<C>>
032           /* extends ReductionAbstract<C> */
033           /* implements CReduction<C> */ {
034    
035    
036        private static final Logger logger = Logger.getLogger(CReductionSeq.class);
037    
038    
039        private final boolean debug = logger.isDebugEnabled();
040    
041    
042        private final boolean info = logger.isInfoEnabled();
043    
044    
045        /**
046         * Greatest common divisor engine.
047         */
048        protected final GreatestCommonDivisor<C> engine;
049    
050    
051        /**
052         * Polynomial coefficient ring factory.
053         */
054        protected final RingFactory<C> cofac;
055    
056    
057        /**
058         * Flag if top-reduction only should be used.
059         */
060        protected boolean top = true; // false;
061    
062    
063        /**
064         * Constructor.
065         * @param rf coefficient factory.
066         */
067        public CReductionSeq(RingFactory<C> rf) {
068            cofac = rf;
069            // System.out.println("cofac = " + cofac);
070            engine = GCDFactory.<C> getImplementation(cofac);
071        }
072    
073    
074        /**
075         * S-Polynomial.
076         * @param Ap polynomial.
077         * @param Bp polynomial.
078         * @return spol(Ap,Bp) the S-polynomial of Ap and Bp.
079         */
080        public ColorPolynomial<C> SPolynomial(ColorPolynomial<C> Ap, ColorPolynomial<C> Bp) {
081            if (Bp == null || Bp.isZERO()) {
082                return Bp;
083            }
084            if (Ap == null || Ap.isZERO()) {
085                return Ap;
086            }
087    
088            Map.Entry<ExpVector, GenPolynomial<C>> ma = Ap.red.leadingMonomial();
089            Map.Entry<ExpVector, GenPolynomial<C>> mb = Bp.red.leadingMonomial();
090    
091            ExpVector e = ma.getKey();
092            ExpVector f = mb.getKey();
093    
094            ExpVector g = e.lcm(f); // EVLCM(e,f);
095            ExpVector e1 = g.subtract(e); // EVDIF(g,e);
096            ExpVector f1 = g.subtract(f); // EVDIF(g,f);
097    
098            GenPolynomial<C> a = ma.getValue();
099            GenPolynomial<C> b = mb.getValue();
100    
101            GenPolynomial<C> c = engine.gcd(a, b);
102            if (!c.isONE()) {
103                // System.out.println("gcd =s " + c);
104                a = a.divide(c);
105                b = b.divide(c);
106            }
107    
108            ColorPolynomial<C> App = Ap.multiply(b, e1);
109            ColorPolynomial<C> Bpp = Bp.multiply(a, f1);
110            ColorPolynomial<C> Cp = App.subtract(Bpp);
111            return Cp;
112        }
113    
114    
115        /**
116         * Is top reducible.
117         * @param A polynomial.
118         * @param P polynomial list.
119         * @return true if A is top reducible with respect to P.
120         */
121        public boolean isTopReducible(List<ColorPolynomial<C>> P, ColorPolynomial<C> A) {
122            if (P == null || P.isEmpty()) {
123                return false;
124            }
125            if (A == null || A.isZERO()) {
126                return false;
127            }
128            boolean mt = false;
129            ExpVector e = A.leadingExpVector();
130            for (ColorPolynomial<C> p : P) {
131                if (p == null) {
132                    return false;
133                }
134                ExpVector f = p.leadingExpVector();
135                if (f == null) {
136                    return false;
137                }
138                if (e == null) {
139                    return false;
140                }
141                mt = e.multipleOf(f); // EVMT( e, p.leadingExpVector() );
142                if (mt) {
143                    return true;
144                }
145            }
146            return false;
147        }
148    
149    
150        /**
151         * Is reducible.
152         * @param Ap polynomial.
153         * @param Pp polynomial list.
154         * @return true if Ap is reducible with respect to Pp.
155         */
156        public boolean isReducible(List<ColorPolynomial<C>> Pp, ColorPolynomial<C> Ap) {
157            return !isNormalform(Pp, Ap);
158        }
159    
160    
161        /**
162         * Is in Normalform.
163         * @param Ap polynomial.
164         * @param Pp polynomial list.
165         * @return true if Ap is in normalform with respect to Pp.
166         */
167        @SuppressWarnings("unchecked")
168        public boolean isNormalform(List<ColorPolynomial<C>> Pp, ColorPolynomial<C> Ap) {
169            if (Pp == null || Pp.isEmpty()) {
170                return true;
171            }
172            if (Ap == null || Ap.isZERO()) {
173                return true;
174            }
175            int l;
176            ColorPolynomial<C>[] P;
177            synchronized (Pp) {
178                l = Pp.size();
179                P = new ColorPolynomial[l];
180                // P = Pp.toArray();
181                for (int i = 0; i < Pp.size(); i++) {
182                    P[i] = Pp.get(i);
183                }
184            }
185            ExpVector[] htl = new ExpVector[l];
186            ColorPolynomial<C>[] p = new ColorPolynomial[l];
187            Map.Entry<ExpVector, GenPolynomial<C>> m;
188            int i;
189            int j = 0;
190            for (i = 0; i < l; i++) {
191                p[i] = P[i];
192                m = p[i].red.leadingMonomial();
193                if (m != null) {
194                    p[j] = p[i];
195                    htl[j] = m.getKey();
196                    j++;
197                }
198            }
199            l = j;
200            boolean mt = false;
201            for (ExpVector e : Ap.red.getMap().keySet()) {
202                for (i = 0; i < l; i++) {
203                    mt = e.multipleOf(htl[i]); // EVMT( e, htl[i] );
204                    if (mt) {
205                       System.out.println("not normalform " + Ap + ", P[i] = " + P[i]);
206                       return false;
207                    }
208                }
209                if ( top ) {
210                   return true;
211                }
212            }
213            for (ExpVector e : Ap.white.getMap().keySet()) {
214                for (i = 0; i < l; i++) {
215                    mt = e.multipleOf(htl[i]); // EVMT( e, htl[i] );
216                    if (mt) {
217                       System.out.println("not normalform " + Ap + ", P[i] = " + P[i]);
218                       return false;
219                    }
220                }
221                if ( top ) {
222                   return true;
223                }
224            }
225            return true;
226        }
227    
228    
229        /**
230         * Is in Normalform.
231         * @param Pp polynomial list.
232         * @return true if each Ap in Pp is in normalform with respect to Pp\{Ap}.
233         */
234        public boolean isNormalform(List<ColorPolynomial<C>> Pp) {
235            if (Pp == null || Pp.isEmpty()) {
236                return true;
237            }
238            ColorPolynomial<C> Ap;
239            List<ColorPolynomial<C>> P = new LinkedList<ColorPolynomial<C>>(Pp);
240            int s = P.size();
241            for (int i = 0; i < s; i++) {
242                Ap = P.remove(i);
243                if (!isNormalform(P, Ap)) {
244                    return false;
245                }
246                P.add(Ap);
247            }
248            return true;
249        }
250    
251    
252        /**
253         * Normalform.
254         * @param Ap polynomial.
255         * @param Pp polynomial list.
256         * @param cond condition for these polynomials.
257         * @return nf(Ap) with respect to Pp.
258         */
259        @SuppressWarnings("unchecked")
260        public ColorPolynomial<C> normalform(Condition<C> cond, List<ColorPolynomial<C>> Pp,
261                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,
396                GenPolynomial<GenPolynomial<C>> A) {
397            if (A == null || A.isZERO()) {
398                return cd;
399            }
400            if (cd == null) {
401                cd = new ArrayList<Condition<C>>();
402            }
403            if (cd.size() == 0) { // construct empty condition
404                RingFactory<GenPolynomial<C>> crfac = A.ring.coFac;
405                GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) crfac;
406                Condition<C> sc = new Condition<C>(cfac);
407                cd.add(sc);
408            }
409            GenPolynomial<GenPolynomial<C>> Ap;
410            GenPolynomial<GenPolynomial<C>> Bp;
411    
412            List<Condition<C>> C = new ArrayList<Condition<C>>( /* leer! */);
413            for (Condition<C> cond : cd) {
414                // System.out.println("caseDist: " + cond);
415                Condition<C> cz = cond;
416                Ap = A;
417                while (!Ap.isZERO()) {
418                    GenPolynomial<C> c = Ap.leadingBaseCoefficient();
419                    Bp = Ap.reductum();
420                    //System.out.println("to color: " + c);
421                    switch (cz.color(c)) {
422                    case GREEN:
423                        // System.out.println("color green: " + c);
424                        Ap = Bp;
425                        continue;
426                    case RED:
427                        // System.out.println("color red: " + c);
428                        C.add(cz);
429                        // wrong: return C;
430                        Ap = A.ring.getZERO();
431                        continue;
432                        // break;
433                    case WHITE:
434                    default:
435                        // System.out.println("color white: " + c);
436                        Condition<C> nc = cz.extendNonZero(c);
437                        if (nc != null) { // no contradiction
438                            if (!cz.equals(nc)) {
439                                C.add(nc);
440                            } else {
441                                cz = null;
442                                Ap = A.ring.getZERO();
443                                continue;
444                            }
445                        } else {
446                            System.out.println("this should not be printed " + c);
447                        }
448                        Condition<C> ez = cz.extendZero(c);
449                        if (ez != null) {
450                            cz = ez;
451                        } else { // contradiction
452                            cz = null;
453                            Ap = A.ring.getZERO();
454                            continue;
455                        }
456                        Ap = Bp;
457                    }
458                }
459                // System.out.println("cond cz: " + cz);
460                if (cz == null || cz.isContradictory() || C.contains(cz)) {
461                    // System.out.println("not added entry " + cz);
462                } else {
463                    C.add(cz);
464                }
465            }
466            // System.out.println("C = " + C);
467            return C;
468        }
469    
470    
471        /**
472         * Case distinction conditions of parametric polynomial list.
473         * @param A a parametric polynomial.
474         * @param cond a condition.
475         * @return list of case distinction conditions.
476         */
477        public List<Condition<C>> caseDistinction(Condition<C> cond,
478                GenPolynomial<GenPolynomial<C>> A) {
479            List<Condition<C>> cd = new ArrayList<Condition<C>>();
480            if (A == null || A.isZERO()) {
481                return cd;
482            }
483            cd.add(cond);
484            cd = caseDistinction(cd, A);
485            if (info) {
486                StringBuffer s = new StringBuffer("extending condition: " + cond + "\n");
487                s.append("case distinctions: [ \n");
488                for (Condition<C> c : cd) {
489                    s.append(c.toString() + "\n");
490                }
491                s.append("]");
492                logger.info(s.toString());
493            }
494            return cd;
495        }
496    
497    
498        /**
499         * Determine polynomial list.
500         * @param H polynomial list.
501         * @return new determined list of colored systems.
502         */
503        public List<ColoredSystem<C>> determine(List<GenPolynomial<GenPolynomial<C>>> H) {
504            if (H == null || H.size() == 0) {
505                List<ColoredSystem<C>> CS = new ArrayList<ColoredSystem<C>>();
506                return CS;
507            }
508            //System.out.println("of determine     = " + H);
509            Collections.reverse(H);
510            List<Condition<C>> cd = caseDistinction(H);
511            //System.out.println("case Distinction = " + cd);
512            //System.out.println("of determine     = " + H);
513            return determine(cd, H);
514        }
515    
516    
517        /**
518         * Determine polynomial list.
519         * @param H polynomial list.
520         * @param cd case distiction, a condition list.
521         * @return new determined list of colored systems.
522         */
523        public List<ColoredSystem<C>> determine(List<Condition<C>> cd,
524                List<GenPolynomial<GenPolynomial<C>>> H) {
525            List<ColoredSystem<C>> CS = new ArrayList<ColoredSystem<C>>();
526            if (H == null || H.size() == 0) {
527                return CS;
528            }
529            for (Condition<C> cond : cd) {
530                logger.info("determine wrt cond = " + cond);
531                if (cond.zero.isONE()) { // should not happen
532                    System.out.println("ideal is one = " + cond.zero);
533                    // continue; // can treat all coeffs as green
534                }
535                // if ( cond.isEmpty() ) { // do not use this code
536                // continue; // can skip condition (?)
537                // }
538                List<ColorPolynomial<C>> S = cond.determine(H);
539                ColoredSystem<C> cs = new ColoredSystem<C>(cond, S);
540                CS.add(cs);
541            }
542            return CS;
543        }
544    
545    }