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