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