001/*
002 * $Id: SolvableQuotientRing.java 5738 2017-02-18 20:37:26Z kredel $
003 */
004
005package edu.jas.fd;
006
007
008import java.io.Reader;
009import java.util.ArrayList;
010import java.util.List;
011import java.util.Random;
012
013import org.apache.log4j.Logger;
014
015import edu.jas.gbufd.SolvableSyzygyAbstract;
016import edu.jas.gbufd.SolvableSyzygySeq;
017import edu.jas.kern.StringUtil;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenSolvablePolynomial;
020import edu.jas.poly.GenSolvablePolynomialRing;
021import edu.jas.poly.PolynomialList;
022import edu.jas.structure.GcdRingElem;
023import edu.jas.structure.QuotPairFactory;
024import edu.jas.structure.RingFactory;
025
026
027/**
028 * SolvableQuotient ring factory based on GenPolynomial with RingElem interface.
029 * Objects of this class are immutable.
030 * @author Heinz Kredel
031 */
032public class SolvableQuotientRing<C extends GcdRingElem<C>> implements RingFactory<SolvableQuotient<C>>,
033                QuotPairFactory<GenPolynomial<C>, SolvableQuotient<C>> {
034    // should be QuotPairFactory<GenSolvablePolynomial<C>
035
036
037    private static final Logger logger = Logger.getLogger(SolvableQuotientRing.class);
038
039
040    //private static final boolean debug = logger.isDebugEnabled();
041
042
043    /**
044     * Solvable polynomial ring of the factory.
045     */
046    public final GenSolvablePolynomialRing<C> ring;
047
048
049    /**
050     * Syzygy engine of the factory.
051     */
052    public final SolvableSyzygyAbstract<C> engine;
053
054
055    /**
056     * The constructor creates a SolvableQuotientRing object from a
057     * GenSolvablePolynomialRing.
058     * @param r solvable polynomial ring.
059     */
060    public SolvableQuotientRing(GenSolvablePolynomialRing<C> r) {
061        ring = r;
062        engine = new SolvableSyzygySeq<C>(ring.coFac);
063        logger.debug("quotient ring constructed");
064    }
065
066
067    /**
068     * Factory for base elements.
069     */
070    public GenSolvablePolynomialRing<C> pairFactory() {
071        return ring;
072    }
073
074
075    /**
076     * Create from numerator.
077     */
078    @SuppressWarnings("unchecked")
079    public SolvableQuotient<C> create(GenPolynomial<C> n) {
080        return new SolvableQuotient<C>(this, (GenSolvablePolynomial<C>) n);
081    }
082
083
084    /**
085     * Create from numerator, denominator pair.
086     */
087    @SuppressWarnings("unchecked")
088    public SolvableQuotient<C> create(GenPolynomial<C> n, GenPolynomial<C> d) {
089        return new SolvableQuotient<C>(this, (GenSolvablePolynomial<C>) n, (GenSolvablePolynomial<C>) d);
090    }
091
092
093    /**
094     * Is this structure finite or infinite.
095     * @return true if this structure is finite, else false.
096     */
097    public boolean isFinite() {
098        return ring.isFinite();
099    }
100
101
102    /**
103     * Copy SolvableQuotient element c.
104     * @param c
105     * @return a copy of c.
106     */
107    public SolvableQuotient<C> copy(SolvableQuotient<C> c) {
108        return new SolvableQuotient<C>(c.ring, c.num, c.den, true);
109    }
110
111
112    /**
113     * Get the zero element.
114     * @return 0 as SolvableQuotient.
115     */
116    public SolvableQuotient<C> getZERO() {
117        return new SolvableQuotient<C>(this, ring.getZERO());
118    }
119
120
121    /**
122     * Get the one element.
123     * @return 1 as SolvableQuotient.
124     */
125    public SolvableQuotient<C> getONE() {
126        return new SolvableQuotient<C>(this, ring.getONE());
127    }
128
129
130    /**
131     * Get a list of the generating elements.
132     * @return list of generators for the algebraic structure.
133     */
134    public List<SolvableQuotient<C>> generators() {
135        List<GenSolvablePolynomial<C>> pgens = PolynomialList.<C> castToSolvableList(ring.generators());
136        List<SolvableQuotient<C>> gens = new ArrayList<SolvableQuotient<C>>(pgens.size() * 2 - 1);
137        GenSolvablePolynomial<C> one = ring.getONE();
138        for (GenSolvablePolynomial<C> p : pgens) {
139            SolvableQuotient<C> q = new SolvableQuotient<C>(this, p);
140            gens.add(q);
141            if (!p.isONE()) {
142                q = new SolvableQuotient<C>(this, one, p);
143                gens.add(q);
144            }
145        }
146        return gens;
147    }
148
149
150    /**
151     * Query if this ring is commutative.
152     * @return true if this ring is commutative, else false.
153     */
154    public boolean isCommutative() {
155        return ring.isCommutative();
156    }
157
158
159    /**
160     * Query if this ring is associative.
161     * @return true if this ring is associative, else false.
162     */
163    public boolean isAssociative() {
164        if (!ring.isAssociative()) {
165            return false;
166        }
167        SolvableQuotient<C> Xi, Xj, Xk, p, q;
168        List<SolvableQuotient<C>> gens = generators();
169        int ngen = gens.size();
170        for (int i = 0; i < ngen; i++) {
171            Xi = gens.get(i);
172            for (int j = i + 1; j < ngen; j++) {
173                Xj = gens.get(j);
174                for (int k = j + 1; k < ngen; k++) {
175                    Xk = gens.get(k);
176                    p = Xk.multiply(Xj).multiply(Xi);
177                    q = Xk.multiply(Xj.multiply(Xi));
178                    if (!p.equals(q)) {
179                        if (logger.isInfoEnabled()) {
180                            logger.info("Xk = " + Xk + ", Xj = " + Xj + ", Xi = " + Xi);
181                            logger.info("p = ( Xk * Xj ) * Xi = " + p);
182                            logger.info("q = Xk * ( Xj * Xi ) = " + q);
183                        }
184                        return false;
185                    }
186                }
187            }
188        }
189        return true;
190    }
191
192
193    /**
194     * Query if this ring is a field.
195     * @return true.
196     */
197    public boolean isField() {
198        return true;
199    }
200
201
202    /**
203     * Characteristic of this ring.
204     * @return characteristic of this ring.
205     */
206    public java.math.BigInteger characteristic() {
207        return ring.characteristic();
208    }
209
210
211    /**
212     * Get a SolvableQuotient element from a BigInteger value.
213     * @param a BigInteger.
214     * @return a SolvableQuotient.
215     */
216    public SolvableQuotient<C> fromInteger(java.math.BigInteger a) {
217        return new SolvableQuotient<C>(this, ring.fromInteger(a));
218    }
219
220
221    /**
222     * Get a SolvableQuotient element from a long value.
223     * @param a long.
224     * @return a SolvableQuotient.
225     */
226    public SolvableQuotient<C> fromInteger(long a) {
227        return new SolvableQuotient<C>(this, ring.fromInteger(a));
228    }
229
230
231    /**
232     * Get the String representation as RingFactory.
233     */
234    @Override
235    public String toString() {
236        String s = null;
237        if (ring.coFac.characteristic().signum() == 0) {
238            s = "RatFunc";
239        } else {
240            s = "ModFunc";
241        }
242        return s + "( " + ring.toString() + " )";
243    }
244
245
246    /**
247     * Get a scripting compatible string representation.
248     * @return script compatible representation for this ElemFactory.
249     */
250    @Override
251    public String toScript() {
252        // Python case
253        return "SRF(" + ring.toScript() + ")";
254    }
255
256
257    /**
258     * Comparison with any other object.
259     */
260    @Override
261    @SuppressWarnings("unchecked")
262    public boolean equals(Object b) {
263        if (b == null) {
264            return false;
265        }
266        if (!(b instanceof SolvableQuotientRing)) {
267            return false;
268        }
269        SolvableQuotientRing<C> a = (SolvableQuotientRing<C>) b;
270        return ring.equals(a.ring);
271    }
272
273
274    /**
275     * Hash code for this quotient ring.
276     */
277    @Override
278    public int hashCode() {
279        int h;
280        h = ring.hashCode();
281        return h;
282    }
283
284
285    /**
286     * SolvableQuotient random.
287     * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
288     * @return a random quotient element.
289     */
290    public SolvableQuotient<C> random(int n) {
291        GenSolvablePolynomial<C> r = ring.random(n).monic();
292        GenSolvablePolynomial<C> s;
293        do {
294            s = ring.random(n).monic();
295        } while (s.isZERO());
296        return new SolvableQuotient<C>(this, r, s, false);
297    }
298
299
300    /**
301     * Generate a random quotient.
302     * @param k bitsize of random coefficients.
303     * @param l number of terms.
304     * @param d maximal degree in each variable.
305     * @param q density of nozero exponents.
306     * @return a random quotient.
307     */
308    public SolvableQuotient<C> random(int k, int l, int d, float q) {
309        GenSolvablePolynomial<C> r = ring.random(k, l, d, q).monic();
310        GenSolvablePolynomial<C> s = ring.random(k, l, d, q).monic();
311        do {
312            s = ring.random(k, l, d, q).monic();
313        } while (s.isZERO());
314        return new SolvableQuotient<C>(this, r, s, false);
315    }
316
317
318    /**
319     * SolvableQuotient random.
320     * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
321     * @param rnd is a source for random bits.
322     * @return a random quotient element.
323     */
324    public SolvableQuotient<C> random(int n, Random rnd) {
325        GenSolvablePolynomial<C> r = ring.random(n, rnd).monic();
326        GenSolvablePolynomial<C> s = ring.random(n, rnd).monic();
327        do {
328            s = ring.random(n, rnd).monic();
329        } while (s.isZERO());
330        return new SolvableQuotient<C>(this, r, s, false);
331    }
332
333
334    /**
335     * Parse SolvableQuotient from String. Syntax: "{ polynomial | polynomial }"
336     * or "{ polynomial }" or " polynomial | polynomial " or " polynomial "
337     * @param s String.
338     * @return SolvableQuotient from s.
339     */
340    public SolvableQuotient<C> parse(String s) {
341        int i = s.indexOf("{");
342        if (i >= 0) {
343            s = s.substring(i + 1);
344        }
345        i = s.lastIndexOf("}");
346        if (i >= 0) {
347            s = s.substring(0, i);
348        }
349        i = s.indexOf("|");
350        if (i < 0) {
351            GenSolvablePolynomial<C> n = ring.parse(s);
352            return new SolvableQuotient<C>(this, n);
353        }
354        String s1 = s.substring(0, i);
355        String s2 = s.substring(i + 1);
356        GenSolvablePolynomial<C> n = ring.parse(s1);
357        GenSolvablePolynomial<C> d = ring.parse(s2);
358        return new SolvableQuotient<C>(this, n, d);
359    }
360
361
362    /**
363     * Parse SolvableQuotient from Reader.
364     * @param r Reader.
365     * @return next SolvableQuotient from r.
366     */
367    public SolvableQuotient<C> parse(Reader r) {
368        String s = StringUtil.nextPairedString(r, '{', '}');
369        return parse(s);
370    }
371
372}