001/*
002 * $Id: ColorPolynomial.java 5122 2015-02-17 08:35:15Z kredel $
003 */
004
005package edu.jas.application;
006
007
008import java.io.Serializable;
009import java.util.ArrayList;
010import java.util.Collection;
011import java.util.Comparator;
012import java.util.List;
013import java.util.Map;
014
015import org.apache.log4j.Logger;
016
017import edu.jas.poly.ExpVector;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenSolvablePolynomial;
020import edu.jas.structure.RingElem;
021
022
023/**
024 * Colored Polynomials with green, red and white coefficients. Not implementing
025 * RingElem. <b>Note:</b> not general purpose, use only in comprehensive GB.
026 * @param <C> coefficient type
027 * @author Heinz Kredel
028 */
029
030public class ColorPolynomial<C extends RingElem<C>> implements Serializable
031    /* implements RingElem< ColorPolynomial<C> > */ {
032
033
034    private static final Logger logger = Logger.getLogger(ColorPolynomial.class);
035
036
037    /**
038     * The part with green (= zero) terms and coefficients.
039     */
040    public final GenPolynomial<GenPolynomial<C>> green;
041
042
043    /**
044     * The part with red (= non zero) terms and coefficients.
045     */
046    public final GenPolynomial<GenPolynomial<C>> red;
047
048
049    /**
050     * The part with white (= unknown color) terms and coefficients.
051     */
052    public final GenPolynomial<GenPolynomial<C>> white;
053
054
055    /**
056     * The constructor creates a colored polynomial from the colored parts.
057     * @param g green colored terms and coefficients.
058     * @param r red colored terms and coefficients.
059     * @param w white colored terms and coefficients.
060     */
061    public ColorPolynomial(GenPolynomial<GenPolynomial<C>> g,
062            GenPolynomial<GenPolynomial<C>> r, GenPolynomial<GenPolynomial<C>> w) {
063        if (g == null || r == null || w == null) {
064            throw new IllegalArgumentException("g,r,w may not be null");
065        }
066        green = g;
067        red = r;
068        white = w;
069    }
070
071
072    /**
073     * String representation of ColorPolynomial.
074     * @see java.lang.Object#toString()
075     */
076    @Override
077    public String toString() {
078        StringBuffer s = new StringBuffer();
079        s.append(":green: ");
080        s.append(green.toString());
081        s.append(" :red: ");
082        s.append(red.toString());
083        s.append(" :white: ");
084        s.append(white.toString());
085        return s.toString();
086    }
087
088
089    /**
090     * Script representation of ColorPolynomial.
091     * @see edu.jas.structure.Element#toScript()
092     */
093    public String toScript() {
094        StringBuffer s = new StringBuffer();
095        s.append(":green: ");
096        s.append(green.toScript());
097        s.append(" :red: ");
098        s.append(red.toScript());
099        s.append(" :white: ");
100        s.append(white.toScript());
101        return s.toString();
102    }
103
104
105    /**
106     * Is this polynomial ZERO.
107     * @return true, if there are only green terms, else false.
108     */
109    public boolean isZERO() {
110        return (red.isZERO() && white.isZERO());
111    }
112
113
114    /**
115     * Is this polynomial ONE.
116     * @return true, if the only non green term is 1, else false.
117     */
118    public boolean isONE() {
119        return ((red.isZERO() && white.isONE()) || (red.isONE() && white.isZERO()));
120    }
121
122
123    /**
124     * Is this polynomial equal to other.
125     * @param p other polynomial.
126     * @return true, if this is equal to other, else false.
127     */
128    @Override
129    @SuppressWarnings("unchecked")
130    public boolean equals(Object p) {
131        ColorPolynomial<C> cp = null;
132        try {
133            cp = (ColorPolynomial<C>) p;
134        } catch (ClassCastException e) {
135            return false;
136        }
137        if (cp == null) {
138            return false;
139        }
140        return (green.equals(cp.green) && red.equals(cp.red) && white.equals(cp.white));
141    }
142
143
144    /**
145     * Hash code for this colored polynomial.
146     * @see java.lang.Object#hashCode()
147     */
148    @Override
149    public int hashCode() {
150        int h;
151        h = green.hashCode();
152        h = h << 11;
153        h += red.hashCode();
154        h = h << 11;
155        h += white.hashCode();
156        return h;
157    }
158
159
160    /**
161     * Is this polynomial determined.
162     * @return true, if there are nonzero red terms or if this == 0, else false.
163     */
164    public boolean isDetermined() {
165        return (!red.isZERO() || white.isZERO());
166    }
167
168
169    /**
170     * Check ordering invariants. TT(green) > LT(red) and TT(red) > LT(white).
171     * @return true, if all ordering invariants are met, else false.
172     */
173    public boolean checkInvariant() {
174        boolean t = true;
175        ExpVector ttg, ltr, ttr, ltw;
176        Comparator<ExpVector> cmp;
177        if (green.isZERO() && red.isZERO() && white.isZERO()) {
178            return true;
179        }
180        if (green.isZERO() && red.isZERO()) {
181            return true;
182        }
183        if (red.isZERO() && white.isZERO()) {
184            return true;
185        }
186
187        if (!green.isZERO() && !red.isZERO()) {
188            ttg = green.trailingExpVector();
189            ltr = red.leadingExpVector();
190            cmp = green.ring.tord.getDescendComparator();
191            t = t && (cmp.compare(ttg, ltr) < 0);
192        }
193        if (!red.isZERO() && !white.isZERO()) {
194            ttr = red.trailingExpVector();
195            ltw = white.leadingExpVector();
196            cmp = white.ring.tord.getDescendComparator();
197            t = t && (cmp.compare(ttr, ltw) < 0);
198        }
199        if (red.isZERO() && !green.isZERO() && !white.isZERO()) {
200            ttg = green.trailingExpVector();
201            ltw = white.leadingExpVector();
202            cmp = white.ring.tord.getDescendComparator();
203            t = t && (cmp.compare(ttg, ltw) < 0);
204        }
205        if (!t) {
206            System.out.println("not invariant " + this);
207            // throw new RuntimeException("test");
208        }
209        return t;
210    }
211
212
213    /**
214     * Get zero condition on coefficients.
215     * @return green coefficients.
216     */
217    public List<GenPolynomial<C>> getGreenCoefficients() {
218        Collection<GenPolynomial<C>> c = green.getMap().values();
219        return new ArrayList<GenPolynomial<C>>(c);
220    }
221
222
223    /**
224     * Get non zero condition on coefficients.
225     * @return red coefficients.
226     */
227    public List<GenPolynomial<C>> getRedCoefficients() {
228        Collection<GenPolynomial<C>> c = red.getMap().values();
229        return new ArrayList<GenPolynomial<C>>(c);
230    }
231
232
233    /**
234     * Get full polynomial.
235     * @return sum of all parts.
236     */
237    public GenPolynomial<GenPolynomial<C>> getPolynomial() {
238        GenPolynomial<GenPolynomial<C>> f = green.sum(red).sum(white);
239        int s = green.length() + red.length() + white.length();
240        int t = f.length();
241        if (t != s) {
242            throw new RuntimeException("illegal coloring state " + s + " != " + t);
243        }
244        return f;
245    }
246
247
248    /**
249     * Get essential polynomial.
250     * @return sum of red and white parts.
251     */
252    public GenPolynomial<GenPolynomial<C>> getEssentialPolynomial() {
253        GenPolynomial<GenPolynomial<C>> f = red.sum(white);
254        int s = red.length() + white.length();
255        int t = f.length();
256        if (t != s) {
257            logger.warn("illegal coloring state " + s + " != " + t);
258            logger.info("f = " + f + ", red = " + red + ", white = " + white);
259            //throw new RuntimeException("illegal coloring state " + s + " != " + t);
260        }
261        return f;
262    }
263
264
265    /**
266     * Length of red and white parts.
267     * @return length of essential parts.
268     */
269    public int length() {
270        int s = red.length() + white.length();
271        return s;
272    }
273
274
275    /**
276     * Get leading exponent vector.
277     * @return LT of red or white parts.
278     */
279    public ExpVector leadingExpVector() {
280        if (!red.isZERO()) {
281            return red.leadingExpVector();
282        }
283        return white.leadingExpVector();
284    }
285
286
287    /**
288     * Get leading monomial.
289     * @return LM of red or white parts.
290     */
291    public Map.Entry<ExpVector, GenPolynomial<C>> leadingMonomial() {
292        if (!red.isZERO()) {
293            return red.leadingMonomial();
294        }
295        return white.leadingMonomial();
296    }
297
298
299    /**
300     * ColorPolynomial absolute value.
301     * @return abs(this).
302     */
303    public ColorPolynomial<C> abs() {
304        GenPolynomial<GenPolynomial<C>> g, r, w;
305        int s = green.signum();
306        if (s > 0) {
307            return this;
308        }
309        if (s < 0) {
310            g = green.negate();
311            r = red.negate();
312            w = white.negate();
313            return new ColorPolynomial<C>(g, r, w);
314        }
315        // green == 0
316        g = green;
317        s = red.signum();
318        if (s > 0) {
319            return this;
320        }
321        if (s < 0) {
322            r = red.negate();
323            w = white.negate();
324            return new ColorPolynomial<C>(g, r, w);
325        }
326        // red == 0
327        r = red;
328        s = white.signum();
329        if (s > 0) {
330            return this;
331        }
332        if (s < 0) {
333            w = white.negate();
334            return new ColorPolynomial<C>(g, r, w);
335        }
336        // white == 0
337        w = white;
338        return new ColorPolynomial<C>(g, r, w);
339    }
340
341
342    /**
343     * ColorPolynomial summation. <b>Note:</b> green coefficients stay green,
344     * all others become white.
345     * @param S ColorPolynomial.
346     * @return this+S.
347     */
348    public ColorPolynomial<C> sum(ColorPolynomial<C> S) {
349        GenPolynomial<GenPolynomial<C>> g, r, w;
350        g = green.sum(S.green);
351        r = red.ring.getZERO();
352        w = getEssentialPolynomial().sum(S.getEssentialPolynomial());
353        return new ColorPolynomial<C>(g, r, w);
354    }
355
356
357    /**
358     * ColorPolynomial summation.
359     * @param s GenPolynomial.
360     * @param e exponent vector.
361     * @return this+(c e).
362     */
363    public ColorPolynomial<C> sum(GenPolynomial<C> s, ExpVector e) {
364        GenPolynomial<GenPolynomial<C>> g, r, w;
365        g = green;
366        r = red;
367        w = white;
368        if (green.getMap().keySet().contains(e)) {
369            g = green.sum(s, e);
370        } else if (red.getMap().keySet().contains(e)) {
371            r = red.sum(s, e);
372        } else {
373            w = white.sum(s, e);
374        }
375        return new ColorPolynomial<C>(g, r, w);
376    }
377
378
379    /**
380     * ColorPolynomial subtraction. <b>Note:</b> green coefficients stay green,
381     * all others become white.
382     * @param S ColorPolynomial.
383     * @return this-S.
384     */
385    public ColorPolynomial<C> subtract(ColorPolynomial<C> S) {
386        GenPolynomial<GenPolynomial<C>> g, r, w;
387        g = green.subtract(S.green);
388        r = red.ring.getZERO();
389        w = getEssentialPolynomial().subtract(S.getEssentialPolynomial());
390        return new ColorPolynomial<C>(g, r, w);
391    }
392
393
394    /**
395     * ColorPolynomial subtract.
396     * @param s GenPolynomial.
397     * @param e exponent vector.
398     * @return this-(c e).
399     */
400    public ColorPolynomial<C> subtract(GenPolynomial<C> s, ExpVector e) {
401        GenPolynomial<GenPolynomial<C>> g, r, w;
402        g = green;
403        r = red;
404        w = white;
405        if (green.getMap().keySet().contains(e)) {
406            g = green.subtract(s, e);
407        } else if (red.getMap().keySet().contains(e)) {
408            r = red.subtract(s, e);
409        } else {
410            w = white.subtract(s, e);
411        }
412        return new ColorPolynomial<C>(g, r, w);
413    }
414
415
416    /**
417     * ColorPolynomial multiplication by monomial.
418     * @param s Coefficient.
419     * @param e Expvector.
420     * @return this * (c t).
421     */
422    public ColorPolynomial<C> multiply(GenPolynomial<C> s, ExpVector e) {
423        GenPolynomial<GenPolynomial<C>> g, r, w;
424        if (green instanceof GenSolvablePolynomial) {
425            logger.info("use left multiplication");
426            GenSolvablePolynomial<GenPolynomial<C>> gs, rs, ws;
427            gs = (GenSolvablePolynomial<GenPolynomial<C>>) green;
428            rs = (GenSolvablePolynomial<GenPolynomial<C>>) red;
429            ws = (GenSolvablePolynomial<GenPolynomial<C>>) white;
430            g = gs.multiplyLeft(s, e);
431            r = rs.multiplyLeft(s, e);
432            w = ws.multiplyLeft(s, e);
433        } else {
434            g = green.multiply(s, e);
435            r = red.multiply(s, e);
436            w = white.multiply(s, e);
437        }
438        return new ColorPolynomial<C>(g, r, w);
439    }
440
441
442    /**
443     * ColorPolynomial multiplication by coefficient.
444     * @param s Coefficient.
445     * @return this * (s).
446     */
447    public ColorPolynomial<C> multiply(GenPolynomial<C> s) {
448        GenPolynomial<GenPolynomial<C>> g, r, w;
449        // coefficients commute
450        g = green.multiply(s);
451        r = red.multiply(s);
452        w = white.multiply(s);
453        return new ColorPolynomial<C>(g, r, w);
454    }
455
456
457    /**
458     * ColorPolynomial division by coefficient.
459     * @param s Coefficient.
460     * @return this / (s).
461     */
462    public ColorPolynomial<C> divide(GenPolynomial<C> s) {
463        GenPolynomial<GenPolynomial<C>> g, r, w;
464        g = green.divide(s);
465        r = red.divide(s);
466        w = white.divide(s);
467        return new ColorPolynomial<C>(g, r, w);
468    }
469
470
471}