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