001/*
002 * $Id: SolvableGroebnerBaseSeq.java 5687 2017-01-03 08:44:03Z kredel $
003 */
004
005package edu.jas.gb;
006
007
008import java.util.ArrayList;
009import java.util.List;
010import java.util.ListIterator;
011
012import org.apache.log4j.Logger;
013
014import edu.jas.poly.ExpVector;
015import edu.jas.poly.GenPolynomial;
016import edu.jas.poly.GenSolvablePolynomial;
017import edu.jas.poly.GenSolvablePolynomialRing;
018import edu.jas.poly.QLRSolvablePolynomialRing;
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 = Logger.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) = " + H.leadingExpVector() + ", lc(H) = " + 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 = new ArrayList<GenSolvablePolynomial<C>>(nzlen);
194                for (int j = 0; j < nzlen; j++) {
195                    row.add(null);
196                }
197                //C c = p.leadingBaseCoefficient();
198                //c = c.inverse();
199                //p = p.multiply( c );
200                row.set(k, mone); //.multiply(c) );
201                k++;
202                if (p.isUnit()) {
203                    G.clear();
204                    G.add(p);
205                    G2F.clear();
206                    G2F.add(row);
207                    oneInGB = true;
208                    break;
209                }
210                G.add(p);
211                G2F.add(row);
212                if (pairlist == null) {
213                    //pairlist = new CriticalPairList<C>( modv, p.ring );
214                    pairlist = strategy.create(modv, p.ring);
215                }
216                // putOne not required
217                pairlist.put(p);
218            } else {
219                len--;
220            }
221        }
222        SolvableExtendedGB<C> exgb;
223        if (len <= 1 || oneInGB) {
224            // adjust F2G
225            for (GenSolvablePolynomial<C> f : F) {
226                row = new ArrayList<GenSolvablePolynomial<C>>(G.size());
227                for (int j = 0; j < G.size(); j++) {
228                    row.add(null);
229                }
230                H = sred.leftNormalform(row, G, f);
231                if (!H.isZERO()) {
232                    logger.error("nonzero H = " + H);
233                }
234                F2G.add(row);
235            }
236            exgb = new SolvableExtendedGB<C>(F, G, F2G, G2F);
237            //System.out.println("exgb 1 = " + exgb);
238            return exgb;
239        }
240        logger.info("start " + pairlist);
241
242        Pair<C> pair;
243        int i, j;
244        GenSolvablePolynomial<C> pi, pj, S, x, y;
245        //GenPolynomial<C> z;
246        while (pairlist.hasNext() && !oneInGB) {
247            pair = pairlist.removeNext();
248            if (pair == null) {
249                //pairlist.update(); // ?
250                continue;
251            }
252            i = pair.i;
253            j = pair.j;
254            pi = (GenSolvablePolynomial<C>) pair.pi;
255            pj = (GenSolvablePolynomial<C>) pair.pj;
256            if (debug) {
257                logger.info("i, pi    = " + i + ", " + pi);
258                logger.info("j, pj    = " + j + ", " + pj);
259            }
260
261            rows = new ArrayList<GenSolvablePolynomial<C>>(G.size());
262            for (int m = 0; m < G.size(); m++) {
263                rows.add(null);
264            }
265            S = sred.leftSPolynomial(rows, i, pi, j, pj);
266            if (debug) {
267                logger.debug("is reduction S = " + sred.isLeftReductionNF(rows, G, ring.getZERO(), S));
268            }
269            if (S.isZERO()) {
270                pair.setZero();
271                //pairlist.update( pair, S );
272                // do not add to G2F
273                continue;
274            }
275            if (debug) {
276                logger.debug("ht(S) = " + S.leadingExpVector());
277            }
278
279            rowh = new ArrayList<GenSolvablePolynomial<C>>(G.size());
280            for (int m = 0; m < G.size(); m++) {
281                rowh.add(null);
282            }
283            H = sred.leftNormalform(rowh, G, S);
284            if (debug) {
285                //System.out.println("H = " + H);
286                logger.debug("is reduction H = " + sred.isLeftReductionNF(rowh, G, S, H));
287            }
288            if (H.isZERO()) {
289                pair.setZero();
290                //pairlist.update( pair, H );
291                // do not add to G2F
292                continue;
293            }
294            if (debug) {
295                logger.debug("ht(H) = " + H.leadingExpVector());
296            }
297
298            row = new ArrayList<GenSolvablePolynomial<C>>(G.size() + 1);
299            for (int m = 0; m < G.size(); m++) {
300                x = rows.get(m);
301                if (x != null) {
302                    //System.out.println("ms = " + m + " " + x);
303                    x = (GenSolvablePolynomial<C>) x.negate();
304                }
305                y = rowh.get(m);
306                if (y != null) {
307                    y = (GenSolvablePolynomial<C>) y.negate();
308                    //System.out.println("mh = " + m + " " + y);
309                }
310                if (x == null) {
311                    x = y;
312                } else {
313                    x = (GenSolvablePolynomial<C>) x.sum(y);
314                }
315                //System.out.println("mx = " + m + " " + x);
316                row.add(x);
317            }
318            if (debug) {
319                logger.debug("is reduction 0+sum(row,G) == H : "
320                                + sred.isLeftReductionNF(row, G, H, ring.getZERO()));
321            }
322            row.add(null);
323
324            //  H = H.monic();
325            C c = H.leadingBaseCoefficient();
326            c = c.inverse();
327            H = H.multiply(c);
328            // 1*c*row, leads to wrong method dispatch:
329            row = PolynomialList.<C> castToSolvableList(blas.scalarProduct(mone.multiply(c),
330                            PolynomialList.<C> castToList(row)));
331            row.set(G.size(), mone);
332            if (H.isONE()) {
333                // pairlist.record( pair, H );
334                // G.clear(); 
335                G.add(H);
336                G2F.add(row);
337                oneInGB = true;
338                break;
339            }
340            if (debug) {
341                logger.debug("H = " + H);
342            }
343            G.add(H);
344            //pairlist.update( pair, H );
345            pairlist.put(H);
346            G2F.add(row);
347        }
348        if (debug) {
349            exgb = new SolvableExtendedGB<C>(F, G, F2G, G2F);
350            logger.info("exgb unnorm = " + exgb);
351        }
352        G2F = normalizeMatrix(F.size(), G2F);
353        if (debug) {
354            exgb = new SolvableExtendedGB<C>(F, G, F2G, G2F);
355            logger.info("exgb nonmin = " + exgb);
356            boolean t2 = isLeftReductionMatrix(exgb);
357            logger.debug("exgb t2 = " + t2);
358        }
359        exgb = minimalSolvableExtendedGB(F.size(), G, G2F);
360        G = exgb.G;
361        G2F = exgb.G2F;
362        logger.debug("#sequential list = " + G.size());
363        logger.info("end " + pairlist);
364        // setup matrices F and F2G
365        for (GenSolvablePolynomial<C> f : F) {
366            row = new ArrayList<GenSolvablePolynomial<C>>(G.size());
367            for (int m = 0; m < G.size(); m++) {
368                row.add(null);
369            }
370            H = sred.leftNormalform(row, G, f);
371            if (!H.isZERO()) {
372                logger.error("nonzero H = " + H);
373            }
374            F2G.add(row);
375        }
376        logger.info("extGB end");
377        return new SolvableExtendedGB<C>(F, G, F2G, G2F);
378    }
379
380
381    /**
382     * Twosided Groebner base using pairlist class.
383     * @param modv number of module variables.
384     * @param Fp solvable polynomial list.
385     * @return tsGB(Fp) a twosided Groebner base of Fp.
386     */
387    @SuppressWarnings("unchecked")
388    public List<GenSolvablePolynomial<C>> twosidedGB(int modv, List<GenSolvablePolynomial<C>> Fp) {
389        List<GenSolvablePolynomial<C>> F = normalizeZerosOnes(Fp);
390        F = PolynomialList.castToSolvableList(PolyUtil.<C> monic(PolynomialList.castToList(F)));
391        if (F.size() < 1) { // 0 not 1
392            return F;
393        }
394        if (F.size() == 1 && F.get(0).isONE()) {
395            return F;
396        }
397        GenSolvablePolynomialRing<C> ring = F.get(0).ring;
398        if (!ring.coFac.isField() && ring.coFac.isCommutative()) {
399            throw new IllegalArgumentException("coefficients not from a field");
400        }
401        // add also coefficient generators
402        List<GenSolvablePolynomial<C>> X;
403        X = PolynomialList.castToSolvableList(ring.generators(modv)); 
404        logger.info("right multipliers = " + X);
405        List<GenSolvablePolynomial<C>> G = new ArrayList<GenSolvablePolynomial<C>>(F.size() * (1 + X.size()));
406        G.addAll(F);
407        logger.info("right multipy: G = " + G);
408        GenSolvablePolynomial<C> p, q;
409        for (int i = 0; i < G.size(); i++) { // G changes
410            p = G.get(i);
411            for (GenSolvablePolynomial<C> x : X) {
412                //x = X.get(j);
413                if (x.isONE()) {
414                    continue;
415                }
416                q = p.multiply(x);
417                logger.info("right multipy: p = " + p + ", x = " + x + ", q = " + q);
418                q = sred.leftNormalform(G, q);
419                q = q.monic();
420                logger.info("right multipy: red(q) = " + q);
421                if (!q.isZERO()) {
422                    //System.out.println("q generating: = " + q + ", p = " + p + ", x = " + x);
423                    if (q.isONE()) {
424                        //System.out.println("G generated so far: " + G);
425                        G.clear();
426                        G.add(q);
427                        return G; // since no threads are activated
428                    }
429                    if (!G.contains(q)) { // why?
430                       G.add(q);
431                    } else {
432                       logger.info("right multipy contained: q = " + q);
433                    } 
434                }
435            }
436        }
437        if (G.size() <= 1) { // 1 ok
438            return G; // since no threads are activated
439        }
440        //System.out.println("G generated = " + G);
441        PairList<C> pairlist = strategy.create(modv, ring);
442        pairlist.put(PolynomialList.castToList(G));
443        logger.info("twosided start " + pairlist);
444
445        Pair<C> pair;
446        GenSolvablePolynomial<C> pi, pj, S, H;
447        while (pairlist.hasNext()) {
448            pair = pairlist.removeNext();
449            if (pair == null) {
450                continue;
451            }
452
453            pi = (GenSolvablePolynomial<C>) pair.pi;
454            pj = (GenSolvablePolynomial<C>) pair.pj;
455            if (debug) {
456                logger.debug("pi    = " + pi);
457                logger.debug("pj    = " + pj);
458            }
459
460            S = sred.leftSPolynomial(pi, pj);
461            if (S.isZERO()) {
462                pair.setZero();
463                continue;
464            }
465            if (debug) {
466                logger.debug("ht(S) = " + S.leadingExpVector());
467            }
468
469            H = sred.leftNormalform(G, S);
470            if (H.isZERO()) {
471                pair.setZero();
472                continue;
473            }
474            if (debug) {
475                logger.debug("ht(H) = " + H.leadingExpVector());
476            }
477
478            H = H.monic();
479            if (H.isONE()) {
480                G.clear();
481                G.add(H);
482                return G; // since no threads are activated
483            }
484            if (debug) {
485                logger.debug("H = " + H);
486            }
487            if (H.length() > 0) {
488                G.add(H);
489                pairlist.put(H);
490                //System.out.println("H generated = " + H);
491                for (GenSolvablePolynomial<C> x : X) {
492                    //x = X.get(j);
493                    if (x.isONE()) {
494                        continue;
495                    }
496                    q = H.multiply(x);
497                    p = sred.leftNormalform(G, q);
498                    if (!p.isZERO()) {
499                        //System.out.println("p generated = " + p + ", x = " + x);
500                        p = p.monic();
501                        if (p.isONE()) {
502                            G.clear();
503                            G.add(p);
504                            return G; // since no threads are activated
505                        }
506                        G.add(p);
507                        pairlist.put(p);
508                    }
509                }
510                //System.out.println("G generated = " + G);
511            }
512        }
513        logger.debug("#sequential list = " + G.size());
514        G = leftMinimalGB(G);
515        logger.info("twosided end " + pairlist);
516        return G;
517    }
518
519
520    /**
521     * Normalize M. Make all rows the same size and make certain column elements
522     * zero.
523     * @param M a reduction matrix.
524     * @return normalized M.
525     */
526    public List<List<GenSolvablePolynomial<C>>> normalizeMatrix(int flen,
527                    List<List<GenSolvablePolynomial<C>>> M) {
528        if (M == null) {
529            return M;
530        }
531        if (M.size() == 0) {
532            return M;
533        }
534        List<List<GenSolvablePolynomial<C>>> N = new ArrayList<List<GenSolvablePolynomial<C>>>();
535        List<List<GenSolvablePolynomial<C>>> K = new ArrayList<List<GenSolvablePolynomial<C>>>();
536        int len = M.get(M.size() - 1).size(); // longest row
537        // pad / extend rows
538        for (List<GenSolvablePolynomial<C>> row : M) {
539            List<GenSolvablePolynomial<C>> nrow = new ArrayList<GenSolvablePolynomial<C>>(row);
540            for (int i = row.size(); i < len; i++) {
541                nrow.add(null);
542            }
543            N.add(nrow);
544        }
545        // System.out.println("norm N fill = " + N);
546        // make zero columns
547        int k = flen;
548        for (int i = 0; i < N.size(); i++) { // 0
549            List<GenSolvablePolynomial<C>> row = N.get(i);
550            if (debug) {
551                logger.info("row = " + row);
552            }
553            K.add(row);
554            if (i < flen) { // skip identity part
555                continue;
556            }
557            List<GenSolvablePolynomial<C>> xrow;
558            GenSolvablePolynomial<C> a;
559            //System.out.println("norm i = " + i);
560            for (int j = i + 1; j < N.size(); j++) {
561                List<GenSolvablePolynomial<C>> nrow = N.get(j);
562                //System.out.println("nrow j = " +j + ", " + nrow);
563                if (k < nrow.size()) { // always true
564                    a = nrow.get(k);
565                    //System.out.println("k, a = " + k + ", " + a);
566                    if (a != null && !a.isZERO()) { // a*row + nrow, leads to wrong method dispatch
567                        List<GenPolynomial<C>> yrow = blas.scalarProduct(a,
568                                        PolynomialList.<C> castToList(row));
569                        yrow = blas.vectorAdd(yrow, PolynomialList.<C> castToList(nrow));
570                        xrow = PolynomialList.<C> castToSolvableList(yrow);
571                        N.set(j, xrow);
572                    }
573                }
574            }
575            k++;
576        }
577        //System.out.println("norm K reduc = " + K);
578        // truncate 
579        N.clear();
580        for (List<GenSolvablePolynomial<C>> row : K) {
581            List<GenSolvablePolynomial<C>> tr = new ArrayList<GenSolvablePolynomial<C>>();
582            for (int i = 0; i < flen; i++) {
583                tr.add(row.get(i));
584            }
585            N.add(tr);
586        }
587        K = N;
588        //System.out.println("norm K trunc = " + K);
589        return K;
590    }
591
592
593    /**
594     * Test if M is a left reduction matrix.
595     * @param exgb an SolvableExtendedGB container.
596     * @return true, if exgb contains a left reduction matrix, else false.
597     */
598    @Override
599    public boolean isLeftReductionMatrix(SolvableExtendedGB<C> exgb) {
600        if (exgb == null) {
601            return true;
602        }
603        return isLeftReductionMatrix(exgb.F, exgb.G, exgb.F2G, exgb.G2F);
604    }
605
606
607    /**
608     * Minimal solvable extended groebner basis.
609     * @param Gp a left Groebner base.
610     * @param M a left reduction matrix, is modified.
611     * @return a (partially) reduced left Groebner base of Gp in a container.
612     */
613    public SolvableExtendedGB<C> minimalSolvableExtendedGB(int flen, List<GenSolvablePolynomial<C>> Gp,
614                    List<List<GenSolvablePolynomial<C>>> M) {
615        if (Gp == null) {
616            return null; //new SolvableExtendedGB<C>(null,Gp,null,M);
617        }
618        if (Gp.size() <= 1) {
619            return new SolvableExtendedGB<C>(null, Gp, null, M);
620        }
621        List<GenSolvablePolynomial<C>> G;
622        List<GenSolvablePolynomial<C>> F;
623        G = new ArrayList<GenSolvablePolynomial<C>>(Gp);
624        F = new ArrayList<GenSolvablePolynomial<C>>(Gp.size());
625
626        List<List<GenSolvablePolynomial<C>>> Mg;
627        List<List<GenSolvablePolynomial<C>>> Mf;
628        Mg = new ArrayList<List<GenSolvablePolynomial<C>>>(M.size());
629        Mf = new ArrayList<List<GenSolvablePolynomial<C>>>(M.size());
630        List<GenSolvablePolynomial<C>> row;
631        for (List<GenSolvablePolynomial<C>> r : M) {
632            // must be copied also
633            row = new ArrayList<GenSolvablePolynomial<C>>(r);
634            Mg.add(row);
635        }
636        row = null;
637
638        GenSolvablePolynomial<C> a;
639        ExpVector e;
640        ExpVector f;
641        GenSolvablePolynomial<C> p;
642        boolean mt;
643        ListIterator<GenSolvablePolynomial<C>> it;
644        ArrayList<Integer> ix = new ArrayList<Integer>();
645        ArrayList<Integer> jx = new ArrayList<Integer>();
646        int k = 0;
647        //System.out.println("flen, Gp, M = " + flen + ", " + Gp.size() + ", " + M.size() );
648        while (G.size() > 0) {
649            a = G.remove(0);
650            e = a.leadingExpVector();
651
652            it = G.listIterator();
653            mt = false;
654            while (it.hasNext() && !mt) {
655                p = it.next();
656                f = p.leadingExpVector();
657                mt = e.multipleOf(f);
658            }
659            it = F.listIterator();
660            while (it.hasNext() && !mt) {
661                p = it.next();
662                f = p.leadingExpVector();
663                mt = e.multipleOf(f);
664            }
665            //System.out.println("k, mt = " + k + ", " + mt);
666            if (!mt) {
667                F.add(a);
668                ix.add(k);
669            } else { // drop polynomial and corresponding row and column
670                // F.add( a.ring.getZERO() );
671                jx.add(k);
672            }
673            k++;
674        }
675        if (debug) {
676            logger.debug("ix, #M, jx = " + ix + ", " + Mg.size() + ", " + jx);
677        }
678        int fix = -1; // copied polys
679        // copy Mg to Mf as indicated by ix
680        for (int i = 0; i < ix.size(); i++) {
681            int u = ix.get(i);
682            if (u >= flen && fix == -1) {
683                fix = Mf.size();
684            }
685            //System.out.println("copy u, fix = " + u + ", " + fix);
686            if (u >= 0) {
687                row = Mg.get(u);
688                Mf.add(row);
689            }
690        }
691        if (F.size() <= 1 || fix == -1) {
692            return new SolvableExtendedGB<C>(null, F, null, Mf);
693        }
694        // must return, since extended normalform has not correct order of polys
695        /*
696        G = F;
697        F = new ArrayList<GenSolvablePolynomial<C>>( G.size() );
698        List<GenSolvablePolynomial<C>> temp;
699        k = 0;
700        final int len = G.size();
701        while ( G.size() > 0 ) {
702            a = G.remove(0);
703            if ( k >= fix ) { // dont touch copied polys
704               row = Mf.get( k );
705               //System.out.println("doing k = " + k + ", " + a);
706               // must keep order, but removed polys missing
707               temp = new ArrayList<GenPolynomial<C>>( len );
708               temp.addAll( F );
709               temp.add( a.ring.getZERO() ); // ??
710               temp.addAll( G );
711               //System.out.println("row before = " + row);
712               a = sred.leftNormalform( row, temp, a );
713               //System.out.println("row after  = " + row);
714            }
715            F.add( a );
716            k++;
717        }
718        // does Mf need renormalization?
719        */
720        return new SolvableExtendedGB<C>(null, F, null, Mf);
721    }
722
723
724    /**
725     * Right Groebner base via right reduction using pairlist
726     * class. Overides rightGB() via opposite ring.
727     * @param modv number of module variables.
728     * @param F solvable polynomial list.
729     * @return rightGB(F) a right Groebner base of F.
730     */
731    @Override
732    @SuppressWarnings("unchecked")
733    public List<GenSolvablePolynomial<C>> rightGB(int modv, List<GenSolvablePolynomial<C>> F) {
734        List<GenSolvablePolynomial<C>> G = normalizeZerosOnes(F);
735        G = PolynomialList.castToSolvableList(PolyUtil.<C> monic(PolynomialList.castToList(G)));
736        if (G.size() <= 1) {
737            return G;
738        }
739        GenSolvablePolynomialRing<C> ring = G.get(0).ring;
740        if (!ring.coFac.isField() && ring.coFac.isCommutative()) {
741            throw new IllegalArgumentException("coefficients not from a field");
742        }
743        PairList<C> pairlist = strategy.create(modv, ring);
744        pairlist.put(PolynomialList.castToList(G));
745        logger.info("start " + pairlist);
746
747        GenSolvablePolynomial<C> pi, pj, S, H;
748        Pair<C> pair;
749        while (pairlist.hasNext()) {
750            pair = pairlist.removeNext();
751            if (pair == null) {
752                continue;
753            }
754            pi = (GenSolvablePolynomial<C>) pair.pi;
755            pj = (GenSolvablePolynomial<C>) pair.pj;
756            if (debug) {
757                logger.info("pi    = " + pi);
758                logger.info("pj    = " + pj);
759            }
760
761            S = sred.rightSPolynomial(pi, pj);
762            if (S.isZERO()) {
763                pair.setZero();
764                continue;
765            }
766            if (debug) {
767                logger.info("ht(S) = " + S.leadingExpVector());
768            }
769
770            H = sred.rightNormalform(G, S);
771            if (H.isZERO()) {
772                pair.setZero();
773                continue;
774            }
775            if (debug) {
776                logger.info("ht(H) = " + H.leadingExpVector());
777            }
778
779            H = H.monic();
780            if (H.isONE()) {
781                G.clear();
782                G.add(H);
783                return G; // since no threads are activated
784            }
785            if (debug) {
786                logger.info("H = " + H);
787            }
788            if (H.length() > 0) {
789                //l++;
790                G.add(H);
791                pairlist.put(H);
792            }
793        }
794        logger.debug("#sequential list = " + G.size());
795        G = rightMinimalGB(G);
796        logger.info("end " + pairlist);
797        return G;
798    }
799
800}