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