001/*
002 * $Id: GroebnerBaseSeqPairSeq.java 5869 2018-07-20 15:53:10Z 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.logging.log4j.Logger;
013import org.apache.logging.log4j.LogManager; 
014
015import edu.jas.poly.GenPolynomial;
016import edu.jas.poly.GenPolynomialRing;
017import edu.jas.structure.RingElem;
018
019
020/**
021 * Groebner Base sequential algorithm. Implements Groebner bases and GB test.
022 * Uses sequential pair list class.
023 * @param <C> coefficient type
024 * @author Heinz Kredel
025 */
026
027public class GroebnerBaseSeqPairSeq<C extends RingElem<C>> extends GroebnerBaseAbstract<C> {
028
029
030    private static final Logger logger = LogManager.getLogger(GroebnerBaseSeqPairSeq.class);
031
032
033    private static final boolean debug = logger.isDebugEnabled();
034
035
036    /**
037     * Constructor.
038     */
039    public GroebnerBaseSeqPairSeq() {
040        super();
041    }
042
043
044    /**
045     * Constructor.
046     * @param red Reduction engine
047     */
048    public GroebnerBaseSeqPairSeq(Reduction<C> red) {
049        super(red);
050    }
051
052
053    /**
054     * Groebner base using pairlist class.
055     * @param modv module variable number.
056     * @param F polynomial list.
057     * @return GB(F) a Groebner base of F.
058     */
059    public List<GenPolynomial<C>> GB(int modv, List<GenPolynomial<C>> F) {
060        List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>();
061        if (F == null) {
062            return G;
063        }
064        GenPolynomial<C> p;
065        CriticalPairList<C> pairlist = null;
066        int len = F.size();
067        ListIterator<GenPolynomial<C>> it = F.listIterator();
068        while (it.hasNext()) {
069            p = it.next();
070            if (p.length() > 0) {
071                p = p.monic();
072                if (p.isONE()) {
073                    G.clear();
074                    G.add(p);
075                    return G; // since no threads are activated
076                }
077                G.add(p);
078                if (pairlist == null) {
079                    pairlist = new CriticalPairList<C>(modv, p.ring);
080                }
081                // putOne not required
082                pairlist.put(p);
083            } else {
084                len--;
085            }
086        }
087        if (len <= 1) {
088            return G; // since no threads are activated
089        }
090
091        CriticalPair<C> pair;
092        GenPolynomial<C> pi;
093        GenPolynomial<C> pj;
094        GenPolynomial<C> S;
095        GenPolynomial<C> H;
096        while (pairlist.hasNext()) {
097            pair = pairlist.getNext();
098            if (pair == null) {
099                pairlist.update(); // ?
100                continue;
101            }
102            pi = pair.pi;
103            pj = pair.pj;
104            if (debug) {
105                logger.debug("pi    = " + pi);
106                logger.debug("pj    = " + pj);
107            }
108
109            S = red.SPolynomial(pi, pj);
110            if (S.isZERO()) {
111                pairlist.update(pair, S);
112                continue;
113            }
114            if (debug) {
115                logger.debug("ht(S) = " + S.leadingExpVector());
116            }
117
118            H = red.normalform(G, S);
119            if (H.isZERO()) {
120                pairlist.update(pair, H);
121                continue;
122            }
123            if (debug) {
124                logger.debug("ht(H) = " + H.leadingExpVector());
125            }
126
127            H = H.monic();
128            if (H.isONE()) {
129                // pairlist.record( pair, H );
130                G.clear();
131                G.add(H);
132                return G; // since no threads are activated
133            }
134            if (debug) {
135                logger.debug("H = " + H);
136            }
137            G.add(H);
138            pairlist.update(pair, H);
139            //pairlist.update();
140        }
141        logger.debug("#sequential list = " + G.size());
142        G = minimalGB(G);
143        logger.info("" + pairlist);
144        return G;
145    }
146
147
148    /**
149     * Extended Groebner base using critical pair class.
150     * @param modv module variable number.
151     * @param F polynomial list.
152     * @return a container for an extended Groebner base of F.
153     */
154    @Override
155    public ExtendedGB<C> extGB(int modv, List<GenPolynomial<C>> F) {
156        if ( F == null || F.isEmpty() ) {
157            throw new IllegalArgumentException("null or empty F not allowed");
158        }
159        List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>();
160        List<List<GenPolynomial<C>>> F2G = new ArrayList<List<GenPolynomial<C>>>();
161        List<List<GenPolynomial<C>>> G2F = new ArrayList<List<GenPolynomial<C>>>();
162        CriticalPairList<C> pairlist = null;
163        boolean oneInGB = false;
164        int len = F.size();
165
166        List<GenPolynomial<C>> row = null;
167        List<GenPolynomial<C>> rows = null;
168        List<GenPolynomial<C>> rowh = null;
169        GenPolynomialRing<C> ring = null;
170        GenPolynomial<C> H;
171        GenPolynomial<C> p;
172
173        int nzlen = 0;
174        for (GenPolynomial<C> f : F) {
175            if (f.length() > 0) {
176                nzlen++;
177            }
178            if (ring == null) {
179                ring = f.ring;
180            }
181        }
182        GenPolynomial<C> mone = ring.getONE(); //.negate();
183        int k = 0;
184        ListIterator<GenPolynomial<C>> it = F.listIterator();
185        while (it.hasNext()) {
186            p = it.next();
187            if (p.length() > 0) {
188                row = new ArrayList<GenPolynomial<C>>(nzlen);
189                for (int j = 0; j < nzlen; j++) {
190                    row.add(null);
191                }
192                //C c = p.leadingBaseCoefficient();
193                //c = c.inverse();
194                //p = p.multiply( c );
195                row.set(k, mone); //.multiply(c) );
196                k++;
197                if (p.isUnit()) {
198                    G.clear();
199                    G.add(p);
200                    G2F.clear();
201                    G2F.add(row);
202                    oneInGB = true;
203                    break;
204                }
205                G.add(p);
206                G2F.add(row);
207                if (pairlist == null) {
208                    pairlist = new CriticalPairList<C>(modv, p.ring);
209                }
210                // putOne not required
211                pairlist.put(p);
212            } else {
213                len--;
214            }
215        }
216        ExtendedGB<C> exgb;
217        if (len <= 1 || oneInGB) {
218            // adjust F2G
219            for (GenPolynomial<C> f : F) {
220                row = new ArrayList<GenPolynomial<C>>(G.size());
221                for (int j = 0; j < G.size(); j++) {
222                    row.add(null);
223                }
224                H = red.normalform(row, G, f);
225                if (!H.isZERO()) {
226                    logger.error("nonzero H = " + H);
227                }
228                F2G.add(row);
229            }
230            exgb = new ExtendedGB<C>(F, G, F2G, G2F);
231            //System.out.println("exgb 1 = " + exgb);
232            return exgb;
233        }
234
235        CriticalPair<C> pair;
236        int i, j;
237        GenPolynomial<C> pi;
238        GenPolynomial<C> pj;
239        GenPolynomial<C> S;
240        GenPolynomial<C> x;
241        GenPolynomial<C> y;
242        //GenPolynomial<C> z;
243        while (pairlist.hasNext() && !oneInGB) {
244            pair = pairlist.getNext();
245            if (pair == null) {
246                pairlist.update(); // ?
247                continue;
248            }
249            i = pair.i;
250            j = pair.j;
251            pi = pair.pi;
252            pj = pair.pj;
253            if (debug) {
254                logger.info("i, pi    = " + i + ", " + pi);
255                logger.info("j, pj    = " + j + ", " + pj);
256            }
257
258            rows = new ArrayList<GenPolynomial<C>>(G.size());
259            for (int m = 0; m < G.size(); m++) {
260                rows.add(null);
261            }
262            S = red.SPolynomial(rows, i, pi, j, pj);
263            if (debug) {
264                logger.debug("is reduction S = " + red.isReductionNF(rows, G, ring.getZERO(), S));
265            }
266            if (S.isZERO()) {
267                pairlist.update(pair, S);
268                // do not add to G2F
269                continue;
270            }
271            if (debug) {
272                logger.debug("ht(S) = " + S.leadingExpVector());
273            }
274
275            rowh = new ArrayList<GenPolynomial<C>>(G.size());
276            for (int m = 0; m < G.size(); m++) {
277                rowh.add(null);
278            }
279            H = red.normalform(rowh, G, S);
280            if (debug) {
281                logger.debug("is reduction H = " + red.isReductionNF(rowh, G, S, H));
282            }
283            if (H.isZERO()) {
284                pairlist.update(pair, H);
285                // do not add to G2F
286                continue;
287            }
288            if (debug) {
289                logger.debug("ht(H) = " + H.leadingExpVector());
290            }
291
292            row = new ArrayList<GenPolynomial<C>>(G.size() + 1);
293            for (int m = 0; m < G.size(); m++) {
294                x = rows.get(m);
295                if (x != null) {
296                    //System.out.println("ms = " + m + " " + x);
297                    x = x.negate();
298                }
299                y = rowh.get(m);
300                if (y != null) {
301                    y = y.negate();
302                    //System.out.println("mh = " + m + " " + y);
303                }
304                if (x == null) {
305                    x = y;
306                } else {
307                    x = x.sum(y);
308                }
309                //System.out.println("mx = " + m + " " + x);
310                row.add(x);
311            }
312            if (debug) {
313                logger.debug("is reduction 0+sum(row,G) == H : "
314                        + red.isReductionNF(row, G, H, ring.getZERO()));
315            }
316            row.add(null);
317
318
319            //  H = H.monic();
320            C c = H.leadingBaseCoefficient();
321            c = c.inverse();
322            H = H.multiply(c);
323            row = blas.scalarProduct(mone.multiply(c), row);
324            row.set(G.size(), mone);
325            if (H.isONE()) {
326                // pairlist.record( pair, H );
327                // G.clear(); 
328                G.add(H);
329                G2F.add(row);
330                oneInGB = true;
331                break;
332            }
333            if (debug) {
334                logger.debug("H = " + H);
335            }
336            G.add(H);
337            pairlist.update(pair, H);
338            G2F.add(row);
339        }
340        if (debug) {
341            exgb = new ExtendedGB<C>(F, G, F2G, G2F);
342            logger.info("exgb unnorm = " + exgb);
343        }
344        G2F = normalizeMatrix(F.size(), G2F);
345        if (debug) {
346            exgb = new ExtendedGB<C>(F, G, F2G, G2F);
347            logger.info("exgb nonmin = " + exgb);
348            boolean t2 = isReductionMatrix(exgb);
349            logger.info("exgb t2 = " + t2);
350        }
351        exgb = minimalExtendedGB(F.size(), G, G2F);
352        G = exgb.G;
353        G2F = exgb.G2F;
354        logger.debug("#sequential list = " + G.size());
355        logger.info("" + pairlist); 
356        // setup matrices F and F2G
357        for (GenPolynomial<C> f : F) {
358            row = new ArrayList<GenPolynomial<C>>(G.size());
359            for (int m = 0; m < G.size(); m++) {
360                row.add(null);
361            }
362            H = red.normalform(row, G, f);
363            if (!H.isZERO()) {
364                logger.error("nonzero H = " + H);
365            }
366            F2G.add(row);
367        }
368        exgb = new ExtendedGB<C>(F, G, F2G, G2F);
369        if (debug) {
370            logger.info("exgb nonmin = " + exgb);
371            boolean t2 = isReductionMatrix(exgb);
372            logger.info("exgb t2 = " + t2);
373        }
374        return exgb;
375    }
376
377}