001/*
002 * $Id: GenPolynomialRing.java 5666 2016-12-26 14:24:30Z kredel $
003 */
004
005package edu.jas.poly;
006
007
008import java.io.IOException;
009import java.io.Reader;
010import java.io.StringReader;
011import java.math.BigInteger;
012import java.util.ArrayList;
013import java.util.Arrays;
014import java.util.HashSet;
015import java.util.Iterator;
016import java.util.List;
017import java.util.Random;
018import java.util.Set;
019
020import org.apache.log4j.Logger;
021
022import edu.jas.arith.ModIntegerRing;
023import edu.jas.kern.PreemptStatus;
024import edu.jas.kern.PrettyPrint;
025import edu.jas.kern.Scripting;
026import edu.jas.structure.RingElem;
027import edu.jas.structure.RingFactory;
028import edu.jas.util.CartesianProduct;
029import edu.jas.util.CartesianProductInfinite;
030import edu.jas.util.LongIterable;
031
032
033/**
034 * GenPolynomialRing generic polynomial factory. It implements
035 * RingFactory for n-variate ordered polynomials over coefficients
036 * C. The variables commute with each other and with the
037 * coefficients. For non-commutative coefficients some care is taken
038 * to respect the multiplication order.
039 *
040 * Almost immutable object, except variable names.
041 * @param <C> coefficient type
042 * @author Heinz Kredel
043 */
044
045public class GenPolynomialRing<C extends RingElem<C>> implements RingFactory<GenPolynomial<C>>,
046                Iterable<GenPolynomial<C>> {
047
048
049    /**
050     * The factory for the coefficients.
051     */
052    public final RingFactory<C> coFac;
053
054
055    /**
056     * The number of variables.
057     */
058    public final int nvar;
059
060
061    /**
062     * The term order.
063     */
064    public final TermOrder tord;
065
066
067    /**
068     * True for partially reversed variables.
069     */
070    protected boolean partial;
071
072
073    /**
074     * The names of the variables. This value can be modified.
075     */
076    protected String[] vars;
077
078
079    /**
080     * The names of all known variables.
081     */
082    private static Set<String> knownVars = new HashSet<String>();
083
084
085    /**
086     * The constant polynomial 0 for this ring.
087     */
088    public final GenPolynomial<C> ZERO;
089
090
091    /**
092     * The constant polynomial 1 for this ring.
093     */
094    public final GenPolynomial<C> ONE;
095
096
097    /**
098     * The constant exponent vector 0 for this ring.
099     */
100    public final ExpVector evzero;
101
102
103    /**
104     * A default random sequence generator.
105     */
106    protected final static Random random = new Random();
107
108
109    /**
110     * Indicator if this ring is a field.
111     */
112    protected int isField = -1; // initially unknown
113
114
115    /**
116     * Log4j logger object.
117     */
118    private static final Logger logger = Logger.getLogger(GenPolynomialRing.class);
119
120
121    /**
122     * Count for number of polynomial creations.
123     */
124    static int creations = 0;
125
126
127    /**
128     * Flag to enable if preemptive interrrupt is checked.
129     */
130    final boolean checkPreempt = PreemptStatus.isAllowed();
131
132
133    /**
134     * The constructor creates a polynomial factory object with the default term
135     * order.
136     * @param cf factory for coefficients of type C.
137     * @param n number of variables.
138     */
139    public GenPolynomialRing(RingFactory<C> cf, int n) {
140        this(cf, n, new TermOrder(), null);
141    }
142
143
144    /**
145     * The constructor creates a polynomial factory object.
146     * @param cf factory for coefficients of type C.
147     * @param n number of variables.
148     * @param t a term order.
149     */
150    public GenPolynomialRing(RingFactory<C> cf, int n, TermOrder t) {
151        this(cf, n, t, null);
152    }
153
154
155    /**
156     * The constructor creates a polynomial factory object.
157     * @param cf factory for coefficients of type C.
158     * @param v names for the variables.
159     */
160    public GenPolynomialRing(RingFactory<C> cf, String[] v) {
161        this(cf, v.length, v);
162    }
163
164
165    /**
166     * The constructor creates a polynomial factory object.
167     * @param cf factory for coefficients of type C.
168     * @param n number of variables.
169     * @param v names for the variables.
170     */
171    public GenPolynomialRing(RingFactory<C> cf, int n, String[] v) {
172        this(cf, n, new TermOrder(), v);
173    }
174
175
176    /**
177     * The constructor creates a polynomial factory object.
178     * @param cf factory for coefficients of type C.
179     * @param t a term order.
180     * @param v names for the variables.
181     */
182    public GenPolynomialRing(RingFactory<C> cf, TermOrder t, String[] v) {
183        this(cf, v.length, t, v);
184    }
185
186
187    /**
188     * The constructor creates a polynomial factory object.
189     * @param cf factory for coefficients of type C.
190     * @param v names for the variables.
191     * @param t a term order.
192     */
193    public GenPolynomialRing(RingFactory<C> cf, String[] v, TermOrder t) {
194        this(cf, v.length, t, v);
195    }
196
197
198    /**
199     * The constructor creates a polynomial factory object.
200     * @param cf factory for coefficients of type C.
201     * @param n number of variables.
202     * @param t a term order.
203     * @param v names for the variables.
204     */
205    public GenPolynomialRing(RingFactory<C> cf, int n, TermOrder t, String[] v) {
206        coFac = cf;
207        nvar = n;
208        tord = t;
209        partial = false;
210        if (v == null) {
211            vars = null;
212        } else {
213            vars = Arrays.copyOf(v, v.length); // > Java-5
214        }
215        ZERO = new GenPolynomial<C>(this);
216        C coeff = coFac.getONE();
217        evzero = ExpVector.create(nvar);
218        ONE = new GenPolynomial<C>(this, coeff, evzero);
219        if (vars == null) {
220            if (PrettyPrint.isTrue()) {
221                vars = newVars("x", nvar);
222            }
223        } else {
224            if (vars.length != nvar) {
225                throw new IllegalArgumentException("incompatible variable size " + vars.length + ", " + nvar);
226            }
227            addVars(vars);
228        }
229    }
230
231
232    /**
233     * The constructor creates a polynomial factory object with the the same
234     * term order, number of variables and variable names as the given
235     * polynomial factory, only the coefficient factories differ.
236     * @param cf factory for coefficients of type C.
237     * @param o other polynomial ring.
238     */
239    public GenPolynomialRing(RingFactory<C> cf, GenPolynomialRing o) {
240        this(cf, o.nvar, o.tord, o.vars);
241    }
242
243
244    /**
245     * The constructor creates a polynomial factory object with the the same
246     * coefficient factory, number of variables and variable names as the given
247     * polynomial factory, only the term order differs.
248     * @param to term order.
249     * @param o other polynomial ring.
250     */
251    public GenPolynomialRing(GenPolynomialRing<C> o, TermOrder to) {
252        this(o.coFac, o.nvar, to, o.vars);
253    }
254
255
256    /**
257     * Copy this factory.
258     * @return a clone of this.
259     */
260    public GenPolynomialRing<C> copy() {
261        return new GenPolynomialRing<C>(coFac, this);
262    }
263
264
265    /**
266     * Get the String representation.
267     * @see java.lang.Object#toString()
268     */
269    @SuppressWarnings("cast")
270    @Override
271    public String toString() {
272        String res = null;
273        if (PrettyPrint.isTrue()) { // wrong: && coFac != null
274            String scf = coFac.getClass().getSimpleName();
275            if (coFac instanceof AlgebraicNumberRing) {
276                AlgebraicNumberRing an = (AlgebraicNumberRing) coFac;
277                //String[] v = an.ring.vars;
278                res = "AN[ (" + an.ring.varsToString() + ") (" + an.toString() + ") ]";
279            }
280            if (coFac instanceof GenPolynomialRing) {
281                GenPolynomialRing rf = (GenPolynomialRing) coFac;
282                //String[] v = rf.vars;
283                //RingFactory cf = rf.coFac;
284                //String cs;
285                //if (cf instanceof ModIntegerRing) {
286                //    cs = cf.toString();
287                //} else {
288                //    cs = " " + cf.getClass().getSimpleName();
289                //}
290                //res = "IntFunc" + "{" + cs + "( " + rf.varsToString() + " )" + " } ";
291                res = "IntFunc" + "( " + rf.toString() + " )";
292            }
293            if (((Object) coFac) instanceof ModIntegerRing) {
294                ModIntegerRing mn = (ModIntegerRing) ((Object) coFac);
295                res = "Mod " + mn.getModul() + " ";
296            }
297            if (res == null) {
298                res = coFac.toString();
299                if (res.matches("[0-9].*")) {
300                    res = scf;
301                }
302            }
303            res += "( " + varsToString() + " ) " + tord.toString() + " ";
304        } else {
305            res = this.getClass().getSimpleName() + "[ " + coFac.toString() + " ";
306            //  + coFac.getClass().getSimpleName();
307            if (coFac instanceof AlgebraicNumberRing) {
308                AlgebraicNumberRing an = (AlgebraicNumberRing) coFac;
309                res = "AN[ (" + an.ring.varsToString() + ") (" + an.modul + ") ]";
310            }
311            if (coFac instanceof GenPolynomialRing) {
312                GenPolynomialRing rf = (GenPolynomialRing) coFac;
313                //String[] v = rf.vars;
314                //RingFactory cf = rf.coFac;
315                //String cs;
316                //if (cf instanceof ModIntegerRing) {
317                //    cs = cf.toString();
318                //} else {
319                //    cs = " " + cf.getClass().getSimpleName();
320                //}
321                //res = "IntFunc{ " + cs + "( " + rf.varsToString() + " )" + " } ";
322                res = "IntFunc" + "( " + rf.toString() + " )";
323            }
324            if (((Object) coFac) instanceof ModIntegerRing) {
325                ModIntegerRing mn = (ModIntegerRing) ((Object) coFac);
326                res = "Mod " + mn.getModul() + " ";
327            }
328            //res += ", " + nvar + ", " + tord.toString() + ", " + varsToString() + ", " + partial + " ]";
329            res += "( " + varsToString() + " ) " + tord.toString() + " ]";
330        }
331        return res;
332    }
333
334
335    /**
336     * Get a scripting compatible string representation.
337     * @return script compatible representation for this Element.
338     * @see edu.jas.structure.Element#toScript()
339     */
340    @Override
341    public String toScript() {
342        StringBuffer s = new StringBuffer();
343        switch (Scripting.getLang()) {
344        case Ruby:
345            s.append("PolyRing.new(");
346            break;
347        case Python:
348        default:
349            s.append("PolyRing(");
350        }
351        if (coFac instanceof RingElem) {
352            s.append(((RingElem<C>) coFac).toScriptFactory());
353        } else {
354            s.append(coFac.toScript().trim());
355        }
356        s.append(",\"" + varsToString() + "\"");
357        String to = tord.toScript();
358        //if (tord.getEvord() == TermOrder.INVLEX) {
359        //    to = "PolyRing.lex";
360        //}
361        //if (tord.getEvord() == TermOrder.IGRLEX) {
362        //    to = "PolyRing.grad";
363        //}
364        s.append("," + to);
365        s.append(")");
366        return s.toString();
367    }
368
369
370    /**
371     * Get a scripting compatible string representation of an ExpVector of this
372     * ring.
373     * @param e exponent vector
374     * @return script compatible representation for the ExpVector.
375     */
376    public String toScript(ExpVector e) {
377        if (e == null) {
378            return "null";
379        }
380        if (vars != null) {
381            return e.toScript(vars);
382        }
383        return e.toScript();
384    }
385
386
387    /**
388     * Comparison with any other object.
389     * @see java.lang.Object#equals(java.lang.Object)
390     */
391    @Override
392    @SuppressWarnings("unchecked")
393    public boolean equals(Object other) {
394        if (other == null) {
395            return false;
396        }
397        if (!(other instanceof GenPolynomialRing)) {
398            return false;
399        }
400        GenPolynomialRing<C> oring = (GenPolynomialRing<C>) other;
401        if (nvar != oring.nvar) {
402            return false;
403        }
404        if (!coFac.equals(oring.coFac)) {
405            return false;
406        }
407        if (!tord.equals(oring.tord)) {
408            return false;
409        }
410        // same variables required ?
411        if (!Arrays.deepEquals(vars, oring.vars)) {
412            return false;
413        }
414        return true;
415    }
416
417
418    /**
419     * Hash code for this polynomial ring.
420     * @see java.lang.Object#hashCode()
421     */
422    @Override
423    public int hashCode() {
424        int h;
425        h = (nvar << 27);
426        h += (coFac.hashCode() << 11);
427        h += tord.hashCode();
428        return h;
429    }
430
431
432    /**
433     * Get the number of polynomial creations.
434     * @return creations.
435     */
436    public int getCreations() {
437        return creations;
438    }
439
440
441    /**
442     * Get the variable names.
443     * @return vars.
444     */
445    public String[] getVars() {
446        return Arrays.copyOf(vars, vars.length); // > Java-5
447    }
448
449
450    /**
451     * Set the variable names.
452     * @return old vars.
453     */
454    public String[] setVars(String[] v) {
455        if (v.length != nvar) {
456            throw new IllegalArgumentException("v not matching number of variables: " + Arrays.toString(v)
457                            + ", nvar " + nvar);
458        }
459        String[] t = vars;
460        vars = Arrays.copyOf(v, v.length); // > Java-5 
461        return t;
462    }
463
464
465    /**
466     * Get a String representation of the variable names.
467     * @return names seperated by commas.
468     */
469    public String varsToString() {
470        if (vars == null) {
471            return "#" + nvar;
472        }
473        //return Arrays.toString(vars);
474        return ExpVector.varsToString(vars);
475    }
476
477
478    /**
479     * Get the zero element from the coefficients.
480     * @return 0 as C.
481     */
482    public C getZEROCoefficient() {
483        return coFac.getZERO();
484    }
485
486
487    /**
488     * Get the one element from the coefficients.
489     * @return 1 as C.
490     */
491    public C getONECoefficient() {
492        return coFac.getONE();
493    }
494
495
496    /**
497     * Get the zero element.
498     * @return 0 as GenPolynomial<C>.
499     */
500    public GenPolynomial<C> getZERO() {
501        return ZERO;
502    }
503
504
505    /**
506     * Get the one element.
507     * @return 1 as GenPolynomial<C>.
508     */
509    public GenPolynomial<C> getONE() {
510        return ONE;
511    }
512
513
514    /**
515     * Query if this ring is commutative.
516     * @return true if this ring is commutative, else false.
517     */
518    public boolean isCommutative() {
519        return coFac.isCommutative();
520    }
521
522
523    /**
524     * Query if this ring is associative.
525     * @return true if this ring is associative, else false.
526     */
527    public boolean isAssociative() {
528        return coFac.isAssociative();
529    }
530
531
532    /**
533     * Query if this ring is a field.
534     * @return false.
535     */
536    public boolean isField() {
537        if (isField > 0) {
538            return true;
539        }
540        if (isField == 0) {
541            return false;
542        }
543        if (coFac.isField() && nvar == 0) {
544            isField = 1;
545            return true;
546        }
547        isField = 0;
548        return false;
549    }
550
551
552    /**
553     * Characteristic of this ring.
554     * @return characteristic of this ring.
555     */
556    public java.math.BigInteger characteristic() {
557        return coFac.characteristic();
558    }
559
560
561    /**
562     * Get a (constant) GenPolynomial&lt;C&gt; element from a coefficient value.
563     * @param a coefficient.
564     * @return a GenPolynomial&lt;C&gt;.
565     */
566    public GenPolynomial<C> valueOf(C a) {
567        return new GenPolynomial<C>(this, a);
568    }
569
570
571    /**
572     * Get a GenPolynomial&lt;C&gt; element from an exponent vector.
573     * @param e exponent vector.
574     * @return a GenPolynomial&lt;C&gt;.
575     */
576    public GenPolynomial<C> valueOf(ExpVector e) {
577        if (e == null) {
578            return getZERO();
579        }
580        return new GenPolynomial<C>(this, coFac.getONE(), e);
581    }
582
583
584    /**
585     * Get a GenPolynomial&lt;C&gt; element from a list of exponent vectors.
586     * @param E list of exponent vector.
587     * @return a GenPolynomial&lt;C&gt;.
588     */
589    public List<GenPolynomial<C>> valueOf(Iterable<ExpVector> E) {
590        if (E == null) {
591            return null;
592        }
593        List<GenPolynomial<C>> P = new ArrayList<GenPolynomial<C>>(); //E.size());
594        for ( ExpVector e : E ) {
595            GenPolynomial<C> p = valueOf(e);
596            P.add(p);
597        }
598        return P;
599    }
600
601
602    /**
603     * Get a GenPolynomial&lt;C&gt; element from a coeffcient and an exponent
604     * vector.
605     * @param a coefficient.
606     * @param e exponent vector.
607     * @return a GenPolynomial&lt;C&gt;.
608     */
609    public GenPolynomial<C> valueOf(C a, ExpVector e) {
610        return new GenPolynomial<C>(this, a, e);
611    }
612
613
614    /**
615     * Get a GenPolynomial&lt;C&gt; element from a monomial.
616     * @param m monomial.
617     * @return a GenPolynomial&lt;C&gt;.
618     */
619    public GenPolynomial<C> valueOf(Monomial<C> m) {
620        return new GenPolynomial<C>(this, m.c, m.e);
621    }
622
623
624    /**
625     * Get a (constant) GenPolynomial&lt;C&gt; element from a long value.
626     * @param a long.
627     * @return a GenPolynomial&lt;C&gt;.
628     */
629    public GenPolynomial<C> fromInteger(long a) {
630        return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero);
631    }
632
633
634    /**
635     * Get a (constant) GenPolynomial&lt;C&gt; element from a BigInteger value.
636     * @param a BigInteger.
637     * @return a GenPolynomial&lt;C&gt;.
638     */
639    public GenPolynomial<C> fromInteger(BigInteger a) {
640        return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero);
641    }
642
643
644    /**
645     * Random polynomial. Generates a random polynomial with k = 5, l = n, d =
646     * (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3.
647     * @param n number of terms.
648     * @return a random polynomial.
649     */
650    public GenPolynomial<C> random(int n) {
651        return random(n, random);
652    }
653
654
655    /**
656     * Random polynomial. Generates a random polynomial with k = 5, l = n, d =
657     * n, q = (nvar == 1) ? 0.5 : 0.3.
658     * @param n number of terms.
659     * @param rnd is a source for random bits.
660     * @return a random polynomial.
661     */
662    public GenPolynomial<C> random(int n, Random rnd) {
663        if (nvar == 1) {
664            return random(3, n, n, 0.5f, rnd);
665        }
666        return random(3, n, n, 0.3f, rnd);
667    }
668
669
670    /**
671     * Generate a random polynomial.
672     * @param k bitsize of random coefficients.
673     * @param l number of terms.
674     * @param d maximal degree in each variable.
675     * @param q density of nozero exponents.
676     * @return a random polynomial.
677     */
678    public GenPolynomial<C> random(int k, int l, int d, float q) {
679        return random(k, l, d, q, random);
680    }
681
682
683    /**
684     * Generate a random polynomial.
685     * @param k bitsize of random coefficients.
686     * @param l number of terms.
687     * @param d maximal degree in each variable.
688     * @param q density of nozero exponents.
689     * @param rnd is a source for random bits.
690     * @return a random polynomial.
691     */
692    public GenPolynomial<C> random(int k, int l, int d, float q, Random rnd) {
693        GenPolynomial<C> r = getZERO(); //.clone() or copy( ZERO ); 
694        ExpVector e;
695        C a;
696        // add l random coeffs and exponents
697        for (int i = 0; i < l; i++) {
698            e = ExpVector.EVRAND(nvar, d, q, rnd);
699            a = coFac.random(k, rnd);
700            r = r.sum(a, e); // somewhat inefficient but clean
701            //System.out.println("e = " + e + " a = " + a);
702        }
703        // System.out.println("r = " + r);
704        return r;
705    }
706
707
708    /**
709     * Copy polynomial c.
710     * @param c
711     * @return a copy of c.
712     */
713    public GenPolynomial<C> copy(GenPolynomial<C> c) {
714        //System.out.println("GP copy = " + this);
715        return new GenPolynomial<C>(this, c.val);
716    }
717
718
719    /**
720     * Copy polynomial list.
721     * @param L polynomial list
722     * @return a copy of L in this ring.
723     */
724    public List<GenPolynomial<C>> copy(List<GenPolynomial<C>> L) {
725        if (L == null) {
726            return L;
727        }
728        List<GenPolynomial<C>> R = new ArrayList<GenPolynomial<C>>(L.size());
729        for ( GenPolynomial<C> a : L ) {
730            R.add( copy(a) );
731        }
732        return R;
733    }
734
735
736    /**
737     * Parse a polynomial with the use of GenPolynomialTokenizer.
738     * @param s String.
739     * @return GenPolynomial from s.
740     */
741    public GenPolynomial<C> parse(String s) {
742        String val = s;
743        if (!s.contains("|")) {
744            val = val.replace("{", "").replace("}", "");
745        }
746        return parse(new StringReader(val));
747    }
748
749
750    /**
751     * Parse a polynomial with the use of GenPolynomialTokenizer.
752     * @param r Reader.
753     * @return next GenPolynomial from r.
754     */
755    @SuppressWarnings({ "unchecked", "cast" })
756    public GenPolynomial<C> parse(Reader r) {
757        GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r);
758        GenPolynomial<C> p = null;
759        try {
760            p = (GenPolynomial<C>) pt.nextPolynomial();
761        } catch (IOException e) {
762            logger.error(e.toString() + " parse " + this);
763            p = ZERO;
764        }
765        return p;
766    }
767
768
769    /**
770     * Generate univariate polynomial in a given variable with given exponent.
771     * @param x the name of a variable.
772     * @return x as univariate polynomial.
773     */
774    public GenPolynomial<C> univariate(String x) {
775        return univariate(x, 1L);
776    }
777
778
779    /**
780     * Generate univariate polynomial in a given variable with given exponent.
781     * @param x the name of the variable.
782     * @param e the exponent of the variable.
783     * @return x^e as univariate polynomial.
784     */
785    public GenPolynomial<C> univariate(String x, long e) {
786        if (vars == null) { // should not happen
787            throw new IllegalArgumentException("no variables defined for polynomial ring");
788        }
789        if (x == null || x.isEmpty()) {
790            throw new IllegalArgumentException("no variable name given");
791        }
792        int i;
793        for ( i = 0 ; i < vars.length; i++ ) {
794            if (x.equals(vars[i])) { // use HashMap or TreeMap
795                break;
796            }
797        }
798        if (i >= vars.length) {
799            throw new IllegalArgumentException("variable '" + x + "' not defined in polynomial ring");
800        }
801        return univariate(0, nvar - i - 1, e);
802    }
803
804
805    /**
806     * Generate univariate polynomial in a given variable.
807     * @param i the index of the variable.
808     * @return X_i as univariate polynomial.
809     */
810    public GenPolynomial<C> univariate(int i) {
811        return univariate(0, i, 1L);
812    }
813
814
815    /**
816     * Generate univariate polynomial in a given variable with given exponent.
817     * @param i the index of the variable.
818     * @param e the exponent of the variable.
819     * @return X_i^e as univariate polynomial.
820     */
821    public GenPolynomial<C> univariate(int i, long e) {
822        return univariate(0, i, e);
823    }
824
825
826    /**
827     * Generate univariate polynomial in a given variable with given exponent.
828     * @param modv number of module variables.
829     * @param i the index of the variable.
830     * @param e the exponent of the variable.
831     * @return X_i^e as univariate polynomial.
832     */
833    public GenPolynomial<C> univariate(int modv, int i, long e) {
834        GenPolynomial<C> p = getZERO();
835        int r = nvar - modv;
836        if (0 <= i && i < r) {
837            C one = coFac.getONE();
838            ExpVector f = ExpVector.create(r, i, e);
839            if (modv > 0) {
840                f = f.extend(modv, 0, 0l);
841            }
842            p = p.sum(one, f);
843        }
844        return p;
845    }
846
847
848    /**
849     * Get the generating elements excluding the generators for the coefficient
850     * ring.
851     * @return a list of generating elements for this ring.
852     */
853    public List<GenPolynomial<C>> getGenerators() {
854        List<? extends GenPolynomial<C>> univs = univariateList();
855        List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + 1);
856        gens.add(getONE());
857        gens.addAll(univs);
858        return gens;
859    }
860
861
862    /**
863     * Get a list of the generating elements.
864     * @return list of generators for the algebraic structure.
865     * @see edu.jas.structure.ElemFactory#generators()
866     */
867    public List<GenPolynomial<C>> generators() {
868        List<? extends C> cogens = coFac.generators();
869        List<? extends GenPolynomial<C>> univs = univariateList();
870        List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size());
871        for (C c : cogens) {
872            gens.add(getONE().multiply(c));
873        }
874        gens.addAll(univs);
875        return gens;
876    }
877
878
879    /**
880     * Get a list of the generating elements excluding the module variables.
881     * @param modv number of module variables
882     * @return list of generators for the polynomial ring.
883     */
884    public List<GenPolynomial<C>> generators(int modv) {
885        List<? extends C> cogens = coFac.generators();
886        List<? extends GenPolynomial<C>> univs = univariateList(modv);
887        List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size());
888        for (C c : cogens) {
889            gens.add(getONE().multiply(c));
890        }
891        gens.addAll(univs);
892        return gens;
893    }
894
895
896    /**
897     * Is this structure finite or infinite.
898     * @return true if this structure is finite, else false.
899     * @see edu.jas.structure.ElemFactory#isFinite()
900     */
901    public boolean isFinite() {
902        return (nvar == 0) && coFac.isFinite();
903    }
904
905
906    /**
907     * Generate list of univariate polynomials in all variables.
908     * @return List(X_1,...,X_n) a list of univariate polynomials.
909     */
910    public List<? extends GenPolynomial<C>> univariateList() {
911        return univariateList(0, 1L);
912    }
913
914
915    /**
916     * Generate list of univariate polynomials in all variables.
917     * @param modv number of module variables.
918     * @return List(X_1,...,X_n) a list of univariate polynomials.
919     */
920    public List<? extends GenPolynomial<C>> univariateList(int modv) {
921        return univariateList(modv, 1L);
922    }
923
924
925    /**
926     * Generate list of univariate polynomials in all variables with given
927     * exponent.
928     * @param modv number of module variables.
929     * @param e the exponent of the variables.
930     * @return List(X_1^e,...,X_n^e) a list of univariate polynomials.
931     */
932    public List<? extends GenPolynomial<C>> univariateList(int modv, long e) {
933        List<GenPolynomial<C>> pols = new ArrayList<GenPolynomial<C>>(nvar);
934        int nm = nvar - modv;
935        for (int i = 0; i < nm; i++) {
936            GenPolynomial<C> p = univariate(modv, nm - 1 - i, e);
937            pols.add(p);
938        }
939        return pols;
940    }
941
942
943    /**
944     * Extend variables. Used e.g. in module embedding. Extend number of
945     * variables by i.
946     * @param i number of variables to extend.
947     * @return extended polynomial ring factory.
948     */
949    public GenPolynomialRing<C> extend(int i) {
950        // add module variable names
951        String[] v = newVars("e", i);
952        return extend(v);
953    }
954
955
956    /**
957     * Extend variables. Used e.g. in module embedding. Extend number of
958     * variables by length(vn).
959     * @param vn names for extended variables.
960     * @return extended polynomial ring factory.
961     */
962    public GenPolynomialRing<C> extend(String[] vn) {
963        if (vn == null || vars == null) {
964            throw new IllegalArgumentException("vn and vars may not be null");
965        }
966        int i = vn.length;
967        String[] v = new String[vars.length + i];
968        for (int k = 0; k < vars.length; k++) {
969            v[k] = vars[k];
970        }
971        for (int k = 0; k < vn.length; k++) {
972            v[vars.length + k] = vn[k];
973        }
974
975        TermOrder to = tord.extend(nvar, i);
976        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v);
977        return pfac;
978    }
979
980
981    /**
982     * Extend lower variables. Extend number of variables by i.
983     * @param i number of variables to extend.
984     * @return extended polynomial ring factory.
985     */
986    public GenPolynomialRing<C> extendLower(int i) {
987        String[] v = newVars("e", i);
988        return extendLower(v);
989    }
990
991
992    /**
993     * Extend lower variables. Extend number of variables by length(vn).
994     * @param vn names for extended lower variables.
995     * @return extended polynomial ring factory.
996     */
997    public GenPolynomialRing<C> extendLower(String[] vn) {
998        if (vn == null || vars == null) {
999            throw new IllegalArgumentException("vn and vars may not be null");
1000        }
1001        int i = vn.length;
1002        String[] v = new String[vars.length + i];
1003        for (int k = 0; k < vn.length; k++) {
1004            v[k] = vn[k];
1005        }
1006        for (int k = 0; k < vars.length; k++) {
1007            v[vn.length + k] = vars[k];
1008        }
1009        TermOrder to = tord.extendLower(nvar, i);
1010        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v);
1011        return pfac;
1012    }
1013
1014
1015    /**
1016     * Contract variables. Used e.g. in module embedding. Contract number of
1017     * variables by i.
1018     * @param i number of variables to remove.
1019     * @return contracted polynomial ring factory.
1020     */
1021    public GenPolynomialRing<C> contract(int i) {
1022        String[] v = null;
1023        if (vars != null) {
1024            v = new String[vars.length - i];
1025            for (int j = 0; j < vars.length - i; j++) {
1026                v[j] = vars[j];
1027            }
1028        }
1029        TermOrder to = tord.contract(i, nvar - i);
1030        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar - i, to, v);
1031        return pfac;
1032    }
1033
1034
1035    /**
1036     * Recursive representation as polynomial with i main variables.
1037     * @param i number of main variables.
1038     * @return recursive polynomial ring factory.
1039     */
1040    public GenPolynomialRing<GenPolynomial<C>> recursive(int i) {
1041        if (i <= 0 || i >= nvar) {
1042            throw new IllegalArgumentException("wrong: 0 < " + i + " < " + nvar);
1043        }
1044        GenPolynomialRing<C> cfac = contract(i);
1045        String[] v = null;
1046        if (vars != null) {
1047            v = new String[i];
1048            int k = 0;
1049            for (int j = nvar - i; j < nvar; j++) {
1050                v[k++] = vars[j];
1051            }
1052        }
1053        TermOrder to = tord.contract(0, i); // ??
1054        GenPolynomialRing<GenPolynomial<C>> pfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, i, to, v);
1055        return pfac;
1056    }
1057
1058
1059    /**
1060     * Distributive representation as polynomial with all main variables.
1061     * @return distributive polynomial ring factory.
1062     */
1063    @SuppressWarnings("cast")
1064    public GenPolynomialRing<C> distribute() {
1065        if (!(coFac instanceof GenPolynomialRing)) {
1066            return this;
1067        }
1068        RingFactory cf = coFac;
1069        RingFactory<GenPolynomial<C>> cfp = (RingFactory<GenPolynomial<C>>) cf;
1070        GenPolynomialRing cr = (GenPolynomialRing) cfp;
1071        GenPolynomialRing<C> pfac;
1072        if (cr.vars != null) {
1073            pfac = extend(cr.vars);
1074        } else {
1075            pfac = extend(cr.nvar);
1076        }
1077        return pfac;
1078    }
1079
1080
1081    /**
1082     * Reverse variables. Used e.g. in opposite rings.
1083     * @return polynomial ring factory with reversed variables.
1084     */
1085    public GenPolynomialRing<C> reverse() {
1086        return reverse(false);
1087    }
1088
1089
1090    /**
1091     * Reverse variables. Used e.g. in opposite rings.
1092     * @param partial true for partialy reversed term orders.
1093     * @return polynomial ring factory with reversed variables.
1094     */
1095    public GenPolynomialRing<C> reverse(boolean partial) {
1096        String[] v = null;
1097        if (vars != null) { // vars are not inversed
1098            v = new String[vars.length];
1099            int k = tord.getSplit();
1100            if (partial && k < vars.length) {
1101                // copy upper
1102                for (int j = 0; j < k; j++) {
1103                    //v[vars.length - k + j] = vars[vars.length - 1 - j]; // reverse upper
1104                    v[vars.length - k + j] = vars[vars.length - k + j];
1105                }
1106                // reverse lower
1107                for (int j = 0; j < vars.length - k; j++) {
1108                    //v[j] = vars[j]; // copy upper
1109                    v[j] = vars[vars.length - k - j - 1];
1110                }
1111            } else {
1112                for (int j = 0; j < vars.length; j++) {
1113                    v[j] = vars[vars.length - 1 - j];
1114                }
1115            }
1116            //System.out.println("vars = " + Arrays.toString(vars));
1117            //System.out.println("v    = " + Arrays.toString(v));
1118        }
1119        TermOrder to = tord.reverse(partial);
1120        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar, to, v);
1121        pfac.partial = partial;
1122        return pfac;
1123    }
1124
1125
1126    /**
1127     * Get PolynomialComparator.
1128     * @return polynomial comparator.
1129     */
1130    public PolynomialComparator<C> getComparator() {
1131        return new PolynomialComparator<C>(tord, false);
1132    }
1133
1134
1135    /**
1136     * Get PolynomialComparator.
1137     * @param rev for reverse comparator.
1138     * @return polynomial comparator.
1139     */
1140    public PolynomialComparator<C> getComparator(boolean rev) {
1141        return new PolynomialComparator<C>(tord, rev);
1142    }
1143
1144
1145    /**
1146     * New variable names. Generate new names for variables,
1147     * @param prefix name prefix.
1148     * @param n number of variables.
1149     * @return new variable names.
1150     */
1151    public static String[] newVars(String prefix, int n) {
1152        String[] vars = new String[n];
1153        synchronized (knownVars) {
1154            int m = knownVars.size();
1155            String name = prefix + m;
1156            for (int i = 0; i < n; i++) {
1157                while (knownVars.contains(name)) {
1158                    m++;
1159                    name = prefix + m;
1160                }
1161                vars[i] = name;
1162                //System.out.println("new variable: " + name);
1163                knownVars.add(name);
1164                m++;
1165                name = prefix + m;
1166            }
1167        }
1168        return vars;
1169    }
1170
1171
1172    /**
1173     * New variable names. Generate new names for variables,
1174     * @param prefix name prefix.
1175     * @return new variable names.
1176     */
1177    public String[] newVars(String prefix) {
1178        return newVars(prefix, nvar);
1179    }
1180
1181
1182    /**
1183     * New variable names. Generate new names for variables,
1184     * @param n number of variables.
1185     * @return new variable names.
1186     */
1187    public static String[] newVars(int n) {
1188        return newVars("x", n);
1189    }
1190
1191
1192    /**
1193     * New variable names. Generate new names for variables,
1194     * @return new variable names.
1195     */
1196    public String[] newVars() {
1197        return newVars(nvar);
1198    }
1199
1200
1201    /**
1202     * Add variable names.
1203     * @param vars variable names to be recorded.
1204     */
1205    public static void addVars(String[] vars) {
1206        if (vars == null) {
1207            return;
1208        }
1209        synchronized (knownVars) {
1210            for (int i = 0; i < vars.length; i++) {
1211                knownVars.add(vars[i]); // eventualy names 'overwritten'
1212            }
1213        }
1214    }
1215
1216
1217    /**
1218     * Permute variable names.
1219     * @param vars variable names.
1220     * @param P permutation.
1221     * @return P(vars).
1222     */
1223    public static String[] permuteVars(List<Integer> P, String[] vars) {
1224        if (vars == null || vars.length <= 1) {
1225            return vars;
1226        }
1227        String[] b = new String[vars.length];
1228        int j = 0;
1229        for (Integer i : P) {
1230            b[j++] = vars[i];
1231        }
1232        return b;
1233    }
1234
1235
1236    /**
1237     * Permutation of polynomial ring variables.
1238     * @param P permutation.
1239     * @return P(this).
1240     */
1241    public GenPolynomialRing<C> permutation(List<Integer> P) {
1242        if (nvar <= 1) {
1243            return this;
1244        }
1245        TermOrder tp = tord.permutation(P);
1246        if (vars == null) {
1247            return new GenPolynomialRing<C>(coFac, nvar, tp);
1248        }
1249        String[] v1 = new String[vars.length];
1250        for (int i = 0; i < v1.length; i++) {
1251            v1[i] = vars[v1.length - 1 - i];
1252        }
1253        String[] vp = permuteVars(P, v1);
1254        String[] v2 = new String[vp.length];
1255        for (int i = 0; i < vp.length; i++) {
1256            v2[i] = vp[vp.length - 1 - i];
1257        }
1258        return new GenPolynomialRing<C>(coFac, nvar, tp, v2);
1259    }
1260
1261
1262    /**
1263     * Get a GenPolynomial iterator.
1264     * @return an iterator over all polynomials.
1265     */
1266    public Iterator<GenPolynomial<C>> iterator() {
1267        if (coFac.isFinite()) {
1268            return new GenPolynomialIterator<C>(this);
1269        }
1270        logger.warn("ring of coefficients " + coFac
1271                        + " is infinite, constructing iterator only over monomials");
1272        return new GenPolynomialMonomialIterator<C>(this);
1273        //throw new IllegalArgumentException("only for finite iterable coefficients implemented");
1274    }
1275
1276}
1277
1278
1279/**
1280 * Polynomial iterator.
1281 * @author Heinz Kredel
1282 */
1283class GenPolynomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> {
1284
1285
1286    /**
1287     * data structure.
1288     */
1289    final GenPolynomialRing<C> ring;
1290
1291
1292    final Iterator<List<Long>> eviter;
1293
1294
1295    final List<ExpVector> powers;
1296
1297
1298    final List<Iterable<C>> coeffiter;
1299
1300
1301    Iterator<List<C>> itercoeff;
1302
1303
1304    GenPolynomial<C> current;
1305
1306
1307    /**
1308     * Polynomial iterator constructor.
1309     */
1310    @SuppressWarnings("unchecked")
1311    public GenPolynomialIterator(GenPolynomialRing<C> fac) {
1312        ring = fac;
1313        LongIterable li = new LongIterable();
1314        li.setNonNegativeIterator();
1315        List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar);
1316        for (int i = 0; i < ring.nvar; i++) {
1317            tlist.add(li);
1318        }
1319        CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist);
1320        eviter = ei.iterator();
1321        RingFactory<C> cf = ring.coFac;
1322        coeffiter = new ArrayList<Iterable<C>>();
1323        if (cf instanceof Iterable && cf.isFinite()) {
1324            Iterable<C> cfi = (Iterable<C>) cf;
1325            coeffiter.add(cfi);
1326        } else {
1327            throw new IllegalArgumentException("only for finite iterable coefficients implemented");
1328        }
1329        CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter);
1330        itercoeff = tuples.iterator();
1331        powers = new ArrayList<ExpVector>();
1332        ExpVector e = ExpVector.create(eviter.next());
1333        powers.add(e);
1334        //System.out.println("new e = " + e);
1335        //System.out.println("powers = " + powers);
1336        List<C> c = itercoeff.next();
1337        //System.out.println("coeffs = " + c);
1338        current = new GenPolynomial<C>(ring, c.get(0), e);
1339    }
1340
1341
1342    /**
1343     * Test for availability of a next element.
1344     * @return true if the iteration has more elements, else false.
1345     */
1346    public boolean hasNext() {
1347        return true;
1348    }
1349
1350
1351    /**
1352     * Get next polynomial.
1353     * @return next polynomial.
1354     */
1355    public synchronized GenPolynomial<C> next() {
1356        GenPolynomial<C> res = current;
1357        if (!itercoeff.hasNext()) {
1358            ExpVector e = ExpVector.create(eviter.next());
1359            powers.add(0, e); // add new ev at beginning
1360            //System.out.println("new e = " + e);
1361            //System.out.println("powers = " + powers);
1362            if (coeffiter.size() == 1) { // shorten frist iterator by one element
1363                coeffiter.add(coeffiter.get(0));
1364                Iterable<C> it = coeffiter.get(0);
1365                List<C> elms = new ArrayList<C>();
1366                for (C elm : it) {
1367                    elms.add(elm);
1368                }
1369                elms.remove(0);
1370                coeffiter.set(0, elms);
1371            } else {
1372                coeffiter.add(coeffiter.get(1));
1373            }
1374            CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter);
1375            itercoeff = tuples.iterator();
1376        }
1377        List<C> coeffs = itercoeff.next();
1378        //      while ( coeffs.get(0).isZERO() ) {
1379        //             System.out.println(" skip zero ");
1380        //          coeffs = itercoeff.next(); // skip tuples with zero in first component
1381        //      }
1382        //System.out.println("coeffs = " + coeffs);
1383        GenPolynomial<C> pol = ring.getZERO().copy();
1384        int i = 0;
1385        for (ExpVector f : powers) {
1386            C c = coeffs.get(i++);
1387            if (c.isZERO()) {
1388                continue;
1389            }
1390            if (pol.val.get(f) != null) {
1391                System.out.println("error f in pol = " + f + ", " + pol.getMap().get(f));
1392                throw new RuntimeException("error in iterator");
1393            }
1394            pol.doPutToMap(f, c);
1395        }
1396        current = pol;
1397        return res;
1398    }
1399
1400
1401    /**
1402     * Remove an element if allowed.
1403     */
1404    public void remove() {
1405        throw new UnsupportedOperationException("cannnot remove elements");
1406    }
1407}
1408
1409
1410/**
1411 * Polynomial monomial iterator.
1412 * @author Heinz Kredel
1413 */
1414class GenPolynomialMonomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> {
1415
1416
1417    /**
1418     * data structure.
1419     */
1420    final GenPolynomialRing<C> ring;
1421
1422
1423    final Iterator<List> iter;
1424
1425
1426    GenPolynomial<C> current;
1427
1428
1429    /**
1430     * Polynomial iterator constructor.
1431     */
1432    @SuppressWarnings("unchecked")
1433    public GenPolynomialMonomialIterator(GenPolynomialRing<C> fac) {
1434        ring = fac;
1435        LongIterable li = new LongIterable();
1436        li.setNonNegativeIterator();
1437        List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar);
1438        for (int i = 0; i < ring.nvar; i++) {
1439            tlist.add(li);
1440        }
1441        CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist);
1442        //Iterator<List<Long>> eviter = ei.iterator();
1443
1444        RingFactory<C> cf = ring.coFac;
1445        Iterable<C> coeffiter;
1446        if (cf instanceof Iterable && !cf.isFinite()) {
1447            Iterable<C> cfi = (Iterable<C>) cf;
1448            coeffiter = cfi;
1449        } else {
1450            throw new IllegalArgumentException("only for infinite iterable coefficients implemented");
1451        }
1452
1453        // Cantor iterator for exponents and coeffcients
1454        List<Iterable> eci = new ArrayList<Iterable>(2); // no type parameter
1455        eci.add(ei);
1456        eci.add(coeffiter);
1457        CartesianProductInfinite ecp = new CartesianProductInfinite(eci);
1458        iter = ecp.iterator();
1459
1460        List ec = iter.next();
1461        List<Long> ecl = (List<Long>) ec.get(0);
1462        C c = (C) ec.get(1); // zero
1463        ExpVector e = ExpVector.create(ecl);
1464        //System.out.println("exp    = " + e);
1465        //System.out.println("coeffs = " + c);
1466        current = new GenPolynomial<C>(ring, c, e);
1467    }
1468
1469
1470    /**
1471     * Test for availability of a next element.
1472     * @return true if the iteration has more elements, else false.
1473     */
1474    public boolean hasNext() {
1475        return true;
1476    }
1477
1478
1479    /**
1480     * Get next polynomial.
1481     * @return next polynomial.
1482     */
1483    @SuppressWarnings("unchecked")
1484    public synchronized GenPolynomial<C> next() {
1485        GenPolynomial<C> res = current;
1486
1487        List ec = iter.next();
1488        C c = (C) ec.get(1);
1489        while (c.isZERO()) { // zero already done in first next
1490            ec = iter.next();
1491            c = (C) ec.get(1);
1492        }
1493        List<Long> ecl = (List<Long>) ec.get(0);
1494        ExpVector e = ExpVector.create(ecl);
1495        //System.out.println("exp    = " + e);
1496        //System.out.println("coeffs = " + c);
1497        current = new GenPolynomial<C>(ring, c, e);
1498
1499        return res;
1500    }
1501
1502
1503    /**
1504     * Remove an element if allowed.
1505     */
1506    public void remove() {
1507        throw new UnsupportedOperationException("cannnot remove elements");
1508    }
1509}