001    /*
002     * $Id: DReductionSeq.java 3288 2010-08-25 21:46:14Z kredel $
003     */
004    
005    package edu.jas.gb;
006    
007    
008    import java.util.ArrayList;
009    import java.util.Iterator;
010    import java.util.List;
011    import java.util.Map;
012    
013    import org.apache.log4j.Logger;
014    
015    import edu.jas.poly.ExpVector;
016    import edu.jas.poly.GenPolynomial;
017    import edu.jas.poly.GenSolvablePolynomial;
018    
019    import edu.jas.structure.RingElem;
020    
021    
022    /**
023     * Polynomial D-Reduction sequential use algorithm. Implements normalform.
024     * @param <C> coefficient type
025     * @author Heinz Kredel
026     */
027    
028    public class DReductionSeq<C extends RingElem<C>> extends ReductionAbstract<C> implements DReduction<C> {
029    
030    
031        private static final Logger logger = Logger.getLogger(DReductionSeq.class);
032    
033    
034        private final boolean debug = logger.isDebugEnabled();
035    
036    
037        /**
038         * Constructor.
039         */
040        public DReductionSeq() {
041        }
042    
043    
044        /**
045         * Is top reducible.
046         * @param A polynomial.
047         * @param P polynomial list.
048         * @return true if A is top reducible with respect to P.
049         */
050        //SuppressWarnings("unchecked") // not jet working
051        @Override
052        public boolean isTopReducible(List<GenPolynomial<C>> P, GenPolynomial<C> A) {
053            if (P == null || P.isEmpty()) {
054                return false;
055            }
056            if (A == null || A.isZERO()) {
057                return false;
058            }
059            boolean mt = false;
060            ExpVector e = A.leadingExpVector();
061            C a = A.leadingBaseCoefficient();
062            for (GenPolynomial<C> p : P) {
063                mt = e.multipleOf(p.leadingExpVector());
064                if (mt) {
065                    C b = p.leadingBaseCoefficient();
066                    C r = a.remainder(b);
067                    mt = r.isZERO();
068                    if (mt) {
069                        return true;
070                    }
071                }
072            }
073            return false;
074        }
075    
076    
077        /**
078         * Is in Normalform.
079         * @param Ap polynomial.
080         * @param Pp polynomial list.
081         * @return true if Ap is in normalform with respect to Pp.
082         */
083        @SuppressWarnings("unchecked")
084        @Override
085        public boolean isNormalform(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) {
086            if (Pp == null || Pp.isEmpty()) {
087                return true;
088            }
089            if (Ap == null || Ap.isZERO()) {
090                return true;
091            }
092            int l;
093            GenPolynomial<C>[] P;
094            synchronized (Pp) {
095                l = Pp.size();
096                P = new GenPolynomial[l];
097                //P = Pp.toArray();
098                for (int i = 0; i < Pp.size(); i++) {
099                    P[i] = Pp.get(i);
100                }
101            }
102            ExpVector[] htl = new ExpVector[l];
103            C[] lbc = (C[]) new RingElem[l]; // want <C>
104            GenPolynomial<C>[] p = new GenPolynomial[l];
105            Map.Entry<ExpVector, C> m;
106            int i;
107            int j = 0;
108            for (i = 0; i < l; i++) {
109                p[i] = P[i];
110                m = p[i].leadingMonomial();
111                if (m != null) {
112                    p[j] = p[i];
113                    htl[j] = m.getKey();
114                    lbc[j] = m.getValue();
115                    j++;
116                }
117            }
118            l = j;
119            boolean mt = false;
120            Map<ExpVector, C> Am = Ap.getMap();
121            for (ExpVector e : Am.keySet()) {
122                for (i = 0; i < l; i++) {
123                    mt = e.multipleOf(htl[i]);
124                    if (mt) {
125                        C a = Am.get(e);
126                        C r = a.remainder(lbc[i]);
127                        mt = r.isZERO();
128                        if (mt) {
129                            return false;
130                        }
131                    }
132                }
133            }
134            return true;
135        }
136    
137    
138        /**
139         * Normalform using d-reduction.
140         * @param Ap polynomial.
141         * @param Pp polynomial list.
142         * @return d-nf(Ap) with respect to Pp.
143         */
144        @SuppressWarnings("unchecked")
145        public GenPolynomial<C> normalform(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) {
146            if (Pp == null || Pp.isEmpty()) {
147                return Ap;
148            }
149            if (Ap == null || Ap.isZERO()) {
150                return Ap;
151            }
152            int l;
153            GenPolynomial<C>[] P;
154            synchronized (Pp) {
155                l = Pp.size();
156                P = (GenPolynomial<C>[]) new GenPolynomial[l];
157                //P = Pp.toArray();
158                for (int i = 0; i < Pp.size(); i++) {
159                    P[i] = Pp.get(i).abs();
160                }
161            }
162            //System.out.println("l = " + l);
163            Map.Entry<ExpVector, C> m;
164            ExpVector[] htl = new ExpVector[l];
165            C[] lbc = (C[]) new RingElem[l]; // want <C>
166            GenPolynomial<C>[] p = (GenPolynomial<C>[]) new GenPolynomial[l];
167            int i;
168            int j = 0;
169            for (i = 0; i < l; i++) {
170                p[i] = P[i];
171                m = p[i].leadingMonomial();
172                if (m != null) {
173                    p[j] = p[i];
174                    htl[j] = m.getKey();
175                    lbc[j] = m.getValue();
176                    j++;
177                }
178            }
179            l = j;
180            ExpVector e;
181            C a;
182            C r = null;
183            boolean mt = false;
184            GenPolynomial<C> R = Ap.ring.getZERO();
185            GenPolynomial<C> Q = null;
186            GenPolynomial<C> S = Ap;
187            while (S.length() > 0) {
188                m = S.leadingMonomial();
189                e = m.getKey();
190                a = m.getValue();
191                for (i = 0; i < l; i++) {
192                    mt = e.multipleOf(htl[i]);
193                    if (mt) {
194                        r = a.remainder(lbc[i]);
195                        mt = r.isZERO(); // && mt
196                    }
197                    if (mt)
198                        break;
199                }
200                if (!mt) {
201                    //logger.debug("irred");
202                    R = R.sum(a, e);
203                    //S = S.subtract( a, e ); 
204                    S = S.reductum();
205                    //System.out.println(" S = " + S);
206                } else {
207                    //logger.info("red div = " + e);
208                    ExpVector f = e.subtract(htl[i]);
209                    C b = a.divide(lbc[i]);
210                    R = R.sum(r, e);
211                    Q = p[i].multiply(b, f);
212                    S = S.reductum().subtract(Q.reductum()); // ok also with reductum
213                }
214            }
215            return R.abs();
216        }
217    
218    
219        /**
220         * S-Polynomial.
221         * @param Ap polynomial.
222         * @param Bp polynomial.
223         * @return spol(Ap,Bp) the S-polynomial of Ap and Bp.
224         */
225        @Override
226        public GenPolynomial<C> SPolynomial(GenPolynomial<C> Ap, GenPolynomial<C> Bp) {
227            if (logger.isInfoEnabled()) {
228                if (Bp == null || Bp.isZERO()) {
229                    return Ap.ring.getZERO();
230                }
231                if (Ap == null || Ap.isZERO()) {
232                    return Bp.ring.getZERO();
233                }
234                if (!Ap.ring.equals(Bp.ring)) {
235                    logger.error("rings not equal");
236                }
237            }
238            Map.Entry<ExpVector, C> ma = Ap.leadingMonomial();
239            Map.Entry<ExpVector, C> mb = Bp.leadingMonomial();
240    
241            ExpVector e = ma.getKey();
242            ExpVector f = mb.getKey();
243    
244            ExpVector g = e.lcm(f);
245            ExpVector e1 = g.subtract(e);
246            ExpVector f1 = g.subtract(f);
247    
248            C a = ma.getValue();
249            C b = mb.getValue();
250            C c = a.gcd(b);
251            C m = a.multiply(b);
252            C l = m.divide(c); // = lcm(a,b)
253    
254            C a1 = l.divide(a);
255            C b1 = l.divide(b);
256    
257            GenPolynomial<C> App = Ap.multiply(a1, e1);
258            GenPolynomial<C> Bpp = Bp.multiply(b1, f1);
259            GenPolynomial<C> Cp = App.subtract(Bpp);
260            return Cp;
261        }
262    
263    
264        /**
265         * G-Polynomial.
266         * @param Ap polynomial.
267         * @param Bp polynomial.
268         * @return gpol(Ap,Bp) the g-polynomial of Ap and Bp.
269         */
270        public GenPolynomial<C> GPolynomial(GenPolynomial<C> Ap, GenPolynomial<C> Bp) {
271            if (logger.isInfoEnabled()) {
272                if (Bp == null || Bp.isZERO()) {
273                    return Ap.ring.getZERO();
274                }
275                if (Ap == null || Ap.isZERO()) {
276                    return Bp.ring.getZERO();
277                }
278                if (!Ap.ring.equals(Bp.ring)) {
279                    logger.error("rings not equal");
280                }
281            }
282            Map.Entry<ExpVector, C> ma = Ap.leadingMonomial();
283            Map.Entry<ExpVector, C> mb = Bp.leadingMonomial();
284    
285            ExpVector e = ma.getKey();
286            ExpVector f = mb.getKey();
287    
288            ExpVector g = e.lcm(f);
289            ExpVector e1 = g.subtract(e);
290            ExpVector f1 = g.subtract(f);
291    
292            C a = ma.getValue();
293            C b = mb.getValue();
294            C[] c = a.egcd(b);
295    
296            //System.out.println("egcd[0] " + c[0]);
297    
298            GenPolynomial<C> App = Ap.multiply(c[1], e1);
299            GenPolynomial<C> Bpp = Bp.multiply(c[2], f1);
300            GenPolynomial<C> Cp = App.sum(Bpp);
301            return Cp;
302        }
303    
304    
305        /**
306         * D-Polynomial with recording.
307         * @param S recording matrix, is modified.
308         * @param i index of Ap in basis list.
309         * @param Ap a polynomial.
310         * @param j index of Bp in basis list.
311         * @param Bp a polynomial.
312         * @return gpol(Ap, Bp), the g-Polynomial for Ap and Bp.
313         */
314        public GenPolynomial<C> GPolynomial(List<GenPolynomial<C>> S, int i, GenPolynomial<C> Ap, int j,
315                GenPolynomial<C> Bp) {
316            throw new UnsupportedOperationException("not jet implemented");
317        }
318    
319    
320        /**
321         * GB criterium 4. Use only for commutative polynomial rings. This version
322         * works also for d-Groebner bases.
323         * @param A polynomial.
324         * @param B polynomial.
325         * @param e = lcm(ht(A),ht(B))
326         * @return true if the S-polynomial(i,j) is required, else false.
327         */
328        @Override
329        public boolean criterion4(GenPolynomial<C> A, GenPolynomial<C> B, ExpVector e) {
330            if (logger.isInfoEnabled()) {
331                if (!A.ring.equals(B.ring)) {
332                    logger.error("rings equal");
333                }
334                if (A instanceof GenSolvablePolynomial || B instanceof GenSolvablePolynomial) {
335                    logger.error("GBCriterion4 not applicabable to SolvablePolynomials");
336                    return true;
337                }
338            }
339            ExpVector ei = A.leadingExpVector();
340            ExpVector ej = B.leadingExpVector();
341            ExpVector g = ei.sum(ej);
342            // boolean t =  g == e ;
343            ExpVector h = g.subtract(e);
344            int s = h.signum();
345            if (s == 0) { // disjoint ht
346                C a = A.leadingBaseCoefficient();
347                C b = B.leadingBaseCoefficient();
348                C d = a.gcd(b);
349                if (d.isONE()) { // disjoint hc
350                    //System.out.println("d1 = " + d + ", a = " + a + ", b = " + b);
351                    return false; // can skip pair
352                }
353            }
354            return true; //! ( s == 0 );
355        }
356    
357    
358        /**
359         * GB criterium 4. Use only for commutative polynomial rings. This version
360         * works also for d-Groebner bases.
361         * @param A polynomial.
362         * @param B polynomial.
363         * @return true if the S-polynomial(i,j) is required, else false.
364         */
365        @Override
366        public boolean criterion4(GenPolynomial<C> A, GenPolynomial<C> B) {
367            if (logger.isInfoEnabled()) {
368                if (A instanceof GenSolvablePolynomial || B instanceof GenSolvablePolynomial) {
369                    logger.error("GBCriterion4 not applicabable to SolvablePolynomials");
370                    return true;
371                }
372            }
373            ExpVector ei = A.leadingExpVector();
374            ExpVector ej = B.leadingExpVector();
375            ExpVector g = ei.sum(ej);
376            ExpVector e = ei.lcm(ej);
377            //        boolean t =  g == e ;
378            ExpVector h = g.subtract(e);
379            int s = h.signum();
380            if (s == 0) { // disjoint ht
381                C a = A.leadingBaseCoefficient();
382                C b = B.leadingBaseCoefficient();
383                C d = a.gcd(b);
384                if (d.isONE()) { // disjoint hc
385                    return false; // can skip pair
386                }
387            }
388            return true; //! ( s == 0 );
389        }
390    
391    
392        /**
393         * Normalform with recording.
394         * @param row recording matrix, is modified.
395         * @param Pp a polynomial list for reduction.
396         * @param Ap a polynomial.
397         * @return nf(Pp,Ap), the normal form of Ap wrt. Pp.
398         */
399        @SuppressWarnings("unchecked")
400        // not jet working
401        public GenPolynomial<C> normalform(List<GenPolynomial<C>> row, List<GenPolynomial<C>> Pp,
402                GenPolynomial<C> Ap) {
403            if (Pp == null || Pp.isEmpty()) {
404                return Ap;
405            }
406            if (Ap == null || Ap.isZERO()) {
407                return Ap;
408            }
409            throw new UnsupportedOperationException("not jet implemented");
410            /*
411            int l = Pp.size();
412            GenPolynomial<C>[] P = new GenPolynomial[l];
413            synchronized (Pp) {
414                //P = Pp.toArray();
415                for ( int i = 0; i < Pp.size(); i++ ) {
416                    P[i] = Pp.get(i);
417                }
418            }
419            ExpVector[] htl = new ExpVector[ l ];
420            Object[] lbc = new Object[ l ]; // want <C>
421            GenPolynomial<C>[] p = new GenPolynomial[ l ];
422            Map.Entry<ExpVector,C> m;
423            int j = 0;
424            int i;
425            for ( i = 0; i < l; i++ ) { 
426                p[i] = P[i];
427                m = p[i].leadingMonomial();
428                if ( m != null ) { 
429                    p[j] = p[i];
430                    htl[j] = m.getKey();
431                    lbc[j] = m.getValue();
432                    j++;
433                }
434            }
435            l = j;
436            ExpVector e;
437            C a;
438            boolean mt = false;
439            GenPolynomial<C> zero = Ap.ring.getZERO();
440            GenPolynomial<C> R = Ap.ring.getZERO();
441    
442            GenPolynomial<C> fac = null;
443            // GenPolynomial<C> T = null;
444            GenPolynomial<C> Q = null;
445            GenPolynomial<C> S = Ap;
446            while ( S.length() > 0 ) { 
447                m = S.leadingMonomial();
448                e = m.getKey();
449                a = m.getValue();
450                for ( i = 0; i < l; i++ ) {
451                    mt =  e.multipleOf( htl[i] );
452                    if ( mt ) break; 
453                }
454                if ( ! mt ) { 
455                    //logger.debug("irred");
456                    R = R.sum( a, e );
457                    S = S.subtract( a, e ); 
458                    // System.out.println(" S = " + S);
459                    //throw new RuntimeException("Syzygy no GB");
460                } else { 
461                    e =  e.subtract( htl[i] );
462                    //logger.info("red div = " + e);
463                    C c = (C)lbc[i];
464                    a = a.divide( c );
465                    Q = p[i].multiply( a, e );
466                    S = S.subtract( Q );
467                    fac = row.get(i);
468                    if ( fac == null ) {
469                        fac = zero.sum( a, e );
470                    } else {
471                        fac = fac.sum( a, e );
472                    }
473                    row.set(i,fac);
474                }
475            }
476            return R;
477            */
478        }
479    
480    
481        /**
482         * Irreducible set.
483         * @param Pp polynomial list.
484         * @return a list P of polynomials which are in normalform wrt. P.
485         */
486        @Override
487        public List<GenPolynomial<C>> irreducibleSet(List<GenPolynomial<C>> Pp) {
488            ArrayList<GenPolynomial<C>> P = new ArrayList<GenPolynomial<C>>();
489            if (Pp == null) {
490                return null;
491            }
492            for (GenPolynomial<C> a : Pp) {
493                if (!a.isZERO()) {
494                    P.add(a);
495                }
496            }
497            int l = P.size();
498            if (l <= 1)
499                return P;
500    
501            int irr = 0;
502            ExpVector e;
503            ExpVector f;
504            GenPolynomial<C> a;
505            Iterator<GenPolynomial<C>> it;
506            logger.debug("irr = ");
507            while (irr != l) {
508                //it = P.listIterator(); 
509                //a = P.get(0); //it.next();
510                a = P.remove(0);
511                e = a.leadingExpVector();
512                a = normalform(P, a);
513                logger.debug(String.valueOf(irr));
514                if (a.isZERO()) {
515                    l--;
516                    if (l <= 1) {
517                        return P;
518                    }
519                } else {
520                    f = a.leadingExpVector();
521                    if (e.equals(f)) {
522                        irr++;
523                    } else {
524                        irr = 0;
525                    }
526                    P.add(a);
527                }
528            }
529            //System.out.println();
530            return P;
531        }
532    
533    }