001/*
002 * $Id: RecSolvableWordPolynomialRing.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 * RecSolvableWordPolynomialRing generic recursive solvable polynomial factory
026 * implementing RingFactory and extending GenSolvablePolynomialRing factory.
027 * Factory for n-variate ordered solvable polynomials over non-commutative word
028 * polynomial coefficients. The non-commutative multiplication relations are
029 * maintained in a relation table and the non-commutative multiplication
030 * relations between the coefficients and the main variables are maintained in a
031 * coefficient relation table. Almost immutable object, except variable names
032 * and relation table contents.
033 * @param <C> base coefficient type.
034 * @author Heinz Kredel
035 */
036
037public class RecSolvableWordPolynomialRing<C extends RingElem<C>> extends
038                GenSolvablePolynomialRing<GenWordPolynomial<C>> {
039
040
041    /**
042     * The solvable multiplication relations between variables and coefficients.
043     */
044    public final RelationTable<GenWordPolynomial<C>> coeffTable;
045
046
047    /**
048     * The constant polynomial 0 for this ring. Hides super ZERO.
049     */
050    public final RecSolvableWordPolynomial<C> ZERO;
051
052
053    /**
054     * The constant polynomial 1 for this ring. Hides super ONE.
055     */
056    public final RecSolvableWordPolynomial<C> ONE;
057
058
059    private static final Logger logger = Logger.getLogger(RecSolvableWordPolynomialRing.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 RecSolvableWordPolynomialRing(RingFactory<GenWordPolynomial<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 RecSolvableWordPolynomialRing(RingFactory<GenWordPolynomial<C>> cf, int n,
084                    RelationTable<GenWordPolynomial<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 RecSolvableWordPolynomialRing(RingFactory<GenWordPolynomial<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 RecSolvableWordPolynomialRing(RingFactory<GenWordPolynomial<C>> cf, int n, TermOrder t,
110                    RelationTable<GenWordPolynomial<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 RecSolvableWordPolynomialRing(RingFactory<GenWordPolynomial<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 RecSolvableWordPolynomialRing(RingFactory<GenWordPolynomial<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 RecSolvableWordPolynomialRing(RingFactory<GenWordPolynomial<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 RecSolvableWordPolynomialRing(RingFactory<GenWordPolynomial<C>> cf, int n, TermOrder t,
161                    String[] v, RelationTable<GenWordPolynomial<C>> rt) {
162        super(cf, n, t, v, rt);
163        //if (rt == null) { // handled in super }
164        coeffTable = new RelationTable<GenWordPolynomial<C>>(this, true);
165        ZERO = new RecSolvableWordPolynomial<C>(this);
166        GenWordPolynomial<C> coeff = coFac.getONE();
167        //evzero = ExpVector.create(nvar); // from super
168        ONE = new RecSolvableWordPolynomial<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 RecSolvableWordPolynomialRing(RingFactory<GenWordPolynomial<C>> cf, RecSolvableWordPolynomialRing 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<GenWordPolynomial<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 RecSolvableWordPolynomialRing)) {
252            return false;
253        }
254        // do a super.equals( )
255        if (!super.equals(other)) {
256            return false;
257        }
258        RecSolvableWordPolynomialRing<C> oring = (RecSolvableWordPolynomialRing<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 RecSolvableWordPolynomial<C>.
287     */
288    @Override
289    public RecSolvableWordPolynomial<C> getZERO() {
290        return ZERO;
291    }
292
293
294    /**
295     * Get the one element.
296     * @return 1 as RecSolvableWordPolynomial<C>.
297     */
298    @Override
299    public RecSolvableWordPolynomial<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        RecSolvableWordPolynomial<C> Xi, Xj, Xk, p, q;
330        List<GenPolynomial<GenWordPolynomial<C>>> gens = generators();
331        //System.out.println("Rec word gens = " + gens);
332        int ngen = gens.size();
333        for (int i = 0; i < ngen; i++) {
334            Xi = (RecSolvableWordPolynomial<C>) gens.get(i);
335            if (Xi.isONE()) {
336                continue;
337            }
338            for (int j = i + 1; j < ngen; j++) {
339                Xj = (RecSolvableWordPolynomial<C>) gens.get(j);
340                for (int k = j + 1; k < ngen; k++) {
341                    Xk = (RecSolvableWordPolynomial<C>) gens.get(k);
342                    try {
343                        p = Xk.multiply(Xj).multiply(Xi);
344                        q = Xk.multiply(Xj.multiply(Xi));
345                        if (!p.equals(q)) {
346                            if (true || debug) {
347                                logger.info("Xk = " + Xk + ", Xj = " + Xj + ", Xi = " + Xi);
348                                logger.info("p = ( Xk * Xj ) * Xi = " + p);
349                                logger.info("q = Xk * ( Xj * Xi ) = " + q);
350                            }
351                            return false;
352                        }
353                    } catch (RuntimeException e) {
354                        e.printStackTrace();
355                        System.out.println("Xk = " + Xk + ", Xj = " + Xj + ", Xi = " + Xi);
356                    }
357                }
358            }
359        }
360        return true;
361    }
362
363
364    /**
365     * Get a (constant) RecSolvableWordPolynomial&lt;C&gt; element from a
366     * coefficient value.
367     * @param a coefficient.
368     * @return a RecSolvableWordPolynomial&lt;C&gt;.
369     */
370    @Override
371    public RecSolvableWordPolynomial<C> valueOf(GenWordPolynomial<C> a) {
372        return new RecSolvableWordPolynomial<C>(this, a);
373    }
374
375
376    /**
377     * Get a RecSolvableWordPolynomial&lt;C&gt; element from an ExpVector.
378     * @param e exponent vector.
379     * @return a RecSolvableWordPolynomial&lt;C&gt;.
380     */
381    @Override
382    public RecSolvableWordPolynomial<C> valueOf(ExpVector e) {
383        return valueOf(coFac.getONE(), e);
384    }
385
386
387    /**
388     * Get a RecSolvableWordPolynomial&lt;C&gt; element from a coeffcient and an
389     * ExpVector.
390     * @param a coefficient.
391     * @param e exponent vector.
392     * @return a RecSolvableWordPolynomial&lt;C&gt;.
393     */
394    @Override
395    public RecSolvableWordPolynomial<C> valueOf(GenWordPolynomial<C> a, ExpVector e) {
396        return new RecSolvableWordPolynomial<C>(this, a, e);
397    }
398
399
400    /**
401     * Get a (constant) RecSolvableWordPolynomial&lt;C&gt; element from a long
402     * value.
403     * @param a long.
404     * @return a RecSolvableWordPolynomial&lt;C&gt;.
405     */
406    @Override
407    public RecSolvableWordPolynomial<C> fromInteger(long a) {
408        return new RecSolvableWordPolynomial<C>(this, coFac.fromInteger(a), evzero);
409    }
410
411
412    /**
413     * Get a (constant) RecSolvableWordPolynomial&lt;C&gt; element from a
414     * BigInteger value.
415     * @param a BigInteger.
416     * @return a RecSolvableWordPolynomial&lt;C&gt;.
417     */
418    @Override
419    public RecSolvableWordPolynomial<C> fromInteger(BigInteger a) {
420        return new RecSolvableWordPolynomial<C>(this, coFac.fromInteger(a), evzero);
421    }
422
423
424    /**
425     * Random solvable polynomial. Generates a random solvable polynomial with k
426     * = 5, l = n, d = (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3.
427     * @param n number of terms.
428     * @return a random solvable polynomial.
429     */
430    @Override
431    public RecSolvableWordPolynomial<C> random(int n) {
432        return random(n, random);
433    }
434
435
436    /**
437     * Random solvable polynomial. Generates a random solvable polynomial with k
438     * = 5, l = n, d = (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3.
439     * @param n number of terms.
440     * @param rnd is a source for random bits.
441     * @return a random solvable polynomial.
442     */
443    @Override
444    public RecSolvableWordPolynomial<C> random(int n, Random rnd) {
445        if (nvar == 1) {
446            return random(5, n, n, 0.7f, rnd);
447        }
448        return random(5, n, 3, 0.3f, rnd);
449    }
450
451
452    /**
453     * Generate a random solvable polynomial.
454     * @param k bitsize of random coefficients.
455     * @param l number of terms.
456     * @param d maximal degree in each variable.
457     * @param q density of nozero exponents.
458     * @return a random solvable polynomial.
459     */
460    @Override
461    public RecSolvableWordPolynomial<C> random(int k, int l, int d, float q) {
462        return random(k, l, d, q, random);
463    }
464
465
466    /**
467     * Random solvable polynomial.
468     * @param k size of random coefficients.
469     * @param l number of terms.
470     * @param d maximal degree in each variable.
471     * @param q density of nozero exponents.
472     * @param rnd is a source for random bits.
473     * @return a random solvable polynomial.
474     */
475    @Override
476    public RecSolvableWordPolynomial<C> random(int k, int l, int d, float q, Random rnd) {
477        RecSolvableWordPolynomial<C> r = getZERO(); // copy( ZERO ); 
478        ExpVector e;
479        GenWordPolynomial<C> a;
480        // add random coeffs and exponents
481        for (int i = 0; i < l; i++) {
482            e = ExpVector.EVRAND(nvar, d, q, rnd);
483            a = coFac.random(k, rnd);
484            r = (RecSolvableWordPolynomial<C>) r.sum(a, e);
485            // somewhat inefficient but clean
486        }
487        return r;
488    }
489
490
491    /**
492     * Copy polynomial c.
493     * @param c
494     * @return a copy of c.
495     */
496    public RecSolvableWordPolynomial<C> copy(RecSolvableWordPolynomial<C> c) {
497        return new RecSolvableWordPolynomial<C>(this, c.val);
498    }
499
500
501    /**
502     * Parse a solvable polynomial with the use of GenPolynomialTokenizer
503     * @param s String.
504     * @return RecSolvableWordPolynomial from s.
505     */
506    @Override
507    public RecSolvableWordPolynomial<C> parse(String s) {
508        return parse(new StringReader(s));
509    }
510
511
512    /**
513     * Parse a solvable polynomial with the use of GenPolynomialTokenizer
514     * @param r Reader.
515     * @return next RecSolvableWordPolynomial from r.
516     */
517    @Override
518    @SuppressWarnings("unchecked")
519    public RecSolvableWordPolynomial<C> parse(Reader r) {
520        GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r);
521        RecSolvableWordPolynomial<C> p = null;
522        try {
523            GenSolvablePolynomial<GenWordPolynomial<C>> s = pt.nextSolvablePolynomial();
524            p = new RecSolvableWordPolynomial<C>(this, s);
525        } catch (IOException e) {
526            logger.error(e.toString() + " parse " + this);
527            p = ZERO;
528        }
529        return p;
530    }
531
532
533    /**
534     * Generate univariate solvable polynomial in a given variable.
535     * @param i the index of the variable.
536     * @return X_i as solvable univariate polynomial.
537     */
538    @Override
539    public RecSolvableWordPolynomial<C> univariate(int i) {
540        return (RecSolvableWordPolynomial<C>) super.univariate(i);
541    }
542
543
544    /**
545     * Generate univariate solvable polynomial in a given variable with given
546     * exponent.
547     * @param i the index of the variable.
548     * @param e the exponent of the variable.
549     * @return X_i^e as solvable univariate polynomial.
550     */
551    @Override
552    public RecSolvableWordPolynomial<C> univariate(int i, long e) {
553        return (RecSolvableWordPolynomial<C>) super.univariate(i, e);
554    }
555
556
557    /**
558     * Generate univariate solvable polynomial in a given variable with given
559     * exponent.
560     * @param modv number of module variables.
561     * @param i the index of the variable.
562     * @param e the exponent of the variable.
563     * @return X_i^e as solvable univariate polynomial.
564     */
565    @Override
566    public RecSolvableWordPolynomial<C> univariate(int modv, int i, long e) {
567        return (RecSolvableWordPolynomial<C>) super.univariate(modv, i, e);
568    }
569
570
571    /**
572     * Generate list of univariate polynomials in all variables.
573     * @return List(X_1,...,X_n) a list of univariate polynomials.
574     */
575    @Override
576    public List<RecSolvableWordPolynomial<C>> univariateList() {
577        //return castToSolvableList( super.univariateList() );
578        return univariateList(0, 1L);
579    }
580
581
582    /**
583     * Generate list of univariate polynomials in all variables.
584     * @param modv number of module variables.
585     * @return List(X_1,...,X_n) a list of univariate polynomials.
586     */
587    @Override
588    public List<RecSolvableWordPolynomial<C>> univariateList(int modv) {
589        return univariateList(modv, 1L);
590    }
591
592
593    /**
594     * Generate list of univariate polynomials in all variables with given
595     * exponent.
596     * @param modv number of module variables.
597     * @param e the exponent of the variables.
598     * @return List(X_1^e,...,X_n^e) a list of univariate polynomials.
599     */
600    @Override
601    public List<RecSolvableWordPolynomial<C>> univariateList(int modv, long e) {
602        List<RecSolvableWordPolynomial<C>> pols = new ArrayList<RecSolvableWordPolynomial<C>>(nvar);
603        int nm = nvar - modv;
604        for (int i = 0; i < nm; i++) {
605            RecSolvableWordPolynomial<C> p = univariate(modv, nm - 1 - i, e);
606            pols.add(p);
607        }
608        return pols;
609    }
610
611
612    /**
613     * Extend variables. Used e.g. in module embedding. Extend number of
614     * variables by i.
615     * @param i number of variables to extend.
616     * @return extended solvable polynomial ring factory.
617     */
618    @Override
619    public RecSolvableWordPolynomialRing<C> extend(int i) {
620        GenSolvablePolynomialRing<GenWordPolynomial<C>> pfac = super.extend(i);
621        RecSolvableWordPolynomialRing<C> spfac = new RecSolvableWordPolynomialRing<C>(pfac.coFac, pfac.nvar,
622                        pfac.tord, pfac.vars, pfac.table);
623        //spfac.table.extend(this.table); // pfac.table
624        spfac.coeffTable.extend(this.coeffTable);
625        return spfac;
626    }
627
628
629    /**
630     * Extend variables. Used e.g. in module embedding. Extend number of
631     * variables by length(vn). New variables commute with the exiting
632     * variables.
633     * @param vs names for extended variables.
634     * @return extended polynomial ring factory.
635     */
636    @Override
637    public RecSolvableWordPolynomialRing<C> extend(String[] vs) {
638        GenSolvablePolynomialRing<GenWordPolynomial<C>> pfac = super.extend(vs);
639        RecSolvableWordPolynomialRing<C> spfac = new RecSolvableWordPolynomialRing<C>(pfac.coFac, pfac.nvar,
640                        pfac.tord, pfac.vars, pfac.table);
641        //spfac.table.extend(this.table); // pfac.table??
642        spfac.coeffTable.extend(this.coeffTable);
643        return spfac;
644    }
645
646
647    /**
648     * Contract variables. Used e.g. in module embedding. Contract number of
649     * variables by i.
650     * @param i number of variables to remove.
651     * @return contracted solvable polynomial ring factory.
652     */
653    @Override
654    public RecSolvableWordPolynomialRing<C> contract(int i) {
655        GenPolynomialRing<GenWordPolynomial<C>> pfac = super.contract(i);
656        RecSolvableWordPolynomialRing<C> spfac = new RecSolvableWordPolynomialRing<C>(pfac.coFac, pfac.nvar,
657                        pfac.tord, pfac.vars);
658        spfac.table.contract(this.table);
659        spfac.coeffTable.contract(this.coeffTable);
660        return spfac;
661    }
662
663
664    /**
665     * Reverse variables. Used e.g. in opposite rings.
666     * @return solvable polynomial ring factory with reversed variables.
667     */
668    @Override
669    public RecSolvableWordPolynomialRing<C> reverse() {
670        return reverse(false);
671    }
672
673
674    /**
675     * Reverse variables. Used e.g. in opposite rings.
676     * @param partial true for partialy reversed term orders.
677     * @return solvable polynomial ring factory with reversed variables.
678     */
679    @Override
680    public RecSolvableWordPolynomialRing<C> reverse(boolean partial) {
681        GenPolynomialRing<GenWordPolynomial<C>> pfac = super.reverse(partial);
682        RecSolvableWordPolynomialRing<C> spfac = new RecSolvableWordPolynomialRing<C>(pfac.coFac, pfac.nvar,
683                        pfac.tord, pfac.vars);
684        spfac.partial = partial;
685        spfac.table.reverse(this.table);
686        spfac.coeffTable.reverse(this.coeffTable);
687        return spfac;
688    }
689
690
691    /* not possible:
692     * Distributive representation as polynomial with all main variables.
693     * @return distributive polynomial ring factory.
694    @SuppressWarnings({"cast","unchecked"})
695    public static <C extends RingElem<C>> // must be static because of types
696       GenSolvablePolynomialRing<C> distribute(RecSolvableWordPolynomialRing<C> rf) {
697    }
698     */
699
700
701    /**
702     * Permutation of polynomial ring variables.
703     * @param P permutation.
704     * @return P(this).
705     */
706    @Override
707    public GenSolvablePolynomialRing<GenWordPolynomial<C>> permutation(List<Integer> P) {
708        if (!coeffTable.isEmpty()) {
709            throw new UnsupportedOperationException("permutation with coeff relations: " + this);
710        }
711        GenSolvablePolynomialRing<GenWordPolynomial<C>> pfac = (GenSolvablePolynomialRing<GenWordPolynomial<C>>) super
712                        .permutation(P);
713        return pfac;
714    }
715
716}