001/*
002 * $Id$
003 */
004
005package edu.jas.gb;
006
007
008import java.util.ArrayList;
009import java.util.List;
010import java.util.ListIterator;
011
012import org.apache.logging.log4j.Logger;
013import org.apache.logging.log4j.LogManager; 
014
015import edu.jas.poly.ExpVector;
016import edu.jas.poly.GenPolynomial;
017import edu.jas.poly.GenSolvablePolynomial;
018import edu.jas.poly.GenSolvablePolynomialRing;
019import edu.jas.poly.QLRSolvablePolynomialRing;
020import edu.jas.poly.PolyUtil;
021import edu.jas.poly.PolynomialList;
022import edu.jas.structure.RingElem;
023
024
025/**
026 * Solvable Groebner bases sequential algorithms. Implements common left, right
027 * and twosided Groebner bases and left, right and twosided GB tests.
028 * @param <C> coefficient type
029 * @author Heinz Kredel
030 */
031
032public class SolvableGroebnerBaseSeq<C extends RingElem<C>> extends SolvableGroebnerBaseAbstract<C> {
033
034
035    private static final Logger logger = LogManager.getLogger(SolvableGroebnerBaseSeq.class);
036
037
038    private static final boolean debug = logger.isDebugEnabled();
039
040
041    /**
042     * Constructor.
043     */
044    public SolvableGroebnerBaseSeq() {
045        super();
046    }
047
048
049    /**
050     * Constructor.
051     * @param sred Solvable reduction engine
052     */
053    public SolvableGroebnerBaseSeq(SolvableReduction<C> sred) {
054        super(sred);
055    }
056
057
058    /**
059     * Constructor.
060     * @param pl pair selection strategy
061     */
062    public SolvableGroebnerBaseSeq(PairList<C> pl) {
063        super(pl);
064    }
065
066
067    /**
068     * Constructor.
069     * @param sred Solvable reduction engine
070     * @param pl pair selection strategy
071     */
072    public SolvableGroebnerBaseSeq(SolvableReduction<C> sred, PairList<C> pl) {
073        super(sred, pl);
074    }
075
076
077    /**
078     * Left Groebner base using pairlist class.
079     * @param modv number of module variables.
080     * @param F solvable polynomial list.
081     * @return leftGB(F) a left Groebner base of F.
082     */
083    @SuppressWarnings("unchecked")
084    public List<GenSolvablePolynomial<C>> leftGB(int modv, List<GenSolvablePolynomial<C>> F) {
085        List<GenSolvablePolynomial<C>> G = normalizeZerosOnes(F);
086        G = PolynomialList.castToSolvableList(PolyUtil.<C> monic(PolynomialList.castToList(G)));
087        if (G.size() <= 1) {
088            return G;
089        }
090        GenSolvablePolynomialRing<C> ring = G.get(0).ring;
091        if (!ring.coFac.isField() && ring.coFac.isCommutative()) {
092            throw new IllegalArgumentException("coefficients not from a field: " + ring.coFac.toScript());
093        }
094        PairList<C> pairlist = strategy.create(modv, ring);
095        pairlist.put(PolynomialList.castToList(G));
096        logger.info("start {}", pairlist);
097
098        GenSolvablePolynomial<C> pi, pj, S, H;
099        Pair<C> pair;
100        while (pairlist.hasNext()) {
101            pair = pairlist.removeNext();
102            if (pair == null) {
103                continue;
104            }
105            pi = (GenSolvablePolynomial<C>) pair.pi;
106            pj = (GenSolvablePolynomial<C>) pair.pj;
107            if (debug) {
108                logger.info("pi    = {}", pi.leadingExpVector());
109                logger.info("pj    = {}", pj.leadingExpVector());
110            }
111
112            S = sred.leftSPolynomial(pi, pj);
113            if (S.isZERO()) {
114                pair.setZero();
115                continue;
116            }
117            if (debug) {
118                logger.info("ht(S) = {}", S.leadingExpVector());
119            }
120
121            H = sred.leftNormalform(G, S);
122            if (H.isZERO()) {
123                pair.setZero();
124                continue;
125            }
126            if (debug) {
127                logger.info("ht(H) = {}", H.leadingExpVector());
128                //logger.info("ht(H) = {}, lc(H) = {}", H.leadingExpVector(), H.leadingBaseCoefficient().toScript());
129            }
130
131            H = H.monic();
132            if (H.isONE()) {
133                G.clear();
134                G.add(H);
135                return G; // since no threads are activated
136            }
137            if (debug) {
138                // logger.info("H = {}", H);
139                logger.info("#monic(H) = {}", H.length());
140            }
141            if (H.length() > 0) {
142                //l++;
143                G.add(H);
144                pairlist.put(H);
145            }
146        }
147        logger.debug("#sequential list = {}", G.size());
148        G = leftMinimalGB(G);
149        logger.info("end {}", pairlist);
150        return G;
151    }
152
153
154    /**
155     * Solvable Extended Groebner base using critical pair class.
156     * @param modv module variable number.
157     * @param F solvable polynomial list.
158     * @return a container for an extended left Groebner base of F.
159     */
160    @Override
161    @SuppressWarnings("unchecked")
162    public SolvableExtendedGB<C> extLeftGB(int modv, List<GenSolvablePolynomial<C>> F) {
163        if (F == null || F.isEmpty()) {
164            throw new IllegalArgumentException("null or empty F not allowed");
165        }
166        List<GenSolvablePolynomial<C>> G = new ArrayList<GenSolvablePolynomial<C>>();
167        List<List<GenSolvablePolynomial<C>>> F2G = new ArrayList<List<GenSolvablePolynomial<C>>>();
168        List<List<GenSolvablePolynomial<C>>> G2F = new ArrayList<List<GenSolvablePolynomial<C>>>();
169        PairList<C> pairlist = null;
170        boolean oneInGB = false;
171        int len = F.size();
172
173        List<GenSolvablePolynomial<C>> row = null;
174        List<GenSolvablePolynomial<C>> rows = null;
175        List<GenSolvablePolynomial<C>> rowh = null;
176        GenSolvablePolynomialRing<C> ring = null;
177        GenSolvablePolynomial<C> p, H;
178
179        int nzlen = 0;
180        for (GenSolvablePolynomial<C> f : F) {
181            if (f.length() > 0) {
182                nzlen++;
183            }
184            if (ring == null) {
185                ring = f.ring;
186            }
187        }
188        GenSolvablePolynomial<C> mone = ring.getONE(); //.negate();
189        int k = 0;
190        ListIterator<GenSolvablePolynomial<C>> it = F.listIterator();
191        while (it.hasNext()) {
192            p = it.next();
193            if (p.length() > 0) {
194                row = PolynomialList.<C> castToSolvableList( blas.genVector(nzlen, null) );
195                //C c = p.leadingBaseCoefficient();
196                //c = c.inverse();
197                //p = p.multiply( c );
198                row.set(k, mone); //.multiply(c) );
199                k++;
200                if (p.isUnit()) {
201                    G.clear();
202                    G.add(p);
203                    G2F.clear();
204                    G2F.add(row);
205                    oneInGB = true;
206                    break;
207                }
208                G.add(p);
209                G2F.add(row);
210                if (pairlist == null) {
211                    //pairlist = new CriticalPairList<C>( modv, p.ring );
212                    pairlist = strategy.create(modv, p.ring);
213                }
214                // putOne not required
215                pairlist.put(p);
216            } else {
217                len--;
218            }
219        }
220        SolvableExtendedGB<C> exgb;
221        if (len <= 1 || oneInGB) {
222            // adjust F2G
223            for (GenSolvablePolynomial<C> f : F) {
224                row = PolynomialList.<C> castToSolvableList( blas.genVector(G.size(), null) );
225                H = sred.leftNormalform(row, G, f);
226                if (!H.isZERO()) {
227                    logger.error("nonzero H = {}", H);
228                }
229                F2G.add(row);
230            }
231            exgb = new SolvableExtendedGB<C>(F, G, F2G, G2F);
232            //System.out.println("exgb 1 = " + exgb);
233            return exgb;
234        }
235        logger.info("start {}", pairlist);
236
237        Pair<C> pair;
238        int i, j;
239        GenSolvablePolynomial<C> pi, pj, S, x, y;
240        //GenPolynomial<C> z;
241        while (pairlist.hasNext() && !oneInGB) {
242            pair = pairlist.removeNext();
243            if (pair == null) {
244                //pairlist.update(); // ?
245                continue;
246            }
247            i = pair.i;
248            j = pair.j;
249            pi = (GenSolvablePolynomial<C>) pair.pi;
250            pj = (GenSolvablePolynomial<C>) pair.pj;
251            if (debug) {
252                logger.info("i, pi    = {}, {}", i, pi);
253                logger.info("j, pj    = {}, {}", j, pj);
254            }
255
256            rows = PolynomialList.<C> castToSolvableList( blas.genVector(G.size(), null) );
257            S = sred.leftSPolynomial(rows, i, pi, j, pj);
258            if (debug) {
259                logger.debug("is reduction S = {}", sred.isLeftReductionNF(rows, G, ring.getZERO(), S));
260            }
261            if (S.isZERO()) {
262                pair.setZero();
263                //pairlist.update( pair, S );
264                // do not add to G2F
265                continue;
266            }
267            if (debug) {
268                logger.debug("ht(S) = {}", S.leadingExpVector());
269            }
270
271            rowh = PolynomialList.<C> castToSolvableList( blas.genVector(G.size(), null) );
272            H = sred.leftNormalform(rowh, G, S);
273            if (debug) {
274                //System.out.println("H = " + H);
275                logger.debug("is reduction H = {}", sred.isLeftReductionNF(rowh, G, S, H));
276            }
277            if (H.isZERO()) {
278                pair.setZero();
279                //pairlist.update( pair, H );
280                // do not add to G2F
281                continue;
282            }
283            if (debug) {
284                logger.debug("ht(H) = {}", H.leadingExpVector());
285            }
286
287            row = PolynomialList.<C>castToSolvableList(blas.vectorCombineOld(PolynomialList.<C>castToList(rows),PolynomialList.<C>castToList(rowh)));
288            // if (debug) {
289            //     logger.debug("is reduction 0+sum(row,G) == H : "
290            //                     + sred.isLeftReductionNF(row, G, H, ring.getZERO()));
291            // }
292
293            //  H = H.monic();
294            C c = H.leadingBaseCoefficient();
295            c = c.inverse();
296            H = H.multiply(c);
297            // 1*c*row, leads to wrong method dispatch:
298            row = PolynomialList.<C> castToSolvableList(blas.scalarProduct(mone.multiply(c),
299                            PolynomialList.<C> castToList(row)));
300            row.set(G.size(), mone);
301            if (H.isONE()) {
302                // pairlist.record( pair, H );
303                // G.clear(); 
304                G.add(H);
305                G2F.add(row);
306                oneInGB = true;
307                break;
308            }
309            if (debug) {
310                logger.debug("H = {}", H);
311            }
312            G.add(H);
313            //pairlist.update( pair, H );
314            pairlist.put(H);
315            G2F.add(row);
316        }
317        if (debug) {
318            exgb = new SolvableExtendedGB<C>(F, G, F2G, G2F);
319            logger.info("exgb unnorm = {}", exgb);
320        }
321        G2F = normalizeMatrix(F.size(), G2F);
322        if (debug) {
323            exgb = new SolvableExtendedGB<C>(F, G, F2G, G2F);
324            logger.info("exgb nonmin = {}", exgb);
325            boolean t2 = isLeftReductionMatrix(exgb);
326            logger.debug("exgb t2 = {}", t2);
327        }
328        exgb = minimalSolvableExtendedGB(F.size(), G, G2F);
329        G = exgb.G;
330        G2F = exgb.G2F;
331        logger.debug("#sequential list = {}", G.size());
332        logger.info("end {}", pairlist);
333        // setup matrices F and F2G
334        for (GenSolvablePolynomial<C> f : F) {
335            row = PolynomialList.<C> castToSolvableList( blas.genVector(G.size(), null) );
336            H = sred.leftNormalform(row, G, f);
337            if (!H.isZERO()) {
338                logger.error("nonzero H = {}", H);
339            }
340            F2G.add(row);
341        }
342        logger.info("extLeftGB end");
343        return new SolvableExtendedGB<C>(F, G, F2G, G2F);
344    }
345
346
347    /**
348     * Twosided Groebner base using pairlist class.
349     * @param modv number of module variables.
350     * @param Fp solvable polynomial list.
351     * @return tsGB(Fp) a twosided Groebner base of Fp.
352     */
353    @SuppressWarnings("unchecked")
354    public List<GenSolvablePolynomial<C>> twosidedGB(int modv, List<GenSolvablePolynomial<C>> Fp) {
355        List<GenSolvablePolynomial<C>> F = normalizeZerosOnes(Fp);
356        F = PolynomialList.castToSolvableList(PolyUtil.<C> monic(PolynomialList.castToList(F)));
357        if (F.size() < 1) { // 0 not 1
358            return F;
359        }
360        if (F.size() == 1 && F.get(0).isONE()) {
361            return F;
362        }
363        GenSolvablePolynomialRing<C> ring = F.get(0).ring;
364        if (!ring.coFac.isField() && ring.coFac.isCommutative()) {
365            throw new IllegalArgumentException("coefficients not from a field");
366        }
367        // add also coefficient generators
368        List<GenSolvablePolynomial<C>> X;
369        X = PolynomialList.castToSolvableList(ring.generators(modv)); 
370        logger.info("right multipliers = {}", X);
371        List<GenSolvablePolynomial<C>> G = new ArrayList<GenSolvablePolynomial<C>>(F.size() * (1 + X.size()));
372        G.addAll(F);
373        logger.info("right multiply: G = {}", G);
374        GenSolvablePolynomial<C> p, q;
375        for (int i = 0; i < G.size(); i++) { // G changes
376            p = G.get(i);
377            for (GenSolvablePolynomial<C> x : X) {
378                //x = X.get(j);
379                if (x.isONE()) {
380                    continue;
381                }
382                q = p.multiply(x);
383                logger.info("right multiply: p = {}, x = {}, q = {}", p, x, q);
384                q = sred.leftNormalform(G, q);
385                q = q.monic();
386                logger.info("right multiply: red(q) = {}", q);
387                if (!q.isZERO()) {
388                    //System.out.println("q generating: = " + q + ", p = " + p + ", x = " + x);
389                    if (q.isONE()) {
390                        //System.out.println("G generated so far: " + G);
391                        G.clear();
392                        G.add(q);
393                        return G; // since no threads are activated
394                    }
395                    if (!G.contains(q)) { // why?
396                       G.add(q);
397                    } else {
398                       logger.info("right multiply contained: q = {}", q);
399                    } 
400                }
401            }
402        }
403        if (G.size() <= 1) { // 1 ok
404            return G; // since no threads are activated
405        }
406        //System.out.println("G generated = " + G);
407        PairList<C> pairlist = strategy.create(modv, ring);
408        pairlist.put(PolynomialList.castToList(G));
409        logger.info("twosided start {}", pairlist);
410
411        Pair<C> pair;
412        GenSolvablePolynomial<C> pi, pj, S, H;
413        while (pairlist.hasNext()) {
414            pair = pairlist.removeNext();
415            if (pair == null) {
416                continue;
417            }
418
419            pi = (GenSolvablePolynomial<C>) pair.pi;
420            pj = (GenSolvablePolynomial<C>) pair.pj;
421            if (debug) {
422                logger.debug("pi    = {}", pi);
423                logger.debug("pj    = {}", pj);
424            }
425
426            S = sred.leftSPolynomial(pi, pj);
427            if (S.isZERO()) {
428                pair.setZero();
429                continue;
430            }
431            if (debug) {
432                logger.debug("ht(S) = {}", S.leadingExpVector());
433            }
434
435            H = sred.leftNormalform(G, S);
436            if (H.isZERO()) {
437                pair.setZero();
438                continue;
439            }
440            if (debug) {
441                logger.debug("ht(H) = {}", H.leadingExpVector());
442            }
443
444            H = H.monic();
445            if (H.isONE()) {
446                G.clear();
447                G.add(H);
448                return G; // since no threads are activated
449            }
450            if (debug) {
451                logger.debug("H = {}", H);
452            }
453            if (H.length() > 0) {
454                G.add(H);
455                pairlist.put(H);
456                //System.out.println("H generated = " + H);
457                for (GenSolvablePolynomial<C> x : X) {
458                    //x = X.get(j);
459                    if (x.isONE()) {
460                        continue;
461                    }
462                    q = H.multiply(x);
463                    p = sred.leftNormalform(G, q);
464                    if (!p.isZERO()) {
465                        //System.out.println("p generated = " + p + ", x = " + x);
466                        p = p.monic();
467                        if (p.isONE()) {
468                            G.clear();
469                            G.add(p);
470                            return G; // since no threads are activated
471                        }
472                        G.add(p);
473                        pairlist.put(p);
474                    }
475                }
476                //System.out.println("G generated = " + G);
477            }
478        }
479        logger.debug("#sequential list = {}", G.size());
480        G = leftMinimalGB(G);
481        logger.info("twosided end {}", pairlist);
482        return G;
483    }
484
485
486    /**
487     * Normalize M. Make all rows the same size and make certain column elements
488     * zero.
489     * @param M a reduction matrix.
490     * @return normalized M.
491     */
492    public List<List<GenSolvablePolynomial<C>>> normalizeMatrix(int flen,
493                    List<List<GenSolvablePolynomial<C>>> M) {
494        if (M == null) {
495            return M;
496        }
497        if (M.size() == 0) {
498            return M;
499        }
500        List<List<GenSolvablePolynomial<C>>> N = new ArrayList<List<GenSolvablePolynomial<C>>>();
501        List<List<GenSolvablePolynomial<C>>> K = new ArrayList<List<GenSolvablePolynomial<C>>>();
502        int len = M.get(M.size() - 1).size(); // longest row
503        // pad / extend rows
504        for (List<GenSolvablePolynomial<C>> row : M) {
505            List<GenSolvablePolynomial<C>> nrow = new ArrayList<GenSolvablePolynomial<C>>(row);
506            for (int i = row.size(); i < len; i++) {
507                nrow.add(null);
508            }
509            N.add(nrow);
510        }
511        // System.out.println("norm N fill = " + N);
512        // make zero columns
513        int k = flen;
514        for (int i = 0; i < N.size(); i++) { // 0
515            List<GenSolvablePolynomial<C>> row = N.get(i);
516            if (debug) {
517                logger.info("row = {}", row);
518            }
519            K.add(row);
520            if (i < flen) { // skip identity part
521                continue;
522            }
523            List<GenSolvablePolynomial<C>> xrow;
524            GenSolvablePolynomial<C> a;
525            //System.out.println("norm i = " + i);
526            for (int j = i + 1; j < N.size(); j++) {
527                List<GenSolvablePolynomial<C>> nrow = N.get(j);
528                //System.out.println("nrow j = " +j + ", " + nrow);
529                if (k < nrow.size()) { // always true
530                    a = nrow.get(k);
531                    //System.out.println("k, a = " + k + ", " + a);
532                    if (a != null && !a.isZERO()) { // a*row + nrow, leads to wrong method dispatch
533                        List<GenPolynomial<C>> yrow = blas.scalarProduct(a,
534                                        PolynomialList.<C> castToList(row));
535                        yrow = blas.vectorAdd(yrow, PolynomialList.<C> castToList(nrow));
536                        xrow = PolynomialList.<C> castToSolvableList(yrow);
537                        N.set(j, xrow);
538                    }
539                }
540            }
541            k++;
542        }
543        //System.out.println("norm K reduc = {}", K);
544        // truncate 
545        N.clear();
546        for (List<GenSolvablePolynomial<C>> row : K) {
547            List<GenSolvablePolynomial<C>> tr = new ArrayList<GenSolvablePolynomial<C>>();
548            for (int i = 0; i < flen; i++) {
549                tr.add(row.get(i));
550            }
551            N.add(tr);
552        }
553        K = N;
554        //System.out.println("norm K trunc = " + K);
555        return K;
556    }
557
558
559    /**
560     * Test if M is a left reduction matrix.
561     * @param exgb an SolvableExtendedGB container.
562     * @return true, if exgb contains a left reduction matrix, else false.
563     */
564    @Override
565    public boolean isLeftReductionMatrix(SolvableExtendedGB<C> exgb) {
566        if (exgb == null) {
567            return true;
568        }
569        return isLeftReductionMatrix(exgb.F, exgb.G, exgb.F2G, exgb.G2F);
570    }
571
572
573    /**
574     * Minimal solvable extended groebner basis.
575     * @param Gp a left Groebner base.
576     * @param M a left reduction matrix, is modified.
577     * @return a (partially) reduced left Groebner base of Gp in a container.
578     */
579    public SolvableExtendedGB<C> minimalSolvableExtendedGB(int flen, List<GenSolvablePolynomial<C>> Gp,
580                    List<List<GenSolvablePolynomial<C>>> M) {
581        if (Gp == null) {
582            return null; //new SolvableExtendedGB<C>(null,Gp,null,M);
583        }
584        if (Gp.size() <= 1) {
585            return new SolvableExtendedGB<C>(null, Gp, null, M);
586        }
587        List<GenSolvablePolynomial<C>> G;
588        List<GenSolvablePolynomial<C>> F;
589        G = new ArrayList<GenSolvablePolynomial<C>>(Gp);
590        F = new ArrayList<GenSolvablePolynomial<C>>(Gp.size());
591
592        List<List<GenSolvablePolynomial<C>>> Mg;
593        List<List<GenSolvablePolynomial<C>>> Mf;
594        Mg = new ArrayList<List<GenSolvablePolynomial<C>>>(M.size());
595        Mf = new ArrayList<List<GenSolvablePolynomial<C>>>(M.size());
596        List<GenSolvablePolynomial<C>> row;
597        for (List<GenSolvablePolynomial<C>> r : M) {
598            // must be copied also
599            row = new ArrayList<GenSolvablePolynomial<C>>(r);
600            Mg.add(row);
601        }
602        row = null;
603
604        GenSolvablePolynomial<C> a;
605        ExpVector e;
606        ExpVector f;
607        GenSolvablePolynomial<C> p;
608        boolean mt;
609        ListIterator<GenSolvablePolynomial<C>> it;
610        ArrayList<Integer> ix = new ArrayList<Integer>();
611        ArrayList<Integer> jx = new ArrayList<Integer>();
612        int k = 0;
613        //System.out.println("flen, Gp, M = " + flen + ", " + Gp.size() + ", " + M.size() );
614        while (G.size() > 0) {
615            a = G.remove(0);
616            e = a.leadingExpVector();
617
618            it = G.listIterator();
619            mt = false;
620            while (it.hasNext() && !mt) {
621                p = it.next();
622                f = p.leadingExpVector();
623                mt = e.multipleOf(f);
624            }
625            it = F.listIterator();
626            while (it.hasNext() && !mt) {
627                p = it.next();
628                f = p.leadingExpVector();
629                mt = e.multipleOf(f);
630            }
631            //System.out.println("k, mt = " + k + ", " + mt);
632            if (!mt) {
633                F.add(a);
634                ix.add(k);
635            } else { // drop polynomial and corresponding row and column
636                // F.add( a.ring.getZERO() );
637                jx.add(k);
638            }
639            k++;
640        }
641        if (debug) {
642            logger.debug("ix, #M, jx = {}, {}, {}", ix, Mg.size(), jx);
643        }
644        int fix = -1; // copied polys
645        // copy Mg to Mf as indicated by ix
646        for (int i = 0; i < ix.size(); i++) {
647            int u = ix.get(i);
648            if (u >= flen && fix == -1) {
649                fix = Mf.size();
650            }
651            //System.out.println("copy u, fix = " + u + ", " + fix);
652            if (u >= 0) {
653                row = Mg.get(u);
654                Mf.add(row);
655            }
656        }
657        if (F.size() <= 1 || fix == -1) {
658            return new SolvableExtendedGB<C>(null, F, null, Mf);
659        }
660        // must return, since extended normalform has not correct order of polys
661        /*
662        G = F;
663        F = new ArrayList<GenSolvablePolynomial<C>>( G.size() );
664        List<GenSolvablePolynomial<C>> temp;
665        k = 0;
666        final int len = G.size();
667        while ( G.size() > 0 ) {
668            a = G.remove(0);
669            if ( k >= fix ) { // dont touch copied polys
670               row = Mf.get( k );
671               //System.out.println("doing k = " + k + ", " + a);
672               // must keep order, but removed polys missing
673               temp = new ArrayList<GenPolynomial<C>>( len );
674               temp.addAll( F );
675               temp.add( a.ring.getZERO() ); // ??
676               temp.addAll( G );
677               //System.out.println("row before = " + row);
678               a = sred.leftNormalform( row, temp, a );
679               //System.out.println("row after  = " + row);
680            }
681            F.add( a );
682            k++;
683        }
684        // does Mf need renormalization?
685        */
686        return new SolvableExtendedGB<C>(null, F, null, Mf);
687    }
688
689
690    /**
691     * Right Groebner base via right reduction using pairlist
692     * class. Overrides rightGB() via opposite ring.
693     * @param modv number of module variables.
694     * @param F solvable polynomial list.
695     * @return rightGB(F) a right Groebner base of F.
696     */
697    @Override
698    @SuppressWarnings("unchecked")
699    public List<GenSolvablePolynomial<C>> rightGB(int modv, List<GenSolvablePolynomial<C>> F) {
700        List<GenSolvablePolynomial<C>> G = normalizeZerosOnes(F);
701        G = PolynomialList.castToSolvableList(PolyUtil.<C> monic(PolynomialList.castToList(G)));
702        if (G.size() <= 1) {
703            return G;
704        }
705        GenSolvablePolynomialRing<C> ring = G.get(0).ring;
706        if (!ring.coFac.isField() && ring.coFac.isCommutative()) {
707            throw new IllegalArgumentException("coefficients not from a field");
708        }
709        PairList<C> pairlist = strategy.create(modv, ring);
710        pairlist.put(PolynomialList.castToList(G));
711        logger.info("start {}", pairlist);
712
713        GenSolvablePolynomial<C> pi, pj, S, H;
714        Pair<C> pair;
715        while (pairlist.hasNext()) {
716            pair = pairlist.removeNext();
717            if (pair == null) {
718                continue;
719            }
720            pi = (GenSolvablePolynomial<C>) pair.pi;
721            pj = (GenSolvablePolynomial<C>) pair.pj;
722            if (debug) {
723                logger.info("pi    = {}", pi);
724                logger.info("pj    = {}", pj);
725            }
726
727            S = sred.rightSPolynomial(pi, pj);
728            if (S.isZERO()) {
729                pair.setZero();
730                continue;
731            }
732            if (debug) {
733                logger.info("ht(S) = {}", S.leadingExpVector());
734            }
735
736            H = sred.rightNormalform(G, S);
737            if (H.isZERO()) {
738                pair.setZero();
739                continue;
740            }
741            if (debug) {
742                logger.info("ht(H) = {}", H.leadingExpVector());
743            }
744
745            H = H.monic();
746            if (H.isONE()) {
747                G.clear();
748                G.add(H);
749                return G; // since no threads are activated
750            }
751            if (debug) {
752                logger.info("H = {}", H);
753            }
754            if (H.length() > 0) {
755                //l++;
756                G.add(H);
757                pairlist.put(H);
758            }
759        }
760        logger.debug("#sequential list = {}", G.size());
761        G = rightMinimalGB(G);
762        logger.info("end {}", pairlist);
763        return G;
764    }
765
766}