001/*
002 * $Id: PolynomialList.java 4125 2012-08-19 19:05:22Z kredel $
003 */
004
005package edu.jas.poly;
006
007
008import java.lang.Comparable;
009import java.util.List;
010import java.util.ArrayList;
011import java.util.Map;
012import java.io.Serializable;
013
014import org.apache.log4j.Logger;
015
016import edu.jas.structure.RingElem;
017import edu.jas.kern.Scripting;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenSolvablePolynomial;
020import edu.jas.poly.GenPolynomialRing;
021import edu.jas.poly.GenSolvablePolynomialRing;
022
023
024/**
025 * List of polynomials.
026 * Mainly for storage and printing / toString and 
027 * conversions to other representations.
028 * @author Heinz Kredel
029 */
030
031public class PolynomialList<C extends RingElem<C> > 
032    implements Comparable<PolynomialList<C>>, Serializable {
033
034
035    /** The factory for the solvable polynomial ring. 
036     */
037    public final GenPolynomialRing< C > ring;
038
039
040    /** The data structure is a List of polynomials. 
041     */
042    public final List< GenPolynomial<C> > list;
043
044
045    private static final Logger logger = Logger.getLogger(PolynomialList.class);
046
047
048    /**
049     * Constructor.
050     * @param r polynomial ring factory.
051     * @param l list of polynomials.
052     */
053    public PolynomialList( GenPolynomialRing< C > r,
054                           List<GenPolynomial< C >> l) {
055        ring = r;
056        list = l; 
057    }
058
059
060    /**
061     * Constructor.
062     * @param r solvable polynomial ring factory.
063     * @param l list of solvable polynomials.
064     */
065    public PolynomialList( GenSolvablePolynomialRing< C > r,
066                           List<GenSolvablePolynomial< C >> l) {
067        this( r, PolynomialList.<C>castToList(l) ); 
068    }
069
070
071    /**
072     * Copy this.
073     * @return a copy of this.
074     */
075    public PolynomialList<C> copy() {
076        return new PolynomialList<C>(ring,new ArrayList<GenPolynomial<C>>(list));
077    }
078
079
080    /** Comparison with any other object.
081     * @see java.lang.Object#equals(java.lang.Object)
082     */
083    @Override 
084    @SuppressWarnings("unchecked")
085    public boolean equals(Object p) {
086        if ( ! (p instanceof PolynomialList) ) {
087            System.out.println("no PolynomialList");
088            return false;
089        }
090        PolynomialList< C > pl = null;
091        try {
092            pl = (PolynomialList< C >)p;
093        } catch (ClassCastException ignored) {
094        }
095        if ( pl == null ) {
096            return false;
097        }
098        if ( ! ring.equals( pl.ring ) ) {
099            System.out.println("not same Ring " + ring.toScript() + ", " + pl.ring.toScript());
100            return false;
101        }
102        return ( compareTo(pl) == 0 );
103        // otherwise tables may be different
104    }
105
106
107    /** Polynomial list comparison.  
108     * @param L other PolynomialList.
109     * @return lexicographical comparison, sign of first different polynomials.
110     */
111    public int compareTo(PolynomialList<C> L) {
112        int si = L.list.size();
113        if ( list.size() < si ) { // minimum
114            si = list.size();
115        }
116        int s = 0;
117        List<GenPolynomial<C>> l1 = OrderedPolynomialList.<C>sort( ring, list );
118        List<GenPolynomial<C>> l2 = OrderedPolynomialList.<C>sort( ring, L.list );
119        for ( int i = 0; i < si; i++ ) {
120            GenPolynomial<C> a = l1.get(i);
121            GenPolynomial<C> b = l2.get(i);
122            s = a.compareTo(b);
123            if ( s != 0 ) {
124                return s;
125            }
126        }
127        if ( list.size() > si ) { 
128            return 1;
129        }
130        if ( L.list.size() > si ) { 
131            return -1;
132        }
133        return s;
134    }
135
136
137    /** Hash code for this polynomial list.
138     * @see java.lang.Object#hashCode()
139     */
140    @Override
141    public int hashCode() { 
142        int h;
143        h = ring.hashCode();
144        h = 37 * h + ( list == null ? 0 : list.hashCode() );
145        return h;
146    }
147
148
149    /**
150     * String representation of the polynomial list.
151     * @see java.lang.Object#toString()
152     */
153    @Override
154    public String toString() {
155        StringBuffer erg = new StringBuffer();
156        String[] vars = null;
157        if ( ring != null ) {
158            erg.append( ring.toString() );
159            vars = ring.getVars();
160        }
161        boolean first = true;
162        erg.append("\n(\n");
163        String sa = null;
164        for ( GenPolynomial<C> oa: list ) {
165            if ( vars != null ) {
166                sa = oa.toString(vars);
167            } else {
168                sa = oa.toString();
169            }
170            if ( first ) {
171                first = false;
172            } else {
173                erg.append( ", " );
174                if ( sa.length() > 10 ) {
175                    erg.append("\n");
176                }
177            }
178            erg.append( "( " + sa + " )" );
179        }
180        erg.append("\n)");
181        return erg.toString();
182    }
183
184
185    /** Get a scripting compatible string representation.
186     * @return script compatible representation for this polynomial list.
187     */
188    public String toScript() {
189        StringBuffer s = new StringBuffer();
190        switch (Scripting.getLang() ) {
191        case Ruby:
192            s.append("SimIdeal.new(");
193            break;
194        case Python:
195        default:
196            s.append("Ideal(");
197        }
198        if ( ring != null ) {
199            s.append( ring.toScript() );
200        }
201        if ( list == null ) {
202            s.append(")");
203            return s.toString();
204        }
205        switch (Scripting.getLang() ) {
206        case Ruby:
207            s.append(",\"\",[");
208            break;
209        case Python:
210        default:
211            s.append(",list=[");
212        }
213        boolean first = true;
214        String sa = null;
215        for ( GenPolynomial<C> oa: list ) {
216            sa = oa.toScript();
217            if ( first ) {
218                first = false;
219            } else {
220                s.append( ", " );
221            }
222            s.append( "( " + sa + " )" );
223        }
224        s.append("])");
225        return s.toString();
226    }
227
228
229    /**
230     * Get ModuleList from PolynomialList.
231     * Extract module from polynomial ring. 
232     * @see edu.jas.poly.ModuleList
233     * @param i number of variables to be contract form the polynomials.
234     * @return module list corresponding to this.
235     */
236    @SuppressWarnings("unchecked")
237    public ModuleList<C> getModuleList(int i) {
238        GenPolynomialRing< C > pfac = ring.contract(i);
239        logger.debug("contracted ring = " + pfac);
240        //System.out.println("contracted ring = " + pfac);
241
242        List<List<GenPolynomial<C>>> vecs = null;
243        if ( list == null ) { 
244            return new ModuleList<C>(pfac,vecs);
245        }
246        int rows = list.size();
247        vecs = new ArrayList<List<GenPolynomial<C>>>( rows );
248        if ( rows == 0 ) { // nothing to do
249            return new ModuleList<C>(pfac,vecs);
250        }
251
252        ArrayList<GenPolynomial<C>> zr 
253            = new ArrayList<GenPolynomial<C>>( i-1 );
254        GenPolynomial<C> zero = pfac.getZERO();
255        for ( int j = 0; j < i; j++ ) {
256            zr.add(j,zero);
257        }
258
259        for ( GenPolynomial<C> p: list ) {
260            if ( p != null ) {
261                Map<ExpVector,GenPolynomial<C>> r = p.contract( pfac );
262                //System.out.println("r = " + r ); 
263                List<GenPolynomial<C>> row 
264                    = (ArrayList<GenPolynomial<C>>)zr.clone();
265                for ( Map.Entry<ExpVector,GenPolynomial<C>> me : r.entrySet() ) {
266                    ExpVector e = me.getKey();
267                    int[] dov = e.dependencyOnVariables();
268                    int ix = 0;
269                    if ( dov.length > 1 ) {
270                        throw new IllegalArgumentException("wrong dependencyOnVariables " + e);
271                    } else if ( dov.length == 1 )  {
272                        ix = dov[0];
273                    }
274                    //ix = i-1 - ix; // revert
275                    //System.out.println("ix = " + ix ); 
276                    GenPolynomial<C> vi = me.getValue(); //r.get( e );
277                    row.set(ix,vi);
278                }
279                //System.out.println("row = " + row ); 
280                vecs.add( row );
281            }
282        }
283        return new ModuleList<C>(pfac,vecs);
284    }
285
286
287    /**
288     * Get list as List of GenSolvablePolynomials.
289     * Required because no List casts allowed. Equivalent to 
290     * cast (List&lt;GenSolvablePolynomial&lt;C&gt;&gt;) list.
291     * @return solvable polynomial list from this.
292     */
293    public List< GenSolvablePolynomial<C> > castToSolvableList() {
294        return castToSolvableList(list);
295    }
296
297
298    /**
299     * Get list as List of GenSolvablePolynomials.
300     * Required because no List casts allowed. Equivalent to 
301     * cast (List&lt;GenSolvablePolynomial&lt;C&gt;&gt;) list.
302     * @param list list of extensions of polynomials.
303     * @return solvable polynomial list from this.
304     */
305    public static <C extends RingElem<C> > 
306                             List< GenSolvablePolynomial<C> > castToSolvableList(List<GenPolynomial<C>> list) {
307        List< GenSolvablePolynomial<C> > slist = null;
308        if ( list == null ) {
309            return slist;
310        }
311        slist = new ArrayList< GenSolvablePolynomial<C> >( list.size() ); 
312        GenSolvablePolynomial<C> s;
313        for ( GenPolynomial<C> p: list ) {
314            if ( ! (p instanceof GenSolvablePolynomial) ) {
315                throw new IllegalArgumentException("no solvable polynomial "+p);
316            }
317            s = (GenSolvablePolynomial<C>) p;
318            slist.add( s );
319        }
320        return slist;
321    }
322
323
324    /**
325     * Get list of list as List of List of GenSolvablePolynomials.
326     * Required because no List casts allowed. Equivalent to 
327     * cast (List&lt;GenSolvablePolynomial&lt;C&gt;&gt;) list.
328     * @param list list of extensions of polynomials.
329     * @return solvable polynomial list from this.
330     */
331    public static <C extends RingElem<C> > 
332                             List<List< GenSolvablePolynomial<C> >> castToSolvableMatrix(List<List<GenPolynomial<C>>> list) {
333        List<List< GenSolvablePolynomial<C> >> slist = null;
334        if ( list == null ) {
335            return slist;
336        }
337        slist = new ArrayList< List<GenSolvablePolynomial<C>> >( list.size() ); 
338        List<GenSolvablePolynomial<C>> s;
339        for ( List<GenPolynomial<C>> p: list ) {
340            s = PolynomialList.<C>castToSolvableList(p);
341            slist.add( s );
342        }
343        return slist;
344    }
345
346
347    /**
348     * Get list of extensions of polynomials as List of GenPolynomials.
349     * Required because no List casts allowed. Equivalent to 
350     * cast (List&lt;GenPolynomial&lt;C&gt;&gt;) list.
351     * Mainly used for lists of GenSolvablePolynomials.
352     * @param slist list of extensions of polynomials.
353     * @return polynomial list from slist.
354     */
355    public static <C extends RingElem<C> > 
356                             List< GenPolynomial<C> > 
357                             castToList( List<? extends GenPolynomial<C>> slist) {
358        logger.warn("will lead to wrong method dispatch");
359        List< GenPolynomial<C> > list = null;
360        if ( slist == null ) {
361            return list;
362        }
363        list = new ArrayList< GenPolynomial<C> >( slist.size() ); 
364        for ( GenPolynomial<C> p: slist ) {
365            list.add( p );
366        }
367        return list;
368    }
369
370
371    /**
372     * Get list of list of extensions of polynomials as List of List of GenPolynomials.
373     * Required because no List casts allowed. Equivalent to 
374     * cast (List&lt;GenPolynomial&lt;C&gt;&gt;) list.
375     * Mainly used for lists of GenSolvablePolynomials.
376     * @param slist list of extensions of polynomials.
377     * @return polynomial list from slist.
378     */
379    public static <C extends RingElem<C> > 
380                             List<List< GenPolynomial<C> >> 
381                             castToMatrix( List<List<? extends GenPolynomial<C>>> slist) {
382        logger.warn("will lead to wrong method dispatch");
383        List<List< GenPolynomial<C> >> list = null;
384        if ( slist == null ) {
385            return list;
386        }
387        list = new ArrayList< List<GenPolynomial<C>> >( slist.size() ); 
388        for ( List<? extends GenPolynomial<C>> p: slist ) {
389            list.add( PolynomialList.<C>castToList(p) );
390        }
391        return list;
392    }
393
394
395    /**
396     * Test if list contains only ZEROs.
397     * @return true, if this is the 0 list, else false
398     */
399    public boolean isZERO() {
400        if ( list == null ) {
401            return true;
402        }
403        for ( GenPolynomial<C> p : list ) {
404            if ( p == null ) {
405                continue;
406            }
407            if ( ! p.isZERO() ) {
408                return false;
409            }
410        }
411        return true;
412    }
413
414
415    /**
416     * Test if list contains a ONE.
417     * @return true, if this contains 1, else false
418     */
419    public boolean isONE() {
420        if ( list == null ) {
421            return false;
422        }
423        for ( GenPolynomial<C> p : list ) {
424            if ( p == null ) {
425                continue;
426            }
427            if ( p.isONE() ) {
428                return true;
429            }
430        }
431        return false;
432    }
433
434
435    /**
436     * Make homogeneous. 
437     * @return polynomial list of homogeneous polynomials.
438     */
439    public PolynomialList<C> homogenize() {
440        GenPolynomialRing<C> pfac = ring.extend(1);
441        List<GenPolynomial<C>> hom = new ArrayList<GenPolynomial<C>>(list.size());
442        for (GenPolynomial<C> p : list) {
443            GenPolynomial<C> h = p.homogenize(pfac);
444            hom.add(h);
445        }
446        return new PolynomialList<C>(pfac,hom);
447    }
448
449    /**
450     * Dehomogenize. 
451     * @return polynomial list of de-homogenized polynomials.
452     */
453    public PolynomialList<C> deHomogenize() {
454        GenPolynomialRing<C> pfac = ring.contract(1);
455        List<GenPolynomial<C>> dehom = new ArrayList<GenPolynomial<C>>(list.size());
456        for (GenPolynomial<C> p : list) {
457            GenPolynomial<C> h = p.deHomogenize(pfac);
458            dehom.add(h);
459        }
460        return new PolynomialList<C>(pfac,dehom);
461    }
462
463
464    /**
465     * Test if all polynomials are homogeneous.
466     * @return true, if all polynomials are homogeneous, else false
467     */
468    public boolean isHomogeneous() {
469        if ( list == null ) {
470            return true;
471        }
472        for ( GenPolynomial<C> p : list ) {
473            if ( p == null ) {
474                continue;
475            }
476            if ( ! p.isHomogeneous() ) {
477                return false;
478            }
479        }
480        return true;
481    }
482
483}