001/*
002 * $Id$
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.LogManager;
016import org.apache.logging.log4j.Logger;
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, GenPolynomial<GenPolynomial<C>> r,
063                    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) &gt; LT(red) and TT(red) &gt;
172     * LT(white).
173     * @return true, if all ordering invariants are met, else false.
174     */
175    public boolean checkInvariant() {
176        boolean t = true;
177        ExpVector ttg, ltr, ttr, ltw;
178        Comparator<ExpVector> cmp;
179        if (green.isZERO() && red.isZERO() && white.isZERO()) {
180            return true;
181        }
182        if (green.isZERO() && red.isZERO()) {
183            return true;
184        }
185        if (red.isZERO() && white.isZERO()) {
186            return true;
187        }
188
189        if (!green.isZERO() && !red.isZERO()) {
190            ttg = green.trailingExpVector();
191            ltr = red.leadingExpVector();
192            cmp = green.ring.tord.getDescendComparator();
193            t = t && (cmp.compare(ttg, ltr) < 0);
194        }
195        if (!red.isZERO() && !white.isZERO()) {
196            ttr = red.trailingExpVector();
197            ltw = white.leadingExpVector();
198            cmp = white.ring.tord.getDescendComparator();
199            t = t && (cmp.compare(ttr, ltw) < 0);
200        }
201        if (red.isZERO() && !green.isZERO() && !white.isZERO()) {
202            ttg = green.trailingExpVector();
203            ltw = white.leadingExpVector();
204            cmp = white.ring.tord.getDescendComparator();
205            t = t && (cmp.compare(ttg, ltw) < 0);
206        }
207        if (!t) {
208            System.out.println("not invariant " + this);
209            // throw new RuntimeException("test");
210        }
211        return t;
212    }
213
214
215    /**
216     * Get zero condition on coefficients.
217     * @return green coefficients.
218     */
219    public List<GenPolynomial<C>> getGreenCoefficients() {
220        Collection<GenPolynomial<C>> c = green.getMap().values();
221        return new ArrayList<GenPolynomial<C>>(c);
222    }
223
224
225    /**
226     * Get non zero condition on coefficients.
227     * @return red coefficients.
228     */
229    public List<GenPolynomial<C>> getRedCoefficients() {
230        Collection<GenPolynomial<C>> c = red.getMap().values();
231        return new ArrayList<GenPolynomial<C>>(c);
232    }
233
234
235    /**
236     * Get full polynomial.
237     * @return sum of all parts.
238     */
239    public GenPolynomial<GenPolynomial<C>> getPolynomial() {
240        GenPolynomial<GenPolynomial<C>> f = green.sum(red).sum(white);
241        int s = green.length() + red.length() + white.length();
242        int t = f.length();
243        if (t != s) {
244            throw new RuntimeException("illegal coloring state " + s + " != " + t);
245        }
246        return f;
247    }
248
249
250    /**
251     * Get essential polynomial.
252     * @return sum of red and white parts.
253     */
254    public GenPolynomial<GenPolynomial<C>> getEssentialPolynomial() {
255        GenPolynomial<GenPolynomial<C>> f = red.sum(white);
256        int s = red.length() + white.length();
257        int t = f.length();
258        if (t != s) {
259            logger.warn("incomplete coloring state {} != {}", s, t);
260            logger.info("f = {}, red = {}, white = {}", f, red, white);
261            //throw new RuntimeException("illegal coloring state " + s + " != " + t);
262        }
263        return f;
264    }
265
266
267    /**
268     * Length of red and white parts.
269     * @return length of essential parts.
270     */
271    public int length() {
272        int s = red.length() + white.length();
273        return s;
274    }
275
276
277    /**
278     * Get leading exponent vector.
279     * @return LT of red or white parts.
280     */
281    public ExpVector leadingExpVector() {
282        if (!red.isZERO()) {
283            return red.leadingExpVector();
284        }
285        return white.leadingExpVector();
286    }
287
288
289    /**
290     * Get leading monomial.
291     * @return LM of red or white parts.
292     */
293    public Map.Entry<ExpVector, GenPolynomial<C>> leadingMonomial() {
294        if (!red.isZERO()) {
295            return red.leadingMonomial();
296        }
297        return white.leadingMonomial();
298    }
299
300
301    /**
302     * ColorPolynomial absolute value.
303     * @return abs(this).
304     */
305    public ColorPolynomial<C> abs() {
306        GenPolynomial<GenPolynomial<C>> g, r, w;
307        int s = green.signum();
308        if (s > 0) {
309            return this;
310        }
311        if (s < 0) {
312            g = green.negate();
313            r = red.negate();
314            w = white.negate();
315            return new ColorPolynomial<C>(g, r, w);
316        }
317        // green == 0
318        g = green;
319        s = red.signum();
320        if (s > 0) {
321            return this;
322        }
323        if (s < 0) {
324            r = red.negate();
325            w = white.negate();
326            return new ColorPolynomial<C>(g, r, w);
327        }
328        // red == 0
329        r = red;
330        s = white.signum();
331        if (s > 0) {
332            return this;
333        }
334        if (s < 0) {
335            w = white.negate();
336            return new ColorPolynomial<C>(g, r, w);
337        }
338        // white == 0
339        w = white;
340        return new ColorPolynomial<C>(g, r, w);
341    }
342
343
344    /**
345     * ColorPolynomial summation. <b>Note:</b> green coefficients stay green,
346     * all others become white.
347     * @param S ColorPolynomial.
348     * @return this+S.
349     */
350    public ColorPolynomial<C> sum(ColorPolynomial<C> S) {
351        GenPolynomial<GenPolynomial<C>> g, r, w;
352        g = green.sum(S.green);
353        r = red.ring.getZERO();
354        w = getEssentialPolynomial().sum(S.getEssentialPolynomial());
355        return new ColorPolynomial<C>(g, r, w);
356    }
357
358
359    /**
360     * ColorPolynomial summation.
361     * @param s GenPolynomial.
362     * @param e exponent vector.
363     * @return this+(c e).
364     */
365    public ColorPolynomial<C> sum(GenPolynomial<C> s, ExpVector e) {
366        GenPolynomial<GenPolynomial<C>> g, r, w;
367        g = green;
368        r = red;
369        w = white;
370        if (green.getMap().keySet().contains(e)) {
371            g = green.sum(s, e);
372        } else if (red.getMap().keySet().contains(e)) {
373            r = red.sum(s, e);
374        } else {
375            w = white.sum(s, e);
376        }
377        return new ColorPolynomial<C>(g, r, w);
378    }
379
380
381    /**
382     * ColorPolynomial subtraction. <b>Note:</b> green coefficients stay green,
383     * all others become white.
384     * @param S ColorPolynomial.
385     * @return this-S.
386     */
387    public ColorPolynomial<C> subtract(ColorPolynomial<C> S) {
388        GenPolynomial<GenPolynomial<C>> g, r, w;
389        g = green.subtract(S.green);
390        r = red.ring.getZERO();
391        w = getEssentialPolynomial().subtract(S.getEssentialPolynomial());
392        return new ColorPolynomial<C>(g, r, w);
393    }
394
395
396    /**
397     * ColorPolynomial subtract.
398     * @param s GenPolynomial.
399     * @param e exponent vector.
400     * @return this-(c e).
401     */
402    public ColorPolynomial<C> subtract(GenPolynomial<C> s, ExpVector e) {
403        GenPolynomial<GenPolynomial<C>> g, r, w;
404        g = green;
405        r = red;
406        w = white;
407        if (green.getMap().keySet().contains(e)) {
408            g = green.subtract(s, e);
409        } else if (red.getMap().keySet().contains(e)) {
410            r = red.subtract(s, e);
411        } else {
412            w = white.subtract(s, e);
413        }
414        return new ColorPolynomial<C>(g, r, w);
415    }
416
417
418    /**
419     * ColorPolynomial multiplication by monomial.
420     * @param s Coefficient.
421     * @param e Expvector.
422     * @return this * (c t).
423     */
424    public ColorPolynomial<C> multiply(GenPolynomial<C> s, ExpVector e) {
425        GenPolynomial<GenPolynomial<C>> g, r, w;
426        if (green instanceof GenSolvablePolynomial) {
427            logger.info("use left multiplication");
428            GenSolvablePolynomial<GenPolynomial<C>> gs, rs, ws;
429            gs = (GenSolvablePolynomial<GenPolynomial<C>>) green;
430            rs = (GenSolvablePolynomial<GenPolynomial<C>>) red;
431            ws = (GenSolvablePolynomial<GenPolynomial<C>>) white;
432            g = gs.multiplyLeft(s, e);
433            r = rs.multiplyLeft(s, e);
434            w = ws.multiplyLeft(s, e);
435        } else {
436            g = green.multiply(s, e);
437            r = red.multiply(s, e);
438            w = white.multiply(s, e);
439        }
440        return new ColorPolynomial<C>(g, r, w);
441    }
442
443
444    /**
445     * ColorPolynomial multiplication by coefficient.
446     * @param s Coefficient.
447     * @return this * (s).
448     */
449    public ColorPolynomial<C> multiply(GenPolynomial<C> s) {
450        GenPolynomial<GenPolynomial<C>> g, r, w;
451        // coefficients commute
452        g = green.multiply(s);
453        r = red.multiply(s);
454        w = white.multiply(s);
455        return new ColorPolynomial<C>(g, r, w);
456    }
457
458
459    /**
460     * ColorPolynomial division by coefficient.
461     * @param s Coefficient.
462     * @return this / (s).
463     */
464    public ColorPolynomial<C> divide(GenPolynomial<C> s) {
465        GenPolynomial<GenPolynomial<C>> g, r, w;
466        g = green.divide(s);
467        r = red.divide(s);
468        w = white.divide(s);
469        return new ColorPolynomial<C>(g, r, w);
470    }
471
472
473}