001/*
002 * $Id: WordReductionAbstract.java 4152 2012-09-02 11:15:48Z kredel $
003 */
004
005package edu.jas.gb;
006
007
008import java.util.ArrayList;
009import java.util.LinkedList;
010import java.util.List;
011import java.util.Map;
012
013import org.apache.log4j.Logger;
014
015import edu.jas.poly.Word;
016import edu.jas.poly.GenWordPolynomial;
017import edu.jas.poly.OverlapList;
018import edu.jas.poly.Overlap;
019import edu.jas.structure.RingElem;
020
021
022/**
023 * Polynomial word reduction abstract class. Implements common S-Polynomial,
024 * normalform, module criterion and irreducible set.
025 * @param <C> coefficient type
026 * @author Heinz Kredel
027 */
028
029public abstract class WordReductionAbstract<C extends RingElem<C>> implements WordReduction<C> {
030
031
032    private static final Logger logger = Logger.getLogger(WordReductionAbstract.class);
033
034
035    private final boolean debug = logger.isDebugEnabled();
036
037
038    /**
039     * Constructor.
040     */
041    public WordReductionAbstract() {
042    }
043
044
045    /**
046     * S-Polynomials of non-commutative polynomials.
047     * @param Ap word polynomial.
048     * @param Bp word polynomial.
049     * @return list of all spol(Ap,Bp) the S-polynomials of Ap and Bp.
050     */
051    public List<GenWordPolynomial<C>> SPolynomials(GenWordPolynomial<C> Ap, 
052                                                   GenWordPolynomial<C> Bp) {
053        List<GenWordPolynomial<C>> sp = new ArrayList<GenWordPolynomial<C>>();
054        Map.Entry<Word, C> ma = Ap.leadingMonomial();
055        Map.Entry<Word, C> mb = Bp.leadingMonomial();
056        Word e = ma.getKey();
057        Word f = mb.getKey();
058        C a = ma.getValue();
059        C b = mb.getValue();
060        OverlapList oll = e.overlap(f); 
061        if ( oll.ols.isEmpty() ) {
062            return sp;
063        }
064        for ( Overlap ol : oll.ols ) {
065            GenWordPolynomial<C> s = SPolynomial(ol, b, Ap, a, Bp);
066            sp.add(s);
067        }
068        return sp;
069    }
070
071
072    /**
073     * S-Polynomials of non-commutative polynomials.
074     * @param a leading base coefficient of B.
075     * @param l1 word.
076     * @param A word polynomial.
077     * @param r1 word.
078     * @param b leading base coefficient of A.
079     * @param l2 word.
080     * @param B word polynomial.
081     * @param r2 word.
082     * @return list of all spol(Ap,Bp) the S-polynomials of Ap and Bp.
083     */
084    public GenWordPolynomial<C> SPolynomial(C a, Word l1, GenWordPolynomial<C> A, Word r1,
085                                            C b, Word l2, GenWordPolynomial<C> B, Word r2) {
086        C one = A.ring.coFac.getONE();
087        GenWordPolynomial<C> s1 = A.multiply(a,l1,one,r1);
088        GenWordPolynomial<C> s2 = B.multiply(b,l2,one,r2);
089        GenWordPolynomial<C> s = s1.subtract(s2);
090        return s;
091    }
092
093
094    /**
095     * S-Polynomials of non-commutative polynomials.
096     * @param ol Overlap tuple.
097     * @param a leading base coefficient of B.
098     * @param A word polynomial.
099     * @param b leading base coefficient of A.
100     * @param B word polynomial.
101     * @return list of all spol(Ap,Bp) the S-polynomials of Ap and Bp.
102     */
103    public GenWordPolynomial<C> SPolynomial(Overlap ol, C a, GenWordPolynomial<C> A,
104                                                        C b, GenWordPolynomial<C> B) {
105        C one = A.ring.coFac.getONE();
106        GenWordPolynomial<C> s1 = A.multiply(a,ol.l1,one,ol.r1);
107        GenWordPolynomial<C> s2 = B.multiply(b,ol.l2,one,ol.r2);
108        GenWordPolynomial<C> s = s1.subtract(s2);
109        return s;
110    }
111
112
113    /**
114     * Normalform Set.
115     * @param Ap polynomial list.
116     * @param Pp polynomial list.
117     * @return list of nf(a) with respect to Pp for all a in Ap.
118     */
119    public List<GenWordPolynomial<C>> normalform(List<GenWordPolynomial<C>> Pp, List<GenWordPolynomial<C>> Ap) {
120        if (Pp == null || Pp.isEmpty()) {
121            return Ap;
122        }
123        if (Ap == null || Ap.isEmpty()) {
124            return Ap;
125        }
126        ArrayList<GenWordPolynomial<C>> red = new ArrayList<GenWordPolynomial<C>>();
127        for (GenWordPolynomial<C> A : Ap) {
128            A = normalform(Pp, A);
129            red.add(A);
130        }
131        return red;
132    }
133
134
135    /**
136     * Is top reducible.
137     * @param A polynomial.
138     * @param P polynomial list.
139     * @return true if A is top reducible with respect to P.
140     */
141    public boolean isTopReducible(List<GenWordPolynomial<C>> P, GenWordPolynomial<C> A) {
142        if (P == null || P.isEmpty()) {
143            return false;
144        }
145        if (A == null || A.isZERO()) {
146            return false;
147        }
148        boolean mt = false;
149        Word e = A.leadingWord();
150        for (GenWordPolynomial<C> p : P) {
151            mt = e.multipleOf(p.leadingWord());
152            if (mt) {
153                return true;
154            }
155        }
156        return false;
157    }
158
159
160    /**
161     * Is reducible.
162     * @param Ap polynomial.
163     * @param Pp polynomial list.
164     * @return true if Ap is reducible with respect to Pp.
165     */
166    public boolean isReducible(List<GenWordPolynomial<C>> Pp, GenWordPolynomial<C> Ap) {
167        return !isNormalform(Pp, Ap);
168    }
169
170
171    /**
172     * Is in Normalform.
173     * @param Ap polynomial.
174     * @param Pp polynomial list.
175     * @return true if Ap is in normalform with respect to Pp.
176     */
177    @SuppressWarnings("unchecked")
178    public boolean isNormalform(List<GenWordPolynomial<C>> Pp, GenWordPolynomial<C> Ap) {
179        if (Pp == null || Pp.isEmpty()) {
180            return true;
181        }
182        if (Ap == null || Ap.isZERO()) {
183            return true;
184        }
185        int l;
186        GenWordPolynomial<C>[] P;
187        synchronized (Pp) {
188            l = Pp.size();
189            P = new GenWordPolynomial[l];
190            //P = Pp.toArray();
191            for (int i = 0; i < Pp.size(); i++) {
192                P[i] = Pp.get(i);
193            }
194        }
195        Word[] htl = new Word[l];
196        GenWordPolynomial<C>[] p = new GenWordPolynomial[l];
197        Map.Entry<Word, C> m;
198        int i;
199        int j = 0;
200        for (i = 0; i < l; i++) {
201            p[i] = P[i];
202            m = p[i].leadingMonomial();
203            if (m != null) {
204                p[j] = p[i];
205                htl[j] = m.getKey();
206                j++;
207            }
208        }
209        l = j;
210        boolean mt = false;
211        for (Word e : Ap.getMap().keySet()) {
212            for (i = 0; i < l; i++) {
213                mt = e.multipleOf(htl[i]);
214                if (mt) {
215                    return false;
216                }
217            }
218        }
219        return true;
220    }
221
222
223    /**
224     * Is in Normalform.
225     * @param Pp polynomial list.
226     * @return true if each Ap in Pp is in normalform with respect to Pp\{Ap}.
227     */
228    public boolean isNormalform(List<GenWordPolynomial<C>> Pp) {
229        if (Pp == null || Pp.isEmpty()) {
230            return true;
231        }
232        GenWordPolynomial<C> Ap;
233        List<GenWordPolynomial<C>> P = new LinkedList<GenWordPolynomial<C>>(Pp);
234        int s = P.size();
235        for (int i = 0; i < s; i++) {
236            Ap = P.remove(i);
237            if (!isNormalform(P, Ap)) {
238                return false;
239            }
240            P.add(Ap);
241        }
242        return true;
243    }
244
245
246    /**
247     * Irreducible set.
248     * @param Pp polynomial list.
249     * @return a list P of monic polynomials which are in normalform wrt. P and
250     *         with ideal(Pp) = ideal(P).
251     */
252    public List<GenWordPolynomial<C>> irreducibleSet(List<GenWordPolynomial<C>> Pp) {
253        ArrayList<GenWordPolynomial<C>> P = new ArrayList<GenWordPolynomial<C>>();
254        for (GenWordPolynomial<C> a : Pp) {
255            if (a.length() != 0) {
256                a = a.monic();
257                if (a.isONE()) {
258                    P.clear();
259                    P.add(a);
260                    return P;
261                }
262                P.add(a);
263            }
264        }
265        int l = P.size();
266        if (l <= 1)
267            return P;
268
269        int irr = 0;
270        Word e;
271        Word f;
272        GenWordPolynomial<C> a;
273        logger.debug("irr = ");
274        while (irr != l) {
275            //it = P.listIterator(); 
276            //a = P.get(0); //it.next();
277            a = P.remove(0);
278            e = a.leadingWord();
279            a = normalform(P, a);
280            logger.debug(String.valueOf(irr));
281            if (a.length() == 0) {
282                l--;
283                if (l <= 1) {
284                    return P;
285                }
286            } else {
287                f = a.leadingWord();
288                if (f.signum() == 0) {
289                    P = new ArrayList<GenWordPolynomial<C>>();
290                    P.add(a.monic());
291                    return P;
292                }
293                if (e.equals(f)) {
294                    irr++;
295                } else {
296                    irr = 0;
297                    a = a.monic();
298                }
299                P.add(a);
300            }
301        }
302        //System.out.println();
303        return P;
304    }
305
306
307    /**
308     * Is reduction of normal form.
309     * @param lrow left recording matrix.
310     * @param rrow right recording matrix.
311     * @param Pp a polynomial list for reduction.
312     * @param Ap a polynomial.
313     * @param Np nf(Pp,Ap), a normal form of Ap wrt. Pp.
314     * @return true, if Np + sum( row[i]*Pp[i] ) == Ap, else false.
315     */
316    public boolean isReductionNF(List<GenWordPolynomial<C>> lrow, List<GenWordPolynomial<C>> rrow, 
317                                 List<GenWordPolynomial<C>> Pp, 
318                                 GenWordPolynomial<C> Ap, GenWordPolynomial<C> Np) {
319        if (lrow == null && rrow == null && Pp == null) {
320            if (Ap == null) {
321                return (Np == null);
322            }
323            return Ap.equals(Np);
324        }
325        if (lrow == null || rrow == null || Pp == null) {
326            return false;
327        }
328        if (lrow.size() != Pp.size() || rrow.size() != Pp.size()) {
329            return false;
330        }
331        GenWordPolynomial<C> t = Np;
332        //System.out.println("t0 = " + t );
333        GenWordPolynomial<C> r, rl, rr;
334        GenWordPolynomial<C> p;
335        for (int m = 0; m < Pp.size(); m++) {
336            rl = lrow.get(m);
337            rr = rrow.get(m);
338            p = Pp.get(m);
339            if (rl != null && rr != null && p != null) {
340                if (t == null) {
341                    t = p.multiply(rl,rr);
342                } else {
343                    t = t.sum(p.multiply(rl,rr));
344                }
345            }
346            //System.out.println("r = " + r );
347            //System.out.println("p = " + p );
348        }
349        //System.out.println("t+ = " + t );
350        if (t == null) {
351            if (Ap == null) {
352                return true;
353            }
354            return Ap.isZERO();
355        }
356        r = t.subtract(Ap);
357        boolean z = r.isZERO();
358        if (!z) {
359            logger.info("t = " + t);
360            logger.info("a = " + Ap);
361            logger.info("t-a = " + r);
362        }
363        return z;
364    }
365}