001    /*
002     * $Id: ModuleList.java 3654 2011-06-02 18:19:30Z kredel $
003     */
004    
005    package edu.jas.poly;
006    
007    import java.util.List;
008    import java.util.ArrayList;
009    import java.io.Serializable;
010    
011    import org.apache.log4j.Logger;
012    
013    import edu.jas.kern.Scripting;
014    import edu.jas.structure.RingElem;
015    import edu.jas.vector.GenVector;
016    import 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    
026    public 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 != null && ml.list == null ) {
127                //System.out.println("List, null");
128                return false;
129            }
130            if ( list.size() != ml.list.size() ) {
131                //System.out.println("List, size");
132                return false;
133            }
134            // compare sorted lists
135            List otl = OrderedModuleList.sort( ring, list );
136            List oml = OrderedModuleList.sort( ring, ml.list );
137            if ( ! otl.equals(oml) ) {
138                return false;
139            }
140            return true;
141        }
142    
143    
144        /** Hash code for this module list.
145         * @see java.lang.Object#hashCode()
146         */
147        @Override
148        public int hashCode() { 
149           int h;
150           h = ring.hashCode();
151           h = 37 * h + ( list == null ? 0 : list.hashCode() );
152           return h;
153        }
154    
155    
156        /**
157         * String representation of the module list.
158         * @see java.lang.Object#toString()
159         */
160        @Override
161        //@SuppressWarnings("unchecked") 
162        public String toString() {
163            StringBuffer erg = new StringBuffer();
164            String[] vars = null;
165            if ( ring != null ) {
166               erg.append( ring.toString() );
167               vars = ring.getVars();
168            }
169            if ( list == null ) {
170                erg.append(")");
171                return erg.toString();
172            }
173            boolean first = true;
174            erg.append("(\n");
175            for ( List< GenPolynomial<C> > row: list ) {
176                if ( first ) {
177                   first = false;
178                } else {
179                   erg.append( ",\n" );
180                }
181                boolean ifirst = true;
182                erg.append(" ( ");
183                String os;
184                for ( GenPolynomial<C> oa: row ) {
185                    if ( oa == null ) {
186                       os = "0";
187                    } else if ( vars != null ) {
188                       os = oa.toString(vars);
189                    } else {
190                       os = oa.toString();
191                    }
192                    if ( ifirst ) {
193                       ifirst = false;
194                    } else {
195                       erg.append( ", " );
196                       if ( os.length() > 100 ) {
197                          erg.append("\n");
198                       }
199                    }
200                    erg.append( os );
201                }
202                erg.append(" )");
203            }
204            erg.append("\n)");
205            return erg.toString();
206        }
207    
208    
209        /** Get a scripting compatible string representation.
210         * @return script compatible representation for this ModuleList.
211         */
212        public String toScript() {
213            StringBuffer s = new StringBuffer();
214            if ( ring instanceof GenSolvablePolynomialRing ) {
215                s.append("Solvable");
216            }
217            switch (Scripting.getLang() ) {
218            case Ruby:
219                s.append("SubModule.new(");
220                break;
221            case Python:
222            default:
223                s.append("SubModule(");
224            }
225            if ( ring != null ) {
226               s.append( ring.toScript() );
227            }
228            if ( list == null ) {
229                s.append(")");
230                return s.toString();
231            }
232            s.append(",list=[");
233            boolean first = true;
234            for ( List< GenPolynomial<C> > row: list ) {
235                if ( first ) {
236                   first = false;
237                } else {
238                   s.append( "," );
239                }
240                boolean ifirst = true;
241                s.append(" ( ");
242                String os;
243                for ( GenPolynomial<C> oa: row ) {
244                    if ( oa == null ) {
245                       os = "0";
246                    } else {
247                       os = oa.toScript();
248                    }
249                    if ( ifirst ) {
250                       ifirst = false;
251                    } else {
252                       s.append( ", " );
253                    }
254                    s.append( os );
255                }
256                s.append(" )");
257            }
258            s.append(" ])");
259            return s.toString();
260        }
261    
262    
263        /**
264         * Pad columns and remove zero rows.
265         * Make all rows have the same number of columns.
266         * @param ring polynomial ring factory.
267         * @param l list of list of polynomials.
268         * @return list of list of polynomials with same number of colums.
269         */
270        public static <C extends RingElem<C> >
271            List< List<GenPolynomial< C >>> 
272                          padCols(GenPolynomialRing< C > ring,
273                                  List< List<GenPolynomial< C >>> l) {
274            if ( l == null ) {
275               return l;
276            }
277            int mcols = 0;
278            int rs = 0;
279            for ( List< GenPolynomial<C> > row: l ) {
280                if ( row != null ) {
281                   rs++;
282                   if ( row.size() > mcols ) {
283                      mcols = row.size();
284                   }
285                }
286            }
287            List< List<GenPolynomial<C>> > norm 
288                = new ArrayList< List<GenPolynomial<C>> >( rs );
289            for ( List< GenPolynomial<C> > row: l ) {
290                if ( row != null ) {
291                    List<GenPolynomial<C>> rn 
292                        = new ArrayList<GenPolynomial<C>>( row );
293                    while ( rn.size() < mcols ) {
294                        rn.add( ring.getZERO() );
295                    }
296                    norm.add( rn );
297                }
298            }
299            return norm;
300        }
301    
302    
303    
304        /**
305         * Get PolynomialList.
306         * Embed module in a polynomial ring. 
307         * @see edu.jas.poly.PolynomialList
308         * @return polynomial list corresponding to this.
309         */
310        public PolynomialList<C> getPolynomialList() {
311            GenPolynomialRing< C > pfac = ring.extend(cols);
312            logger.debug("extended ring = " + pfac);
313            //System.out.println("extended ring = " + pfac);
314    
315            List<GenPolynomial<C>> pols = null;
316            if ( list == null ) { // rows < 0
317               return new PolynomialList<C>(pfac,pols);
318            }
319            pols = new ArrayList<GenPolynomial<C>>( rows );
320            if ( rows == 0 ) { // nothing to do
321               return new PolynomialList<C>(pfac,pols);
322            }
323    
324            GenPolynomial<C> zero = pfac.getZERO();
325            GenPolynomial<C> d = null;
326            for ( List<GenPolynomial<C>> r: list ) {
327                GenPolynomial<C> ext = zero;
328                //int m = cols-1;
329                int m = 0;
330                for ( GenPolynomial<C> c: r ) {
331                    d = c.extend( pfac, m, 1l );
332                    ext = ext.sum(d); 
333                    m++;
334                }
335                pols.add( ext );
336            }
337            return new PolynomialList<C>(pfac, pols);
338        }
339    
340    
341        /**
342         * Get list as List of GenSolvablePolynomials.
343         * Required because no List casts allowed. Equivalent to 
344         * cast (List&lt;List&lt;GenSolvablePolynomial&lt;C&gt;&gt;&gt;) list.
345         * @return list of solvable polynomial lists from this.
346         */
347        public List< List< GenSolvablePolynomial<C> > > castToSolvableList() {
348            List< List<GenSolvablePolynomial<C>> > slist = null;
349            if ( list == null ) {
350                return slist;
351            }
352            slist = new ArrayList< List<GenSolvablePolynomial<C>> >( list.size() ); 
353            for ( List< GenPolynomial<C>> row: list ) {
354                List< GenSolvablePolynomial<C> > srow 
355                    = new ArrayList< GenSolvablePolynomial<C> >( row.size() ); 
356                for ( GenPolynomial<C> p: row ) {
357                    if ( ! (p instanceof GenSolvablePolynomial) ) {
358                        throw new RuntimeException("no solvable polynomial "+p);
359                    }
360                    GenSolvablePolynomial<C> s
361                        = (GenSolvablePolynomial<C>) p;
362                    srow.add( s );
363                }
364                slist.add( srow );
365            }
366            return slist;
367        }
368    
369    
370        /**
371         * Get a solvable polynomials list as List of GenPolynomials.
372         * Required because no List casts allowed. Equivalent to 
373         * cast (List&lt;List&lt;GenPolynomial&lt;C&gt;&gt;&gt;) list.
374         * @param slist list of solvable polynomial lists.
375         * @return list of polynomial lists from slist.
376         */
377        public static <C extends RingElem<C> >
378               List< List< GenPolynomial<C> > > 
379               castToList( List< List<GenSolvablePolynomial<C>> > slist ) {
380            List< List<GenPolynomial<C>> > list = null;
381            if ( slist == null ) {
382                return list;
383            }
384            list = new ArrayList< List<GenPolynomial<C>> >( slist.size() ); 
385            for ( List< GenSolvablePolynomial<C>> srow: slist ) {
386                List< GenPolynomial<C> > row 
387                    = new ArrayList< GenPolynomial<C> >( srow.size() ); 
388                for ( GenSolvablePolynomial<C> s: srow ) {
389                    row.add( s );
390                }
391                list.add( row );
392            }
393            return list;
394        }
395    
396    
397        /**
398         * Get a list of vectors as List of list of GenPolynomials.
399         * @param vlist list of vectors of polynomials.
400         * @return list of polynomial lists from vlist.
401         */
402        public static <C extends RingElem<C> >
403               List< List< GenPolynomial<C> > > 
404               vecToList( List< GenVector<GenPolynomial<C>> > vlist ) {
405            List< List<GenPolynomial<C>> > list = null;
406            if ( vlist == null ) {
407                return list;
408            }
409            list = new ArrayList< List<GenPolynomial<C>> >( vlist.size() ); 
410            for ( GenVector< GenPolynomial<C>> srow: vlist ) {
411                List< GenPolynomial<C> > row = srow.val; 
412                list.add( row );
413            }
414            return list;
415        }
416    
417    }