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