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