001/*
002 * $Id$
003 */
004
005package edu.jas.gb;
006
007
008import java.util.List;
009import java.util.Map;
010
011import org.apache.logging.log4j.LogManager;
012import org.apache.logging.log4j.Logger;
013
014import edu.jas.poly.ExpVector;
015import edu.jas.poly.GenSolvablePolynomial;
016import edu.jas.structure.RingElem;
017
018
019/**
020 * Solvable polynomial Reduction algorithm. Implements left, right normalform.
021 * @param <C> coefficient type
022 * @author Heinz Kredel
023 */
024
025public class SolvableReductionSeq<C extends RingElem<C>> extends SolvableReductionAbstract<C> {
026
027
028    private static final Logger logger = LogManager.getLogger(SolvableReductionSeq.class);
029
030
031    /**
032     * Constructor.
033     */
034    public SolvableReductionSeq() {
035    }
036
037
038    /**
039     * Left Normalform.
040     * @param Ap solvable polynomial.
041     * @param Pp solvable polynomial list.
042     * @return left-nf(Ap) with respect to Pp.
043     */
044    @SuppressWarnings("unchecked")
045    public GenSolvablePolynomial<C> leftNormalform(List<GenSolvablePolynomial<C>> Pp,
046                    GenSolvablePolynomial<C> Ap) {
047        if (Pp == null || Pp.isEmpty()) {
048            return Ap;
049        }
050        if (Ap == null || Ap.isZERO()) {
051            return Ap;
052        }
053        Map.Entry<ExpVector, C> m;
054        GenSolvablePolynomial<C>[] P = new GenSolvablePolynomial[0];
055        synchronized (Pp) {
056            P = Pp.toArray(P);
057        }
058        int l = P.length;
059        int i;
060        ExpVector[] htl = new ExpVector[l];
061        //C[] lbc = (C[]) new RingElem[l];
062        GenSolvablePolynomial<C>[] p = new GenSolvablePolynomial[l];
063        int j = 0;
064        for (i = 0; i < l; i++) {
065            if (P[i] == null) {
066                continue;
067            }
068            p[i] = P[i];
069            m = p[i].leadingMonomial();
070            if (m != null) {
071                p[j] = p[i];
072                htl[j] = m.getKey();
073                //lbc[j] = m.getValue();
074                j++;
075            }
076        }
077        l = j;
078        ExpVector e; //, f;
079        C a, b;
080        boolean mt = false;
081        GenSolvablePolynomial<C> R = Ap.ring.getZERO().copy();
082        GenSolvablePolynomial<C> Q = null;
083        GenSolvablePolynomial<C> S = Ap.copy();
084        GenSolvablePolynomial<C> Sp;
085        while (S.length() > 0) {
086            m = S.leadingMonomial();
087            e = m.getKey();
088            logger.debug("red, e = {}", e);
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 = (GenSolvablePolynomial<C>) R.sum(a, e);
098                //S = (GenSolvablePolynomial<C>) S.subtract(a, e);
099                R.doPutToMap(e, a);
100                S.doRemoveFromMap(e, a);
101                // System.out.println(" S = " + S);
102            } else {
103                //f = e;
104                e = e.subtract(htl[i]);
105                //logger.debug("red div = {}", e);
106                Q = p[i].multiplyLeft(e);
107                b = a;
108                a = a.divide(Q.leadingBaseCoefficient());
109                //Q = Q.multiplyLeft(a);
110                //S = (GenSolvablePolynomial<C>) S.subtract(Q);
111                ExpVector g1 = S.leadingExpVector();
112                Sp = S;
113                S = S.subtractMultiple(a, Q);
114                //S = S.subtractMultiple(a, e, p[i]);
115                ExpVector g2 = S.leadingExpVector();
116                if (g1.equals(g2)) {
117                    logger.info("g1.equals(g2): Pp       = {}", Pp);
118                    logger.info("g1.equals(g2): Ap       = {}", Ap);
119                    logger.info("g1.equals(g2): p[i]     = {}", p[i]);
120                    logger.info("g1.equals(g2): Q        = {}", Q);
121                    logger.info("g1.equals(g2): R        = {}", R);
122                    logger.info("g1.equals(g2): Sp       = {}", Sp);
123                    logger.info("g1.equals(g2): S        = {}", S);
124                    throw new RuntimeException("g1.equals(g2): " + g1 + ", a = " + a + ", b = " + b);
125                }
126            }
127        }
128        return R;
129    }
130
131
132    /**
133     * LeftNormalform with recording.
134     * @param row recording matrix, is modified.
135     * @param Pp a polynomial list for reduction.
136     * @param Ap a polynomial.
137     * @return nf(Pp,Ap), the left normal form of Ap wrt. Pp.
138     */
139    @SuppressWarnings({ "cast", "unchecked" })
140    public GenSolvablePolynomial<C> leftNormalform(List<GenSolvablePolynomial<C>> row,
141                    List<GenSolvablePolynomial<C>> Pp, GenSolvablePolynomial<C> Ap) {
142        if (Pp == null || Pp.isEmpty()) {
143            return Ap;
144        }
145        if (Ap == null || Ap.isZERO()) {
146            return Ap;
147        }
148        GenSolvablePolynomial<C>[] P = new GenSolvablePolynomial[0];
149        synchronized (Pp) {
150            P = Pp.toArray(P);
151        }
152        int l = P.length;
153        ExpVector[] htl = new ExpVector[l];
154        //C[] lbc = (C[]) new RingElem[l];
155        GenSolvablePolynomial<C>[] p = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[l];
156        Map.Entry<ExpVector, C> m;
157        int j = 0;
158        int i;
159        for (i = 0; i < l; i++) {
160            p[i] = P[i];
161            m = p[i].leadingMonomial();
162            if (m != null) {
163                p[j] = p[i];
164                htl[j] = m.getKey();
165                //lbc[j] = m.getValue();
166                j++;
167            }
168        }
169        l = j;
170        ExpVector e;
171        C a;
172        boolean mt = false;
173        //GenSolvablePolynomial<C> zero = Ap.ring.getZERO();
174        GenSolvablePolynomial<C> R = Ap.ring.getZERO().copy();
175
176        GenSolvablePolynomial<C> fac = null;
177        GenSolvablePolynomial<C> Q = null;
178        GenSolvablePolynomial<C> S = Ap.copy();
179        while (S.length() > 0) {
180            m = S.leadingMonomial();
181            e = m.getKey();
182            a = m.getValue();
183            for (i = 0; i < l; i++) {
184                mt = e.multipleOf(htl[i]);
185                if (mt)
186                    break;
187            }
188            if (!mt) {
189                //logger.debug("irred");
190                //R = (GenSolvablePolynomial<C>) R.sum(a, e);
191                //S = (GenSolvablePolynomial<C>) S.subtract(a, e);
192                R.doPutToMap(e, a);
193                S.doRemoveFromMap(e, a);
194                // System.out.println(" S = " + S);
195            } else {
196                e = e.subtract(htl[i]);
197                //logger.info("red div = {}", e);
198                //a = a.divide( (C)lbc[i] );
199                //Q = p[i].multiplyLeft( a, e );
200                Q = p[i].multiplyLeft(e);
201                a = a.divide(Q.leadingBaseCoefficient());
202                //Q = Q.multiplyLeft(a);
203                //S = (GenSolvablePolynomial<C>) S.subtract(Q);
204                ExpVector g1 = S.leadingExpVector();
205                S = S.subtractMultiple(a, Q);
206                ExpVector g2 = S.leadingExpVector();
207                if (g1.equals(g2)) {
208                    throw new RuntimeException("g1.equals(g2): " + g1 + ", a = " + a + ", lc(S) = "
209                                    + S.leadingBaseCoefficient());
210                }
211                fac = row.get(i);
212                if (fac == null) {
213                    //fac = (GenSolvablePolynomial<C>) zero.sum(a, e);
214                    fac = Ap.ring.valueOf(a, e);
215                } else {
216                    //fac = (GenSolvablePolynomial<C>) fac.sum(a, e);
217                    fac.doAddTo(a, e);
218                }
219                row.set(i, fac);
220            }
221        }
222        return R;
223    }
224
225
226    /**
227     * Right Normalform.
228     * @param Ap solvable polynomial.
229     * @param Pp solvable polynomial list.
230     * @return right-nf(Ap) with respect to Pp.
231     */
232    @SuppressWarnings({ "cast", "unchecked" })
233    public GenSolvablePolynomial<C> rightNormalform(List<GenSolvablePolynomial<C>> Pp,
234                    GenSolvablePolynomial<C> Ap) {
235        if (Pp == null || Pp.isEmpty()) {
236            return Ap;
237        }
238        if (Ap == null || Ap.isZERO()) {
239            return Ap;
240        }
241        int l;
242        Map.Entry<ExpVector, C> m;
243        GenSolvablePolynomial<C>[] P;
244        synchronized (Pp) {
245            l = Pp.size();
246            P = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[l];
247            //P = Pp.toArray();
248            for (int j = 0; j < Pp.size(); j++) {
249                P[j] = Pp.get(j);
250            }
251        }
252        int i;
253        ExpVector[] htl = new ExpVector[l];
254        //C[] lbc = (C[]) new RingElem[l];
255        GenSolvablePolynomial<C>[] p = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[l];
256        int j = 0;
257        for (i = 0; i < l; i++) {
258            p[i] = P[i];
259            m = p[i].leadingMonomial();
260            if (m != null) {
261                p[j] = p[i];
262                htl[j] = m.getKey();
263                //lbc[j] = m.getValue();
264                j++;
265            }
266        }
267        l = j;
268        ExpVector e;
269        C a;
270        boolean mt = false;
271        GenSolvablePolynomial<C> R = Ap.ring.getZERO().copy();
272
273        //GenSolvablePolynomial<C> T = null;
274        GenSolvablePolynomial<C> Q = null;
275        GenSolvablePolynomial<C> S = Ap.copy();
276        while (S.length() > 0) {
277            m = S.leadingMonomial();
278            e = m.getKey();
279            //logger.info("red = {}", e);
280            a = m.getValue();
281            for (i = 0; i < l; i++) {
282                mt = e.multipleOf(htl[i]);
283                if (mt)
284                    break;
285            }
286            if (!mt) {
287                //logger.debug("irred");
288                //R = (GenSolvablePolynomial<C>) R.sum(a, e);
289                //S = (GenSolvablePolynomial<C>) S.subtract(a, e);
290                R.doPutToMap(e, a);
291                S.doRemoveFromMap(e, a);
292                // System.out.println(" S = " + S);
293            } else {
294                //logger.debug("red");
295                e = e.subtract(htl[i]);
296                //a = a.divide( (C)lbc[i] );
297                Q = p[i].multiply(e); // p_i * (a e) TODO
298                a = a.divide(Q.leadingBaseCoefficient());
299                Q = Q.multiply(a); // p_i * (e a) !!
300                ExpVector g1 = S.leadingExpVector();
301                S = (GenSolvablePolynomial<C>) S.subtract(Q);
302                //S = S.subtractMultiple(Q, a);
303                ExpVector g2 = S.leadingExpVector();
304                if (g1.equals(g2)) {
305                    throw new RuntimeException("g1.equals(g2): " + g1 + ", a = " + a + ", lc(S) = "
306                                    + S.leadingBaseCoefficient());
307                }
308            }
309        }
310        return R;
311    }
312
313
314    /**
315     * RightNormalform with recording.
316     * @param row recording matrix, is modified.
317     * @param Pp a polynomial list for reduction.
318     * @param Ap a polynomial.
319     * @return nf(Pp,Ap), the right normal form of Ap wrt. Pp.
320     */
321    @SuppressWarnings({ "cast", "unchecked" })
322    public GenSolvablePolynomial<C> rightNormalform(List<GenSolvablePolynomial<C>> row,
323                    List<GenSolvablePolynomial<C>> Pp, GenSolvablePolynomial<C> Ap) {
324        if (Pp == null || Pp.isEmpty()) {
325            return Ap;
326        }
327        if (Ap == null || Ap.isZERO()) {
328            return Ap;
329        }
330        int l = Pp.size();
331        GenSolvablePolynomial<C>[] P = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[l];
332        synchronized (Pp) {
333            //P = Pp.toArray();
334            for (int i = 0; i < Pp.size(); i++) {
335                P[i] = Pp.get(i);
336            }
337        }
338        ExpVector[] htl = new ExpVector[l];
339        //C[] lbc = (C[]) new RingElem[l];
340        GenSolvablePolynomial<C>[] p = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[l];
341        Map.Entry<ExpVector, C> m;
342        int j = 0;
343        int i;
344        for (i = 0; i < l; i++) {
345            p[i] = P[i];
346            m = p[i].leadingMonomial();
347            if (m != null) {
348                p[j] = p[i];
349                htl[j] = m.getKey();
350                //lbc[j] = m.getValue();
351                j++;
352            }
353        }
354        l = j;
355        ExpVector e;
356        C a;
357        boolean mt = false;
358        GenSolvablePolynomial<C> zero = Ap.ring.getZERO();
359        GenSolvablePolynomial<C> R = Ap.ring.getZERO().copy();
360
361        GenSolvablePolynomial<C> fac = null;
362        // GenSolvablePolynomial<C> T = null;
363        GenSolvablePolynomial<C> Q = null;
364        GenSolvablePolynomial<C> S = Ap.copy();
365        while (S.length() > 0) {
366            m = S.leadingMonomial();
367            e = m.getKey();
368            a = m.getValue();
369            for (i = 0; i < l; i++) {
370                mt = e.multipleOf(htl[i]);
371                if (mt)
372                    break;
373            }
374            if (!mt) {
375                //logger.debug("irred");
376                //R = (GenSolvablePolynomial<C>) R.sum(a, e);
377                //S = (GenSolvablePolynomial<C>) S.subtract(a, e);
378                R.doPutToMap(e, a);
379                S.doRemoveFromMap(e, a);
380            } else {
381                e = e.subtract(htl[i]);
382                //logger.info("red div = {}", e);
383                //a = a.divide( (C)lbc[i] );
384                //Q = p[i].multiply( a, e );
385                Q = p[i].multiply(e); // p_i * (a e) TODO
386                a = a.divide(Q.leadingBaseCoefficient());
387                Q = Q.multiply(a); // p_i * (e a)
388                ExpVector g1 = S.leadingExpVector();
389                S = (GenSolvablePolynomial<C>) S.subtract(Q);
390                //S = S.subtractMultiple(Q, a);
391                ExpVector g2 = S.leadingExpVector();
392                if (g1.equals(g2)) {
393                    throw new RuntimeException("g1.equals(g2): " + g1 + ", a = " + a + ", lc(S) = "
394                                    + S.leadingBaseCoefficient());
395                }
396                fac = row.get(i);
397                if (fac == null) {
398                    //fac = (GenSolvablePolynomial<C>) zero.sum(a, e);
399                    fac = Ap.ring.valueOf(a, e);
400                } else {
401                    //fac = (GenSolvablePolynomial<C>) fac.sum(a, e);
402                    fac.doAddTo(a, e);
403                }
404                row.set(i, fac);
405            }
406        }
407        return R;
408    }
409
410}