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