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