001    /*
002     * $Id: GenSolvablePolynomialRing.java 3470 2011-01-06 19:19:11Z kredel $
003     */
004    
005    package edu.jas.poly;
006    
007    import java.math.BigInteger;
008    
009    import java.io.IOException;
010    import java.io.Reader;
011    import java.io.StringReader;
012    
013    import java.util.List;
014    import java.util.ArrayList;
015    import java.util.Random;
016    
017    import org.apache.log4j.Logger;
018    
019    import edu.jas.structure.RingElem;
020    import edu.jas.structure.RingFactory;
021    import edu.jas.kern.PrettyPrint;
022    import edu.jas.kern.Scripting;
023    
024    
025    /**
026     * GenSolvablePolynomialRing generic solvable polynomial factory 
027     * implementing RingFactory and extending GenPolynomialRing factory;
028     * Factory for n-variate ordered solvable polynomials over C.
029     * The non-commutative multiplication relations are maintained in
030     * a relation table.
031     * Almost immutable object, except variable names and  
032     * relation table contents.
033     * @param <C> coefficient type.
034     * @author Heinz Kredel
035     */
036    
037    public class GenSolvablePolynomialRing<C extends RingElem<C> > 
038        extends GenPolynomialRing<C> {
039        //  implements RingFactory< GenSolvablePolynomial<C> > {
040    
041    
042        /** The solvable multiplication relations. 
043         */
044        public final RelationTable<C> table;
045    
046    
047        /**
048         * The constant polynomial 0 for this ring.
049         * Hides super ZERO.
050         */
051        public final GenSolvablePolynomial<C> ZERO;
052    
053    
054        /**
055         * The constant polynomial 1 for this ring.
056         * Hides super ONE.
057         */
058        public final GenSolvablePolynomial<C> ONE;
059    
060    
061        private static final Logger logger = Logger.getLogger(GenSolvablePolynomialRing.class);
062        private final boolean debug = logger.isDebugEnabled();
063    
064    
065        /** The constructor creates a solvable polynomial factory object
066         * with the default term order and commutative relations.
067         * @param cf factory for coefficients of type C.
068         * @param n number of variables.
069         */
070        public GenSolvablePolynomialRing(RingFactory< C > cf, int n) {
071            this(cf,n,new TermOrder(),null,null);
072        }
073    
074    
075        /** The constructor creates a solvable polynomial factory object
076         * with the default term order.
077         * @param cf factory for coefficients of type C.
078         * @param n number of variables.
079         * @param rt solvable multiplication relations.
080         */
081        public GenSolvablePolynomialRing(RingFactory< C > cf, int n, 
082                                         RelationTable<C> rt) {
083            this(cf,n,new TermOrder(),null,rt);
084        }
085    
086    
087        /** The constructor creates a solvable polynomial factory object
088         * with the given term order and commutative relations.
089         * @param cf factory for coefficients of type C.
090         * @param n number of variables.
091         * @param t a term order.
092         */
093        public GenSolvablePolynomialRing(RingFactory< C > cf, int n, TermOrder t) {
094            this(cf,n,t,null,null);
095        }
096    
097    
098        /** The constructor creates a solvable polynomial factory object
099         * with the given term order.
100         * @param cf factory for coefficients of type C.
101         * @param n number of variables.
102         * @param t a term order.
103         * @param rt solvable multiplication relations.
104         */
105        public GenSolvablePolynomialRing(RingFactory< C > cf, int n, TermOrder t, 
106                                         RelationTable<C> rt) {
107            this(cf,n,t,null,rt);
108        }
109    
110    
111        /** The constructor creates a solvable polynomial factory object
112         * with the given term order and commutative relations.
113         * @param cf factory for coefficients of type C.
114         * @param n number of variables.
115         * @param t a term order.
116         * @param v names for the variables.
117         */
118        public GenSolvablePolynomialRing(RingFactory< C > cf, int n, TermOrder t, 
119                                         String[] v) {
120            this(cf,n,t,v,null);
121        }
122    
123    
124        /** The constructor creates a solvable polynomial factory object
125         * with the given term order.
126         * @param cf factory for coefficients of type C.
127         * @param n number of variables.
128         * @param t a term order.
129         * @param v names for the variables.
130         * @param rt solvable multiplication relations.
131         */
132        public GenSolvablePolynomialRing(RingFactory< C > cf, int n, TermOrder t, 
133                                         String[] v, RelationTable<C> rt) {
134            super(cf,n,t,v);
135            if ( rt == null ) {
136                table = new RelationTable<C>(this);
137            } else {
138                table = rt;
139            }
140            ZERO = new GenSolvablePolynomial<C>( this );
141            C coeff = coFac.getONE();
142            //evzero = ExpVector.create(nvar); // from super
143            ONE  = new GenSolvablePolynomial<C>( this, coeff, evzero );
144        }
145    
146    
147        /** The constructor creates a solvable polynomial factory object
148         * with the the same term order, number of variables
149         * and variable names as the given polynomial factory,
150         * only the coefficient factories differ and 
151         * the solvable multiplication relations are <b>empty</b>.
152         * @param cf factory for coefficients of type C.
153         * @param o other solvable polynomial ring.
154         */
155        public GenSolvablePolynomialRing(RingFactory< C > cf, GenSolvablePolynomialRing o) {
156            this(cf,o.nvar,o.tord,o.getVars(),null);
157        }
158    
159    
160        /** Get the String representation.
161         * @see java.lang.Object#toString()
162         */
163        @Override
164        public String toString() {
165            String res = super.toString();
166            if ( PrettyPrint.isTrue() ) {
167                res += "\n"
168                    + table.toString(vars);
169            } else {
170                res += ", #rel = " + table.size();
171            }
172            return res;
173        }
174    
175    
176        /** Get a scripting compatible string representation.
177         * @return script compatible representation for this Element.
178         * @see edu.jas.structure.Element#toScript()
179         */
180        @Override
181        public String toScript() {
182            StringBuffer s = new StringBuffer();
183            switch (Scripting.getLang() ) {
184            case Ruby:
185                s.append("SolvPolyRing.new(");
186                break;
187            case Python:
188            default:
189                s.append("SolvPolyRing(");
190            }
191            if (coFac instanceof RingElem) {
192                s.append( ((RingElem<C>) coFac).toScriptFactory() );
193            } else {
194                s.append( coFac.toScript().trim() );
195            }
196            s.append(",\"" + varsToString() + "\",");
197            String to = tord.toString();
198            if (tord.getEvord() == TermOrder.INVLEX) {
199                to = "PolyRing.lex";
200            }
201            if (tord.getEvord() == TermOrder.IGRLEX) {
202                to = "PolyRing.grad";
203            }
204            s.append(to);
205            if ( table.size() > 0 ) {
206                String rel = table.toScript();
207                s.append(",rel=");
208                s.append(rel);
209            }
210            s.append(")");
211            return s.toString();
212        }
213    
214    
215        /** Comparison with any other object.
216         * @see java.lang.Object#equals(java.lang.Object)
217         */
218        @Override
219        @SuppressWarnings("unchecked") 
220            public boolean equals( Object other ) { 
221            if ( ! (other instanceof GenSolvablePolynomialRing) ) {
222                return false;
223            }
224            // do a super.equals( )
225            if ( ! super.equals( other ) ) {
226                return false;
227            }
228            GenSolvablePolynomialRing<C> oring = null;
229            try {
230                oring = (GenSolvablePolynomialRing<C>)other;
231            } catch (ClassCastException ignored) {
232            }
233            if ( oring == null ) {
234                return false;
235            }
236            // @todo check same base relations
237            //if ( ! table.equals(oring.table) ) {
238            //    return false;
239            //}
240            return true;
241        }
242    
243    
244        /** Hash code for this polynomial ring.
245         * @see java.lang.Object#hashCode()
246         */
247        @Override
248        public int hashCode() { 
249            int h;
250            h = super.hashCode();
251            h = 37 * h + table.hashCode();
252            return h;
253        }
254    
255    
256        /** Get the zero element.
257         * @return 0 as GenSolvablePolynomial<C>.
258         */
259        @Override
260        public GenSolvablePolynomial<C> getZERO() {
261            return ZERO;
262        }
263    
264    
265        /** Get the one element.
266         * @return 1 as GenSolvablePolynomial<C>.
267         */
268        @Override
269        public GenSolvablePolynomial<C> getONE() {
270            return ONE;
271        }
272    
273    
274        /**
275         * Query if this ring is commutative.
276         * @return true if this ring is commutative, else false.
277         */
278        @Override
279        public boolean isCommutative() {
280            if ( table.size() == 0 ) {
281                return super.isCommutative();
282            }
283            // todo: check structure of relations
284            return false;
285        }
286    
287    
288        /**
289         * Query if this ring is associative.
290         * Test if the relations define an associative solvable ring.
291         * @return true, if this ring is associative, else false.
292         */
293        @Override
294        public boolean isAssociative() {
295            GenSolvablePolynomial<C> Xi;
296            GenSolvablePolynomial<C> Xj;
297            GenSolvablePolynomial<C> Xk;
298            GenSolvablePolynomial<C> p;
299            GenSolvablePolynomial<C> q;
300            for ( int i = 0; i < nvar; i++ ) {
301                Xi = univariate(i);
302                for ( int j = i+1; j < nvar; j++ ) {
303                    Xj = univariate(j);
304                    for ( int k = j+1; k < nvar; k++ ) {
305                        Xk = univariate(k);
306                        p = Xk.multiply(Xj).multiply(Xi);
307                        q = Xk.multiply(Xj.multiply(Xi));
308                        if ( !p.equals(q) ) {
309                            if ( true || debug ) {
310                                logger.info("Xi = " + Xi + ", Xj = " + Xj + ", Xk = " + Xk);
311                                logger.info("p = ( Xk * Xj ) * Xi = " + p);
312                                logger.info("q = Xk * ( Xj * Xi ) = " + q);
313                            }
314                            return false;
315                        }
316                    }
317                }
318            }
319            return true;
320        }
321    
322    
323        /** Get a (constant) GenSolvablePolynomial&lt;C&gt; element from a long value.
324         * @param a long.
325         * @return a GenSolvablePolynomial&lt;C&gt;.
326         */
327        @Override
328        public GenSolvablePolynomial<C> fromInteger(long a) {
329            return new GenSolvablePolynomial<C>( this, coFac.fromInteger(a), 
330                                                 evzero );
331        }
332    
333    
334        /** Get a (constant) GenSolvablePolynomial&lt;C&gt; element from 
335         * a BigInteger value.
336         * @param a BigInteger.
337         * @return a GenSolvablePolynomial&lt;C&gt;.
338         */
339        @Override
340        public GenSolvablePolynomial<C> fromInteger(BigInteger a) {
341            return new GenSolvablePolynomial<C>( this, coFac.fromInteger(a), 
342                                                 evzero );
343        }
344    
345    
346        /**
347         * Random solvable polynomial.
348         * Generates a random solvable polynomial with
349         * k = 5, 
350         * l = n, 
351         * d = (nvar == 1) ?   n : 3,
352         * q = (nvar == 1) ? 0.7 : 0.3. 
353         * @param n number of terms.
354         * @return a random solvable polynomial.
355         */
356        @Override
357        public GenSolvablePolynomial<C> random(int n) {
358            return random(n,random);
359        }
360     
361    
362        /**
363         * Random solvable polynomial.
364         * Generates a random solvable polynomial with
365         * k = 5, 
366         * l = n, 
367         * d = (nvar == 1) ?   n : 3,
368         * q = (nvar == 1) ? 0.7 : 0.3.
369         * @param n number of terms.
370         * @param rnd is a source for random bits.
371         * @return a random solvable polynomial.
372         */
373        @Override
374        public GenSolvablePolynomial<C> random(int n, Random rnd) {
375            if ( nvar == 1 ) {
376                return random(5,n,n,0.7f,rnd);
377            } else {
378                return random(5,n,3,0.3f,rnd);
379            }
380        }
381    
382    
383        /**
384         * Generate a random solvable polynomial.
385         * @param k bitsize of random coefficients.
386         * @param l number of terms.
387         * @param d maximal degree in each variable.
388         * @param q density of nozero exponents.
389         * @return a random solvable polynomial.
390         */
391        @Override
392        public GenSolvablePolynomial<C> random(int k, int l, int d, float q) {
393            return random(k,l,d,q,random);
394        }
395    
396    
397        /**
398         * Random solvable polynomial.
399         * @param k size of random coefficients.
400         * @param l number of terms.
401         * @param d maximal degree in each variable.
402         * @param q density of nozero exponents.
403         * @param rnd is a source for random bits.
404         * @return a random solvable polynomial.
405         */
406        @Override
407        public GenSolvablePolynomial<C> random(int k, int l, int d, float q,
408                                               Random rnd) {
409            GenSolvablePolynomial<C> r = getZERO(); //.clone();
410            // copy( ZERO ); 
411            // new GenPolynomial<C>( this, getZERO().val );
412            ExpVector e;
413            C a;
414            // add random coeffs and exponents
415            for ( int i = 0; i < l; i++ ) {
416                e = ExpVector.EVRAND(nvar, d, q, rnd);
417                a = coFac.random(k,rnd);
418                r = (GenSolvablePolynomial<C>)r.sum(a,e); 
419                // somewhat inefficient but clean
420            }
421            return r;
422        }
423    
424    
425        /**
426         * Copy polynomial c.
427         * @param c
428         * @return a copy of c.
429         */
430        public GenSolvablePolynomial<C> copy(GenSolvablePolynomial<C> c) {
431            return new GenSolvablePolynomial<C>( this, c.val );
432        }
433    
434    
435        /**
436         * Parse a solvable polynomial with the use of GenPolynomialTokenizer
437         * @param s String.
438         * @return GenSolvablePolynomial from s.
439         */
440        @Override
441        public GenSolvablePolynomial<C> parse(String s) {
442            //return getZERO();
443            return parse( new StringReader(s) );
444        }
445    
446    
447        /**
448         * Parse a solvable polynomial with the use of GenPolynomialTokenizer
449         * @param r Reader.
450         * @return next GenSolvablePolynomial from r.
451         */
452        @Override
453        @SuppressWarnings("unchecked") 
454            public GenSolvablePolynomial<C> parse(Reader r) {
455            GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this,r);
456            GenSolvablePolynomial<C> p = null;
457            try {
458                p = (GenSolvablePolynomial<C>)pt.nextSolvablePolynomial();
459            } catch (IOException e) {
460                logger.error(e.toString()+" parse " + this);
461                p = ZERO;
462            }
463            return p;
464        }
465    
466    
467        /**
468         * Generate univariate solvable polynomial in a given variable.
469         * @param i the index of the variable.
470         * @return X_i as solvable univariate polynomial.
471         */
472        @Override
473        public GenSolvablePolynomial<C> univariate(int i) {
474            return (GenSolvablePolynomial<C>)super.univariate(i);
475        }
476    
477    
478        /**
479         * Generate univariate solvable polynomial in a given variable with given exponent.
480         * @param i the index of the variable.
481         * @param e the exponent of the variable.
482         * @return X_i^e as solvable univariate polynomial.
483         */
484        @Override
485        public GenSolvablePolynomial<C> univariate(int i,long e) {
486            return (GenSolvablePolynomial<C>)super.univariate(i,e);
487        }
488    
489    
490        /**
491         * Generate univariate solvable polynomial in a given variable with given exponent.
492         * @param modv number of module variables.
493         * @param i the index of the variable.
494         * @param e the exponent of the variable.
495         * @return X_i^e as solvable univariate polynomial.
496         */
497        @Override
498        public GenSolvablePolynomial<C> univariate(int modv,int i,long e) {
499            return (GenSolvablePolynomial<C>)super.univariate(modv,i,e);
500        }
501    
502    
503        /**
504         * Generate list of univariate polynomials in all variables.
505         * @return List(X_1,...,X_n) a list of univariate polynomials.
506         */
507        @Override
508        public List<GenSolvablePolynomial<C>> univariateList() {
509            //return castToSolvableList( super.univariateList() );
510            return univariateList(0,1L);
511        }
512    
513    
514        /**
515         * Generate list of univariate polynomials in all variables.
516         * @param modv number of module variables.
517         * @return List(X_1,...,X_n) a list of univariate polynomials.
518         */
519        @Override
520        public List<GenSolvablePolynomial<C>> univariateList(int modv) {
521            return univariateList(modv,1L);
522        }
523    
524    
525        /**
526         * Generate list of univariate polynomials in all variables with given exponent.
527         * @param modv number of module variables.
528         * @param e the exponent of the variables.
529         * @return List(X_1^e,...,X_n^e) a list of univariate polynomials.
530         */
531        @Override
532        public List<GenSolvablePolynomial<C>> univariateList(int modv, long e) {
533            List<GenSolvablePolynomial<C>> pols 
534                = new ArrayList<GenSolvablePolynomial<C>>(nvar);
535            int nm = nvar-modv;
536            for ( int i = 0; i < nm; i++ ) {
537                GenSolvablePolynomial<C> p = univariate(modv,nm-1-i,e);
538                pols.add( p );
539            }
540            return pols;
541        }
542    
543    
544        /*
545         * Generate list of univariate polynomials in all variables with given exponent.
546         * @param modv number of module variables.
547         * @param e the exponent of the variables.
548         * @return List(X_1^e,...,X_n^e) a list of univariate polynomials.
549         @Override
550         public List<GenSolvablePolynomial<C>> univariateList(int modv, long e) {
551         List<GenPolynomial<C>> pol = super.univariateList(modv,e);
552         UnaryFunctor<GenPolynomial<C>,GenSolvablePolynomial<C>> fc 
553         = new UnaryFunctor<GenPolynomial<C>,GenSolvablePolynomial<C>>() {
554         public GenSolvablePolynomial<C> eval(GenPolynomial<C> p) {
555         if ( ! (p instanceof GenSolvablePolynomial) ) {
556         throw new RuntimeException("no solvable polynomial "+p);
557         }
558         return (GenSolvablePolynomial<C>) p;
559         }
560         };
561         List<GenSolvablePolynomial<C>> pols 
562         = ListUtil.<GenPolynomial<C>,GenSolvablePolynomial<C>>map(this,pol,fc);
563         return pols;
564         }
565        */
566    
567    
568        /* include here ?
569         * Get list as List of GenSolvablePolynomials.
570         * Required because no List casts allowed. Equivalent to 
571         * cast (List&lt;GenSolvablePolynomial&lt;C&gt;&gt;) list.
572         * @return solvable polynomial list from this.
573         public List<GenSolvablePolynomial<C>> castToSolvableList(List<GenPolynomial<C>> list) {
574         List< GenSolvablePolynomial<C> > slist = null;
575         if ( list == null ) {
576         return slist;
577         }
578         slist = new ArrayList< GenSolvablePolynomial<C> >( list.size() ); 
579         GenSolvablePolynomial<C> s;
580         for ( GenPolynomial<C> p: list ) {
581         if ( ! (p instanceof GenSolvablePolynomial) ) {
582         throw new RuntimeException("no solvable polynomial "+p);
583         }
584         s = (GenSolvablePolynomial<C>) p;
585         slist.add( s );
586         }
587         return slist;
588         }
589        */
590    
591    
592        /**
593         * Extend variables. Used e.g. in module embedding.
594         * Extend number of variables by i.
595         * @param i number of variables to extend.
596         * @return extended solvable polynomial ring factory.
597         */
598        @Override
599        public GenSolvablePolynomialRing<C> extend(int i) {
600            GenPolynomialRing<C> pfac = super.extend(i);
601            GenSolvablePolynomialRing<C> spfac 
602                = new GenSolvablePolynomialRing<C>(pfac.coFac, pfac.nvar,
603                                                   pfac.tord, pfac.vars);
604            spfac.table.extend(this.table);
605            return spfac;
606        }
607    
608    
609        /**
610         * Contract variables. Used e.g. in module embedding.
611         * Contract number of variables by i.
612         * @param i number of variables to remove.
613         * @return contracted solvable polynomial ring factory.
614         */
615        @Override
616        public GenSolvablePolynomialRing<C> contract(int i) {
617            GenPolynomialRing<C> pfac = super.contract(i);
618            GenSolvablePolynomialRing<C> spfac 
619                = new GenSolvablePolynomialRing<C>(pfac.coFac, pfac.nvar,
620                                                   pfac.tord, pfac.vars);
621            spfac.table.contract(this.table);
622            return spfac;
623        }
624    
625    
626        /**
627         * Reverse variables. Used e.g. in opposite rings.
628         * @return solvable polynomial ring factory with reversed variables.
629         */
630        @Override
631        public GenSolvablePolynomialRing<C> reverse() {
632            return reverse(false);
633        }
634    
635    
636        /**
637         * Reverse variables. Used e.g. in opposite rings.
638         * @param partial true for partialy reversed term orders.
639         * @return solvable polynomial ring factory with reversed variables.
640         */
641        @Override
642        public GenSolvablePolynomialRing<C> reverse(boolean partial) {
643            GenPolynomialRing<C> pfac = super.reverse(partial);
644            GenSolvablePolynomialRing<C> spfac 
645                = new GenSolvablePolynomialRing<C>(pfac.coFac, pfac.nvar,
646                                                   pfac.tord, pfac.vars);
647            spfac.partial = partial;
648            spfac.table.reverse(this.table);
649            return spfac;
650        }
651    
652    }