001/*
002 * $Id: ModuleList.java 3992 2012-07-14 21:32:18Z kredel $
003 */
004
005package edu.jas.poly;
006
007import java.util.List;
008import java.util.ArrayList;
009import java.io.Serializable;
010
011import org.apache.log4j.Logger;
012
013import edu.jas.kern.Scripting;
014import edu.jas.structure.RingElem;
015import edu.jas.vector.GenVector;
016import edu.jas.vector.GenVectorModul;
017
018
019/**
020 * List of vectors of polynomials.
021 * Mainly for storage and printing / toString and 
022 * conversions to other representations.
023 * @author Heinz Kredel
024 */
025
026public class ModuleList<C extends RingElem<C> > implements Serializable {
027
028
029    /** The factory for the solvable polynomial ring. 
030     */
031    public final GenPolynomialRing< C > ring;
032
033
034    /** The data structure is a List of Lists of polynomials. 
035     */
036    public final List< List< GenPolynomial<C> > > list;
037
038
039    /** Number of rows in the data structure. 
040     */
041    public final int rows; // -1 is undefined
042
043
044    /** Number of columns in the data structure. 
045     */
046    public final int cols; // -1 is undefined
047
048
049    private static final Logger logger = Logger.getLogger(ModuleList.class);
050
051
052    /**
053     * Constructor.
054     * @param r polynomial ring factory.
055     * @param l list of list of polynomials.
056     */
057    public ModuleList( GenPolynomialRing< C > r,
058                       List< List<GenPolynomial< C >>> l) {
059        ring = r;
060        list = ModuleList.<C>padCols(r,l); 
061        if ( list == null ) {
062            rows = -1; 
063            cols = -1;
064        } else {
065            rows = list.size();
066            if ( rows > 0 ) {
067                cols = list.get(0).size();
068            } else {
069                cols = -1;
070            }
071        }
072    }
073
074
075    /**
076     * Constructor.
077     * @param r solvable polynomial ring factory.
078     * @param l list of list of solvable polynomials.
079     */
080    public ModuleList( GenSolvablePolynomialRing< C > r,
081                       List< List<GenSolvablePolynomial< C >>> l) {
082        this( r, ModuleList.<C>castToList(l) );
083    }
084
085
086    /**
087     * Constructor.
088     * @param r polynomial ring factory.
089     * @param l list of vectors of polynomials.
090     */
091    public ModuleList( GenVectorModul<GenPolynomial<C>> r,
092                       List< GenVector<GenPolynomial< C >>> l) {
093        this( (GenPolynomialRing<C>)r.coFac, ModuleList.<C>vecToList(l) );
094    }
095
096
097    /** Comparison with any other object.
098     * @see java.lang.Object#equals(java.lang.Object)
099     */
100    @Override
101    @SuppressWarnings("unchecked") // not jet working
102    public boolean equals(Object m) {
103        if ( ! (m instanceof ModuleList) ) {
104            //System.out.println("ModuleList");
105            return false;
106        }
107        ModuleList<C> ml = null;
108        try {
109            ml = (ModuleList<C>)m;
110        } catch (ClassCastException ignored) {
111        }
112        if ( ml == null ) { 
113            return false;
114        }
115        if ( ! ring.equals( ml.ring ) ) {
116            //System.out.println("Ring");
117            return false;
118        }
119        if ( list == ml.list ) {
120            return true;
121        }
122        if ( list == null || ml.list == null ) {
123            //System.out.println("List, null");
124            return false;
125        }
126        if ( list.size() != ml.list.size() ) {
127            //System.out.println("List, size");
128            return false;
129        }
130        // compare sorted lists
131        List otl = OrderedModuleList.sort( ring, list );
132        List oml = OrderedModuleList.sort( ring, ml.list );
133        if ( ! otl.equals(oml) ) {
134            return false;
135        }
136        return true;
137    }
138
139
140    /** Hash code for this module list.
141     * @see java.lang.Object#hashCode()
142     */
143    @Override
144    public int hashCode() { 
145       int h;
146       h = ring.hashCode();
147       h = 37 * h + ( list == null ? 0 : list.hashCode() );
148       return h;
149    }
150
151
152    /**
153     * String representation of the module list.
154     * @see java.lang.Object#toString()
155     */
156    @Override
157    //@SuppressWarnings("unchecked") 
158    public String toString() {
159        StringBuffer erg = new StringBuffer();
160        String[] vars = null;
161        if ( ring != null ) {
162           erg.append( ring.toString() );
163           vars = ring.getVars();
164        }
165        if ( list == null ) {
166            erg.append(")");
167            return erg.toString();
168        }
169        boolean first = true;
170        erg.append("(\n");
171        for ( List< GenPolynomial<C> > row: list ) {
172            if ( first ) {
173               first = false;
174            } else {
175               erg.append( ",\n" );
176            }
177            boolean ifirst = true;
178            erg.append(" ( ");
179            String os;
180            for ( GenPolynomial<C> oa: row ) {
181                if ( oa == null ) {
182                   os = "0";
183                } else if ( vars != null ) {
184                   os = oa.toString(vars);
185                } else {
186                   os = oa.toString();
187                }
188                if ( ifirst ) {
189                   ifirst = false;
190                } else {
191                   erg.append( ", " );
192                   if ( os.length() > 100 ) {
193                      erg.append("\n");
194                   }
195                }
196                erg.append( os );
197            }
198            erg.append(" )");
199        }
200        erg.append("\n)");
201        return erg.toString();
202    }
203
204
205    /** Get a scripting compatible string representation.
206     * @return script compatible representation for this ModuleList.
207     */
208    public String toScript() {
209        StringBuffer s = new StringBuffer();
210        if ( ring instanceof GenSolvablePolynomialRing ) {
211            s.append("Solvable");
212        }
213        switch (Scripting.getLang() ) {
214        case Ruby:
215            s.append("SubModule.new(");
216            break;
217        case Python:
218        default:
219            s.append("SubModule(");
220        }
221        if ( ring != null ) {
222           s.append( ring.toScript() );
223        }
224        if ( list == null ) {
225            s.append(")");
226            return s.toString();
227        }
228        switch (Scripting.getLang() ) {
229        case Ruby:
230            s.append(",\"\",[");
231            break;
232        case Python:
233        default:
234            s.append(",list=[");
235        }
236        boolean first = true;
237        for ( List< GenPolynomial<C> > row: list ) {
238            if ( first ) {
239               first = false;
240            } else {
241               s.append( "," );
242            }
243            boolean ifirst = true;
244            s.append(" ( ");
245            String os;
246            for ( GenPolynomial<C> oa: row ) {
247                if ( oa == null ) {
248                   os = "0";
249                } else {
250                   os = oa.toScript();
251                }
252                if ( ifirst ) {
253                   ifirst = false;
254                } else {
255                   s.append( ", " );
256                }
257                s.append( os );
258            }
259            s.append(" )");
260        }
261        s.append(" ])");
262        return s.toString();
263    }
264
265
266    /**
267     * Pad columns and remove zero rows.
268     * Make all rows have the same number of columns.
269     * @param ring polynomial ring factory.
270     * @param l list of list of polynomials.
271     * @return list of list of polynomials with same number of colums.
272     */
273    public static <C extends RingElem<C> >
274        List< List<GenPolynomial< C >>> 
275                      padCols(GenPolynomialRing< C > ring,
276                              List< List<GenPolynomial< C >>> l) {
277        if ( l == null ) {
278           return l;
279        }
280        int mcols = 0;
281        int rs = 0;
282        for ( List< GenPolynomial<C> > row: l ) {
283            if ( row != null ) {
284               rs++;
285               if ( row.size() > mcols ) {
286                  mcols = row.size();
287               }
288            }
289        }
290        List< List<GenPolynomial<C>> > norm 
291            = new ArrayList< List<GenPolynomial<C>> >( rs );
292        for ( List< GenPolynomial<C> > row: l ) {
293            if ( row != null ) {
294                List<GenPolynomial<C>> rn 
295                    = new ArrayList<GenPolynomial<C>>( row );
296                while ( rn.size() < mcols ) {
297                    rn.add( ring.getZERO() );
298                }
299                norm.add( rn );
300            }
301        }
302        return norm;
303    }
304
305
306
307    /**
308     * Get PolynomialList.
309     * Embed module in a polynomial ring. 
310     * @see edu.jas.poly.PolynomialList
311     * @return polynomial list corresponding to this.
312     */
313    public PolynomialList<C> getPolynomialList() {
314        GenPolynomialRing< C > pfac = ring.extend(cols);
315        logger.debug("extended ring = " + pfac);
316        //System.out.println("extended ring = " + pfac);
317
318        List<GenPolynomial<C>> pols = null;
319        if ( list == null ) { // rows < 0
320           return new PolynomialList<C>(pfac,pols);
321        }
322        pols = new ArrayList<GenPolynomial<C>>( rows );
323        if ( rows == 0 ) { // nothing to do
324           return new PolynomialList<C>(pfac,pols);
325        }
326
327        GenPolynomial<C> zero = pfac.getZERO();
328        GenPolynomial<C> d = null;
329        for ( List<GenPolynomial<C>> r: list ) {
330            GenPolynomial<C> ext = zero;
331            //int m = cols-1;
332            int m = 0;
333            for ( GenPolynomial<C> c: r ) {
334                d = c.extend( pfac, m, 1l );
335                ext = ext.sum(d); 
336                m++;
337            }
338            pols.add( ext );
339        }
340        return new PolynomialList<C>(pfac, pols);
341    }
342
343
344    /**
345     * Get list as List of GenSolvablePolynomials.
346     * Required because no List casts allowed. Equivalent to 
347     * cast (List&lt;List&lt;GenSolvablePolynomial&lt;C&gt;&gt;&gt;) list.
348     * @return list of solvable polynomial lists from this.
349     */
350    public List< List< GenSolvablePolynomial<C> > > castToSolvableList() {
351        List< List<GenSolvablePolynomial<C>> > slist = null;
352        if ( list == null ) {
353            return slist;
354        }
355        slist = new ArrayList< List<GenSolvablePolynomial<C>> >( list.size() ); 
356        for ( List< GenPolynomial<C>> row: list ) {
357            List< GenSolvablePolynomial<C> > srow 
358                = new ArrayList< GenSolvablePolynomial<C> >( row.size() ); 
359            for ( GenPolynomial<C> p: row ) {
360                if ( ! (p instanceof GenSolvablePolynomial) ) {
361                    throw new RuntimeException("no solvable polynomial "+p);
362                }
363                GenSolvablePolynomial<C> s
364                    = (GenSolvablePolynomial<C>) p;
365                srow.add( s );
366            }
367            slist.add( srow );
368        }
369        return slist;
370    }
371
372
373    /**
374     * Get a solvable polynomials list as List of GenPolynomials.
375     * Required because no List casts allowed. Equivalent to 
376     * cast (List&lt;List&lt;GenPolynomial&lt;C&gt;&gt;&gt;) list.
377     * @param slist list of solvable polynomial lists.
378     * @return list of polynomial lists from slist.
379     */
380    public static <C extends RingElem<C> >
381           List< List< GenPolynomial<C> > > 
382           castToList( List< List<GenSolvablePolynomial<C>> > slist ) {
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< GenSolvablePolynomial<C>> srow: slist ) {
389            List< GenPolynomial<C> > row 
390                = new ArrayList< GenPolynomial<C> >( srow.size() ); 
391            for ( GenSolvablePolynomial<C> s: srow ) {
392                row.add( s );
393            }
394            list.add( row );
395        }
396        return list;
397    }
398
399
400    /**
401     * Get a list of vectors as List of list of GenPolynomials.
402     * @param vlist list of vectors of polynomials.
403     * @return list of polynomial lists from vlist.
404     */
405    public static <C extends RingElem<C> >
406           List< List< GenPolynomial<C> > > 
407           vecToList( List< GenVector<GenPolynomial<C>> > vlist ) {
408        List< List<GenPolynomial<C>> > list = null;
409        if ( vlist == null ) {
410            return list;
411        }
412        list = new ArrayList< List<GenPolynomial<C>> >( vlist.size() ); 
413        for ( GenVector< GenPolynomial<C>> srow: vlist ) {
414            List< GenPolynomial<C> > row = srow.val; 
415            list.add( row );
416        }
417        return list;
418    }
419
420}