001/*
002 * $Id: QuotSolvablePolynomial.java 5267 2015-07-27 17:57:50Z kredel $
003 */
004
005package edu.jas.gbufd;
006
007
008import java.util.Map;
009import java.util.Set;
010import java.util.SortedMap;
011
012import org.apache.log4j.Logger;
013
014import edu.jas.poly.ExpVector;
015import edu.jas.poly.GenSolvablePolynomial;
016import edu.jas.poly.RecSolvablePolynomial;
017import edu.jas.poly.TableRelation;
018import edu.jas.structure.GcdRingElem;
019
020
021/**
022 * QuotSolvablePolynomial generic recursive solvable polynomials implementing
023 * RingElem. n-variate ordered solvable polynomials over solvable polynomial
024 * coefficients. Objects of this class are intended to be immutable. The
025 * implementation is based on TreeMap respectively SortedMap from exponents to
026 * coefficients by extension of GenPolynomial.
027 * @param <C> coefficient type
028 * @author Heinz Kredel will be deprecated use QLRSolvablePolynomial
029 */
030
031public class QuotSolvablePolynomial<C extends GcdRingElem<C>> extends
032                GenSolvablePolynomial<SolvableQuotient<C>> {
033
034
035    /**
036     * The factory for the recursive solvable polynomial ring. Hides super.ring.
037     */
038    public final QuotSolvablePolynomialRing<C> ring;
039
040
041    private static final Logger logger = Logger.getLogger(QuotSolvablePolynomial.class);
042
043
044    private final boolean debug = logger.isDebugEnabled();
045
046
047    /**
048     * Constructor for zero QuotSolvablePolynomial.
049     * @param r solvable polynomial ring factory.
050     */
051    public QuotSolvablePolynomial(QuotSolvablePolynomialRing<C> r) {
052        super(r);
053        ring = r;
054    }
055
056
057    /**
058     * Constructor for QuotSolvablePolynomial.
059     * @param r solvable polynomial ring factory.
060     * @param c coefficient polynomial.
061     * @param e exponent.
062     */
063    public QuotSolvablePolynomial(QuotSolvablePolynomialRing<C> r, SolvableQuotient<C> c, ExpVector e) {
064        this(r);
065        if (c != null && !c.isZERO()) {
066            val.put(e, c);
067        }
068    }
069
070
071    /**
072     * Constructor for QuotSolvablePolynomial.
073     * @param r solvable polynomial ring factory.
074     * @param c coefficient polynomial.
075     */
076    public QuotSolvablePolynomial(QuotSolvablePolynomialRing<C> r, SolvableQuotient<C> c) {
077        this(r, c, r.evzero);
078    }
079
080
081    /**
082     * Constructor for QuotSolvablePolynomial.
083     * @param r solvable polynomial ring factory.
084     * @param S solvable polynomial.
085     */
086    public QuotSolvablePolynomial(QuotSolvablePolynomialRing<C> r,
087                    GenSolvablePolynomial<SolvableQuotient<C>> S) {
088        this(r, S.getMap());
089    }
090
091
092    /**
093     * Constructor for QuotSolvablePolynomial.
094     * @param r solvable polynomial ring factory.
095     * @param v the SortedMap of some other (solvable) polynomial.
096     */
097    protected QuotSolvablePolynomial(QuotSolvablePolynomialRing<C> r,
098                    SortedMap<ExpVector, SolvableQuotient<C>> v) {
099        this(r);
100        val.putAll(v); // assume no zero coefficients
101    }
102
103
104    /**
105     * Get the corresponding element factory.
106     * @return factory for this Element.
107     * @see edu.jas.structure.Element#factory()
108     */
109    @Override
110    public QuotSolvablePolynomialRing<C> factory() {
111        return ring;
112    }
113
114
115    /**
116     * Clone this QuotSolvablePolynomial.
117     * @see java.lang.Object#clone()
118     */
119    @Override
120    public QuotSolvablePolynomial<C> copy() {
121        return new QuotSolvablePolynomial<C>(ring, this.val);
122    }
123
124
125    /**
126     * Comparison with any other object.
127     * @see java.lang.Object#equals(java.lang.Object)
128     */
129    @Override
130    public boolean equals(Object B) {
131        if (!(B instanceof QuotSolvablePolynomial)) {
132            return false;
133        }
134        return super.equals(B);
135    }
136
137
138    /**
139     * QuotSolvablePolynomial multiplication.
140     * @param Bp QuotSolvablePolynomial.
141     * @return this*Bp, where * denotes solvable multiplication.
142     */
143    // not @Override
144    public QuotSolvablePolynomial<C> multiply(QuotSolvablePolynomial<C> Bp) {
145        if (Bp == null || Bp.isZERO()) {
146            return ring.getZERO();
147        }
148        if (this.isZERO()) {
149            return this;
150        }
151        if (Bp.isONE()) {
152            return this;
153        }
154        if (this.isONE()) {
155            return Bp;
156        }
157        assert (ring.nvar == Bp.ring.nvar);
158        if (debug) {
159            logger.debug("ring = " + ring);
160        }
161        //System.out.println("this = " + this + ", Bp = " + Bp);
162        ExpVector Z = ring.evzero;
163        QuotSolvablePolynomial<C> Dp = ring.getZERO().copy();
164        QuotSolvablePolynomial<C> zero = ring.getZERO().copy();
165        SolvableQuotient<C> one = ring.getONECoefficient();
166
167        //QuotSolvablePolynomial<C> C1 = null;
168        //QuotSolvablePolynomial<C> C2 = null;
169        Map<ExpVector, SolvableQuotient<C>> A = val;
170        Map<ExpVector, SolvableQuotient<C>> B = Bp.val;
171        Set<Map.Entry<ExpVector, SolvableQuotient<C>>> Bk = B.entrySet();
172        for (Map.Entry<ExpVector, SolvableQuotient<C>> y : A.entrySet()) {
173            SolvableQuotient<C> a = y.getValue();
174            ExpVector e = y.getKey();
175            if (debug)
176                logger.info("e = " + e + ", a = " + a);
177            // int[] ep = e.dependencyOnVariables();
178            // int el1 = ring.nvar + 1;
179            // if (ep.length > 0) {
180            //     el1 = ep[0];
181            // }
182            // int el1s = ring.nvar + 1 - el1;
183            for (Map.Entry<ExpVector, SolvableQuotient<C>> x : Bk) {
184                SolvableQuotient<C> b = x.getValue();
185                ExpVector f = x.getKey();
186                if (debug)
187                    logger.info("f = " + f + ", b = " + b);
188                int[] fp = f.dependencyOnVariables();
189                int fl1 = 0;
190                if (fp.length > 0) {
191                    fl1 = fp[fp.length - 1];
192                }
193                int fl1s = ring.nvar + 1 - fl1;
194                // polynomial with coefficient multiplication 
195                QuotSolvablePolynomial<C> Cps = ring.getZERO().copy();
196                //QuotSolvablePolynomial<C> Cs;
197                QuotSolvablePolynomial<C> qp;
198                if (ring.polCoeff.coeffTable.isEmpty() || b.isConstant() || e.isZERO()) { // symmetric
199                    Cps = new QuotSolvablePolynomial<C>(ring, b, e);
200                    if (debug)
201                        logger.info("symmetric coeff: b = " + b + ", e = " + e);
202                } else { // unsymmetric
203                    if (debug)
204                        logger.info("unsymmetric coeff: b = " + b + ", e = " + e);
205                    // compute e * b as ( e * 1/b.den ) * b.num
206                    if (b.den.isONE()) { // recursion base
207                        // recursive polynomial coefficient multiplication : e * b.num
208                        RecSolvablePolynomial<C> rsp1 = new RecSolvablePolynomial<C>(ring.polCoeff, e);
209                        RecSolvablePolynomial<C> rsp2 = new RecSolvablePolynomial<C>(ring.polCoeff, b.num);
210                        RecSolvablePolynomial<C> rsp3 = rsp1.multiply(rsp2);
211                        QuotSolvablePolynomial<C> rsp = ring.fromPolyCoefficients(rsp3);
212                        Cps = rsp;
213                    } else { // b.den != 1
214                        if (debug)
215                            logger.info("coeff-num: Cps = " + Cps + ", num = " + b.num + ", den = " + b.den);
216                        Cps = new QuotSolvablePolynomial<C>(ring, b.ring.getONE(), e);
217
218                        // coefficient multiplication with 1/den: 
219                        QuotSolvablePolynomial<C> qv = Cps;
220                        SolvableQuotient<C> qden = new SolvableQuotient<C>(b.ring, b.den); // den/1
221                        //System.out.println("qv = " + qv + ", den = " + den);
222                        // recursion with den==1:
223                        QuotSolvablePolynomial<C> v = qv.multiply(qden);
224                        QuotSolvablePolynomial<C> vl = qv.multiplyLeft(qden);
225                        //System.out.println("v = " + v + ", vl = " + vl + ", qden = " + qden);
226                        QuotSolvablePolynomial<C> vr = (QuotSolvablePolynomial<C>) v.subtract(vl);
227                        SolvableQuotient<C> qdeni = new SolvableQuotient<C>(b.ring, b.ring.ring.getONE(),
228                                        b.den);
229                        //System.out.println("vr = " + vr + ", qdeni = " + qdeni);
230                        // recursion with smaller head term:
231                        QuotSolvablePolynomial<C> rq = vr.multiply(qdeni);
232                        qp = (QuotSolvablePolynomial<C>) qv.subtract(rq);
233                        qp = qp.multiplyLeft(qdeni);
234                        //System.out.println("qp_i = " + qp);
235                        Cps = qp;
236
237                        if (!b.num.isONE()) {
238                            SolvableQuotient<C> qnum = new SolvableQuotient<C>(b.ring, b.num); // num/1
239                            // recursion with den == 1:
240                            Cps = Cps.multiply(qnum);
241                        }
242                    }
243                } // end coeff
244                if (debug)
245                    logger.info("coeff-den: Cps = " + Cps);
246                // polynomial multiplication 
247                QuotSolvablePolynomial<C> Dps = ring.getZERO().copy();
248                QuotSolvablePolynomial<C> Ds = null;
249                QuotSolvablePolynomial<C> D1, D2;
250                if (ring.table.isEmpty() || Cps.isConstant() || f.isZERO()) { // symmetric
251                    if (debug)
252                        logger.info("symmetric poly: b = " + b + ", e = " + e);
253                    ExpVector g = e.sum(f);
254                    if (Cps.isConstant()) {
255                        Ds = new QuotSolvablePolynomial<C>(ring, Cps.leadingBaseCoefficient(), g); // symmetric!
256                    } else {
257                        Ds = shift(Cps, f); // symmetric
258                    }
259                } else { // eventually unsymmetric
260                    if (debug)
261                        logger.info("unsymmetric poly: Cps = " + Cps + ", f = " + f);
262                    for (Map.Entry<ExpVector, SolvableQuotient<C>> z : Cps.val.entrySet()) {
263                        // split g = g1 * g2, f = f1 * f2
264                        SolvableQuotient<C> c = z.getValue();
265                        ExpVector g = z.getKey();
266                        if (debug)
267                            logger.info("g = " + g + ", c = " + c);
268                        int[] gp = g.dependencyOnVariables();
269                        int gl1 = ring.nvar + 1;
270                        if (gp.length > 0) {
271                            gl1 = gp[0];
272                        }
273                        int gl1s = ring.nvar + 1 - gl1;
274                        if (gl1s <= fl1s) { // symmetric
275                            ExpVector h = g.sum(f);
276                            if (debug)
277                                logger.info("disjoint poly: g = " + g + ", f = " + f + ", h = " + h);
278                            Ds = (QuotSolvablePolynomial<C>) zero.sum(one, h); // symmetric!
279                        } else {
280                            ExpVector g1 = g.subst(gl1, 0);
281                            ExpVector g2 = Z.subst(gl1, g.getVal(gl1)); // bug el1, gl1
282                            ExpVector g4;
283                            ExpVector f1 = f.subst(fl1, 0);
284                            ExpVector f2 = Z.subst(fl1, f.getVal(fl1));
285                            if (debug) {
286                                logger.info("poly, g1 = " + g1 + ", f1 = " + f1 + ", Dps = " + Dps);
287                                logger.info("poly, g2 = " + g2 + ", f2 = " + f2);
288                            }
289                            TableRelation<SolvableQuotient<C>> rel = ring.table.lookup(g2, f2);
290                            if (debug)
291                                logger.info("poly, g  = " + g + ", f  = " + f + ", rel = " + rel);
292                            Ds = new QuotSolvablePolynomial<C>(ring, rel.p); //ring.copy(rel.p);
293                            if (rel.f != null) {
294                                D2 = new QuotSolvablePolynomial<C>(ring, one, rel.f);
295                                Ds = Ds.multiply(D2);
296                                if (rel.e == null) {
297                                    g4 = g2;
298                                } else {
299                                    g4 = g2.subtract(rel.e);
300                                }
301                                ring.table.update(g4, f2, Ds);
302                            }
303                            if (rel.e != null) {
304                                D1 = new QuotSolvablePolynomial<C>(ring, one, rel.e);
305                                Ds = D1.multiply(Ds);
306                                ring.table.update(g2, f2, Ds);
307                            }
308                            if (!f1.isZERO()) {
309                                D2 = new QuotSolvablePolynomial<C>(ring, one, f1);
310                                Ds = Ds.multiply(D2);
311                                //ring.table.update(?,f1,Ds)
312                            }
313                            if (!g1.isZERO()) {
314                                D1 = new QuotSolvablePolynomial<C>(ring, one, g1);
315                                Ds = D1.multiply(Ds);
316                                //ring.table.update(e1,?,Ds)
317                            }
318                        }
319                        Ds = Ds.multiplyLeft(c); // c * Ds
320                        Dps = (QuotSolvablePolynomial<C>) Dps.sum(Ds);
321                    } // end Dps loop
322                    Ds = Dps;
323                }
324                Ds = Ds.multiplyLeft(a); // multiply(a,b); // non-symmetric 
325                if (debug)
326                    logger.debug("Ds = " + Ds);
327                Dp = (QuotSolvablePolynomial<C>) Dp.sum(Ds);
328            } // end B loop
329        } // end A loop
330          //System.out.println("this * Bp = " + Dp);
331        return Dp;
332    }
333
334
335    /**
336     * QuotSolvablePolynomial left and right multiplication. Product with two
337     * polynomials.
338     * @param S QuotSolvablePolynomial.
339     * @param T QuotSolvablePolynomial.
340     * @return S*this*T.
341     */
342    // not @Override
343    public QuotSolvablePolynomial<C> multiply(QuotSolvablePolynomial<C> S, QuotSolvablePolynomial<C> T) {
344        if (S.isZERO() || T.isZERO() || this.isZERO()) {
345            return ring.getZERO();
346        }
347        if (S.isONE()) {
348            return multiply(T);
349        }
350        if (T.isONE()) {
351            return S.multiply(this);
352        }
353        return S.multiply(this).multiply(T);
354    }
355
356
357    /**
358     * QuotSolvablePolynomial multiplication. Product with coefficient ring
359     * element.
360     * @param b solvable coefficient.
361     * @return this*b, where * is coefficient multiplication.
362     */
363    @Override
364    public QuotSolvablePolynomial<C> multiply(SolvableQuotient<C> b) {
365        QuotSolvablePolynomial<C> Cp = ring.getZERO().copy();
366        if (b == null || b.isZERO()) {
367            return Cp;
368        }
369        if (b.isONE()) {
370            return this;
371        }
372        Cp = new QuotSolvablePolynomial<C>(ring, b, ring.evzero);
373        return multiply(Cp);
374    }
375
376
377    /**
378     * QuotSolvablePolynomial left and right multiplication. Product with
379     * coefficient ring element.
380     * @param b coefficient polynomial.
381     * @param c coefficient polynomial.
382     * @return b*this*c, where * is coefficient multiplication.
383     */
384    @Override
385    public QuotSolvablePolynomial<C> multiply(SolvableQuotient<C> b, SolvableQuotient<C> c) {
386        QuotSolvablePolynomial<C> Cp = ring.getZERO().copy();
387        if (b == null || b.isZERO()) {
388            return Cp;
389        }
390        if (c == null || c.isZERO()) {
391            return Cp;
392        }
393        if (b.isONE() && c.isONE()) {
394            return this;
395        }
396        Cp = new QuotSolvablePolynomial<C>(ring, b, ring.evzero);
397        QuotSolvablePolynomial<C> Dp = new QuotSolvablePolynomial<C>(ring, c, ring.evzero);
398        return multiply(Cp, Dp);
399    }
400
401
402    /**
403     * QuotSolvablePolynomial multiplication. Product with exponent vector.
404     * @param e exponent.
405     * @return this * x<sup>e</sup>, where * denotes solvable multiplication.
406     */
407    @Override
408    public QuotSolvablePolynomial<C> multiply(ExpVector e) {
409        if (e == null || e.isZERO()) {
410            return this;
411        }
412        SolvableQuotient<C> b = ring.getONECoefficient();
413        return multiply(b, e);
414    }
415
416
417    /**
418     * QuotSolvablePolynomial left and right multiplication. Product with
419     * exponent vector.
420     * @param e exponent.
421     * @param f exponent.
422     * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable
423     *         multiplication.
424     */
425    @Override
426    public QuotSolvablePolynomial<C> multiply(ExpVector e, ExpVector f) {
427        if (e == null || e.isZERO()) {
428            return this;
429        }
430        if (f == null || f.isZERO()) {
431            return this;
432        }
433        SolvableQuotient<C> b = ring.getONECoefficient();
434        return multiply(b, e, b, f);
435    }
436
437
438    /**
439     * QuotSolvablePolynomial multiplication. Product with ring element and
440     * exponent vector.
441     * @param b coefficient polynomial.
442     * @param e exponent.
443     * @return this * b x<sup>e</sup>, where * denotes solvable multiplication.
444     */
445    @Override
446    public QuotSolvablePolynomial<C> multiply(SolvableQuotient<C> b, ExpVector e) {
447        if (b == null || b.isZERO()) {
448            return ring.getZERO();
449        }
450        if (b.isONE() && e.isZERO()) {
451            return this;
452        }
453        QuotSolvablePolynomial<C> Cp = new QuotSolvablePolynomial<C>(ring, b, e);
454        return multiply(Cp);
455    }
456
457
458    /**
459     * QuotSolvablePolynomial left and right multiplication. Product with ring
460     * element and exponent vector.
461     * @param b coefficient polynomial.
462     * @param e exponent.
463     * @param c coefficient polynomial.
464     * @param f exponent.
465     * @return b x<sup>e</sup> * this * c x<sup>f</sup>, where * denotes
466     *         solvable multiplication.
467     */
468    @Override
469    public QuotSolvablePolynomial<C> multiply(SolvableQuotient<C> b, ExpVector e, SolvableQuotient<C> c,
470                    ExpVector f) {
471        if (b == null || b.isZERO()) {
472            return ring.getZERO();
473        }
474        if (c == null || c.isZERO()) {
475            return ring.getZERO();
476        }
477        if (b.isONE() && e.isZERO() && c.isONE() && f.isZERO()) {
478            return this;
479        }
480        QuotSolvablePolynomial<C> Cp = new QuotSolvablePolynomial<C>(ring, b, e);
481        QuotSolvablePolynomial<C> Dp = new QuotSolvablePolynomial<C>(ring, c, f);
482        return multiply(Cp, Dp);
483    }
484
485
486    /**
487     * QuotSolvablePolynomial multiplication. Left product with ring element and
488     * exponent vector.
489     * @param b coefficient polynomial.
490     * @param e exponent.
491     * @return b x<sup>e</sup> * this, where * denotes solvable multiplication.
492     */
493    @Override
494    public QuotSolvablePolynomial<C> multiplyLeft(SolvableQuotient<C> b, ExpVector e) {
495        if (b == null || b.isZERO()) {
496            return ring.getZERO();
497        }
498        QuotSolvablePolynomial<C> Cp = new QuotSolvablePolynomial<C>(ring, b, e);
499        return Cp.multiply(this);
500    }
501
502
503    /**
504     * QuotSolvablePolynomial multiplication. Left product with exponent vector.
505     * @param e exponent.
506     * @return x<sup>e</sup> * this, where * denotes solvable multiplication.
507     */
508    @Override
509    public QuotSolvablePolynomial<C> multiplyLeft(ExpVector e) {
510        if (e == null || e.isZERO()) {
511            return this;
512        }
513        SolvableQuotient<C> b = ring.getONECoefficient();
514        QuotSolvablePolynomial<C> Cp = new QuotSolvablePolynomial<C>(ring, b, e);
515        return Cp.multiply(this);
516    }
517
518
519    /**
520     * QuotSolvablePolynomial multiplication. Left product with coefficient ring
521     * element.
522     * @param b coefficient polynomial.
523     * @return b*this, where * is coefficient multiplication.
524     */
525    @Override
526    public QuotSolvablePolynomial<C> multiplyLeft(SolvableQuotient<C> b) {
527        QuotSolvablePolynomial<C> Cp = ring.getZERO().copy();
528        if (b == null || b.isZERO()) {
529            return Cp;
530        }
531        Map<ExpVector, SolvableQuotient<C>> Cm = Cp.val; //getMap();
532        Map<ExpVector, SolvableQuotient<C>> Am = val;
533        SolvableQuotient<C> c;
534        for (Map.Entry<ExpVector, SolvableQuotient<C>> y : Am.entrySet()) {
535            ExpVector e = y.getKey();
536            SolvableQuotient<C> a = y.getValue();
537            c = b.multiply(a);
538            if (!c.isZERO()) {
539                Cm.put(e, c);
540            }
541        }
542        return Cp;
543    }
544
545
546    /**
547     * QuotSolvablePolynomial multiplication. Left product with 'monomial'.
548     * @param m 'monomial'.
549     * @return m * this, where * denotes solvable multiplication.
550     */
551    @Override
552    public QuotSolvablePolynomial<C> multiplyLeft(Map.Entry<ExpVector, SolvableQuotient<C>> m) {
553        if (m == null) {
554            return ring.getZERO();
555        }
556        return multiplyLeft(m.getValue(), m.getKey());
557    }
558
559
560    /**
561     * QuotSolvablePolynomial multiplication. Product with 'monomial'.
562     * @param m 'monomial'.
563     * @return this * m, where * denotes solvable multiplication.
564     */
565    @Override
566    public QuotSolvablePolynomial<C> multiply(Map.Entry<ExpVector, SolvableQuotient<C>> m) {
567        if (m == null) {
568            return ring.getZERO();
569        }
570        return multiply(m.getValue(), m.getKey());
571    }
572
573
574    /**
575     * QuotSolvablePolynomial multiplication. Left product with coefficient ring
576     * element.
577     * @param B solvable polynomial.
578     * @param f exponent vector.
579     * @return B*f, where * is commutative multiplication.
580     */
581    protected QuotSolvablePolynomial<C> shift(QuotSolvablePolynomial<C> B, ExpVector f) {
582        QuotSolvablePolynomial<C> C = ring.getZERO().copy();
583        if (B == null || B.isZERO()) {
584            return C;
585        }
586        if (f == null || f.isZERO()) {
587            return B;
588        }
589        Map<ExpVector, SolvableQuotient<C>> Cm = C.val;
590        Map<ExpVector, SolvableQuotient<C>> Bm = B.val;
591        for (Map.Entry<ExpVector, SolvableQuotient<C>> y : Bm.entrySet()) {
592            ExpVector e = y.getKey();
593            SolvableQuotient<C> a = y.getValue();
594            ExpVector d = e.sum(f);
595            if (!a.isZERO()) {
596                Cm.put(d, a);
597            }
598        }
599        return C;
600    }
601
602}