001/*
002 * $Id: PseudoReductionSeq.java 4290 2012-11-04 14:47:45Z kredel $
003 */
004
005package edu.jas.gbufd;
006
007
008import java.util.List;
009import java.util.Map;
010
011import org.apache.log4j.Logger;
012
013import edu.jas.gb.ReductionAbstract;
014import edu.jas.poly.ExpVector;
015import edu.jas.poly.GenPolynomial;
016import edu.jas.structure.RingElem;
017
018
019/**
020 * Polynomial pseudo reduction sequential use algorithm. Coefficients of
021 * polynomials must not be from a field, i.e. the fraction free reduction is
022 * implemented. Implements normalform.
023 * @param <C> coefficient type
024 * @author Heinz Kredel
025 */
026
027public class PseudoReductionSeq<C extends RingElem<C>> extends ReductionAbstract<C> implements
028                PseudoReduction<C> {
029
030
031    private static final Logger logger = Logger.getLogger(PseudoReductionSeq.class);
032
033
034    /**
035     * Constructor.
036     */
037    public PseudoReductionSeq() {
038    }
039
040
041    /**
042     * Normalform.
043     * @param Ap polynomial.
044     * @param Pp polynomial list.
045     * @return nf(Ap) with respect to Pp.
046     */
047    @SuppressWarnings("unchecked")
048    public GenPolynomial<C> normalform(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) {
049        if (Pp == null || Pp.isEmpty()) {
050            return Ap;
051        }
052        if (Ap == null || Ap.isZERO()) {
053            return Ap;
054        }
055        Map.Entry<ExpVector, C> m;
056        GenPolynomial<C>[] P = new GenPolynomial[0];
057        synchronized (Pp) {
058            P = Pp.toArray(P);
059        }
060        int l = P.length;
061        ExpVector[] htl = new ExpVector[l];
062        C[] lbc = (C[]) new RingElem[l];
063        GenPolynomial<C>[] p = new GenPolynomial[l];
064        int i;
065        int j = 0;
066        for (i = 0; i < l; i++) {
067            if (P[i] == null) {
068                continue;
069            }
070            p[i] = P[i];
071            m = p[i].leadingMonomial();
072            if (m != null) {
073                p[j] = p[i];
074                htl[j] = m.getKey();
075                lbc[j] = m.getValue();
076                j++;
077            }
078        }
079        l = j;
080        ExpVector e;
081        C a;
082        boolean mt = false;
083        GenPolynomial<C> R = Ap.ring.getZERO().copy();
084
085        GenPolynomial<C> S = Ap.copy();
086        while (S.length() > 0) {
087            m = S.leadingMonomial();
088            e = m.getKey();
089            a = m.getValue();
090            for (i = 0; i < l; i++) {
091                mt = e.multipleOf(htl[i]);
092                if (mt)
093                    break;
094            }
095            if (!mt) {
096                //logger.debug("irred");
097                //R = R.sum(a, e);
098                //S = S.subtract(a, e);
099                R.doPutToMap(e, a);
100                S.doRemoveFromMap(e, a);
101                //System.out.println(" S = " + S);
102            } else {
103                e = e.subtract(htl[i]);
104                //logger.info("red div = " + e);
105                @SuppressWarnings("cast")
106                C c = (C) lbc[i];
107                if (a.remainder(c).isZERO()) { //c.isUnit() ) {
108                    a = a.divide(c);
109                    S = S.subtractMultiple(a, e, p[i]);
110                } else {
111                    R = R.multiply(c);
112                    //S = S.multiply(c);
113                    S = S.scaleSubtractMultiple(c, a, e, p[i]);
114                }
115                //Q = p[i].multiply(a, e);
116                //S = S.subtract(Q);
117            }
118        }
119        return R;
120    }
121
122
123    /**
124     * Normalform.
125     * @param Pp polynomial list.
126     * @param Ap polynomial.
127     * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor
128     *         for Ap.
129     */
130    @SuppressWarnings("unchecked")
131    public PseudoReductionEntry<C> normalformFactor(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) {
132        if (Ap == null) {
133            return null;
134        }
135        C mfac = Ap.ring.getONECoefficient();
136        PseudoReductionEntry<C> pf = new PseudoReductionEntry<C>(Ap, mfac);
137        if (Pp == null || Pp.isEmpty()) {
138            return pf;
139        }
140        if (Ap.isZERO()) {
141            return pf;
142        }
143        Map.Entry<ExpVector, C> m;
144        GenPolynomial<C>[] P = new GenPolynomial[0];
145        synchronized (Pp) {
146            P = Pp.toArray(P);
147        }
148        int l = P.length;
149        ExpVector[] htl = new ExpVector[l];
150        C[] lbc = (C[]) new RingElem[l]; // want C[] 
151        GenPolynomial<C>[] p = new GenPolynomial[l];
152        int i;
153        int j = 0;
154        for (i = 0; i < l; i++) {
155            if (P[i] == null) {
156                continue;
157            }
158            p[i] = P[i];
159            m = p[i].leadingMonomial();
160            if (m != null) {
161                p[j] = p[i];
162                htl[j] = m.getKey();
163                lbc[j] = m.getValue();
164                j++;
165            }
166        }
167        l = j;
168        ExpVector e;
169        C a;
170        boolean mt = false;
171        GenPolynomial<C> R = Ap.ring.getZERO().copy();
172
173        GenPolynomial<C> S = Ap.copy();
174        while (S.length() > 0) {
175            m = S.leadingMonomial();
176            e = m.getKey();
177            a = m.getValue();
178            for (i = 0; i < l; i++) {
179                mt = e.multipleOf(htl[i]);
180                if (mt)
181                    break;
182            }
183            if (!mt) {
184                //logger.debug("irred");
185                //R = R.sum(a, e);
186                //S = S.subtract(a, e);
187                R.doPutToMap(e, a);
188                S.doRemoveFromMap(e, a);
189                //System.out.println(" S = " + S);
190            } else {
191                e = e.subtract(htl[i]);
192                //logger.info("red div = " + e);
193                C c = lbc[i];
194                if (a.remainder(c).isZERO()) { //c.isUnit() ) {
195                    a = a.divide(c);
196                    S = S.subtractMultiple(a, e, p[i]);
197                } else {
198                    mfac = mfac.multiply(c);
199                    R = R.multiply(c);
200                    //S = S.multiply(c);
201                    S = S.scaleSubtractMultiple(c, a, e, p[i]);
202                }
203                //Q = p[i].multiply(a, e);
204                //S = S.subtract(Q);
205            }
206        }
207        if (logger.isInfoEnabled()) {
208            logger.info("multiplicative factor = " + mfac);
209        }
210        pf = new PseudoReductionEntry<C>(R, mfac);
211        return pf;
212    }
213
214
215    /**
216     * Normalform with recording. <b>Note:</b> Only meaningful if all divisions
217     * are exact. Compute first the multiplication factor <code>m</code> with
218     * <code>normalform(Pp,Ap,m)</code>, then call this method with
219     * <code>normalform(row,Pp,m*Ap)</code>.
220     * @param row recording matrix, is modified.
221     * @param Pp a polynomial list for reduction.
222     * @param Ap a polynomial.
223     * @return nf(Pp,Ap), the normal form of Ap wrt. Pp.
224     */
225    @SuppressWarnings("unchecked")
226    public GenPolynomial<C> normalform(List<GenPolynomial<C>> row, List<GenPolynomial<C>> Pp,
227                    GenPolynomial<C> Ap) {
228        if (Pp == null || Pp.isEmpty()) {
229            return Ap;
230        }
231        if (Ap == null || Ap.isZERO()) {
232            return Ap;
233        }
234        GenPolynomial<C>[] P = new GenPolynomial[0];
235        synchronized (Pp) {
236            P = Pp.toArray(P);
237        }
238        int l = P.length;
239        ExpVector[] htl = new ExpVector[l];
240        Object[] lbc = new Object[l]; // want C 
241        GenPolynomial<C>[] p = new GenPolynomial[l];
242        Map.Entry<ExpVector, C> m;
243        int j = 0;
244        int i;
245        for (i = 0; i < l; i++) {
246            p[i] = P[i];
247            m = p[i].leadingMonomial();
248            if (m != null) {
249                p[j] = p[i];
250                htl[j] = m.getKey();
251                lbc[j] = m.getValue();
252                j++;
253            }
254        }
255        l = j;
256        ExpVector e;
257        C a;
258        boolean mt = false;
259        GenPolynomial<C> zero = Ap.ring.getZERO();
260        GenPolynomial<C> R = Ap.ring.getZERO().copy();
261        GenPolynomial<C> fac = null;
262        GenPolynomial<C> S = Ap.copy();
263        while (S.length() > 0) {
264            m = S.leadingMonomial();
265            e = m.getKey();
266            a = m.getValue();
267            for (i = 0; i < l; i++) {
268                mt = e.multipleOf(htl[i]);
269                if (mt)
270                    break;
271            }
272            if (!mt) {
273                //logger.debug("irred");
274                //R = R.sum(a, e);
275                //S = S.subtract(a, e);
276                R.doPutToMap(e, a);
277                S.doRemoveFromMap(e, a);
278                // System.out.println(" S = " + S);
279                //throw new RuntimeException("Syzygy no GB");
280            } else {
281                e = e.subtract(htl[i]);
282                //logger.info("red div = " + e);
283                C c = (C) lbc[i];
284                if (a.remainder(c).isZERO()) { //c.isUnit() ) {
285                    a = a.divide(c);
286                    S = S.subtractMultiple(a, e, p[i]);
287                    //System.out.print("|");
288                } else {
289                    //System.out.print("*");
290                    R = R.multiply(c);
291                    //S = S.multiply(c);
292                    S = S.scaleSubtractMultiple(c, a, e, p[i]);
293                }
294                //Q = p[i].multiply(a, e);
295                //S = S.subtract(Q);
296                fac = row.get(i);
297                if (fac == null) {
298                    fac = zero.sum(a, e);
299                } else {
300                    fac = fac.sum(a, e);
301                }
302                row.set(i, fac);
303            }
304        }
305        return R;
306    }
307
308}