001/*
002 * $Id: GenSolvablePolynomial.java 4142 2012-08-26 13:30:59Z kredel $
003 */
004
005package edu.jas.poly;
006
007import java.util.Set;
008import java.util.Map;
009import java.util.SortedMap;
010
011import org.apache.log4j.Logger;
012
013import edu.jas.structure.RingElem;
014import edu.jas.structure.RingFactory;
015
016
017/**
018 * GenSolvablePolynomial generic solvable polynomials implementing RingElem.
019 * n-variate ordered solvable polynomials over C.
020 * Objects of this class are intended to be immutable.
021 * The implementation is based on TreeMap respectively SortedMap 
022 * from exponents to coefficients by extension of GenPolybomial.
023 * Only the coefficients are modeled with generic types,
024 * the exponents are fixed to ExpVector with long entries 
025 * (this will eventually be changed in the future). 
026 * @param <C> coefficient type
027 * @author Heinz Kredel
028 */
029
030public class GenSolvablePolynomial<C extends RingElem<C>> 
031    extends GenPolynomial<C> {
032    //not possible: implements RingElem< GenSolvablePolynomial<C> > {
033
034
035    /** The factory for the solvable polynomial ring. 
036     * Hides super.ring.
037     */
038    public final GenSolvablePolynomialRing< C > ring;
039
040
041    private static final Logger logger = Logger.getLogger(GenSolvablePolynomial.class);
042    private final boolean debug = false; //logger.isDebugEnabled();
043
044
045    /**
046     * Constructor for zero GenSolvablePolynomial.
047     * @param r solvable polynomial ring factory.
048     */
049    public GenSolvablePolynomial(GenSolvablePolynomialRing< C > r) {
050        super(r);
051        ring = r;
052    }
053
054
055    /**
056     * Constructor for GenSolvablePolynomial.
057     * @param r solvable polynomial ring factory.
058     * @param c coefficient.
059     * @param e exponent.
060     */
061    public GenSolvablePolynomial(GenSolvablePolynomialRing< C > r, 
062                                 C c, ExpVector e) {
063        this(r);
064        if ( c != null && ! c.isZERO() ) {
065            val.put(e,c);
066        }
067    }
068
069
070    /**
071     * Constructor for GenSolvablePolynomial.
072     * @param r solvable polynomial ring factory.
073     * @param c coefficient.
074     */
075    public GenSolvablePolynomial(GenSolvablePolynomialRing< C > r, C c) {
076        this(r,c,r.evzero);
077    }
078
079
080    /**
081     * Constructor for GenSolvablePolynomial.
082     * @param r solvable polynomial ring factory.
083     * @param v the SortedMap of some other (solvable) polynomial.
084     */
085    protected GenSolvablePolynomial(GenSolvablePolynomialRing< C > r, 
086                                 SortedMap<ExpVector,C> v) {
087        this(r);
088        val.putAll( v ); // assume no zero coefficients
089    }
090
091
092    /**
093     * Get the corresponding element factory.
094     * @return factory for this Element.
095     * @see edu.jas.structure.Element#factory()
096     */
097    public GenSolvablePolynomialRing<C> factory() {
098        return ring;
099    }
100
101
102    /**
103     * Clone this GenSolvablePolynomial.
104     * @see java.lang.Object#clone()
105     */
106    @Override
107    public GenSolvablePolynomial<C> copy() {
108        //return ring.copy(this);
109        return new GenSolvablePolynomial<C>(ring,this.val);
110    }
111
112
113    /**
114     * Comparison with any other object.
115     * @see java.lang.Object#equals(java.lang.Object)
116     */
117    @Override
118    public boolean equals(Object B) {
119        if (!(B instanceof GenSolvablePolynomial)) {
120            return false;
121        }
122        return super.equals(B);
123    }
124
125
126    /**
127     * GenSolvablePolynomial multiplication. 
128     * @param Bp GenSolvablePolynomial.
129     * @return this*Bp, where * denotes solvable multiplication.
130     */
131    public GenSolvablePolynomial<C> multiply(GenSolvablePolynomial<C> Bp) {  
132        if ( Bp == null || Bp.isZERO() ) {
133            return ring.getZERO();
134        }
135        if ( this.isZERO() ) {
136            return this;
137        }
138        assert (ring.nvar == Bp.ring.nvar);
139        if ( debug ) {
140            logger.debug("ring = " + ring);
141        }
142        ExpVector Z = ring.evzero;
143        GenSolvablePolynomial<C> Cp = ring.getZERO().copy(); 
144        GenSolvablePolynomial<C> zero = ring.getZERO().copy();
145        C one = ring.getONECoefficient();
146
147        GenSolvablePolynomial<C> C1 = null;
148        GenSolvablePolynomial<C> C2 = null;
149        Map<ExpVector,C> A = val; 
150        Map<ExpVector,C> B = Bp.val; 
151        Set<Map.Entry<ExpVector,C>> Bk = B.entrySet();
152        for ( Map.Entry<ExpVector,C> y:  A.entrySet() ) {
153            C a = y.getValue(); 
154            ExpVector e = y.getKey(); 
155            if ( debug ) logger.debug("e = " + e);
156            int[] ep = e.dependencyOnVariables();
157            int el1 = ring.nvar + 1;
158            if ( ep.length > 0 ) {
159                el1 = ep[0];
160            }
161            int el1s = ring.nvar + 1 - el1; 
162            for ( Map.Entry<ExpVector,C> x: Bk ) {
163                C b = x.getValue(); 
164                ExpVector f = x.getKey(); 
165                if ( debug ) logger.debug("f = " + f);
166                int[] fp = f.dependencyOnVariables();
167                int fl1 = 0; 
168                if ( fp.length > 0 ) {
169                    fl1 = fp[fp.length-1];
170                }
171                int fl1s = ring.nvar + 1 - fl1; 
172                if ( debug ) {
173                    logger.debug("el1s = " + el1s + " fl1s = " + fl1s);
174                }
175                GenSolvablePolynomial<C> Cs = null;
176                if ( el1s <= fl1s ) { // symmetric
177                    ExpVector g = e.sum(f); 
178                    //if ( debug ) logger.debug("g = " + g);
179                    Cs = (GenSolvablePolynomial<C>)zero.sum( one, g ); // symmetric!
180                    //Cs = new GenSolvablePolynomial<C>(ring,one,g); // symmetric!
181                } else { // unsymmetric
182                    // split e = e1 * e2, f = f1 * f2
183                    ExpVector e1 = e.subst(el1,0);
184                    ExpVector e2 = Z.subst(el1,e.getVal(el1));
185                    ExpVector e4;
186                    ExpVector f1 = f.subst(fl1,0);
187                    ExpVector f2 = Z.subst(fl1,f.getVal(fl1));
188                    //if ( debug ) logger.debug("e1 = " + e1 + " e2 = " + e2);
189                    //if ( debug ) logger.debug("f1 = " + f1 + " f2 = " + f2);
190                    TableRelation<C> rel = ring.table.lookup(e2,f2); 
191                    //logger.info("relation = " + rel);
192                    Cs = rel.p; //ring.copy( rel.p ); // do not clone() 
193                    if ( rel.f != null ) {
194                        C2 = (GenSolvablePolynomial<C>)zero.sum( one, rel.f );
195                        Cs = Cs.multiply( C2 );
196                        if ( rel.e == null ) {
197                            e4 = e2;
198                        } else {
199                            e4 = e2.subtract( rel.e );
200                        }
201                        ring.table.update(e4,f2,Cs);
202                    }
203                    if ( rel.e != null ) {
204                        C1 = (GenSolvablePolynomial<C>)zero.sum( one, rel.e );
205                        Cs = C1.multiply( Cs );
206                        ring.table.update(e2,f2,Cs);
207                    }
208                    if ( !f1.isZERO() ) {
209                        C2 = (GenSolvablePolynomial<C>)zero.sum( one, f1 );
210                        Cs = Cs.multiply( C2 ); 
211                        //ring.table.update(?,f1,Cs)
212                    }
213                    if ( !e1.isZERO() ) {
214                        C1 = (GenSolvablePolynomial<C>)zero.sum( one, e1 );
215                        Cs = C1.multiply( Cs ); 
216                        //ring.table.update(e1,?,Cs)
217                    }
218                }
219                //C c = a.multiply(b);
220                Cs = Cs.multiply(a,b); // now non-symmetric // Cs.multiply(c); is symmetric!
221                //if ( debug ) logger.debug("Cs = " + Cs);
222                Cp = (GenSolvablePolynomial<C>)Cp.sum( Cs );
223            }
224        }
225        return Cp;
226    }
227
228
229    /**
230     * GenSolvablePolynomial left and right multiplication. Product with
231     * two polynomials.
232     * @param S GenSolvablePolynomial.
233     * @param T GenSolvablePolynomial.
234     * @return S*this*T.
235     */
236    public GenSolvablePolynomial<C> multiply(GenSolvablePolynomial<C> S, GenSolvablePolynomial<C> T) {
237        if ( S.isZERO() || T.isZERO() || this.isZERO() ) {
238            return ring.getZERO();
239        }
240        if ( S.isONE() ) {
241            return multiply(T);
242        }
243        if ( T.isONE() ) {
244            return S.multiply(this);
245        }
246        return S.multiply(this).multiply(T);
247    }
248
249
250    /**
251     * GenSolvablePolynomial multiplication. 
252     * Product with coefficient ring element.
253     * @param b coefficient.
254     * @return this*b, where * is usual multiplication.
255     */
256    @Override
257    public GenSolvablePolynomial<C> multiply(C b) {  
258        GenSolvablePolynomial<C> Cp = ring.getZERO().copy(); 
259        if ( b == null || b.isZERO() ) { 
260            return Cp;
261        }
262        Map<ExpVector,C> Cm = Cp.val; //getMap();
263        Map<ExpVector,C> Am = val; 
264        for ( Map.Entry<ExpVector,C> y: Am.entrySet() ) { 
265            ExpVector e = y.getKey(); 
266            C a = y.getValue(); 
267            C c = a.multiply(b);
268            if ( !c.isZERO() ) {
269                Cm.put( e, c );
270            }
271        }
272        return Cp;
273    }
274
275
276    /**
277     * GenSolvablePolynomial left and right multiplication. 
278     * Product with coefficient ring element.
279     * @param b coefficient.
280     * @param c coefficient.
281     * @return b*this*c, where * is coefficient multiplication.
282     */
283    public GenSolvablePolynomial<C> multiply(C b, C c) {  
284        GenSolvablePolynomial<C> Cp = ring.getZERO().copy(); 
285        if ( b == null || b.isZERO() ) { 
286            return Cp;
287        }
288        if ( c == null || c.isZERO() ) { 
289            return Cp;
290        }
291        Map<ExpVector,C> Cm = Cp.val; //getMap();
292        Map<ExpVector,C> Am = val; 
293        for ( Map.Entry<ExpVector,C> y: Am.entrySet() ) { 
294            ExpVector e = y.getKey(); 
295            C a = y.getValue(); 
296            C d = b.multiply(a).multiply(c);
297            if ( !d.isZERO() ) {
298                Cm.put( e, d );
299            }
300        }
301        return Cp;
302    }
303
304
305    /**
306     * GenSolvablePolynomial multiplication. 
307     * Product with exponent vector.
308     * @param e exponent.
309     * @return this * x<sup>e</sup>, 
310     * where * denotes solvable multiplication.
311     */
312    @Override
313    public GenSolvablePolynomial<C> multiply(ExpVector e) {  
314        if ( e == null || e.isZERO() ) { 
315            return this;
316        }
317        C b = ring.getONECoefficient();
318        return multiply(b, e);
319    }
320
321
322    /**
323     * GenSolvablePolynomial left and right multiplication. 
324     * Product with exponent vector.
325     * @param e exponent.
326     * @param f exponent.
327     * @return x<sup>e</sup> * this * x<sup>f</sup>, 
328     * where * denotes solvable multiplication.
329     */
330    public GenSolvablePolynomial<C> multiply(ExpVector e, ExpVector f) {  
331        if ( e == null || e.isZERO() ) { 
332            return this;
333        }
334        if ( f == null || f.isZERO() ) { 
335            return this;
336        }
337        C b = ring.getONECoefficient();
338        return multiply(b, e, b, f);
339    }
340
341
342    /**
343     * GenSolvablePolynomial multiplication. 
344     * Product with ring element and exponent vector.
345     * @param b coefficient.
346     * @param e exponent.
347     * @return this * b x<sup>e</sup>, 
348     * where * denotes solvable multiplication.
349     */
350    @Override
351    public GenSolvablePolynomial<C> multiply(C b, ExpVector e) {  
352        if ( b == null || b.isZERO() ) { 
353            return ring.getZERO();
354        }
355        GenSolvablePolynomial<C> Cp = new GenSolvablePolynomial<C>(ring,b,e);
356        return multiply(Cp);
357    }
358
359
360    /**
361     * GenSolvablePolynomial left and right multiplication. 
362     * Product with ring element and exponent vector.
363     * @param b coefficient.
364     * @param e exponent.
365     * @param c coefficient.
366     * @param f exponent.
367     * @return b x<sup>e</sup> * this * c x<sup>f</sup>, 
368     * where * denotes solvable multiplication.
369     */
370    public GenSolvablePolynomial<C> multiply(C b, ExpVector e, C c, ExpVector f) {   
371        if ( b == null || b.isZERO() ) { 
372            return ring.getZERO();
373        }
374        if ( c == null || c.isZERO() ) { 
375            return ring.getZERO();
376        }
377        GenSolvablePolynomial<C> Cp = new GenSolvablePolynomial<C>(ring,b,e);
378        GenSolvablePolynomial<C> Dp = new GenSolvablePolynomial<C>(ring,c,f);
379        return multiply(Cp,Dp);
380    }
381
382
383    /**
384     * GenSolvablePolynomial multiplication. 
385     * Left product with ring element and exponent vector.
386     * @param b coefficient.
387     * @param e exponent.
388     * @return b x<sup>e</sup> * this, 
389     * where * denotes solvable multiplication.
390     */
391    public GenSolvablePolynomial<C> multiplyLeft(C b, ExpVector e) {  
392        if ( b == null || b.isZERO() ) { 
393            return ring.getZERO();
394        }
395        GenSolvablePolynomial<C> Cp = new GenSolvablePolynomial<C>(ring,b,e);
396        return Cp.multiply(this);
397    }
398
399
400    /**
401     * GenSolvablePolynomial multiplication. 
402     * Left product with exponent vector.
403     * @param e exponent.
404     * @return x<sup>e</sup> * this, 
405     * where * denotes solvable multiplication.
406     */
407    public GenSolvablePolynomial<C> multiplyLeft(ExpVector e) {  
408        if ( e == null || e.isZERO() ) { 
409            return this;
410        }
411        C b = ring.getONECoefficient();
412        GenSolvablePolynomial<C> Cp = new GenSolvablePolynomial<C>(ring,b,e);
413        return Cp.multiply(this);
414    }
415
416
417    /**
418     * GenSolvablePolynomial multiplication. 
419     * Left product with coefficient ring element.
420     * @param b coefficient.
421     * @return b*this, where * is usual multiplication.
422     */
423    public GenSolvablePolynomial<C> multiplyLeft(C b) {  
424        GenSolvablePolynomial<C> Cp = ring.getZERO().copy(); 
425        if ( b == null || b.isZERO() ) { 
426            return Cp;
427        }
428        Map<ExpVector,C> Cm = Cp.val; //getMap();
429        Map<ExpVector,C> Am = val; 
430        for ( Map.Entry<ExpVector,C> y: Am.entrySet() ) { 
431            ExpVector e = y.getKey(); 
432            C a = y.getValue(); 
433            C c = b.multiply(a);
434            if ( !c.isZERO() ) {
435                Cm.put( e, c );
436            }
437        }
438        return Cp;
439    }
440
441
442    /**
443     * GenSolvablePolynomial multiplication. 
444     * Left product with 'monimial'.
445     * @param m 'monoial'.
446     * @return m * this, 
447     * where * denotes solvable multiplication.
448     */
449    public GenSolvablePolynomial<C> multiplyLeft(Map.Entry<ExpVector,C> m) {  
450        if ( m == null ) {
451            return ring.getZERO();
452        }
453        return multiplyLeft( m.getValue(), m.getKey() );
454    }
455
456}