001/*
002 * $Id$
003 */
004
005package edu.jas.application;
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.gb.GroebnerBase;
016import edu.jas.gb.SolvableGroebnerBase;
017import edu.jas.gbufd.GBFactory;
018import edu.jas.gbufd.SGBFactory;
019import edu.jas.poly.ExpVector;
020import edu.jas.poly.GenPolynomial;
021import edu.jas.poly.GenPolynomialRing;
022import edu.jas.poly.GenSolvablePolynomial;
023import edu.jas.poly.GenSolvablePolynomialRing;
024import edu.jas.poly.PolynomialList;
025import edu.jas.structure.GcdRingElem;
026import edu.jas.structure.RingFactory;
027import edu.jas.ufd.SquarefreeAbstract;
028import edu.jas.ufd.SquarefreeFactory;
029
030
031/**
032 * Comprehensive Groebner Base sequential algorithm. Implements faithful
033 * comprehensive Groebner bases via Groebner systems and CGB test.
034 * @param <C> coefficient type
035 * @author Heinz Kredel
036 */
037
038public class ComprehensiveGroebnerBaseSeq<C extends GcdRingElem<C>>
039/* extends GroebnerBaseAbstract<GenPolynomial<C>> */{
040
041
042    private static final Logger logger = LogManager.getLogger(ComprehensiveGroebnerBaseSeq.class);
043
044
045    private static final boolean debug = logger.isDebugEnabled();
046
047
048    /**
049     * Squarefree for coefficient content and primitive parts.
050     */
051    protected final SquarefreeAbstract<C> engine;
052
053
054    /*
055     * Flag if gcd engine should be used.
056     */
057    //private final boolean notFaithfull = false;
058
059
060    /**
061     * Comprehensive reduction engine.
062     */
063    protected final CReductionSeq<C> cred;
064
065
066    /**
067     * Polynomial coefficient ring factory.
068     */
069    protected final RingFactory<C> cofac;
070
071
072    /**
073     * Constructor.
074     * @param rf base coefficient ring factory.
075     */
076    public ComprehensiveGroebnerBaseSeq(RingFactory<C> rf) {
077        this(new CReductionSeq<C>(rf), rf);
078    }
079
080
081    /**
082     * Constructor.
083     * @param red C-pseudo-Reduction engine
084     * @param rf base coefficient ring factory.
085     */
086    @SuppressWarnings("unchecked")
087    public ComprehensiveGroebnerBaseSeq(CReductionSeq<C> red, RingFactory<C> rf) {
088        // super(null); // red not possible since type of type
089        cred = red;
090        cofac = rf;
091        // selection for C but used for R:
092        //engine e = GCDFactory.<C> getImplementation(cofac);
093        engine = SquarefreeFactory.<C> getImplementation(rf);
094    }
095
096
097    /**
098     * Comprehensive-Groebner base test.
099     * @param F polynomial list.
100     * @return true, if F is a Comprehensive-Groebner base, else false.
101     */
102    // @Override
103    public boolean isGB(List<GenPolynomial<GenPolynomial<C>>> F) {
104        return isGB(0, F);
105    }
106
107
108    /**
109     * Comprehensive-Groebner base test.
110     * @param modv module variable number.
111     * @param F polynomial list.
112     * @return true, if F is a Comprehensive-Groebner base, else false.
113     */
114    // @Override
115    public boolean isGB(int modv, List<GenPolynomial<GenPolynomial<C>>> F) {
116        // return isGBcol( modv, F );
117        return isGBsubst(modv, F);
118    }
119
120
121    /**
122     * Comprehensive-Groebner base test using colored systems.
123     * @param F polynomial list.
124     * @return true, if F is a Comprehensive-Groebner base, else false.
125     */
126    // @Override
127    public boolean isGBcol(List<GenPolynomial<GenPolynomial<C>>> F) {
128        return isGBcol(0, F);
129    }
130
131
132    /**
133     * Comprehensive-Groebner base test using colored systems.
134     * @param modv module variable number.
135     * @param F polynomial list.
136     * @return true, if F is a Comprehensive-Groebner base, else false.
137     */
138    // @Override
139    public boolean isGBcol(int modv, List<GenPolynomial<GenPolynomial<C>>> F) {
140        if (F == null || F.size() == 0) {
141            return true;
142        }
143        List<ColoredSystem<C>> CS = cred.determine(F);
144        return isGBsys(modv, CS);
145    }
146
147
148    /**
149     * Comprehensive-Groebner system test.
150     * @param CS list of colored systems.
151     * @return true, if CS is a Comprehensive-Groebner system, else false.
152     */
153    // @Override
154    public boolean isGBsys(List<ColoredSystem<C>> CS) {
155        return isGBsys(0, CS);
156    }
157
158
159    /**
160     * Comprehensive-Groebner system test.
161     * @param modv module variable number, unused.
162     * @param CS list of colored systems.
163     * @return true, if CS is a Comprehensive-Groebner system, else false.
164     */
165    // @Override
166    public boolean isGBsys(int modv, List<ColoredSystem<C>> CS) {
167        if (CS == null || CS.size() == 0) {
168            return true;
169        }
170        if (modv != 0) {
171            throw new IllegalArgumentException("modv !0 not supported.");
172        }
173        ColorPolynomial<C> p, q, h, hp;
174        for (ColoredSystem<C> cs : CS) {
175            if (debug) {
176                if (!cs.isDetermined()) {
177                    System.out.println("not determined, cs = " + cs);
178                    return false;
179                }
180                if (!cs.checkInvariant()) {
181                    System.out.println("not invariant, cs = " + cs);
182                    return false;
183                }
184            }
185            Condition<C> cond = cs.condition;
186            List<ColorPolynomial<C>> S = cs.list;
187            int k = S.size();
188            for (int j = 0; j < k; j++) {
189                p = S.get(j);
190                for (int l = j + 1; l < k; l++) {
191                    q = S.get(l);
192                    h = cred.SPolynomial(p, q);
193                    // System.out.println("spol(a,b) = " + h);
194                    h = cred.normalform(cond, S, h);
195                    // System.out.println("NF(spol(a,b)) = " + h);
196                    if (debug) {
197                        if (!cred.isNormalform(S, h)) {
198                            System.out.println("not normalform, h = " + h);
199                            System.out.println("cs = " + cs);
200                            return false;
201                        }
202                    }
203                    if (!h.isZERO()) {
204                        hp = cond.reDetermine(h);
205                        if (!hp.isZERO()) {
206                            System.out.println("p = " + p);
207                            System.out.println("q = " + q);
208                            System.out.println("not zero:   NF(spol(p,q))  = " + h);
209                            System.out.println("redetermine(NF(spol(p,q))) = " + hp);
210                            System.out.println("cs = " + cs);
211                            return false;
212                        }
213                    }
214                }
215            }
216        }
217        return true;
218    }
219
220
221    /**
222     * Comprehensive-Groebner base test using substitution.
223     * @param F polynomial list.
224     * @return true, if F is a Comprehensive-Groebner base, else false.
225     */
226    // @Override
227    public boolean isGBsubst(List<GenPolynomial<GenPolynomial<C>>> F) {
228        return isGBsubst(0, F);
229    }
230
231
232    /**
233     * Comprehensive-Groebner base test using substitution.
234     * @param modv module variable number, unused.
235     * @param F polynomial list.
236     * @return true, if F is a Comprehensive-Groebner base, else false.
237     */
238    // @Override
239    public boolean isGBsubst(int modv, List<GenPolynomial<GenPolynomial<C>>> F) {
240        if (F == null || F.isEmpty()) {
241            return true;
242        }
243        if (modv != 0) {
244            throw new IllegalArgumentException("modv !0 not supported.");
245        }
246        GenPolynomial<GenPolynomial<C>> f = F.get(0); // assert non Zero
247        GenPolynomialRing<GenPolynomial<C>> cf = f.ring;
248
249        List<ColoredSystem<C>> CS = cred.determine(F);
250        if (logger.isDebugEnabled()) {
251            logger.info("determined polynomials =\n{}", CS);
252        }
253        // substitute zero conditions into parameter coefficients and test
254        for (ColoredSystem<C> cs : CS) {
255            Ideal<C> id = cs.condition.zero;
256            ResidueRing<C> r = new ResidueRing<C>(id);
257            // if (!r.isField()) {
258            //     System.out.println("condition zero ideal, no field = " + r.toScript());
259            //     // no return true;
260            // }
261            //GroebnerBase<Residue<C>> bb = new GroebnerBasePseudoSeq<Residue<C>>(r);
262            List<GenPolynomial<Residue<C>>> list;
263            boolean t;
264            if (cf instanceof GenSolvablePolynomialRing) {
265                GenSolvablePolynomialRing<Residue<C>> rf = new GenSolvablePolynomialRing<Residue<C>>(r, cf);
266                List<GenSolvablePolynomial<GenPolynomial<C>>> rel = ((GenSolvablePolynomialRing<GenPolynomial<C>>) cf).table
267                                .relationList();
268                List<GenPolynomial<Residue<C>>> relres = PolyUtilApp.<C> toResidue(rf,
269                                PolynomialList.<GenPolynomial<C>> castToList(rel));
270                rf.addRelations(relres);
271                //System.out.println("rf = " + rf.toScript());
272                list = PolyUtilApp.<C> toResidue(rf, F);
273                SolvableGroebnerBase<Residue<C>> bb = SGBFactory.getImplementation(r);
274                t = bb.isLeftGB(PolynomialList.<Residue<C>> castToSolvableList(list));
275            } else {
276                GenPolynomialRing<Residue<C>> rf = new GenPolynomialRing<Residue<C>>(r, cf);
277                //System.out.println("rf = " + rf.toScript());
278                list = PolyUtilApp.<C> toResidue(rf, F);
279                GroebnerBase<Residue<C>> bb = GBFactory.getImplementation(r);
280                t = bb.isGB(list);
281            }
282            if (!t) {
283                System.out.println("test condition = " + cs.condition);
284                System.out.println("test ideal     = " + id.toScript());
285                System.out.println("test F         = " + F);
286                System.out.println("no GB for residue coefficients = " + list);
287                return false;
288            }
289        }
290
291        // substitute random ideal into parameter coefficients and test
292        GenPolynomialRing<C> ccf = (GenPolynomialRing<C>) cf.coFac;
293        int nv = ccf.nvar - 2;
294        if (nv < 1) {
295            nv = 1;
296        }
297        List<GenPolynomial<C>> il = new ArrayList<GenPolynomial<C>>();
298        int i = 0;
299        //int j = 1;
300        while (i < nv) {
301            //j++;
302            GenPolynomial<C> p = ccf.random(3, 2, 3, 0.43f).monic(); //j + 1);
303            //System.out.println("p = " + p);
304            if (p.isConstant()) {
305                continue;
306            }
307            if (p.isZERO()) {
308                continue;
309            }
310            if (p.length() <= 1) {
311                p = p.sum(ccf.getONE());
312            }
313            p = engine.squarefreePart(p);
314            il.add(p);
315            i++;
316        }
317        logger.info("random ideal = {}", il);
318        Ideal<C> id = new Ideal<C>(ccf, il);
319        id.doGB();
320        ResidueRing<C> r = new ResidueRing<C>(id);
321        if (!r.isField()) {
322            //System.out.println("random ideal, no field = " + r.toScript());
323            return true;
324        }
325        //GroebnerBase<Residue<C>> bb = new GroebnerBasePseudoSeq<Residue<C>>(r);
326        List<GenPolynomial<Residue<C>>> list;
327        boolean t;
328        if (cf instanceof GenSolvablePolynomialRing) {
329            GenSolvablePolynomialRing<Residue<C>> rf = new GenSolvablePolynomialRing<Residue<C>>(r, cf);
330            List<GenSolvablePolynomial<GenPolynomial<C>>> rel = ((GenSolvablePolynomialRing<GenPolynomial<C>>) cf).table
331                            .relationList();
332            List<GenPolynomial<Residue<C>>> relres = PolyUtilApp.<C> toResidue(rf,
333                            PolynomialList.<GenPolynomial<C>> castToList(rel));
334            rf.addRelations(relres);
335            //System.out.println("rf = " + rf.toScript());
336            list = PolyUtilApp.<C> toResidue(rf, F);
337            SolvableGroebnerBase<Residue<C>> bb = SGBFactory.getImplementation(r);
338            t = bb.isLeftGB(PolynomialList.<Residue<C>> castToSolvableList(list));
339        } else {
340            GenPolynomialRing<Residue<C>> rf = new GenPolynomialRing<Residue<C>>(r, cf);
341            //System.out.println("rf = " + rf.toScript());
342            list = PolyUtilApp.<C> toResidue(rf, F);
343            GroebnerBase<Residue<C>> bb = GBFactory.getImplementation(r);
344            t = bb.isGB(list);
345        }
346        if (!t) {
347            System.out.println("test random ideal = " + id.toScript());
348            System.out.println("no GB for residue coefficients = " + list);
349            return false;
350        }
351        return true;
352    }
353
354
355    /**
356     * Comprehensive-Groebner system test.
357     * @param F Groebner system.
358     * @return true, if F is a Comprehensive-Groebner system, else false.
359     */
360    // @Override
361    public boolean isGBsys(GroebnerSystem<C> F) {
362        return isGBsys(0, F.list);
363    }
364
365
366    /**
367     * Comprehensive-Groebner base test.
368     * @param F Groebner system.
369     * @return true, if F is a Comprehensive-Groebner base, else false.
370     */
371    // @Override
372    public boolean isCGB(GroebnerSystem<C> F) {
373        return isGB(F.getCGB());
374    }
375
376
377    /**
378     * Comprehensive-Groebner system and base test.
379     * @param F Groebner system.
380     * @return true, if F is a Comprehensive-Groebner system and base, else
381     *         false.
382     */
383    // @Override
384    public boolean isGB(GroebnerSystem<C> F) {
385        return isGBsys(0, F.list) && isGB(F.getCGB());
386    }
387
388
389    /**
390     * Comprehensive Groebner base system using pairlist class.
391     * @param F polynomial list.
392     * @return GBsys(F) a Comprehensive Groebner system of F.
393     */
394    // @Override
395    // @SuppressWarnings("unchecked")
396    public GroebnerSystem<C> GBsys(List<GenPolynomial<GenPolynomial<C>>> F) {
397        if (F == null) {
398            return null;
399        }
400        List<ColoredSystem<C>> CSp = new ArrayList<ColoredSystem<C>>();
401        if (F.size() == 0) {
402            return new GroebnerSystem<C>(CSp);
403        }
404        // extract coefficient factory
405        GenPolynomial<GenPolynomial<C>> f = F.get(0);
406        GenPolynomialRing<GenPolynomial<C>> fac = f.ring;
407        // determine polynomials
408        List<ColoredSystem<C>> CS = cred.determine(F);
409        // System.out.println("CS = " + CS);
410        // CS.remove(0); // empty colored system
411        logger.info("determined polynomials =\n{}", CS);
412
413        // setup pair lists
414        List<ColoredSystem<C>> CSs = new ArrayList<ColoredSystem<C>>();
415        ColoredSystem<C> css;
416        for (ColoredSystem<C> cs : CS) {
417            OrderedCPairlist<C> pairlist = new OrderedCPairlist<C>(fac);
418            for (ColorPolynomial<C> p : cs.list) {
419                // System.out.println("p = " + p);
420                pairlist.put(p);
421            }
422            css = new ColoredSystem<C>(cs.condition, cs.list, pairlist);
423            CSs.add(css);
424        }
425
426        // main loop
427        List<ColoredSystem<C>> CSb = new ArrayList<ColoredSystem<C>>();
428        List<ColoredSystem<C>> ncs;
429        List<ColoredSystem<C>> CSh; //, CSbh;
430        ColoredSystem<C> cs;
431        List<ColorPolynomial<C>> G;
432        OrderedCPairlist<C> pairlist;
433        Condition<C> cond;
434        int si = 0;
435        while (CSs.size() > 0) {
436            cs = CSs.get(0); // remove(0);
437            si++;
438            logger.info("popped GBsys number    {} with condition = {}", si, cs.condition);
439            logger.info("popped GBsys (remaining {}) with pairlist  = {}", (CSs.size() - 1), cs.pairlist);
440            if (!cs.isDetermined()) {
441                cs = cs.reDetermine();
442            }
443            pairlist = cs.pairlist;
444            G = cs.list;
445            cond = cs.condition;
446            // logger.info("{}", pairlist);
447
448            CPair<C> pair;
449            ColorPolynomial<C> pi;
450            ColorPolynomial<C> pj;
451            ColorPolynomial<C> S;
452            // GenPolynomial<GenPolynomial<C>> H;
453            ColorPolynomial<C> H;
454            while (pairlist.hasNext()) {
455                pair = pairlist.removeNext();
456                if (pair == null)
457                    continue;
458
459                pi = pair.pi;
460                pj = pair.pj;
461                if (debug) {
462                    logger.info("pi = {}, pj = {}", pi, pj);
463                }
464
465                S = cred.SPolynomial(pi, pj);
466                if (S.isZERO()) {
467                    pair.setZero();
468                    continue;
469                }
470                if (debug) {
471                    // logger.info("ht(S) = {}", S.leadingExpVector() );
472                    logger.info("S = {}", S);
473                }
474
475                H = cred.normalform(cond, G, S);
476                if (H.isZERO()) {
477                    pair.setZero();
478                    continue;
479                }
480                if (debug) {
481                    logger.info("ht(H) = {}", H.leadingExpVector());
482                }
483
484                H = H.abs();
485                if (debug) {
486                    logger.debug("H = {}", H);
487                }
488                logger.info("H = {}", H);
489                if (!H.isZERO()) {
490                    //CSh = new ArrayList<ColoredSystem<C>>();
491                    ncs = determineAddPairs(cs, H);
492                    if (ncs.size() == 0) {
493                        continue;
494                    }
495                    cs = ncs.remove(0); // remove other?
496                    pairlist = cs.pairlist;
497                    G = cs.list;
498                    cond = cs.condition;
499                    logger.info("replaced main branch = {}", cond);
500                    logger.info("#new systems       = {}", ncs.size());
501                    int yi = CSs.size();
502                    for (ColoredSystem<C> x : ncs) {
503                        if (!x.isDetermined()) {
504                            x = x.reDetermine();
505                        }
506                        CSs = x.addToList(CSs);
507                    }
508                    logger.info("#new systems added = {}", (CSs.size() - yi));
509                }
510            }
511            // all s-pols reduce to zero in this branch
512            if (!cs.isDetermined()) {
513                cs = cs.reDetermine();
514            }
515            CSb.add(cs);
516            CSs.remove(0);
517            logger.info("done with = {}", cs.condition);
518        }
519        // all branches done
520        CSh = new ArrayList<ColoredSystem<C>>();
521        for (ColoredSystem<C> x : CSb) {
522            // System.out.println("G = " + x.list );
523            if (!x.isDetermined()) {
524                x = x.reDetermine();
525            }
526            cs = minimalGB(x);
527            // System.out.println("min(G) = " + cs.list );
528            if (!cs.isDetermined()) {
529                cs = cs.reDetermine();
530            }
531            // cs = new ColoredSystem<C>( x.condition, G, x.pairlist );
532            CSh.add(cs);
533            logger.info("#sequential done = {}", x.condition);
534            logger.info("{}", x.pairlist);
535        }
536        CSb = new ArrayList<ColoredSystem<C>>(CSh);
537        return new GroebnerSystem<C>(CSb);
538    }
539
540
541    /**
542     * Determine polynomial relative to a condition of a colored system and add
543     * pairs.
544     * @param cs a colored system.
545     * @param A color polynomial.
546     * @return list of colored systems, the conditions extending the condition
547     *         of cs.
548     */
549    public List<ColoredSystem<C>> determineAddPairs(ColoredSystem<C> cs, ColorPolynomial<C> A) {
550        List<ColoredSystem<C>> NCS = new ArrayList<ColoredSystem<C>>();
551        if (A == null || A.isZERO()) {
552            // NCS.add( cs );
553            return NCS;
554        }
555        List<ColorPolynomial<C>> S = cs.list;
556        Condition<C> cond = cs.condition; // .clone(); done in Condition
557        // itself
558        OrderedCPairlist<C> pl = cs.pairlist;
559
560        List<ColorPolynomial<C>> Sp;
561        ColorPolynomial<C> nz;
562        ColoredSystem<C> NS;
563        // if ( A.isDetermined() ) { ... } // dont use this
564        // System.out.println("to determine = " + A);
565        GenPolynomial<GenPolynomial<C>> Ap = A.getPolynomial();
566        List<Condition<C>> cd = cred.caseDistinction(cond, Ap);
567        logger.info("# cases = {}", cd.size());
568        for (Condition<C> cnd : cd) {
569            //nz = cnd.determine(Ap);
570            nz = cnd.reDetermine(A);
571            if (nz.isZERO()) {
572                logger.info("zero determined nz = {}", nz);
573                Sp = new ArrayList<ColorPolynomial<C>>(S);
574                OrderedCPairlist<C> PL = pl.copy();
575                NS = new ColoredSystem<C>(cnd, Sp, PL);
576                try {
577                    if (!NS.isDetermined()) {
578                        NS = NS.reDetermine();
579                    }
580                } catch (RuntimeException e) {
581                    System.out.println("Contradiction in NS_0 = " + NS);
582                    //e.printStackTrace();
583                    continue;
584                }
585                NCS = NS.addToList(NCS);
586                continue;
587            }
588            if (S.contains(nz)) {
589                System.out.println("*** S.contains(nz) ***");
590                continue;
591            }
592            logger.info("new determined nz = {}", nz);
593            Sp = new ArrayList<ColorPolynomial<C>>(S);
594            Sp.add(nz);
595            OrderedCPairlist<C> PL = pl.copy();
596            PL.put(nz);
597            NS = new ColoredSystem<C>(cnd, Sp, PL);
598            try {
599                if (!NS.isDetermined()) {
600                    NS = NS.reDetermine();
601                }
602            } catch (RuntimeException e) {
603                System.out.println("Contradiction in NS = " + NS);
604                //e.printStackTrace();
605                continue;
606            }
607            NCS = NS.addToList(NCS);
608        }
609        // System.out.println("new determination = " + NCS);
610        return NCS;
611    }
612
613
614    /**
615     * Comprehensive Groebner base via Groebner system.
616     * @param F polynomial list.
617     * @return GB(F) a Comprehensive Groebner base of F.
618     */
619    // @Override
620    // @SuppressWarnings("unchecked")
621    public List<GenPolynomial<GenPolynomial<C>>> GB(List<GenPolynomial<GenPolynomial<C>>> F) {
622        if (F == null) {
623            return F;
624        }
625        // compute Groebner system
626        GroebnerSystem<C> gs = GBsys(F);
627        // System.out.println("\n\nGBsys = " + gs);
628        return gs.getCGB();
629    }
630
631
632    /**
633     * Minimal ordered Groebner basis.
634     * @param cs colored system.
635     * @return a reduced Groebner base of Gp.
636     */
637    // @Override
638    public ColoredSystem<C> minimalGB(ColoredSystem<C> cs) {
639        // List<ColorPolynomial<C>> Gp ) {
640        if (cs == null || cs.list == null || cs.list.size() <= 1) {
641            return cs;
642        }
643        // remove zero polynomials
644        List<ColorPolynomial<C>> G = new ArrayList<ColorPolynomial<C>>(cs.list.size());
645        for (ColorPolynomial<C> a : cs.list) {
646            if (a != null && !a.isZERO()) { // always true in GB()
647                // already positive a = a.abs();
648                G.add(a);
649            }
650        }
651        if (G.size() <= 1) {
652            return new ColoredSystem<C>(cs.condition, G, cs.pairlist);
653        }
654        // System.out.println("G check " + G);
655        // remove top reducible polynomials
656        Condition<C> cond = cs.condition;
657        ColorPolynomial<C> a, b;
658        List<ColorPolynomial<C>> F;
659        F = new ArrayList<ColorPolynomial<C>>(G.size());
660        while (G.size() > 0) {
661            a = G.remove(0);
662            b = a;
663            // System.out.println("check " + b);
664            //if (false) {
665            //    if (a.red.leadingBaseCoefficient().isConstant()) { // dont drop
666            //        // these
667            //        F.add(a);
668            //        continue;
669            //    }
670            //}
671            if (cred.isTopReducible(G, a) || cred.isTopReducible(F, a)) {
672                // drop polynomial
673                if (debug) {
674                    // System.out.println("trying to drop " + a);
675                    List<ColorPolynomial<C>> ff;
676                    ff = new ArrayList<ColorPolynomial<C>>(G);
677                    ff.addAll(F);
678                    a = cred.normalform(cond, ff, a);
679                    try {
680                        a = cond.reDetermine(a);
681                    } catch (RuntimeException ignored) {
682                    }
683                    if (!a.isZERO()) {
684                        logger.error("nf(a) != 0 {}, {}", b, a);
685                        F.add(b);
686                    }
687                }
688            } else {
689                F.add(a);
690            }
691        }
692        G = F;
693        if (G.size() <= 1) {
694            return new ColoredSystem<C>(cs.condition, G, cs.pairlist);
695        }
696        Collections.reverse(G); // important for lex GB
697        // reduce remaining polynomials
698        int len = G.size();
699        int i = 0;
700        while (i < len) {
701            a = G.remove(0);
702            b = a;
703            ExpVector e = a.red.leadingExpVector();
704            // System.out.println("reducing " + a);
705            a = cred.normalform(cond, G, a); // unchanged by top reduction
706            // System.out.println("reduced " + a);
707            try {
708                a = cond.reDetermine(a);
709            } catch (RuntimeException ignored) {
710            }
711            ExpVector f = a.red.leadingExpVector();
712            // a = ##engine.basePrimitivePart(a); //a.monic(); was not required
713            // a = a.abs();
714            // a = red.normalform( F, a );
715            if (e.equals(f)) {
716                G.add(a); // adds as last
717            } else { // should not happen
718                if (debug) {
719                    logger.error("nf(a) not determined {}, {}", b, a);
720                }
721                G.add(b); // adds as last
722            }
723            i++;
724        }
725        return new ColoredSystem<C>(cs.condition, G, cs.pairlist);
726    }
727
728}