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