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